mirror of https://gitee.com/openkylin/linux.git
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (247 commits) [media] gspca - sunplus: Fix some warnings and simplify code [media] gspca: Fix some warnings tied to 'no debug' [media] gspca: Unset debug by default [media] gspca - cpia1: Remove a bad conditional compilation instruction [media] gspca - main: Remove USB traces [media] gspca - main: Version change to 2.13 [media] gspca - stk014 / t613: Accept the index 0 in querymenu [media] gspca - kinect: Remove __devinitdata [media] gspca - cpia1: Fix some warnings [media] video/Kconfig: Fix mis-classified devices [media] support for medion dvb stick 1660:1921 [media] tm6000: fix uninitialized field, change prink to dprintk [media] cx231xx: Add support for Iconbit U100 [media] saa7134 add new TV cards [media] Use a more consistent value for RC repeat period [media] cx18: Move spinlock and vb_type initialisation into stream_init [media] tm6000: remove tm6010 sif audio start and stop [media] tm6000: remove unused exports [media] tm6000: add pts logging [media] tm6000: change from ioctl to unlocked_ioctl ...
This commit is contained in:
commit
df462b3dbe
|
@ -8,3 +8,4 @@
|
|||
*.dvi
|
||||
*.log
|
||||
*.out
|
||||
media/
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
|
||||
<revhistory>
|
||||
<!-- Put document revisions here, newest first. -->
|
||||
<revision>
|
||||
<revnumber>2.0.4</revnumber>
|
||||
<date>2011-05-06</date>
|
||||
<authorinitials>mcc</authorinitials>
|
||||
<revremark>
|
||||
Add more information about DVB APIv5, better describing the frontend GET/SET props ioctl's.
|
||||
</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>2.0.3</revnumber>
|
||||
<date>2010-07-03</date>
|
||||
|
|
|
@ -1,6 +1,327 @@
|
|||
<section id="FE_GET_PROPERTY">
|
||||
<section id="FE_GET_SET_PROPERTY">
|
||||
<title>FE_GET_PROPERTY/FE_SET_PROPERTY</title>
|
||||
|
||||
<programlisting>
|
||||
/* Reserved fields should be set to 0 */
|
||||
struct dtv_property {
|
||||
__u32 cmd;
|
||||
union {
|
||||
__u32 data;
|
||||
struct {
|
||||
__u8 data[32];
|
||||
__u32 len;
|
||||
__u32 reserved1[3];
|
||||
void *reserved2;
|
||||
} buffer;
|
||||
} u;
|
||||
int result;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
|
||||
#define DTV_IOCTL_MAX_MSGS 64
|
||||
|
||||
struct dtv_properties {
|
||||
__u32 num;
|
||||
struct dtv_property *props;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
<section id="FE_GET_PROPERTY">
|
||||
<title>FE_GET_PROPERTY</title>
|
||||
<para>DESCRIPTION
|
||||
</para>
|
||||
<informaltable><tgroup cols="1"><tbody><row><entry
|
||||
align="char">
|
||||
<para>This ioctl call returns one or more frontend properties. This call only
|
||||
requires read-only access to the device.</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>SYNOPSIS
|
||||
</para>
|
||||
<informaltable><tgroup cols="1"><tbody><row><entry
|
||||
align="char">
|
||||
<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>,
|
||||
dtv_properties ⋆props);</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>PARAMETERS
|
||||
</para>
|
||||
<informaltable><tgroup cols="2"><tbody><row><entry align="char">
|
||||
<para>int fd</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>File descriptor returned by a previous call to open().</para>
|
||||
</entry>
|
||||
</row><row><entry
|
||||
align="char">
|
||||
<para>int num</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para>
|
||||
</entry>
|
||||
</row><row><entry
|
||||
align="char">
|
||||
<para>struct dtv_property *props</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>Points to the location where the front-end property commands are stored.</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>ERRORS</para>
|
||||
<informaltable><tgroup cols="2"><tbody><row>
|
||||
<entry align="char"><para>EINVAL</para></entry>
|
||||
<entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>ENOMEM</para></entry>
|
||||
<entry align="char"><para>Out of memory.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>EFAULT</para></entry>
|
||||
<entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>EOPNOTSUPP</para></entry>
|
||||
<entry align="char"><para>Property type not supported.</para></entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
</section>
|
||||
|
||||
<section id="FE_SET_PROPERTY">
|
||||
<title>FE_SET_PROPERTY</title>
|
||||
<para>DESCRIPTION
|
||||
</para>
|
||||
<informaltable><tgroup cols="1"><tbody><row><entry
|
||||
align="char">
|
||||
<para>This ioctl call sets one or more frontend properties. This call only
|
||||
requires read-only access to the device.</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>SYNOPSIS
|
||||
</para>
|
||||
<informaltable><tgroup cols="1"><tbody><row><entry
|
||||
align="char">
|
||||
<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
|
||||
dtv_properties ⋆props);</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>PARAMETERS
|
||||
</para>
|
||||
<informaltable><tgroup cols="2"><tbody><row><entry align="char">
|
||||
<para>int fd</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>File descriptor returned by a previous call to open().</para>
|
||||
</entry>
|
||||
</row><row><entry
|
||||
align="char">
|
||||
<para>int num</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para>
|
||||
</entry>
|
||||
</row><row><entry
|
||||
align="char">
|
||||
<para>struct dtv_property *props</para>
|
||||
</entry><entry
|
||||
align="char">
|
||||
<para>Points to the location where the front-end property commands are stored.</para>
|
||||
</entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
<para>ERRORS
|
||||
</para>
|
||||
<informaltable><tgroup cols="2"><tbody><row>
|
||||
<entry align="char"><para>EINVAL</para></entry>
|
||||
<entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>ENOMEM</para></entry>
|
||||
<entry align="char"><para>Out of memory.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>EFAULT</para></entry>
|
||||
<entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
|
||||
</row><row>
|
||||
<entry align="char"><para>EOPNOTSUPP</para></entry>
|
||||
<entry align="char"><para>Property type not supported.</para></entry>
|
||||
</row></tbody></tgroup></informaltable>
|
||||
</section>
|
||||
|
||||
<para>
|
||||
On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
|
||||
the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
|
||||
get/set up to 64 properties. The actual meaning of each property is described on the next sections.
|
||||
</para>
|
||||
|
||||
<para>The Available frontend property types are:</para>
|
||||
<programlisting>
|
||||
#define DTV_UNDEFINED 0
|
||||
#define DTV_TUNE 1
|
||||
#define DTV_CLEAR 2
|
||||
#define DTV_FREQUENCY 3
|
||||
#define DTV_MODULATION 4
|
||||
#define DTV_BANDWIDTH_HZ 5
|
||||
#define DTV_INVERSION 6
|
||||
#define DTV_DISEQC_MASTER 7
|
||||
#define DTV_SYMBOL_RATE 8
|
||||
#define DTV_INNER_FEC 9
|
||||
#define DTV_VOLTAGE 10
|
||||
#define DTV_TONE 11
|
||||
#define DTV_PILOT 12
|
||||
#define DTV_ROLLOFF 13
|
||||
#define DTV_DISEQC_SLAVE_REPLY 14
|
||||
#define DTV_FE_CAPABILITY_COUNT 15
|
||||
#define DTV_FE_CAPABILITY 16
|
||||
#define DTV_DELIVERY_SYSTEM 17
|
||||
#define DTV_ISDBT_PARTIAL_RECEPTION 18
|
||||
#define DTV_ISDBT_SOUND_BROADCASTING 19
|
||||
#define DTV_ISDBT_SB_SUBCHANNEL_ID 20
|
||||
#define DTV_ISDBT_SB_SEGMENT_IDX 21
|
||||
#define DTV_ISDBT_SB_SEGMENT_COUNT 22
|
||||
#define DTV_ISDBT_LAYERA_FEC 23
|
||||
#define DTV_ISDBT_LAYERA_MODULATION 24
|
||||
#define DTV_ISDBT_LAYERA_SEGMENT_COUNT 25
|
||||
#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING 26
|
||||
#define DTV_ISDBT_LAYERB_FEC 27
|
||||
#define DTV_ISDBT_LAYERB_MODULATION 28
|
||||
#define DTV_ISDBT_LAYERB_SEGMENT_COUNT 29
|
||||
#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING 30
|
||||
#define DTV_ISDBT_LAYERC_FEC 31
|
||||
#define DTV_ISDBT_LAYERC_MODULATION 32
|
||||
#define DTV_ISDBT_LAYERC_SEGMENT_COUNT 33
|
||||
#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING 34
|
||||
#define DTV_API_VERSION 35
|
||||
#define DTV_CODE_RATE_HP 36
|
||||
#define DTV_CODE_RATE_LP 37
|
||||
#define DTV_GUARD_INTERVAL 38
|
||||
#define DTV_TRANSMISSION_MODE 39
|
||||
#define DTV_HIERARCHY 40
|
||||
#define DTV_ISDBT_LAYER_ENABLED 41
|
||||
#define DTV_ISDBS_TS_ID 42
|
||||
</programlisting>
|
||||
|
||||
<section id="fe_property_common">
|
||||
<title>Parameters that are common to all Digital TV standards</title>
|
||||
<section id="DTV_FREQUENCY">
|
||||
<title><constant>DTV_FREQUENCY</constant></title>
|
||||
|
||||
<para>Central frequency of the channel, in HZ.</para>
|
||||
|
||||
<para>Notes:</para>
|
||||
<para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
|
||||
E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
|
||||
the channel which is 6MHz.</para>
|
||||
|
||||
<para>2)As in ISDB-Tsb the channel consists of only one or three segments the
|
||||
frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
|
||||
central frequency of the channel is expected.</para>
|
||||
</section>
|
||||
|
||||
<section id="DTV_BANDWIDTH_HZ">
|
||||
<title><constant>DTV_BANDWIDTH_HZ</constant></title>
|
||||
|
||||
<para>Bandwidth for the channel, in HZ.</para>
|
||||
|
||||
<para>Possible values:
|
||||
<constant>1712000</constant>,
|
||||
<constant>5000000</constant>,
|
||||
<constant>6000000</constant>,
|
||||
<constant>7000000</constant>,
|
||||
<constant>8000000</constant>,
|
||||
<constant>10000000</constant>.
|
||||
</para>
|
||||
|
||||
<para>Notes:</para>
|
||||
|
||||
<para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para>
|
||||
<para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para>
|
||||
<para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth
|
||||
for DVB-C depends on the symbol rate</para>
|
||||
<para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
|
||||
other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
|
||||
DTV_ISDBT_SB_SEGMENT_COUNT).</para>
|
||||
<para>5) DVB-T supports 6, 7 and 8MHz.</para>
|
||||
<para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para>
|
||||
</section>
|
||||
|
||||
<section id="DTV_DELIVERY_SYSTEM">
|
||||
<title><constant>DTV_DELIVERY_SYSTEM</constant></title>
|
||||
|
||||
<para>Specifies the type of Delivery system</para>
|
||||
|
||||
<para>Possible values: </para>
|
||||
<programlisting>
|
||||
typedef enum fe_delivery_system {
|
||||
SYS_UNDEFINED,
|
||||
SYS_DVBC_ANNEX_AC,
|
||||
SYS_DVBC_ANNEX_B,
|
||||
SYS_DVBT,
|
||||
SYS_DSS,
|
||||
SYS_DVBS,
|
||||
SYS_DVBS2,
|
||||
SYS_DVBH,
|
||||
SYS_ISDBT,
|
||||
SYS_ISDBS,
|
||||
SYS_ISDBC,
|
||||
SYS_ATSC,
|
||||
SYS_ATSCMH,
|
||||
SYS_DMBTH,
|
||||
SYS_CMMB,
|
||||
SYS_DAB,
|
||||
SYS_DVBT2,
|
||||
} fe_delivery_system_t;
|
||||
</programlisting>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="DTV_TRANSMISSION_MODE">
|
||||
<title><constant>DTV_TRANSMISSION_MODE</constant></title>
|
||||
|
||||
<para>Specifies the number of carriers used by the standard</para>
|
||||
|
||||
<para>Possible values are:</para>
|
||||
<programlisting>
|
||||
typedef enum fe_transmit_mode {
|
||||
TRANSMISSION_MODE_2K,
|
||||
TRANSMISSION_MODE_8K,
|
||||
TRANSMISSION_MODE_AUTO,
|
||||
TRANSMISSION_MODE_4K,
|
||||
TRANSMISSION_MODE_1K,
|
||||
TRANSMISSION_MODE_16K,
|
||||
TRANSMISSION_MODE_32K,
|
||||
} fe_transmit_mode_t;
|
||||
</programlisting>
|
||||
|
||||
<para>Notes:</para>
|
||||
<para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
|
||||
'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
|
||||
|
||||
<para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
|
||||
hardware will try to find the correct FFT-size (if capable) and will
|
||||
use TMCC to fill in the missing parameters.</para>
|
||||
<para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
|
||||
<para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
|
||||
</section>
|
||||
|
||||
<section id="DTV_GUARD_INTERVAL">
|
||||
<title><constant>DTV_GUARD_INTERVAL</constant></title>
|
||||
|
||||
<para>Possible values are:</para>
|
||||
<programlisting>
|
||||
typedef enum fe_guard_interval {
|
||||
GUARD_INTERVAL_1_32,
|
||||
GUARD_INTERVAL_1_16,
|
||||
GUARD_INTERVAL_1_8,
|
||||
GUARD_INTERVAL_1_4,
|
||||
GUARD_INTERVAL_AUTO,
|
||||
GUARD_INTERVAL_1_128,
|
||||
GUARD_INTERVAL_19_128,
|
||||
GUARD_INTERVAL_19_256,
|
||||
} fe_guard_interval_t;
|
||||
</programlisting>
|
||||
|
||||
<para>Notes:</para>
|
||||
<para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
|
||||
try to find the correct guard interval (if capable) and will use TMCC to fill
|
||||
in the missing parameters.</para>
|
||||
<para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="isdbt">
|
||||
<title>ISDB-T frontend</title>
|
||||
<para>This section describes shortly what are the possible parameters in the Linux
|
||||
|
@ -32,73 +353,6 @@
|
|||
|
||||
<para>Parameters used by ISDB-T and ISDB-Tsb.</para>
|
||||
|
||||
<section id="isdbt-parms">
|
||||
<title>Parameters that are common with DVB-T and ATSC</title>
|
||||
|
||||
<section id="isdbt-freq">
|
||||
<title><constant>DTV_FREQUENCY</constant></title>
|
||||
|
||||
<para>Central frequency of the channel.</para>
|
||||
|
||||
<para>For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a
|
||||
valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
|
||||
the channel which is 6MHz.</para>
|
||||
|
||||
<para>As in ISDB-Tsb the channel consists of only one or three segments the
|
||||
frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
|
||||
central frequency of the channel is expected.</para>
|
||||
</section>
|
||||
|
||||
<section id="isdbt-bw">
|
||||
<title><constant>DTV_BANDWIDTH_HZ</constant> (optional)</title>
|
||||
|
||||
<para>Possible values:</para>
|
||||
|
||||
<para>For ISDB-T it should be always 6000000Hz (6MHz)</para>
|
||||
<para>For ISDB-Tsb it can vary depending on the number of connected segments</para>
|
||||
|
||||
<para>Note: Hardware specific values might be given here, but standard
|
||||
applications should not bother to set a value to this field as
|
||||
standard demods are ignoring it anyway.</para>
|
||||
|
||||
<para>Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
|
||||
other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
|
||||
DTV_ISDBT_SB_SEGMENT_COUNT).</para>
|
||||
</section>
|
||||
|
||||
<section id="isdbt-delivery-sys">
|
||||
<title><constant>DTV_DELIVERY_SYSTEM</constant></title>
|
||||
|
||||
<para>Possible values: <constant>SYS_ISDBT</constant></para>
|
||||
</section>
|
||||
|
||||
<section id="isdbt-tx-mode">
|
||||
<title><constant>DTV_TRANSMISSION_MODE</constant></title>
|
||||
|
||||
<para>ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
|
||||
'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
|
||||
|
||||
<para>Possible values: <constant>TRANSMISSION_MODE_2K</constant>, <constant>TRANSMISSION_MODE_8K</constant>,
|
||||
<constant>TRANSMISSION_MODE_AUTO</constant>, <constant>TRANSMISSION_MODE_4K</constant></para>
|
||||
|
||||
<para>If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
|
||||
hardware will try to find the correct FFT-size (if capable) and will
|
||||
use TMCC to fill in the missing parameters.</para>
|
||||
|
||||
<para><constant>TRANSMISSION_MODE_4K</constant> is added at the same time as the other new parameters.</para>
|
||||
</section>
|
||||
|
||||
<section id="isdbt-guard-interval">
|
||||
<title><constant>DTV_GUARD_INTERVAL</constant></title>
|
||||
|
||||
<para>Possible values: <constant>GUARD_INTERVAL_1_32</constant>, <constant>GUARD_INTERVAL_1_16</constant>, <constant>GUARD_INTERVAL_1_8</constant>,
|
||||
<constant>GUARD_INTERVAL_1_4</constant>, <constant>GUARD_INTERVAL_AUTO</constant></para>
|
||||
|
||||
<para>If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
|
||||
try to find the correct guard interval (if capable) and will use TMCC to fill
|
||||
in the missing parameters.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section id="isdbt-new-parms">
|
||||
<title>ISDB-T only parameters</title>
|
||||
|
||||
|
@ -314,5 +568,20 @@
|
|||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="dvbt2-params">
|
||||
<title>DVB-T2 parameters</title>
|
||||
|
||||
<para>This section covers parameters that apply only to the DVB-T2 delivery method. DVB-T2
|
||||
support is currently in the early stages development so expect this section to grow
|
||||
and become more detailed with time.</para>
|
||||
|
||||
<section id="dvbt2-plp-id">
|
||||
<title><constant>DTV_DVBT2_PLP_ID</constant></title>
|
||||
|
||||
<para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
|
||||
many data types via a single multiplex. The API will soon support this
|
||||
at which point this section will be expanded.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -176,14 +176,20 @@ typedef enum fe_transmit_mode {
|
|||
TRANSMISSION_MODE_2K,
|
||||
TRANSMISSION_MODE_8K,
|
||||
TRANSMISSION_MODE_AUTO,
|
||||
TRANSMISSION_MODE_4K
|
||||
TRANSMISSION_MODE_4K,
|
||||
TRANSMISSION_MODE_1K,
|
||||
TRANSMISSION_MODE_16K,
|
||||
TRANSMISSION_MODE_32K,
|
||||
} fe_transmit_mode_t;
|
||||
|
||||
typedef enum fe_bandwidth {
|
||||
BANDWIDTH_8_MHZ,
|
||||
BANDWIDTH_7_MHZ,
|
||||
BANDWIDTH_6_MHZ,
|
||||
BANDWIDTH_AUTO
|
||||
BANDWIDTH_AUTO,
|
||||
BANDWIDTH_5_MHZ,
|
||||
BANDWIDTH_10_MHZ,
|
||||
BANDWIDTH_1_712_MHZ,
|
||||
} fe_bandwidth_t;
|
||||
|
||||
|
||||
|
@ -192,7 +198,10 @@ typedef enum fe_guard_interval {
|
|||
GUARD_INTERVAL_1_16,
|
||||
GUARD_INTERVAL_1_8,
|
||||
GUARD_INTERVAL_1_4,
|
||||
GUARD_INTERVAL_AUTO
|
||||
GUARD_INTERVAL_AUTO,
|
||||
GUARD_INTERVAL_1_128,
|
||||
GUARD_INTERVAL_19_128,
|
||||
GUARD_INTERVAL_19_256,
|
||||
} fe_guard_interval_t;
|
||||
|
||||
|
||||
|
@ -306,7 +315,9 @@ struct dvb_frontend_event {
|
|||
|
||||
#define DTV_ISDBS_TS_ID 42
|
||||
|
||||
#define DTV_MAX_COMMAND DTV_ISDBS_TS_ID
|
||||
#define DTV_DVBT2_PLP_ID 43
|
||||
|
||||
#define DTV_MAX_COMMAND DTV_DVBT2_PLP_ID
|
||||
|
||||
typedef enum fe_pilot {
|
||||
PILOT_ON,
|
||||
|
@ -338,6 +349,7 @@ typedef enum fe_delivery_system {
|
|||
SYS_DMBTH,
|
||||
SYS_CMMB,
|
||||
SYS_DAB,
|
||||
SYS_DVBT2,
|
||||
} fe_delivery_system_t;
|
||||
|
||||
struct dtv_cmds_h {
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
<!ENTITY sub-write SYSTEM "v4l/func-write.xml">
|
||||
<!ENTITY sub-io SYSTEM "v4l/io.xml">
|
||||
<!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
|
||||
<!ENTITY sub-m420 SYSTEM "v4l/pixfmt-m420.xml">
|
||||
<!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
|
||||
<!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
|
||||
<!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
|
||||
|
@ -295,6 +296,7 @@
|
|||
<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
|
||||
<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
|
||||
<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
|
||||
<!ENTITY sub-y10b SYSTEM "v4l/pixfmt-y10b.xml">
|
||||
<!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
|
||||
<!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
|
||||
<!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
<refentry id="V4L2-PIX-FMT-M420">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_M420 ('M420')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><constant>V4L2_PIX_FMT_M420</constant></refname>
|
||||
<refpurpose>Format with ½ horizontal and vertical chroma
|
||||
resolution, also known as YUV 4:2:0. Hybrid plane line-interleaved
|
||||
layout.</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>M420 is a YUV format with ½ horizontal and vertical chroma
|
||||
subsampling (YUV 4:2:0). Pixels are organized as interleaved luma and
|
||||
chroma planes. Two lines of luma data are followed by one line of chroma
|
||||
data.</para>
|
||||
<para>The luma plane has one byte per pixel. The chroma plane contains
|
||||
interleaved CbCr pixels subsampled by ½ in the horizontal and
|
||||
vertical directions. Each CbCr pair belongs to four pixels. For example,
|
||||
Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
|
||||
Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
|
||||
Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.</para>
|
||||
|
||||
<para>All line lengths are identical: if the Y lines include pad bytes
|
||||
so do the CbCr lines.</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_M420</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>Y'<subscript>00</subscript></entry>
|
||||
<entry>Y'<subscript>01</subscript></entry>
|
||||
<entry>Y'<subscript>02</subscript></entry>
|
||||
<entry>Y'<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 4:</entry>
|
||||
<entry>Y'<subscript>10</subscript></entry>
|
||||
<entry>Y'<subscript>11</subscript></entry>
|
||||
<entry>Y'<subscript>12</subscript></entry>
|
||||
<entry>Y'<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>Cb<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>01</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>Y'<subscript>20</subscript></entry>
|
||||
<entry>Y'<subscript>21</subscript></entry>
|
||||
<entry>Y'<subscript>22</subscript></entry>
|
||||
<entry>Y'<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 20:</entry>
|
||||
<entry>Y'<subscript>30</subscript></entry>
|
||||
<entry>Y'<subscript>31</subscript></entry>
|
||||
<entry>Y'<subscript>32</subscript></entry>
|
||||
<entry>Y'<subscript>33</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>11</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title>Color Sample Location.</title>
|
||||
<para>
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="7" align="center">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>0</entry><entry></entry><entry>1</entry><entry></entry>
|
||||
<entry>2</entry><entry></entry><entry>3</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-parent-document: "pixfmt.sgml"
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
-->
|
|
@ -0,0 +1,43 @@
|
|||
<refentry id="V4L2-PIX-FMT-Y10BPACK">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_Y10BPACK ('Y10B')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><constant>V4L2_PIX_FMT_Y10BPACK</constant></refname>
|
||||
<refpurpose>Grey-scale image as a bit-packed array</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a packed grey-scale image format with a depth of 10 bits per
|
||||
pixel. Pixels are stored in a bit-packed array of 10bit bits per pixel,
|
||||
with no padding between them and with the most significant bits coming
|
||||
first from the left.</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_Y10BPACK</constant> 4 pixel data stream taking 5 bytes</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Bit-packed representation</title>
|
||||
<para>pixels cross the byte boundary and have a ratio of 5 bytes for each 4
|
||||
pixels.
|
||||
<informaltable frame="all">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>Y'<subscript>00[9:2]</subscript></entry>
|
||||
<entry>Y'<subscript>00[1:0]</subscript>Y'<subscript>01[9:4]</subscript></entry>
|
||||
<entry>Y'<subscript>01[3:0]</subscript>Y'<subscript>02[9:6]</subscript></entry>
|
||||
<entry>Y'<subscript>02[5:0]</subscript>Y'<subscript>03[9:8]</subscript></entry>
|
||||
<entry>Y'<subscript>03[7:0]</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -697,6 +697,7 @@ information.</para>
|
|||
&sub-grey;
|
||||
&sub-y10;
|
||||
&sub-y12;
|
||||
&sub-y10b;
|
||||
&sub-y16;
|
||||
&sub-yuyv;
|
||||
&sub-uyvy;
|
||||
|
@ -712,6 +713,7 @@ information.</para>
|
|||
&sub-nv12m;
|
||||
&sub-nv12mt;
|
||||
&sub-nv16;
|
||||
&sub-m420;
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
|
|
@ -2522,5 +2522,51 @@
|
|||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>JPEG Compressed Formats</title>
|
||||
|
||||
<para>Those data formats consist of an ordered sequence of 8-bit bytes
|
||||
obtained from JPEG compression process. Additionally to the
|
||||
<constant>_JPEG</constant> prefix the format code is made of
|
||||
the following information.
|
||||
<itemizedlist>
|
||||
<listitem>The number of bus samples per entropy encoded byte.</listitem>
|
||||
<listitem>The bus width.</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For instance, for a JPEG baseline process and an 8-bit bus width
|
||||
the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>.
|
||||
</para>
|
||||
</para>
|
||||
|
||||
<para>The following table lists existing JPEG compressed formats.</para>
|
||||
|
||||
<table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-jpeg">
|
||||
<title>JPEG Formats</title>
|
||||
<tgroup cols="3">
|
||||
<colspec colname="id" align="left" />
|
||||
<colspec colname="code" align="left"/>
|
||||
<colspec colname="remarks" align="left"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Identifier</entry>
|
||||
<entry>Code</entry>
|
||||
<entry>Remarks</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<row id="V4L2-MBUS-FMT-JPEG-1X8">
|
||||
<entry>V4L2_MBUS_FMT_JPEG_1X8</entry>
|
||||
<entry>0x4001</entry>
|
||||
<entry>Besides of its usage for the parallel bus this format is
|
||||
recommended for transmission of JPEG data over MIPI CSI bus
|
||||
using the User Defined 8-bit Data types.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -311,6 +311,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link> v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link> v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */
|
||||
|
||||
/* Grey bit-packed formats */
|
||||
#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link> v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */
|
||||
|
||||
/* Palette formats */
|
||||
#define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link> v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */
|
||||
|
||||
|
@ -333,6 +336,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link> v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */
|
||||
#define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link> v4l2_fourcc('H', 'I', '2', '4') /* 8 8-bit color */
|
||||
#define <link linkend="V4L2-PIX-FMT-HM12">V4L2_PIX_FMT_HM12</link> v4l2_fourcc('H', 'M', '1', '2') /* 8 YUV 4:2:0 16x16 macroblocks */
|
||||
#define <link linkend="V4L2-PIX-FMT-M420">V4L2_PIX_FMT_M420</link> v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */
|
||||
|
||||
/* two planes -- one Y, one Cr + Cb interleaved */
|
||||
#define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link> v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
|
||||
|
|
|
@ -551,3 +551,26 @@ Why: These legacy callbacks should no longer be used as i2c-core offers
|
|||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver
|
||||
When: 2.6.42
|
||||
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: 2.6.42
|
||||
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: 2.6.42
|
||||
Why: Superseded by the UVCIOC_CTRL_QUERY ioctl.
|
||||
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
----------------------------
|
||||
|
|
|
@ -166,7 +166,6 @@ Code Seq#(hex) Include File Comments
|
|||
'T' all arch/x86/include/asm/ioctls.h conflict!
|
||||
'T' C0-DF linux/if_tun.h conflict!
|
||||
'U' all sound/asound.h conflict!
|
||||
'U' 00-0F drivers/media/video/uvc/uvcvideo.h conflict!
|
||||
'U' 00-CF linux/uinput.h conflict!
|
||||
'U' 00-EF linux/usbdevice_fs.h
|
||||
'U' C0-CF drivers/bluetooth/hci_uart.h
|
||||
|
@ -259,6 +258,7 @@ Code Seq#(hex) Include File Comments
|
|||
't' 80-8F linux/isdn_ppp.h
|
||||
't' 90 linux/toshiba.h
|
||||
'u' 00-1F linux/smb_fs.h gone
|
||||
'u' 20-3F linux/uvcvideo.h USB video class host driver
|
||||
'v' 00-1F linux/ext2_fs.h conflict!
|
||||
'v' 00-1F linux/fs.h conflict!
|
||||
'v' 00-0F linux/sonypi.h conflict!
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
53 -> Pinnacle Hybrid Pro (em2881)
|
||||
54 -> Kworld VS-DVB-T 323UR (em2882) [eb1a:e323]
|
||||
55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882) [0ccd:005e,0ccd:0042]
|
||||
56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226]
|
||||
56 -> Pinnacle Hybrid Pro (330e) (em2882) [2304:0226]
|
||||
57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316]
|
||||
58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041]
|
||||
60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f]
|
||||
|
|
|
@ -130,7 +130,6 @@ Card number: 4
|
|||
|
||||
Note: No module for the mse3000 is available yet
|
||||
Note: No module for the vpx3224 is available yet
|
||||
Note: use encoder=X or decoder=X for non-default i2c chips
|
||||
|
||||
===========================
|
||||
|
||||
|
|
|
@ -275,6 +275,7 @@ pac7302 093a:2629 Genious iSlim 300
|
|||
pac7302 093a:262a Webcam 300k
|
||||
pac7302 093a:262c Philips SPC 230 NC
|
||||
jeilinj 0979:0280 Sakar 57379
|
||||
jeilinj 0979:0280 Sportscam DV15
|
||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||
vc032x 0ac8:0323 Vimicro Vc0323
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
Linux USB Video Class (UVC) driver
|
||||
==================================
|
||||
|
||||
This file documents some driver-specific aspects of the UVC driver, such as
|
||||
driver-specific ioctls and implementation notes.
|
||||
|
||||
Questions and remarks can be sent to the Linux UVC development mailing list at
|
||||
linux-uvc-devel@lists.berlios.de.
|
||||
|
||||
|
||||
Extension Unit (XU) support
|
||||
---------------------------
|
||||
|
||||
1. Introduction
|
||||
|
||||
The UVC specification allows for vendor-specific extensions through extension
|
||||
units (XUs). The Linux UVC driver supports extension unit controls (XU controls)
|
||||
through two separate mechanisms:
|
||||
|
||||
- through mappings of XU controls to V4L2 controls
|
||||
- through a driver-specific ioctl interface
|
||||
|
||||
The first one allows generic V4L2 applications to use XU controls by mapping
|
||||
certain XU controls onto V4L2 controls, which then show up during ordinary
|
||||
control enumeration.
|
||||
|
||||
The second mechanism requires uvcvideo-specific knowledge for the application to
|
||||
access XU controls but exposes the entire UVC XU concept to user space for
|
||||
maximum flexibility.
|
||||
|
||||
Both mechanisms complement each other and are described in more detail below.
|
||||
|
||||
|
||||
2. Control mappings
|
||||
|
||||
The UVC driver provides an API for user space applications to define so-called
|
||||
control mappings at runtime. These allow for individual XU controls or byte
|
||||
ranges thereof to be mapped to new V4L2 controls. Such controls appear and
|
||||
function exactly like normal V4L2 controls (i.e. the stock controls, such as
|
||||
brightness, contrast, etc.). However, reading or writing of such a V4L2 controls
|
||||
triggers a read or write of the associated XU control.
|
||||
|
||||
The ioctl used to create these control mappings is called UVCIOC_CTRL_MAP.
|
||||
Previous driver versions (before 0.2.0) required another ioctl to be used
|
||||
beforehand (UVCIOC_CTRL_ADD) to pass XU control information to the UVC driver.
|
||||
This is no longer necessary as newer uvcvideo versions query the information
|
||||
directly from the device.
|
||||
|
||||
For details on the UVCIOC_CTRL_MAP ioctl please refer to the section titled
|
||||
"IOCTL reference" below.
|
||||
|
||||
|
||||
3. Driver specific XU control interface
|
||||
|
||||
For applications that need to access XU controls directly, e.g. for testing
|
||||
purposes, firmware upload, or accessing binary controls, a second mechanism to
|
||||
access XU controls is provided in the form of a driver-specific ioctl, namely
|
||||
UVCIOC_CTRL_QUERY.
|
||||
|
||||
A call to this ioctl allows applications to send queries to the UVC driver that
|
||||
directly map to the low-level UVC control requests.
|
||||
|
||||
In order to make such a request the UVC unit ID of the control's extension unit
|
||||
and the control selector need to be known. This information either needs to be
|
||||
hardcoded in the application or queried using other ways such as by parsing the
|
||||
UVC descriptor or, if available, using the media controller API to enumerate a
|
||||
device's entities.
|
||||
|
||||
Unless the control size is already known it is necessary to first make a
|
||||
UVC_GET_LEN requests in order to be able to allocate a sufficiently large buffer
|
||||
and set the buffer size to the correct value. Similarly, to find out whether
|
||||
UVC_GET_CUR or UVC_SET_CUR are valid requests for a given control, a
|
||||
UVC_GET_INFO request should be made. The bits 0 (GET supported) and 1 (SET
|
||||
supported) of the resulting byte indicate which requests are valid.
|
||||
|
||||
With the addition of the UVCIOC_CTRL_QUERY ioctl the UVCIOC_CTRL_GET and
|
||||
UVCIOC_CTRL_SET ioctls have become obsolete since their functionality is a
|
||||
subset of the former ioctl. For the time being they are still supported but
|
||||
application developers are encouraged to use UVCIOC_CTRL_QUERY instead.
|
||||
|
||||
For details on the UVCIOC_CTRL_QUERY ioctl please refer to the section titled
|
||||
"IOCTL reference" below.
|
||||
|
||||
|
||||
4. Security
|
||||
|
||||
The API doesn't currently provide a fine-grained access control facility. The
|
||||
UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls require super user permissions.
|
||||
|
||||
Suggestions on how to improve this are welcome.
|
||||
|
||||
|
||||
5. Debugging
|
||||
|
||||
In order to debug problems related to XU controls or controls in general it is
|
||||
recommended to enable the UVC_TRACE_CONTROL bit in the module parameter 'trace'.
|
||||
This causes extra output to be written into the system log.
|
||||
|
||||
|
||||
6. IOCTL reference
|
||||
|
||||
---- UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ----
|
||||
|
||||
Argument: struct uvc_xu_control_mapping
|
||||
|
||||
Description:
|
||||
This ioctl creates a mapping between a UVC control or part of a UVC
|
||||
control and a V4L2 control. Once mappings are defined, userspace
|
||||
applications can access vendor-defined UVC control through the V4L2
|
||||
control API.
|
||||
|
||||
To create a mapping, applications fill the uvc_xu_control_mapping
|
||||
structure with information about an existing UVC control defined with
|
||||
UVCIOC_CTRL_ADD and a new V4L2 control.
|
||||
|
||||
A UVC control can be mapped to several V4L2 controls. For instance,
|
||||
a UVC pan/tilt control could be mapped to separate pan and tilt V4L2
|
||||
controls. The UVC control is divided into non overlapping fields using
|
||||
the 'size' and 'offset' fields and are then independantly mapped to
|
||||
V4L2 control.
|
||||
|
||||
For signed integer V4L2 controls the data_type field should be set to
|
||||
UVC_CTRL_DATA_TYPE_SIGNED. Other values are currently ignored.
|
||||
|
||||
Return value:
|
||||
On success 0 is returned. On error -1 is returned and errno is set
|
||||
appropriately.
|
||||
|
||||
ENOMEM
|
||||
Not enough memory to perform the operation.
|
||||
EPERM
|
||||
Insufficient privileges (super user privileges are required).
|
||||
EINVAL
|
||||
No such UVC control.
|
||||
EOVERFLOW
|
||||
The requested offset and size would overflow the UVC control.
|
||||
EEXIST
|
||||
Mapping already exists.
|
||||
|
||||
Data types:
|
||||
* struct uvc_xu_control_mapping
|
||||
|
||||
__u32 id V4L2 control identifier
|
||||
__u8 name[32] V4L2 control name
|
||||
__u8 entity[16] UVC extension unit GUID
|
||||
__u8 selector UVC control selector
|
||||
__u8 size V4L2 control size (in bits)
|
||||
__u8 offset V4L2 control offset (in bits)
|
||||
enum v4l2_ctrl_type
|
||||
v4l2_type V4L2 control type
|
||||
enum uvc_control_data_type
|
||||
data_type UVC control data type
|
||||
struct uvc_menu_info
|
||||
*menu_info Array of menu entries (for menu controls only)
|
||||
__u32 menu_count Number of menu entries (for menu controls only)
|
||||
|
||||
* struct uvc_menu_info
|
||||
|
||||
__u32 value Menu entry value used by the device
|
||||
__u8 name[32] Menu entry name
|
||||
|
||||
|
||||
* enum uvc_control_data_type
|
||||
|
||||
UVC_CTRL_DATA_TYPE_RAW Raw control (byte array)
|
||||
UVC_CTRL_DATA_TYPE_SIGNED Signed integer
|
||||
UVC_CTRL_DATA_TYPE_UNSIGNED Unsigned integer
|
||||
UVC_CTRL_DATA_TYPE_BOOLEAN Boolean
|
||||
UVC_CTRL_DATA_TYPE_ENUM Enumeration
|
||||
UVC_CTRL_DATA_TYPE_BITMASK Bitmask
|
||||
|
||||
|
||||
---- UVCIOC_CTRL_QUERY - Query a UVC XU control ----
|
||||
|
||||
Argument: struct uvc_xu_control_query
|
||||
|
||||
Description:
|
||||
This ioctl queries a UVC XU control identified by its extension unit ID
|
||||
and control selector.
|
||||
|
||||
There are a number of different queries available that closely
|
||||
correspond to the low-level control requests described in the UVC
|
||||
specification. These requests are:
|
||||
|
||||
UVC_GET_CUR
|
||||
Obtain the current value of the control.
|
||||
UVC_GET_MIN
|
||||
Obtain the minimum value of the control.
|
||||
UVC_GET_MAX
|
||||
Obtain the maximum value of the control.
|
||||
UVC_GET_DEF
|
||||
Obtain the default value of the control.
|
||||
UVC_GET_RES
|
||||
Query the resolution of the control, i.e. the step size of the
|
||||
allowed control values.
|
||||
UVC_GET_LEN
|
||||
Query the size of the control in bytes.
|
||||
UVC_GET_INFO
|
||||
Query the control information bitmap, which indicates whether
|
||||
get/set requests are supported.
|
||||
UVC_SET_CUR
|
||||
Update the value of the control.
|
||||
|
||||
Applications must set the 'size' field to the correct length for the
|
||||
control. Exceptions are the UVC_GET_LEN and UVC_GET_INFO queries, for
|
||||
which the size must be set to 2 and 1, respectively. The 'data' field
|
||||
must point to a valid writable buffer big enough to hold the indicated
|
||||
number of data bytes.
|
||||
|
||||
Data is copied directly from the device without any driver-side
|
||||
processing. Applications are responsible for data buffer formatting,
|
||||
including little-endian/big-endian conversion. This is particularly
|
||||
important for the result of the UVC_GET_LEN requests, which is always
|
||||
returned as a little-endian 16-bit integer by the device.
|
||||
|
||||
Return value:
|
||||
On success 0 is returned. On error -1 is returned and errno is set
|
||||
appropriately.
|
||||
|
||||
ENOENT
|
||||
The device does not support the given control or the specified
|
||||
extension unit could not be found.
|
||||
ENOBUFS
|
||||
The specified buffer size is incorrect (too big or too small).
|
||||
EINVAL
|
||||
An invalid request code was passed.
|
||||
EBADRQC
|
||||
The given request is not supported by the given control.
|
||||
EFAULT
|
||||
The data pointer references an inaccessible memory area.
|
||||
|
||||
Data types:
|
||||
* struct uvc_xu_control_query
|
||||
|
||||
__u8 unit Extension unit ID
|
||||
__u8 selector Control selector
|
||||
__u8 query Request code to send to the device
|
||||
__u16 size Control data size (in bytes)
|
||||
__u8 *data Control value
|
|
@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
|||
dev->pci = pci;
|
||||
|
||||
/* get chip-revision; this is needed to enable bug-fixes */
|
||||
err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
|
||||
if (err < 0) {
|
||||
ERR(("pci_read_config_dword() failed.\n"));
|
||||
goto err_disable;
|
||||
}
|
||||
dev->revision &= 0xf;
|
||||
dev->revision = pci->revision;
|
||||
|
||||
/* remap the memory from virtual to physical address */
|
||||
|
||||
|
|
|
@ -186,4 +186,12 @@ config MEDIA_TUNER_TDA18218
|
|||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
NXP TDA18218 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_TDA18212
|
||||
tristate "NXP TDA18212 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
NXP TDA18212 silicon tuner driver.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
|
|||
obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
|
||||
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
|
||||
|
|
|
@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
|
|||
case BANDWIDTH_8_MHZ:
|
||||
req_bw = MXL5005S_BANDWIDTH_8MHZ;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* NXP TDA18212HN silicon tuner 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 "tda18212_priv.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
/* write multiple registers */
|
||||
static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[len+1];
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = 0,
|
||||
.len = sizeof(buf),
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
buf[0] = reg;
|
||||
memcpy(&buf[1], val, len);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 1);
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read multiple registers */
|
||||
static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[len];
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = ®,
|
||||
}, {
|
||||
.addr = priv->cfg->i2c_address,
|
||||
.flags = I2C_M_RD,
|
||||
.len = sizeof(buf),
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||
if (ret == 2) {
|
||||
memcpy(val, buf, len);
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write single register */
|
||||
static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
return tda18212_wr_regs(priv, reg, &val, 1);
|
||||
}
|
||||
|
||||
/* read single register */
|
||||
static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val)
|
||||
{
|
||||
return tda18212_rd_regs(priv, reg, val, 1);
|
||||
}
|
||||
|
||||
#if 0 /* keep, useful when developing driver */
|
||||
static void tda18212_dump_regs(struct tda18212_priv *priv)
|
||||
{
|
||||
int i;
|
||||
u8 buf[256];
|
||||
|
||||
#define TDA18212_RD_LEN 32
|
||||
for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN)
|
||||
tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN);
|
||||
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf,
|
||||
sizeof(buf), true);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tda18212_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct tda18212_priv *priv = fe->tuner_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i;
|
||||
u32 if_khz;
|
||||
u8 buf[9];
|
||||
static const u8 bw_params[][3] = {
|
||||
/* 0f 13 23 */
|
||||
{ 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
|
||||
{ 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
|
||||
{ 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
|
||||
{ 0x92, 0x53, 0x03 }, /* DVB-C */
|
||||
};
|
||||
|
||||
dbg("%s: delsys=%d RF=%d BW=%d", __func__,
|
||||
c->delivery_system, c->frequency, c->bandwidth_hz);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
switch (c->delivery_system) {
|
||||
case SYS_DVBT:
|
||||
switch (c->bandwidth_hz) {
|
||||
case 6000000:
|
||||
if_khz = priv->cfg->if_dvbt_6;
|
||||
i = 0;
|
||||
break;
|
||||
case 7000000:
|
||||
if_khz = priv->cfg->if_dvbt_7;
|
||||
i = 1;
|
||||
break;
|
||||
case 8000000:
|
||||
if_khz = priv->cfg->if_dvbt_8;
|
||||
i = 2;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SYS_DVBC_ANNEX_AC:
|
||||
if_khz = priv->cfg->if_dvbc;
|
||||
i = 3;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = tda18212_wr_reg(priv, 0x06, 0x00);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
buf[0] = 0x02;
|
||||
buf[1] = bw_params[i][1];
|
||||
buf[2] = 0x03; /* default value */
|
||||
buf[3] = if_khz / 50;
|
||||
buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
|
||||
buf[5] = ((c->frequency / 1000) >> 8) & 0xff;
|
||||
buf[6] = ((c->frequency / 1000) >> 0) & 0xff;
|
||||
buf[7] = 0xc1;
|
||||
buf[8] = 0x01;
|
||||
ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
exit:
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
static int tda18212_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops tda18212_tuner_ops = {
|
||||
.info = {
|
||||
.name = "NXP TDA18212",
|
||||
|
||||
.frequency_min = 48000000,
|
||||
.frequency_max = 864000000,
|
||||
.frequency_step = 1000,
|
||||
},
|
||||
|
||||
.release = tda18212_release,
|
||||
|
||||
.set_params = tda18212_set_params,
|
||||
};
|
||||
|
||||
struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18212_config *cfg)
|
||||
{
|
||||
struct tda18212_priv *priv = NULL;
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->cfg = cfg;
|
||||
priv->i2c = i2c;
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
|
||||
/* check if the tuner is there */
|
||||
ret = tda18212_rd_reg(priv, 0x00, &val);
|
||||
|
||||
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);
|
||||
if (ret || val != 0xc7) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info("NXP TDA18212HN successfully identified.");
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(tda18212_attach);
|
||||
|
||||
MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* NXP TDA18212HN silicon tuner 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.
|
||||
*/
|
||||
|
||||
#ifndef TDA18212_H
|
||||
#define TDA18212_H
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
struct tda18212_config {
|
||||
u8 i2c_address;
|
||||
|
||||
u16 if_dvbt_6;
|
||||
u16 if_dvbt_7;
|
||||
u16 if_dvbt_8;
|
||||
u16 if_dvbc;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \
|
||||
(defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18212_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, struct tda18212_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* NXP TDA18212HN silicon tuner 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.
|
||||
*/
|
||||
|
||||
#ifndef TDA18212_PRIV_H
|
||||
#define TDA18212_PRIV_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;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -976,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe,
|
|||
tda_warn("bandwidth not set!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (fe->ops.info.type == FE_QAM) {
|
||||
/* DVB-C */
|
||||
map = &std_map->qam_8;
|
||||
bw = 8000000;
|
||||
} else {
|
||||
tda_warn("modulation type not supported!\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -628,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv)
|
|||
dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
|
||||
}
|
||||
|
||||
/*
|
||||
* As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
|
||||
* So, the amount of the needed bandwith is given by:
|
||||
* Bw = Symbol_rate * (1 + 0.15)
|
||||
* As such, the maximum symbol rate supported by 6 MHz is given by:
|
||||
* max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
|
||||
*/
|
||||
#define MAX_SYMBOL_RATE_6MHz 5217391
|
||||
|
||||
static int xc5000_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
|
@ -688,21 +697,32 @@ static int xc5000_set_params(struct dvb_frontend *fe,
|
|||
}
|
||||
priv->rf_mode = XC_RF_MODE_AIR;
|
||||
} else if (fe->ops.info.type == FE_QAM) {
|
||||
dprintk(1, "%s() QAM\n", __func__);
|
||||
switch (params->u.qam.modulation) {
|
||||
case QAM_256:
|
||||
case QAM_AUTO:
|
||||
case QAM_16:
|
||||
case QAM_32:
|
||||
case QAM_64:
|
||||
case QAM_128:
|
||||
case QAM_256:
|
||||
case QAM_AUTO:
|
||||
dprintk(1, "%s() QAM modulation\n", __func__);
|
||||
priv->bandwidth = BANDWIDTH_8_MHZ;
|
||||
priv->video_standard = DTV7_8;
|
||||
priv->freq_hz = params->frequency - 2750000;
|
||||
priv->rf_mode = XC_RF_MODE_CABLE;
|
||||
/*
|
||||
* Using a 8MHz bandwidth sometimes fail
|
||||
* with 6MHz-spaced channels, due to inter-carrier
|
||||
* interference. So, use DTV6 firmware
|
||||
*/
|
||||
if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) {
|
||||
priv->bandwidth = BANDWIDTH_6_MHZ;
|
||||
priv->video_standard = DTV6;
|
||||
priv->freq_hz = params->frequency - 1750000;
|
||||
} else {
|
||||
priv->bandwidth = BANDWIDTH_8_MHZ;
|
||||
priv->video_standard = DTV7_8;
|
||||
priv->freq_hz = params->frequency - 2750000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dprintk(1, "%s() Unsupported QAM type\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -290,10 +290,8 @@ static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
|
|||
static int flexcop_pci_init(struct flexcop_pci *fc_pci)
|
||||
{
|
||||
int ret;
|
||||
u8 card_rev;
|
||||
|
||||
pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
|
||||
info("card revision %x", card_rev);
|
||||
info("card revision %x", fc_pci->pdev->revision);
|
||||
|
||||
if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
|
||||
return ret;
|
||||
|
|
|
@ -460,7 +460,7 @@ static int __devinit bt878_probe(struct pci_dev *dev,
|
|||
goto fail0;
|
||||
}
|
||||
|
||||
pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
|
||||
bt->revision = dev->revision;
|
||||
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
|
||||
|
||||
|
||||
|
|
|
@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
|||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
static inline int find_next_packet(const u8 *buf, int pos, size_t count,
|
||||
const int pktsize)
|
||||
{
|
||||
int start = pos, lost;
|
||||
|
||||
while (pos < count) {
|
||||
if (buf[pos] == 0x47 ||
|
||||
(pktsize == 204 && buf[pos] == 0xB8))
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
|
||||
lost = pos - start;
|
||||
if (lost) {
|
||||
/* This garbage is part of a valid packet? */
|
||||
int backtrack = pos - pktsize;
|
||||
if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
|
||||
(pktsize == 204 && buf[backtrack] == 0xB8)))
|
||||
return backtrack;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
|
||||
static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count, const int pktsize)
|
||||
{
|
||||
int p = 0, i, j;
|
||||
const u8 *q;
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
|
||||
i = demux->tsbufp;
|
||||
j = 188 - i;
|
||||
j = pktsize - i;
|
||||
if (count < j) {
|
||||
memcpy(&demux->tsbuf[i], buf, count);
|
||||
demux->tsbufp += count;
|
||||
goto bailout;
|
||||
}
|
||||
memcpy(&demux->tsbuf[i], buf, j);
|
||||
if (demux->tsbuf[0] == 0x47)
|
||||
if (demux->tsbuf[0] == 0x47) /* double check */
|
||||
dvb_dmx_swfilter_packet(demux, demux->tsbuf);
|
||||
demux->tsbufp = 0;
|
||||
p += j;
|
||||
}
|
||||
|
||||
while (p < count) {
|
||||
if (buf[p] == 0x47) {
|
||||
if (count - p >= 188) {
|
||||
dvb_dmx_swfilter_packet(demux, &buf[p]);
|
||||
p += 188;
|
||||
} else {
|
||||
i = count - p;
|
||||
memcpy(demux->tsbuf, &buf[p], i);
|
||||
demux->tsbufp = i;
|
||||
goto bailout;
|
||||
}
|
||||
} else
|
||||
p++;
|
||||
while (1) {
|
||||
p = find_next_packet(buf, p, count, pktsize);
|
||||
if (p >= count)
|
||||
break;
|
||||
if (count - p < pktsize)
|
||||
break;
|
||||
|
||||
q = &buf[p];
|
||||
|
||||
if (pktsize == 204 && (*q == 0xB8)) {
|
||||
memcpy(demux->tsbuf, q, 188);
|
||||
demux->tsbuf[0] = 0x47;
|
||||
q = demux->tsbuf;
|
||||
}
|
||||
dvb_dmx_swfilter_packet(demux, q);
|
||||
p += pktsize;
|
||||
}
|
||||
|
||||
i = count - p;
|
||||
if (i) {
|
||||
memcpy(demux->tsbuf, &buf[p], i);
|
||||
demux->tsbufp = i;
|
||||
if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
|
||||
demux->tsbuf[0] = 0x47;
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
}
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
_dvb_dmx_swfilter(demux, buf, count, 188);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter);
|
||||
|
||||
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
int p = 0, i, j;
|
||||
u8 tmppack[188];
|
||||
|
||||
spin_lock(&demux->lock);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
i = demux->tsbufp;
|
||||
j = 204 - i;
|
||||
if (count < j) {
|
||||
memcpy(&demux->tsbuf[i], buf, count);
|
||||
demux->tsbufp += count;
|
||||
goto bailout;
|
||||
}
|
||||
memcpy(&demux->tsbuf[i], buf, j);
|
||||
if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
|
||||
memcpy(tmppack, demux->tsbuf, 188);
|
||||
if (tmppack[0] == 0xB8)
|
||||
tmppack[0] = 0x47;
|
||||
dvb_dmx_swfilter_packet(demux, tmppack);
|
||||
}
|
||||
demux->tsbufp = 0;
|
||||
p += j;
|
||||
}
|
||||
|
||||
while (p < count) {
|
||||
if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
|
||||
if (count - p >= 204) {
|
||||
memcpy(tmppack, &buf[p], 188);
|
||||
if (tmppack[0] == 0xB8)
|
||||
tmppack[0] = 0x47;
|
||||
dvb_dmx_swfilter_packet(demux, tmppack);
|
||||
p += 204;
|
||||
} else {
|
||||
i = count - p;
|
||||
memcpy(demux->tsbuf, &buf[p], i);
|
||||
demux->tsbufp = i;
|
||||
goto bailout;
|
||||
}
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock(&demux->lock);
|
||||
_dvb_dmx_swfilter(demux, buf, count, 204);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
||||
static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
|
||||
|
|
|
@ -105,7 +105,8 @@ struct dvb_frontend_private {
|
|||
|
||||
/* thread/frontend values */
|
||||
struct dvb_device *dvbdev;
|
||||
struct dvb_frontend_parameters parameters;
|
||||
struct dvb_frontend_parameters parameters_in;
|
||||
struct dvb_frontend_parameters parameters_out;
|
||||
struct dvb_fe_events events;
|
||||
struct semaphore sem;
|
||||
struct list_head list_head;
|
||||
|
@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
|||
|
||||
e = &events->events[events->eventw];
|
||||
|
||||
memcpy (&e->parameters, &fepriv->parameters,
|
||||
sizeof (struct dvb_frontend_parameters));
|
||||
|
||||
if (status & FE_HAS_LOCK)
|
||||
if (fe->ops.get_frontend)
|
||||
fe->ops.get_frontend(fe, &e->parameters);
|
||||
fe->ops.get_frontend(fe, &fepriv->parameters_out);
|
||||
|
||||
e->parameters = fepriv->parameters_out;
|
||||
|
||||
events->eventw = wp;
|
||||
|
||||
|
@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
|
|||
int ready = 0;
|
||||
int fe_set_err = 0;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
int original_inversion = fepriv->parameters.inversion;
|
||||
u32 original_frequency = fepriv->parameters.frequency;
|
||||
int original_inversion = fepriv->parameters_in.inversion;
|
||||
u32 original_frequency = fepriv->parameters_in.frequency;
|
||||
|
||||
/* are we using autoinversion? */
|
||||
autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
(fepriv->parameters.inversion == INVERSION_AUTO));
|
||||
(fepriv->parameters_in.inversion == INVERSION_AUTO));
|
||||
|
||||
/* setup parameters correctly */
|
||||
while(!ready) {
|
||||
|
@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
|
|||
fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
|
||||
|
||||
/* set the frontend itself */
|
||||
fepriv->parameters.frequency += fepriv->lnb_drift;
|
||||
fepriv->parameters_in.frequency += fepriv->lnb_drift;
|
||||
if (autoinversion)
|
||||
fepriv->parameters.inversion = fepriv->inversion;
|
||||
fepriv->parameters_in.inversion = fepriv->inversion;
|
||||
if (fe->ops.set_frontend)
|
||||
fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters);
|
||||
fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in);
|
||||
fepriv->parameters_out = fepriv->parameters_in;
|
||||
if (fe_set_err < 0) {
|
||||
fepriv->state = FESTATE_ERROR;
|
||||
return fe_set_err;
|
||||
}
|
||||
|
||||
fepriv->parameters.frequency = original_frequency;
|
||||
fepriv->parameters.inversion = original_inversion;
|
||||
fepriv->parameters_in.frequency = original_frequency;
|
||||
fepriv->parameters_in.inversion = original_inversion;
|
||||
|
||||
fepriv->auto_sub_step++;
|
||||
return 0;
|
||||
|
@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
if (fe->ops.set_frontend)
|
||||
retval = fe->ops.set_frontend(fe,
|
||||
&fepriv->parameters);
|
||||
&fepriv->parameters_in);
|
||||
fepriv->parameters_out = fepriv->parameters_in;
|
||||
if (retval < 0)
|
||||
fepriv->state = FESTATE_ERROR;
|
||||
else
|
||||
|
@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
|
||||
/* if we're tuned, then we have determined the correct inversion */
|
||||
if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
|
||||
(fepriv->parameters.inversion == INVERSION_AUTO)) {
|
||||
fepriv->parameters.inversion = fepriv->inversion;
|
||||
(fepriv->parameters_in.inversion == INVERSION_AUTO)) {
|
||||
fepriv->parameters_in.inversion = fepriv->inversion;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -594,12 +596,14 @@ static int dvb_frontend_thread(void *data)
|
|||
|
||||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
|
||||
params = &fepriv->parameters;
|
||||
params = &fepriv->parameters_in;
|
||||
fepriv->state = FESTATE_TUNED;
|
||||
}
|
||||
|
||||
if (fe->ops.tune)
|
||||
fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
|
||||
if (params)
|
||||
fepriv->parameters_out = *params;
|
||||
|
||||
if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
|
||||
dprintk("%s: state changed, adding current state\n", __func__);
|
||||
|
@ -612,11 +616,9 @@ static int dvb_frontend_thread(void *data)
|
|||
dvb_frontend_swzigzag(fe);
|
||||
break;
|
||||
case DVBFE_ALGO_CUSTOM:
|
||||
params = NULL; /* have we been asked to RETUNE ? */
|
||||
dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
|
||||
if (fepriv->state & FESTATE_RETUNE) {
|
||||
dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
|
||||
params = &fepriv->parameters;
|
||||
fepriv->state = FESTATE_TUNED;
|
||||
}
|
||||
/* Case where we are going to search for a carrier
|
||||
|
@ -625,7 +627,7 @@ static int dvb_frontend_thread(void *data)
|
|||
*/
|
||||
if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
|
||||
if (fe->ops.search) {
|
||||
fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
|
||||
fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in);
|
||||
/* We did do a search as was requested, the flags are
|
||||
* now unset as well and has the flags wrt to search.
|
||||
*/
|
||||
|
@ -636,11 +638,12 @@ static int dvb_frontend_thread(void *data)
|
|||
/* Track the carrier if the search was successful */
|
||||
if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
|
||||
if (fe->ops.track)
|
||||
fe->ops.track(fe, &fepriv->parameters);
|
||||
fe->ops.track(fe, &fepriv->parameters_in);
|
||||
} else {
|
||||
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
|
||||
fepriv->delay = HZ / 2;
|
||||
}
|
||||
fepriv->parameters_out = fepriv->parameters_in;
|
||||
fe->ops.read_status(fe, &s);
|
||||
if (s != fepriv->status) {
|
||||
dvb_frontend_add_event(fe, s); /* update event list */
|
||||
|
@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
|
|||
|
||||
static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int i;
|
||||
|
||||
memset(&(fe->dtv_property_cache), 0,
|
||||
sizeof(struct dtv_frontend_properties));
|
||||
memset(c, 0, sizeof(struct dtv_frontend_properties));
|
||||
|
||||
fe->dtv_property_cache.state = DTV_CLEAR;
|
||||
fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
|
||||
fe->dtv_property_cache.inversion = INVERSION_AUTO;
|
||||
fe->dtv_property_cache.fec_inner = FEC_AUTO;
|
||||
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO;
|
||||
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
|
||||
fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
|
||||
fe->dtv_property_cache.symbol_rate = QAM_AUTO;
|
||||
fe->dtv_property_cache.code_rate_HP = FEC_AUTO;
|
||||
fe->dtv_property_cache.code_rate_LP = FEC_AUTO;
|
||||
c->state = DTV_CLEAR;
|
||||
c->delivery_system = SYS_UNDEFINED;
|
||||
c->inversion = INVERSION_AUTO;
|
||||
c->fec_inner = FEC_AUTO;
|
||||
c->transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
c->bandwidth_hz = BANDWIDTH_AUTO;
|
||||
c->guard_interval = GUARD_INTERVAL_AUTO;
|
||||
c->hierarchy = HIERARCHY_AUTO;
|
||||
c->symbol_rate = QAM_AUTO;
|
||||
c->code_rate_HP = FEC_AUTO;
|
||||
c->code_rate_LP = FEC_AUTO;
|
||||
|
||||
fe->dtv_property_cache.isdbt_partial_reception = -1;
|
||||
fe->dtv_property_cache.isdbt_sb_mode = -1;
|
||||
fe->dtv_property_cache.isdbt_sb_subchannel = -1;
|
||||
fe->dtv_property_cache.isdbt_sb_segment_idx = -1;
|
||||
fe->dtv_property_cache.isdbt_sb_segment_count = -1;
|
||||
fe->dtv_property_cache.isdbt_layer_enabled = 0x7;
|
||||
c->isdbt_partial_reception = -1;
|
||||
c->isdbt_sb_mode = -1;
|
||||
c->isdbt_sb_subchannel = -1;
|
||||
c->isdbt_sb_segment_idx = -1;
|
||||
c->isdbt_sb_segment_count = -1;
|
||||
c->isdbt_layer_enabled = 0x7;
|
||||
for (i = 0; i < 3; i++) {
|
||||
fe->dtv_property_cache.layer[i].fec = FEC_AUTO;
|
||||
fe->dtv_property_cache.layer[i].modulation = QAM_AUTO;
|
||||
fe->dtv_property_cache.layer[i].interleaving = -1;
|
||||
fe->dtv_property_cache.layer[i].segment_count = -1;
|
||||
c->layer[i].fec = FEC_AUTO;
|
||||
c->layer[i].modulation = QAM_AUTO;
|
||||
c->layer[i].interleaving = -1;
|
||||
c->layer[i].segment_count = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
|
|||
* it's being used for the legacy or new API, reducing code and complexity.
|
||||
*/
|
||||
static void dtv_property_cache_sync(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
struct dtv_frontend_properties *c,
|
||||
const struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
|
||||
c->frequency = p->frequency;
|
||||
c->inversion = p->inversion;
|
||||
|
||||
|
@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
|
|||
*/
|
||||
static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dvb_frontend_parameters *p = &fepriv->parameters;
|
||||
struct dvb_frontend_parameters *p = &fepriv->parameters_in;
|
||||
|
||||
p->frequency = c->frequency;
|
||||
p->inversion = c->inversion;
|
||||
|
@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
|
|||
dprintk("%s() Preparing QPSK req\n", __func__);
|
||||
p->u.qpsk.symbol_rate = c->symbol_rate;
|
||||
p->u.qpsk.fec_inner = c->fec_inner;
|
||||
c->delivery_system = SYS_DVBS;
|
||||
break;
|
||||
case FE_QAM:
|
||||
dprintk("%s() Preparing QAM req\n", __func__);
|
||||
p->u.qam.symbol_rate = c->symbol_rate;
|
||||
p->u.qam.fec_inner = c->fec_inner;
|
||||
p->u.qam.modulation = c->modulation;
|
||||
c->delivery_system = SYS_DVBC_ANNEX_AC;
|
||||
break;
|
||||
case FE_OFDM:
|
||||
dprintk("%s() Preparing OFDM req\n", __func__);
|
||||
|
@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
|
|||
p->u.ofdm.transmission_mode = c->transmission_mode;
|
||||
p->u.ofdm.guard_interval = c->guard_interval;
|
||||
p->u.ofdm.hierarchy_information = c->hierarchy;
|
||||
c->delivery_system = SYS_DVBT;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
dprintk("%s() Preparing VSB req\n", __func__);
|
||||
p->u.vsb.modulation = c->modulation;
|
||||
if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
|
||||
c->delivery_system = SYS_ATSC;
|
||||
else
|
||||
c->delivery_system = SYS_DVBC_ANNEX_B;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
|
|||
*/
|
||||
static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dvb_frontend_parameters *p = &fepriv->parameters;
|
||||
struct dvb_frontend_parameters *p = &fepriv->parameters_in;
|
||||
|
||||
p->frequency = c->frequency;
|
||||
p->inversion = c->inversion;
|
||||
|
@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
|
|||
break;
|
||||
}
|
||||
|
||||
if(c->delivery_system == SYS_ISDBT) {
|
||||
/* Fake out a generic DVB-T request so we pass validation in the ioctl */
|
||||
p->frequency = c->frequency;
|
||||
p->inversion = c->inversion;
|
||||
/* Fake out a generic DVB-T request so we pass validation in the ioctl */
|
||||
if ((c->delivery_system == SYS_ISDBT) ||
|
||||
(c->delivery_system == SYS_DVBT2)) {
|
||||
p->u.ofdm.constellation = QAM_AUTO;
|
||||
p->u.ofdm.code_rate_HP = FEC_AUTO;
|
||||
p->u.ofdm.code_rate_LP = FEC_AUTO;
|
||||
|
@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
|
|||
|
||||
static void dtv_property_cache_submit(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
|
||||
/* For legacy delivery systems we don't need the delivery_system to
|
||||
* be specified, but we populate the older structures from the cache
|
||||
|
@ -1204,133 +1198,149 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
|||
struct dtv_property *tvp,
|
||||
struct file *file)
|
||||
{
|
||||
int r = 0;
|
||||
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dtv_frontend_properties cdetected;
|
||||
int r;
|
||||
|
||||
/* Allow the frontend to validate incoming properties */
|
||||
if (fe->ops.get_property)
|
||||
r = fe->ops.get_property(fe, tvp);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
/*
|
||||
* If the driver implements a get_frontend function, then convert
|
||||
* detected parameters to S2API properties.
|
||||
*/
|
||||
if (fe->ops.get_frontend) {
|
||||
cdetected = *c;
|
||||
dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out);
|
||||
c = &cdetected;
|
||||
}
|
||||
|
||||
switch(tvp->cmd) {
|
||||
case DTV_FREQUENCY:
|
||||
tvp->u.data = fe->dtv_property_cache.frequency;
|
||||
tvp->u.data = c->frequency;
|
||||
break;
|
||||
case DTV_MODULATION:
|
||||
tvp->u.data = fe->dtv_property_cache.modulation;
|
||||
tvp->u.data = c->modulation;
|
||||
break;
|
||||
case DTV_BANDWIDTH_HZ:
|
||||
tvp->u.data = fe->dtv_property_cache.bandwidth_hz;
|
||||
tvp->u.data = c->bandwidth_hz;
|
||||
break;
|
||||
case DTV_INVERSION:
|
||||
tvp->u.data = fe->dtv_property_cache.inversion;
|
||||
tvp->u.data = c->inversion;
|
||||
break;
|
||||
case DTV_SYMBOL_RATE:
|
||||
tvp->u.data = fe->dtv_property_cache.symbol_rate;
|
||||
tvp->u.data = c->symbol_rate;
|
||||
break;
|
||||
case DTV_INNER_FEC:
|
||||
tvp->u.data = fe->dtv_property_cache.fec_inner;
|
||||
tvp->u.data = c->fec_inner;
|
||||
break;
|
||||
case DTV_PILOT:
|
||||
tvp->u.data = fe->dtv_property_cache.pilot;
|
||||
tvp->u.data = c->pilot;
|
||||
break;
|
||||
case DTV_ROLLOFF:
|
||||
tvp->u.data = fe->dtv_property_cache.rolloff;
|
||||
tvp->u.data = c->rolloff;
|
||||
break;
|
||||
case DTV_DELIVERY_SYSTEM:
|
||||
tvp->u.data = fe->dtv_property_cache.delivery_system;
|
||||
tvp->u.data = c->delivery_system;
|
||||
break;
|
||||
case DTV_VOLTAGE:
|
||||
tvp->u.data = fe->dtv_property_cache.voltage;
|
||||
tvp->u.data = c->voltage;
|
||||
break;
|
||||
case DTV_TONE:
|
||||
tvp->u.data = fe->dtv_property_cache.sectone;
|
||||
tvp->u.data = c->sectone;
|
||||
break;
|
||||
case DTV_API_VERSION:
|
||||
tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
|
||||
break;
|
||||
case DTV_CODE_RATE_HP:
|
||||
tvp->u.data = fe->dtv_property_cache.code_rate_HP;
|
||||
tvp->u.data = c->code_rate_HP;
|
||||
break;
|
||||
case DTV_CODE_RATE_LP:
|
||||
tvp->u.data = fe->dtv_property_cache.code_rate_LP;
|
||||
tvp->u.data = c->code_rate_LP;
|
||||
break;
|
||||
case DTV_GUARD_INTERVAL:
|
||||
tvp->u.data = fe->dtv_property_cache.guard_interval;
|
||||
tvp->u.data = c->guard_interval;
|
||||
break;
|
||||
case DTV_TRANSMISSION_MODE:
|
||||
tvp->u.data = fe->dtv_property_cache.transmission_mode;
|
||||
tvp->u.data = c->transmission_mode;
|
||||
break;
|
||||
case DTV_HIERARCHY:
|
||||
tvp->u.data = fe->dtv_property_cache.hierarchy;
|
||||
tvp->u.data = c->hierarchy;
|
||||
break;
|
||||
|
||||
/* ISDB-T Support here */
|
||||
case DTV_ISDBT_PARTIAL_RECEPTION:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception;
|
||||
tvp->u.data = c->isdbt_partial_reception;
|
||||
break;
|
||||
case DTV_ISDBT_SOUND_BROADCASTING:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode;
|
||||
tvp->u.data = c->isdbt_sb_mode;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SUBCHANNEL_ID:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel;
|
||||
tvp->u.data = c->isdbt_sb_subchannel;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SEGMENT_IDX:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx;
|
||||
tvp->u.data = c->isdbt_sb_segment_idx;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SEGMENT_COUNT:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count;
|
||||
tvp->u.data = c->isdbt_sb_segment_count;
|
||||
break;
|
||||
case DTV_ISDBT_LAYER_ENABLED:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled;
|
||||
tvp->u.data = c->isdbt_layer_enabled;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_FEC:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[0].fec;
|
||||
tvp->u.data = c->layer[0].fec;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_MODULATION:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[0].modulation;
|
||||
tvp->u.data = c->layer[0].modulation;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[0].segment_count;
|
||||
tvp->u.data = c->layer[0].segment_count;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[0].interleaving;
|
||||
tvp->u.data = c->layer[0].interleaving;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_FEC:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[1].fec;
|
||||
tvp->u.data = c->layer[1].fec;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_MODULATION:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[1].modulation;
|
||||
tvp->u.data = c->layer[1].modulation;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[1].segment_count;
|
||||
tvp->u.data = c->layer[1].segment_count;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[1].interleaving;
|
||||
tvp->u.data = c->layer[1].interleaving;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_FEC:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[2].fec;
|
||||
tvp->u.data = c->layer[2].fec;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_MODULATION:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[2].modulation;
|
||||
tvp->u.data = c->layer[2].modulation;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[2].segment_count;
|
||||
tvp->u.data = c->layer[2].segment_count;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
|
||||
tvp->u.data = fe->dtv_property_cache.layer[2].interleaving;
|
||||
tvp->u.data = c->layer[2].interleaving;
|
||||
break;
|
||||
case DTV_ISDBS_TS_ID:
|
||||
tvp->u.data = fe->dtv_property_cache.isdbs_ts_id;
|
||||
tvp->u.data = c->isdbs_ts_id;
|
||||
break;
|
||||
case DTV_DVBT2_PLP_ID:
|
||||
tvp->u.data = c->dvbt2_plp_id;
|
||||
break;
|
||||
default:
|
||||
r = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allow the frontend to override outgoing properties */
|
||||
if (fe->ops.get_property) {
|
||||
r = fe->ops.get_property(fe, tvp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
dtv_property_dump(tvp);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dtv_property_process_set(struct dvb_frontend *fe,
|
||||
|
@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
|||
struct file *file)
|
||||
{
|
||||
int r = 0;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
dtv_property_dump(tvp);
|
||||
|
||||
/* Allow the frontend to validate incoming properties */
|
||||
if (fe->ops.set_property)
|
||||
if (fe->ops.set_property) {
|
||||
r = fe->ops.set_property(fe, tvp);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
switch(tvp->cmd) {
|
||||
case DTV_CLEAR:
|
||||
|
@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
|||
* tunerequest so we can pass validation in the FE_SET_FRONTEND
|
||||
* ioctl.
|
||||
*/
|
||||
fe->dtv_property_cache.state = tvp->cmd;
|
||||
c->state = tvp->cmd;
|
||||
dprintk("%s() Finalised property cache\n", __func__);
|
||||
dtv_property_cache_submit(fe);
|
||||
|
||||
r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
|
||||
&fepriv->parameters);
|
||||
r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
|
||||
&fepriv->parameters_in);
|
||||
break;
|
||||
case DTV_FREQUENCY:
|
||||
fe->dtv_property_cache.frequency = tvp->u.data;
|
||||
c->frequency = tvp->u.data;
|
||||
break;
|
||||
case DTV_MODULATION:
|
||||
fe->dtv_property_cache.modulation = tvp->u.data;
|
||||
c->modulation = tvp->u.data;
|
||||
break;
|
||||
case DTV_BANDWIDTH_HZ:
|
||||
fe->dtv_property_cache.bandwidth_hz = tvp->u.data;
|
||||
c->bandwidth_hz = tvp->u.data;
|
||||
break;
|
||||
case DTV_INVERSION:
|
||||
fe->dtv_property_cache.inversion = tvp->u.data;
|
||||
c->inversion = tvp->u.data;
|
||||
break;
|
||||
case DTV_SYMBOL_RATE:
|
||||
fe->dtv_property_cache.symbol_rate = tvp->u.data;
|
||||
c->symbol_rate = tvp->u.data;
|
||||
break;
|
||||
case DTV_INNER_FEC:
|
||||
fe->dtv_property_cache.fec_inner = tvp->u.data;
|
||||
c->fec_inner = tvp->u.data;
|
||||
break;
|
||||
case DTV_PILOT:
|
||||
fe->dtv_property_cache.pilot = tvp->u.data;
|
||||
c->pilot = tvp->u.data;
|
||||
break;
|
||||
case DTV_ROLLOFF:
|
||||
fe->dtv_property_cache.rolloff = tvp->u.data;
|
||||
c->rolloff = tvp->u.data;
|
||||
break;
|
||||
case DTV_DELIVERY_SYSTEM:
|
||||
fe->dtv_property_cache.delivery_system = tvp->u.data;
|
||||
c->delivery_system = tvp->u.data;
|
||||
break;
|
||||
case DTV_VOLTAGE:
|
||||
fe->dtv_property_cache.voltage = tvp->u.data;
|
||||
c->voltage = tvp->u.data;
|
||||
r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
|
||||
(void *)fe->dtv_property_cache.voltage);
|
||||
(void *)c->voltage);
|
||||
break;
|
||||
case DTV_TONE:
|
||||
fe->dtv_property_cache.sectone = tvp->u.data;
|
||||
c->sectone = tvp->u.data;
|
||||
r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
|
||||
(void *)fe->dtv_property_cache.sectone);
|
||||
(void *)c->sectone);
|
||||
break;
|
||||
case DTV_CODE_RATE_HP:
|
||||
fe->dtv_property_cache.code_rate_HP = tvp->u.data;
|
||||
c->code_rate_HP = tvp->u.data;
|
||||
break;
|
||||
case DTV_CODE_RATE_LP:
|
||||
fe->dtv_property_cache.code_rate_LP = tvp->u.data;
|
||||
c->code_rate_LP = tvp->u.data;
|
||||
break;
|
||||
case DTV_GUARD_INTERVAL:
|
||||
fe->dtv_property_cache.guard_interval = tvp->u.data;
|
||||
c->guard_interval = tvp->u.data;
|
||||
break;
|
||||
case DTV_TRANSMISSION_MODE:
|
||||
fe->dtv_property_cache.transmission_mode = tvp->u.data;
|
||||
c->transmission_mode = tvp->u.data;
|
||||
break;
|
||||
case DTV_HIERARCHY:
|
||||
fe->dtv_property_cache.hierarchy = tvp->u.data;
|
||||
c->hierarchy = tvp->u.data;
|
||||
break;
|
||||
|
||||
/* ISDB-T Support here */
|
||||
case DTV_ISDBT_PARTIAL_RECEPTION:
|
||||
fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data;
|
||||
c->isdbt_partial_reception = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_SOUND_BROADCASTING:
|
||||
fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data;
|
||||
c->isdbt_sb_mode = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SUBCHANNEL_ID:
|
||||
fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data;
|
||||
c->isdbt_sb_subchannel = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SEGMENT_IDX:
|
||||
fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data;
|
||||
c->isdbt_sb_segment_idx = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_SB_SEGMENT_COUNT:
|
||||
fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data;
|
||||
c->isdbt_sb_segment_count = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYER_ENABLED:
|
||||
fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data;
|
||||
c->isdbt_layer_enabled = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_FEC:
|
||||
fe->dtv_property_cache.layer[0].fec = tvp->u.data;
|
||||
c->layer[0].fec = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_MODULATION:
|
||||
fe->dtv_property_cache.layer[0].modulation = tvp->u.data;
|
||||
c->layer[0].modulation = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
|
||||
fe->dtv_property_cache.layer[0].segment_count = tvp->u.data;
|
||||
c->layer[0].segment_count = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
|
||||
fe->dtv_property_cache.layer[0].interleaving = tvp->u.data;
|
||||
c->layer[0].interleaving = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_FEC:
|
||||
fe->dtv_property_cache.layer[1].fec = tvp->u.data;
|
||||
c->layer[1].fec = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_MODULATION:
|
||||
fe->dtv_property_cache.layer[1].modulation = tvp->u.data;
|
||||
c->layer[1].modulation = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
|
||||
fe->dtv_property_cache.layer[1].segment_count = tvp->u.data;
|
||||
c->layer[1].segment_count = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
|
||||
fe->dtv_property_cache.layer[1].interleaving = tvp->u.data;
|
||||
c->layer[1].interleaving = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_FEC:
|
||||
fe->dtv_property_cache.layer[2].fec = tvp->u.data;
|
||||
c->layer[2].fec = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_MODULATION:
|
||||
fe->dtv_property_cache.layer[2].modulation = tvp->u.data;
|
||||
c->layer[2].modulation = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
|
||||
fe->dtv_property_cache.layer[2].segment_count = tvp->u.data;
|
||||
c->layer[2].segment_count = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
|
||||
fe->dtv_property_cache.layer[2].interleaving = tvp->u.data;
|
||||
c->layer[2].interleaving = tvp->u.data;
|
||||
break;
|
||||
case DTV_ISDBS_TS_ID:
|
||||
fe->dtv_property_cache.isdbs_ts_id = tvp->u.data;
|
||||
c->isdbs_ts_id = tvp->u.data;
|
||||
break;
|
||||
case DTV_DVBT2_PLP_ID:
|
||||
c->dvbt2_plp_id = tvp->u.data;
|
||||
break;
|
||||
default:
|
||||
r = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file,
|
|||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_frontend *fe = dvbdev->priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
|
@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file,
|
|||
if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
|
||||
err = dvb_frontend_ioctl_properties(file, cmd, parg);
|
||||
else {
|
||||
fe->dtv_property_cache.state = DTV_UNDEFINED;
|
||||
c->state = DTV_UNDEFINED;
|
||||
err = dvb_frontend_ioctl_legacy(file, cmd, parg);
|
||||
}
|
||||
|
||||
|
@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
|||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_frontend *fe = dvbdev->priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int err = 0;
|
||||
|
||||
struct dtv_properties *tvps = NULL;
|
||||
|
@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
|||
}
|
||||
|
||||
for (i = 0; i < tvps->num; i++) {
|
||||
(tvp + i)->result = dtv_property_process_set(fe, tvp + i, file);
|
||||
err |= (tvp + i)->result;
|
||||
err = dtv_property_process_set(fe, tvp + i, file);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
(tvp + i)->result = err;
|
||||
}
|
||||
|
||||
if(fe->dtv_property_cache.state == DTV_TUNE)
|
||||
if (c->state == DTV_TUNE)
|
||||
dprintk("%s() Property cache is full, tuning\n", __func__);
|
||||
|
||||
} else
|
||||
|
@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file,
|
|||
}
|
||||
|
||||
for (i = 0; i < tvps->num; i++) {
|
||||
(tvp + i)->result = dtv_property_process_get(fe, tvp + i, file);
|
||||
err |= (tvp + i)->result;
|
||||
err = dtv_property_process_get(fe, tvp + i, file);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
(tvp + i)->result = err;
|
||||
}
|
||||
|
||||
if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
|
||||
|
@ -1787,10 +1807,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
break;
|
||||
|
||||
case FE_SET_FRONTEND: {
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct dvb_frontend_tune_settings fetunesettings;
|
||||
|
||||
if(fe->dtv_property_cache.state == DTV_TUNE) {
|
||||
if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
|
||||
if (c->state == DTV_TUNE) {
|
||||
if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
break;
|
||||
}
|
||||
|
||||
memcpy (&fepriv->parameters, parg,
|
||||
memcpy (&fepriv->parameters_in, parg,
|
||||
sizeof (struct dvb_frontend_parameters));
|
||||
dtv_property_cache_sync(fe, &fepriv->parameters);
|
||||
dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
|
||||
}
|
||||
|
||||
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
|
||||
|
@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
|
||||
/* force auto frequency inversion if requested */
|
||||
if (dvb_force_auto_inversion) {
|
||||
fepriv->parameters.inversion = INVERSION_AUTO;
|
||||
fepriv->parameters_in.inversion = INVERSION_AUTO;
|
||||
fetunesettings.parameters.inversion = INVERSION_AUTO;
|
||||
}
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* without hierarchical coding code_rate_LP is irrelevant,
|
||||
* so we tolerate the otherwise invalid FEC_NONE setting */
|
||||
if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
|
||||
fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
|
||||
fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
|
||||
if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
|
||||
fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE)
|
||||
fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO;
|
||||
}
|
||||
|
||||
/* get frontend-specific tuning settings */
|
||||
|
@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
switch(fe->ops.info.type) {
|
||||
case FE_QPSK:
|
||||
fepriv->min_delay = HZ/20;
|
||||
fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
|
||||
fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
|
||||
fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000;
|
||||
fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000;
|
||||
break;
|
||||
|
||||
case FE_QAM:
|
||||
|
@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
|
||||
case FE_GET_FRONTEND:
|
||||
if (fe->ops.get_frontend) {
|
||||
memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
|
||||
err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
|
||||
err = fe->ops.get_frontend(fe, &fepriv->parameters_out);
|
||||
memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -358,6 +358,9 @@ struct dtv_frontend_properties {
|
|||
|
||||
/* ISDB-T specifics */
|
||||
u32 isdbs_ts_id;
|
||||
|
||||
/* DVB-T2 specifics */
|
||||
u32 dvbt2_plp_id;
|
||||
};
|
||||
|
||||
struct dvb_frontend {
|
||||
|
|
|
@ -292,6 +292,11 @@ config DVB_USB_ANYSEE
|
|||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE
|
||||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0900 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV6110 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ISL6423 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Anysee E30, Anysee E30 Plus or
|
||||
Anysee E30 C Plus DVB USB2.0 receiver.
|
||||
|
|
|
@ -78,17 +78,26 @@ static struct rc_map_table rc_map_a800_table[] = {
|
|||
|
||||
static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
u8 key[5];
|
||||
int ret;
|
||||
u8 *key = kmalloc(5, GFP_KERNEL);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
|
||||
0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
|
||||
2000) != 5)
|
||||
return -ENODEV;
|
||||
2000) != 5) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* call the universal NEC remote processor, to find out the key's state and event */
|
||||
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||
if (key[0] != 0)
|
||||
deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||
return 0;
|
||||
ret = 0;
|
||||
out:
|
||||
kfree(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* USB Driver stuff */
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
#include "mt352.h"
|
||||
#include "mt352_priv.h"
|
||||
#include "zl10353.h"
|
||||
#include "tda18212.h"
|
||||
#include "cx24116.h"
|
||||
#include "stv0900.h"
|
||||
#include "stv6110.h"
|
||||
#include "isl6423.h"
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_anysee_debug;
|
||||
|
@ -105,6 +110,27 @@ static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
|
|||
return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
|
||||
}
|
||||
|
||||
/* write single register with mask */
|
||||
static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
|
||||
u8 mask)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
/* no need for read if whole reg is written */
|
||||
if (mask != 0xff) {
|
||||
ret = anysee_read_reg(d, reg, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= mask;
|
||||
tmp &= ~mask;
|
||||
val |= tmp;
|
||||
}
|
||||
|
||||
return anysee_write_reg(d, reg, val);
|
||||
}
|
||||
|
||||
static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
|
||||
{
|
||||
u8 buf[] = {CMD_GET_HW_INFO};
|
||||
|
@ -162,18 +188,18 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
|
||||
u8 buf[6];
|
||||
buf[0] = CMD_I2C_READ;
|
||||
buf[1] = msg[i].addr + 1;
|
||||
buf[1] = (msg[i].addr << 1) | 0x01;
|
||||
buf[2] = msg[i].buf[0];
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
buf[5] = 0x01;
|
||||
buf[3] = msg[i].buf[1];
|
||||
buf[4] = msg[i].len-1;
|
||||
buf[5] = msg[i+1].len;
|
||||
ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
|
||||
msg[i+1].len);
|
||||
inc = 2;
|
||||
} else {
|
||||
u8 buf[4+msg[i].len];
|
||||
buf[0] = CMD_I2C_WRITE;
|
||||
buf[1] = msg[i].addr;
|
||||
buf[1] = (msg[i].addr << 1);
|
||||
buf[2] = msg[i].len;
|
||||
buf[3] = 0x01;
|
||||
memcpy(&buf[4], msg[i].buf, msg[i].len);
|
||||
|
@ -224,7 +250,7 @@ static int anysee_mt352_demod_init(struct dvb_frontend *fe)
|
|||
|
||||
/* Callbacks for DVB USB */
|
||||
static struct tda10023_config anysee_tda10023_config = {
|
||||
.demod_address = 0x1a,
|
||||
.demod_address = (0x1a >> 1),
|
||||
.invert = 0,
|
||||
.xtal = 16000000,
|
||||
.pll_m = 11,
|
||||
|
@ -235,143 +261,539 @@ static struct tda10023_config anysee_tda10023_config = {
|
|||
};
|
||||
|
||||
static struct mt352_config anysee_mt352_config = {
|
||||
.demod_address = 0x1e,
|
||||
.demod_address = (0x1e >> 1),
|
||||
.demod_init = anysee_mt352_demod_init,
|
||||
};
|
||||
|
||||
static struct zl10353_config anysee_zl10353_config = {
|
||||
.demod_address = 0x1e,
|
||||
.demod_address = (0x1e >> 1),
|
||||
.parallel_ts = 1,
|
||||
};
|
||||
|
||||
static struct zl10353_config anysee_zl10353_tda18212_config2 = {
|
||||
.demod_address = (0x1e >> 1),
|
||||
.parallel_ts = 1,
|
||||
.disable_i2c_gate_ctrl = 1,
|
||||
.no_tuner = 1,
|
||||
.if2 = 41500,
|
||||
};
|
||||
|
||||
static struct zl10353_config anysee_zl10353_tda18212_config = {
|
||||
.demod_address = (0x18 >> 1),
|
||||
.parallel_ts = 1,
|
||||
.disable_i2c_gate_ctrl = 1,
|
||||
.no_tuner = 1,
|
||||
.if2 = 41500,
|
||||
};
|
||||
|
||||
static struct tda10023_config anysee_tda10023_tda18212_config = {
|
||||
.demod_address = (0x1a >> 1),
|
||||
.xtal = 16000000,
|
||||
.pll_m = 12,
|
||||
.pll_p = 3,
|
||||
.pll_n = 1,
|
||||
.output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
|
||||
.deltaf = 0xba02,
|
||||
};
|
||||
|
||||
static struct tda18212_config anysee_tda18212_config = {
|
||||
.i2c_address = (0xc0 >> 1),
|
||||
.if_dvbt_6 = 4150,
|
||||
.if_dvbt_7 = 4150,
|
||||
.if_dvbt_8 = 4150,
|
||||
.if_dvbc = 5000,
|
||||
};
|
||||
|
||||
static struct cx24116_config anysee_cx24116_config = {
|
||||
.demod_address = (0xaa >> 1),
|
||||
.mpg_clk_pos_pol = 0x00,
|
||||
.i2c_wr_max = 48,
|
||||
};
|
||||
|
||||
static struct stv0900_config anysee_stv0900_config = {
|
||||
.demod_address = (0xd0 >> 1),
|
||||
.demod_mode = 0,
|
||||
.xtal = 8000000,
|
||||
.clkmode = 3,
|
||||
.diseqc_mode = 2,
|
||||
.tun1_maddress = 0,
|
||||
.tun1_adc = 1, /* 1 Vpp */
|
||||
.path1_mode = 3,
|
||||
};
|
||||
|
||||
static struct stv6110_config anysee_stv6110_config = {
|
||||
.i2c_address = (0xc0 >> 1),
|
||||
.mclk = 16000000,
|
||||
.clk_div = 1,
|
||||
};
|
||||
|
||||
static struct isl6423_config anysee_isl6423_config = {
|
||||
.current_max = SEC_CURRENT_800m,
|
||||
.curlim = SEC_CURRENT_LIM_OFF,
|
||||
.mod_extern = 1,
|
||||
.addr = (0x10 >> 1),
|
||||
};
|
||||
|
||||
/*
|
||||
* New USB device strings: Mfr=1, Product=2, SerialNumber=0
|
||||
* Manufacturer: AMT.CO.KR
|
||||
*
|
||||
* E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
|
||||
* PCB: ?
|
||||
* parts: DNOS404ZH102A(MT352, DTT7579(?))
|
||||
*
|
||||
* E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
|
||||
* PCB: ?
|
||||
* parts: DNOS404ZH103A(ZL10353, DTT7579(?))
|
||||
*
|
||||
* E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
|
||||
* PCB: 507CD (rev1.1)
|
||||
* parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
|
||||
* OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
|
||||
* IOA=4f IOB=ff IOC=00 IOD=06 IOF=01
|
||||
* IOD[0] ZL10353 1=enabled
|
||||
* IOA[7] TS 0=enabled
|
||||
* tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
|
||||
*
|
||||
* E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
|
||||
* PCB: 507DC (rev0.2)
|
||||
* parts: TDA10023, DTOS403IH102B TM, CST56I01
|
||||
* OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
|
||||
* IOA=4f IOB=ff IOC=00 IOD=26 IOF=01
|
||||
* IOD[0] TDA10023 1=enabled
|
||||
*
|
||||
* E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
|
||||
* PCB: 507SI (rev2.1)
|
||||
* parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
|
||||
* OEA=80 OEB=00 OEC=ff OED=ff OEF=fe
|
||||
* IOA=4d IOB=ff IOC=00 IOD=26 IOF=01
|
||||
* IOD[0] CX24116 1=enabled
|
||||
*
|
||||
* E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
|
||||
* PCB: 507FA (rev0.4)
|
||||
* parts: TDA10023, DTOS403IH102B TM, TDA8024
|
||||
* OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
|
||||
* IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
|
||||
* IOD[5] TDA10023 1=enabled
|
||||
* IOE[0] tuner 1=enabled
|
||||
*
|
||||
* E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
|
||||
* PCB: 507FA (rev1.1)
|
||||
* parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
|
||||
* OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
|
||||
* IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
|
||||
* DVB-C:
|
||||
* IOD[5] TDA10023 1=enabled
|
||||
* IOE[0] tuner 1=enabled
|
||||
* DVB-T:
|
||||
* IOD[0] ZL10353 1=enabled
|
||||
* IOE[0] tuner 0=enabled
|
||||
* tuner is behind ZL10353 I2C-gate
|
||||
*
|
||||
* E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
|
||||
* PCB: 508TC (rev0.6)
|
||||
* parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
|
||||
* OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
|
||||
* IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4
|
||||
* IOA[7] TS 1=enabled
|
||||
* IOE[4] TDA18212 1=enabled
|
||||
* DVB-C:
|
||||
* IOD[6] ZL10353 0=disabled
|
||||
* IOD[5] TDA10023 1=enabled
|
||||
* IOE[0] IF 1=enabled
|
||||
* DVB-T:
|
||||
* IOD[5] TDA10023 0=disabled
|
||||
* IOD[6] ZL10353 1=enabled
|
||||
* IOE[0] IF 0=enabled
|
||||
*
|
||||
* E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
|
||||
* PCB: 508S2 (rev0.7)
|
||||
* parts: DNBU10512IST(STV0903, STV6110), ISL6423
|
||||
* OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
|
||||
* IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4
|
||||
* IOA[7] TS 1=enabled
|
||||
* IOE[5] STV0903 1=enabled
|
||||
*
|
||||
*/
|
||||
|
||||
static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
int ret;
|
||||
struct anysee_state *state = adap->dev->priv;
|
||||
u8 hw_info[3];
|
||||
u8 io_d; /* IO port D */
|
||||
u8 tmp;
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = anysee_tda18212_config.i2c_address,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = "\x00",
|
||||
}, {
|
||||
.addr = anysee_tda18212_config.i2c_address,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = &tmp,
|
||||
}
|
||||
};
|
||||
|
||||
/* check which hardware we have
|
||||
We must do this call two times to get reliable values (hw bug). */
|
||||
/* 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)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
ret = anysee_get_hw_info(adap->dev, hw_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
/* Meaning of these info bytes are guessed. */
|
||||
info("firmware version:%d.%d.%d hardware id:%d",
|
||||
0, hw_info[1], hw_info[2], hw_info[0]);
|
||||
info("firmware version:%d.%d hardware id:%d",
|
||||
hw_info[1], hw_info[2], hw_info[0]);
|
||||
|
||||
ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
|
||||
if (ret)
|
||||
return ret;
|
||||
deb_info("%s: IO port D:%02x\n", __func__, io_d);
|
||||
state->hw = hw_info[0];
|
||||
|
||||
/* Select demod using trial and error method. */
|
||||
switch (state->hw) {
|
||||
case ANYSEE_HW_02: /* 2 */
|
||||
/* E30 */
|
||||
|
||||
/* Try to attach demodulator in following order:
|
||||
model demod hw firmware
|
||||
1. E30 MT352 02 0.2.1
|
||||
2. E30 ZL10353 02 0.2.1
|
||||
3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo
|
||||
4. E30 Plus ZL10353 06 0.1.0
|
||||
5. E30C Plus TDA10023 0a 0.1.0 rev 0.2
|
||||
E30C Plus TDA10023 0f 0.1.2 rev 0.4
|
||||
E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo
|
||||
*/
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe)
|
||||
break;
|
||||
|
||||
/* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
|
||||
adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe != NULL) {
|
||||
state->tuner = DVB_PLL_THOMSON_DTT7579;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe != NULL) {
|
||||
state->tuner = DVB_PLL_THOMSON_DTT7579;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for E30 Combo Plus DVB-T demodulator */
|
||||
if (dvb_usb_anysee_delsys) {
|
||||
ret = anysee_write_reg(adap->dev, 0xb0, 0x01);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Zarlink ZL10353 DVB-T demod */
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe != NULL) {
|
||||
state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
|
||||
return 0;
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507CD: /* 6 */
|
||||
/* E30 Plus */
|
||||
|
||||
/* enable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable transport stream on IOA[7] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507DC: /* 10 */
|
||||
/* E30 C Plus */
|
||||
|
||||
/* 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);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507SI: /* 11 */
|
||||
/* E30 S2 Plus */
|
||||
|
||||
/* 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->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507FA: /* 15 */
|
||||
/* E30 Combo Plus */
|
||||
/* E30 C Plus */
|
||||
|
||||
/* enable tuner on IOE[4] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* probe TDA18212 */
|
||||
tmp = 0;
|
||||
ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2);
|
||||
if (ret == 2 && tmp == 0xc7)
|
||||
deb_info("%s: TDA18212 found\n", __func__);
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
/* disable tuner on IOE[4] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
|
||||
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 {
|
||||
/* 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;
|
||||
|
||||
/* attach demod */
|
||||
if (tmp == 0xc7) {
|
||||
/* TDA18212 config */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_tda18212_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
} else {
|
||||
/* PLL config */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508TC: /* 18 */
|
||||
/* E7 TC */
|
||||
|
||||
/* enable transport stream on IOA[7] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
|
||||
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 {
|
||||
/* 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;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_tda18212_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
}
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508S2: /* 19 */
|
||||
/* E7 S2 */
|
||||
|
||||
/* enable transport stream on IOA[7] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-S/S2 demod on IOE[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
|
||||
&adap->dev->i2c_adap, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* connect demod on IO port D for TDA10023 & ZL10353 */
|
||||
ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe != NULL) {
|
||||
state->tuner = DVB_PLL_THOMSON_DTT7579;
|
||||
return 0;
|
||||
if (!adap->fe) {
|
||||
/* we have no frontend :-( */
|
||||
ret = -ENODEV;
|
||||
err("Unsupported Anysee version. " \
|
||||
"Please report the <linux-media@vger.kernel.org>.");
|
||||
}
|
||||
|
||||
/* IO port E - E30C rev 0.4 board requires this */
|
||||
ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Philips TDA10023 DVB-C demod */
|
||||
adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
if (adap->fe != NULL) {
|
||||
state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return IO port D to init value for safe */
|
||||
ret = anysee_write_reg(adap->dev, 0xb0, io_d);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err("Unknown Anysee version: %02x %02x %02x. "\
|
||||
"Please report the <linux-dvb@linuxtv.org>.",
|
||||
hw_info[0], hw_info[1], hw_info[2]);
|
||||
|
||||
return -ENODEV;
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
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__);
|
||||
|
||||
switch (state->tuner) {
|
||||
case DVB_PLL_THOMSON_DTT7579:
|
||||
/* Thomson dtt7579 (not sure) PLL inside of:
|
||||
Samsung DNOS404ZH102A NIM
|
||||
Samsung DNOS404ZH103A NIM */
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61,
|
||||
NULL, DVB_PLL_THOMSON_DTT7579);
|
||||
switch (state->hw) {
|
||||
case ANYSEE_HW_02: /* 2 */
|
||||
/* E30 */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
|
||||
NULL, DVB_PLL_THOMSON_DTT7579);
|
||||
|
||||
break;
|
||||
case DVB_PLL_SAMSUNG_DTOS403IH102A:
|
||||
/* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
|
||||
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
case ANYSEE_HW_507CD: /* 6 */
|
||||
/* E30 Plus */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507DC: /* 10 */
|
||||
/* E30 C Plus */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507SI: /* 11 */
|
||||
/* E30 S2 Plus */
|
||||
|
||||
/* attach LNB controller */
|
||||
fe = dvb_attach(isl6423_attach, adap->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. */
|
||||
|
||||
/* enable tuner on IOE[4] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&anysee_tda18212_config);
|
||||
if (fe)
|
||||
break;
|
||||
|
||||
/* disable tuner on IOE[4] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508TC: /* 18 */
|
||||
/* E7 TC */
|
||||
|
||||
/* enable tuner on IOE[4] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&anysee_tda18212_config);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508S2: /* 19 */
|
||||
/* E7 S2 */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(stv6110_attach, adap->fe,
|
||||
&anysee_stv6110_config, &adap->dev->i2c_adap);
|
||||
|
||||
if (fe) {
|
||||
/* attach LNB controller */
|
||||
fe = dvb_attach(isl6423_attach, adap->fe,
|
||||
&adap->dev->i2c_adap, &anysee_isl6423_config);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
fe = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (fe)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ENODEV;
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int anysee_rc_query(struct dvb_usb_device *d)
|
||||
|
|
|
@ -57,10 +57,29 @@ enum cmd {
|
|||
};
|
||||
|
||||
struct anysee_state {
|
||||
u8 tuner;
|
||||
u8 hw; /* PCB ID */
|
||||
u8 seq;
|
||||
};
|
||||
|
||||
#define ANYSEE_HW_02 2 /* E30 */
|
||||
#define ANYSEE_HW_507CD 6 /* E30 Plus */
|
||||
#define ANYSEE_HW_507DC 10 /* E30 C Plus */
|
||||
#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
|
||||
#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
|
||||
#define ANYSEE_HW_508TC 18 /* E7 TC */
|
||||
#define ANYSEE_HW_508S2 19 /* E7 S2 */
|
||||
|
||||
#define REG_IOA 0x80 /* Port A (bit addressable) */
|
||||
#define REG_IOB 0x90 /* Port B (bit addressable) */
|
||||
#define REG_IOC 0xa0 /* Port C (bit addressable) */
|
||||
#define REG_IOD 0xb0 /* Port D (bit addressable) */
|
||||
#define REG_IOE 0xb1 /* Port E (NOT bit addressable) */
|
||||
#define REG_OEA 0xb2 /* Port A Output Enable */
|
||||
#define REG_OEB 0xb3 /* Port B Output Enable */
|
||||
#define REG_OEC 0xb4 /* Port C Output Enable */
|
||||
#define REG_OED 0xb5 /* Port D Output Enable */
|
||||
#define REG_OEE 0xb6 /* Port E Output Enable */
|
||||
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -136,7 +155,7 @@ General reply packet(s) are always used if not own reply defined.
|
|||
----------------------------------------------------------------------------
|
||||
| 04 | 0x00
|
||||
----------------------------------------------------------------------------
|
||||
| 05 | 0x01
|
||||
| 05 | data length
|
||||
----------------------------------------------------------------------------
|
||||
| 06-59 | don't care
|
||||
----------------------------------------------------------------------------
|
||||
|
|
|
@ -33,8 +33,16 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
|
|||
{
|
||||
int ret;
|
||||
u16 index;
|
||||
u8 usb_buf[6]; /* enough for all known requests,
|
||||
read returns 5 and write 6 bytes */
|
||||
u8 *usb_buf;
|
||||
|
||||
/*
|
||||
* allocate enough for all known requests,
|
||||
* read returns 5 and write 6 bytes
|
||||
*/
|
||||
usb_buf = kmalloc(6, GFP_KERNEL);
|
||||
if (!usb_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (wlen) {
|
||||
case 1:
|
||||
index = wbuf[0] << 8;
|
||||
|
@ -45,14 +53,15 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
|
|||
break;
|
||||
default:
|
||||
warn("wlen = %x, aborting.", wlen);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
|
||||
USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
|
||||
usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
|
||||
usb_buf, 6, AU6610_USB_TIMEOUT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
switch (operation) {
|
||||
case AU6610_REQ_I2C_READ:
|
||||
|
@ -60,7 +69,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
|
|||
/* requested value is always 5th byte in buffer */
|
||||
rbuf[0] = usb_buf[4];
|
||||
}
|
||||
|
||||
error:
|
||||
kfree(usb_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
|
|||
u8 requesttype;
|
||||
u16 value;
|
||||
u16 index;
|
||||
u8 buf[req->data_len];
|
||||
u8 *buf;
|
||||
|
||||
request = req->cmd;
|
||||
value = req->value;
|
||||
|
@ -62,6 +62,12 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
|
|||
goto error;
|
||||
}
|
||||
|
||||
buf = kmalloc(req->data_len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
|
||||
/* write */
|
||||
memcpy(buf, req->data, req->data_len);
|
||||
|
@ -74,7 +80,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
|
|||
msleep(1); /* avoid I2C errors */
|
||||
|
||||
ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
|
||||
buf, sizeof(buf), CE6230_USB_TIMEOUT);
|
||||
buf, req->data_len, CE6230_USB_TIMEOUT);
|
||||
|
||||
ce6230_debug_dump(request, requesttype, value, index, buf,
|
||||
req->data_len, deb_xfer);
|
||||
|
@ -88,6 +94,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
|
|||
if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
|
||||
memcpy(req->data, buf, req->data_len);
|
||||
|
||||
kfree(buf);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,9 @@ struct dib0700_state {
|
|||
u8 is_dib7000pc;
|
||||
u8 fw_use_new_i2c_api;
|
||||
u8 disable_streaming_master_mode;
|
||||
u32 fw_version;
|
||||
u32 nb_packet_buffer_size;
|
||||
u32 fw_version;
|
||||
u32 nb_packet_buffer_size;
|
||||
u8 buf[255];
|
||||
};
|
||||
|
||||
extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
|
||||
|
|
|
@ -27,19 +27,25 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
|
||||
u32 *romversion, u32 *ramversion, u32 *fwtype)
|
||||
{
|
||||
u8 b[16];
|
||||
int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
struct dib0700_state *st = d->priv;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
REQUEST_GET_VERSION,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
|
||||
st->buf, 16, USB_CTRL_GET_TIMEOUT);
|
||||
if (hwversion != NULL)
|
||||
*hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
||||
*hwversion = (st->buf[0] << 24) | (st->buf[1] << 16) |
|
||||
(st->buf[2] << 8) | st->buf[3];
|
||||
if (romversion != NULL)
|
||||
*romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
|
||||
*romversion = (st->buf[4] << 24) | (st->buf[5] << 16) |
|
||||
(st->buf[6] << 8) | st->buf[7];
|
||||
if (ramversion != NULL)
|
||||
*ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
*ramversion = (st->buf[8] << 24) | (st->buf[9] << 16) |
|
||||
(st->buf[10] << 8) | st->buf[11];
|
||||
if (fwtype != NULL)
|
||||
*fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
|
||||
*fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
|
||||
(st->buf[14] << 8) | st->buf[15];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -101,24 +107,31 @@ 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)
|
||||
{
|
||||
u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
|
||||
return dib0700_ctrl_wr(d, buf, sizeof(buf));
|
||||
struct dib0700_state *st = d->priv;
|
||||
s16 ret;
|
||||
|
||||
st->buf[0] = REQUEST_SET_GPIO;
|
||||
st->buf[1] = gpio;
|
||||
st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 b[3];
|
||||
int ret;
|
||||
|
||||
if (st->fw_version >= 0x10201) {
|
||||
b[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
b[1] = (nb_ts_packets >> 8) & 0xff;
|
||||
b[2] = nb_ts_packets & 0xff;
|
||||
st->buf[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
st->buf[1] = (nb_ts_packets >> 8) & 0xff;
|
||||
st->buf[2] = nb_ts_packets & 0xff;
|
||||
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, b, sizeof(b));
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
|
@ -137,11 +150,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
properly support i2c read calls not preceded by a write */
|
||||
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct dib0700_state *st = d->priv;
|
||||
uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */
|
||||
uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
|
||||
uint8_t en_start = 0;
|
||||
uint8_t en_stop = 0;
|
||||
uint8_t buf[255]; /* TBV: malloc ? */
|
||||
int result, i;
|
||||
|
||||
/* Ensure nobody else hits the i2c bus while we're sending our
|
||||
|
@ -195,24 +208,24 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
|
||||
} else {
|
||||
/* Write request */
|
||||
buf[0] = REQUEST_NEW_I2C_WRITE;
|
||||
buf[1] = msg[i].addr << 1;
|
||||
buf[2] = (en_start << 7) | (en_stop << 6) |
|
||||
st->buf[0] = REQUEST_NEW_I2C_WRITE;
|
||||
st->buf[1] = msg[i].addr << 1;
|
||||
st->buf[2] = (en_start << 7) | (en_stop << 6) |
|
||||
(msg[i].len & 0x3F);
|
||||
/* I2C ctrl + FE bus; */
|
||||
buf[3] = ((gen_mode << 6) & 0xC0) |
|
||||
st->buf[3] = ((gen_mode << 6) & 0xC0) |
|
||||
((bus_mode << 4) & 0x30);
|
||||
/* The Actual i2c payload */
|
||||
memcpy(&buf[4], msg[i].buf, msg[i].len);
|
||||
memcpy(&st->buf[4], msg[i].buf, msg[i].len);
|
||||
|
||||
deb_data(">>> ");
|
||||
debug_dump(buf, msg[i].len + 4, deb_data);
|
||||
debug_dump(st->buf, msg[i].len + 4, deb_data);
|
||||
|
||||
result = usb_control_msg(d->udev,
|
||||
usb_sndctrlpipe(d->udev, 0),
|
||||
REQUEST_NEW_I2C_WRITE,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
0, 0, buf, msg[i].len + 4,
|
||||
0, 0, st->buf, msg[i].len + 4,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
if (result < 0) {
|
||||
deb_info("i2c write error (status = %d)\n", result);
|
||||
|
@ -231,27 +244,29 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
|||
struct i2c_msg *msg, int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct dib0700_state *st = d->priv;
|
||||
int i,len;
|
||||
u8 buf[255];
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
/* fill in the address */
|
||||
buf[1] = msg[i].addr << 1;
|
||||
st->buf[1] = msg[i].addr << 1;
|
||||
/* fill the buffer */
|
||||
memcpy(&buf[2], msg[i].buf, msg[i].len);
|
||||
memcpy(&st->buf[2], msg[i].buf, msg[i].len);
|
||||
|
||||
/* write/read request */
|
||||
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
|
||||
buf[0] = REQUEST_I2C_READ;
|
||||
buf[1] |= 1;
|
||||
st->buf[0] = REQUEST_I2C_READ;
|
||||
st->buf[1] |= 1;
|
||||
|
||||
/* special thing in the current firmware: when length is zero the read-failed */
|
||||
if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
|
||||
len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
|
||||
msg[i+1].buf, msg[i+1].len);
|
||||
if (len <= 0) {
|
||||
deb_info("I2C read failed on address 0x%02x\n",
|
||||
msg[i].addr);
|
||||
msg[i].addr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -259,13 +274,13 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
|||
|
||||
i++;
|
||||
} else {
|
||||
buf[0] = REQUEST_I2C_WRITE;
|
||||
if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0)
|
||||
st->buf[0] = REQUEST_I2C_WRITE;
|
||||
if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -297,15 +312,23 @@ struct i2c_algorithm dib0700_i2c_algo = {
|
|||
int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold)
|
||||
{
|
||||
u8 b[16];
|
||||
s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
|
||||
s16 ret;
|
||||
u8 *b;
|
||||
|
||||
b = kmalloc(16, GFP_KERNEL);
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
deb_info("FW GET_VERSION length: %d\n",ret);
|
||||
|
||||
*cold = ret <= 0;
|
||||
|
||||
deb_info("cold: %d\n", *cold);
|
||||
|
||||
kfree(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -313,43 +336,50 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
|||
u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
|
||||
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
|
||||
{
|
||||
u8 b[10];
|
||||
b[0] = REQUEST_SET_CLOCK;
|
||||
b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
|
||||
b[2] = (pll_prediv >> 8) & 0xff; // MSB
|
||||
b[3] = pll_prediv & 0xff; // LSB
|
||||
b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
|
||||
b[5] = pll_loopdiv & 0xff; // LSB
|
||||
b[6] = (free_div >> 8) & 0xff; // MSB
|
||||
b[7] = free_div & 0xff; // LSB
|
||||
b[8] = (dsuScaler >> 8) & 0xff; // MSB
|
||||
b[9] = dsuScaler & 0xff; // LSB
|
||||
struct dib0700_state *st = d->priv;
|
||||
s16 ret;
|
||||
|
||||
return dib0700_ctrl_wr(d, b, 10);
|
||||
st->buf[0] = REQUEST_SET_CLOCK;
|
||||
st->buf[1] = (en_pll << 7) | (pll_src << 6) |
|
||||
(pll_range << 5) | (clock_gpio3 << 4);
|
||||
st->buf[2] = (pll_prediv >> 8) & 0xff; /* MSB */
|
||||
st->buf[3] = pll_prediv & 0xff; /* LSB */
|
||||
st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */
|
||||
st->buf[5] = pll_loopdiv & 0xff; /* LSB */
|
||||
st->buf[6] = (free_div >> 8) & 0xff; /* MSB */
|
||||
st->buf[7] = free_div & 0xff; /* LSB */
|
||||
st->buf[8] = (dsuScaler >> 8) & 0xff; /* MSB */
|
||||
st->buf[9] = dsuScaler & 0xff; /* LSB */
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u16 divider;
|
||||
u8 b[8];
|
||||
|
||||
if (scl_kHz == 0)
|
||||
return -EINVAL;
|
||||
|
||||
b[0] = REQUEST_SET_I2C_PARAM;
|
||||
st->buf[0] = REQUEST_SET_I2C_PARAM;
|
||||
divider = (u16) (30000 / scl_kHz);
|
||||
b[2] = (u8) (divider >> 8);
|
||||
b[3] = (u8) (divider & 0xff);
|
||||
st->buf[1] = 0;
|
||||
st->buf[2] = (u8) (divider >> 8);
|
||||
st->buf[3] = (u8) (divider & 0xff);
|
||||
divider = (u16) (72000 / scl_kHz);
|
||||
b[4] = (u8) (divider >> 8);
|
||||
b[5] = (u8) (divider & 0xff);
|
||||
st->buf[4] = (u8) (divider >> 8);
|
||||
st->buf[5] = (u8) (divider & 0xff);
|
||||
divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
|
||||
b[6] = (u8) (divider >> 8);
|
||||
b[7] = (u8) (divider & 0xff);
|
||||
st->buf[6] = (u8) (divider >> 8);
|
||||
st->buf[7] = (u8) (divider & 0xff);
|
||||
|
||||
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
|
||||
(b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz);
|
||||
return dib0700_ctrl_wr(d, b, 8);
|
||||
(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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -364,32 +394,45 @@ int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
|
|||
|
||||
static int dib0700_jumpram(struct usb_device *udev, u32 address)
|
||||
{
|
||||
int ret, actlen;
|
||||
u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
|
||||
(address >> 24) & 0xff,
|
||||
(address >> 16) & 0xff,
|
||||
(address >> 8) & 0xff,
|
||||
address & 0xff };
|
||||
int ret = 0, actlen;
|
||||
u8 *buf;
|
||||
|
||||
buf = kmalloc(8, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
buf[0] = REQUEST_JUMPRAM;
|
||||
buf[1] = 0;
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = (address >> 24) & 0xff;
|
||||
buf[5] = (address >> 16) & 0xff;
|
||||
buf[6] = (address >> 8) & 0xff;
|
||||
buf[7] = address & 0xff;
|
||||
|
||||
if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
|
||||
deb_fw("jumpram to 0x%x failed\n",address);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
if (actlen != 8) {
|
||||
deb_fw("jumpram to 0x%x failed\n",address);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
|
||||
{
|
||||
struct hexline hx;
|
||||
int pos = 0, ret, act_len, i, adap_num;
|
||||
u8 b[16];
|
||||
u8 *buf;
|
||||
u32 fw_version;
|
||||
|
||||
u8 buf[260];
|
||||
buf = kmalloc(260, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
|
||||
deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
|
||||
|
@ -411,7 +454,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
|
||||
if (ret < 0) {
|
||||
err("firmware download failed at %d with %d",pos,ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,8 +475,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
REQUEST_GET_VERSION,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
|
||||
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
buf, 16, USB_CTRL_GET_TIMEOUT);
|
||||
fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
|
||||
|
||||
/* set the buffer size - DVB-USB is allocating URB buffers
|
||||
* only after the firwmare download was successful */
|
||||
|
@ -451,14 +494,14 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct dib0700_state *st = adap->dev->priv;
|
||||
u8 b[4];
|
||||
int ret;
|
||||
|
||||
if ((onoff != 0) && (st->fw_version >= 0x10201)) {
|
||||
|
@ -472,15 +515,17 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
}
|
||||
|
||||
b[0] = REQUEST_ENABLE_VIDEO;
|
||||
b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
|
||||
st->buf[0] = REQUEST_ENABLE_VIDEO;
|
||||
/* this bit gives a kind of command,
|
||||
* rather than enabling something or not */
|
||||
st->buf[1] = (onoff << 4) | 0x00;
|
||||
|
||||
if (st->disable_streaming_master_mode == 1)
|
||||
b[2] = 0x00;
|
||||
st->buf[2] = 0x00;
|
||||
else
|
||||
b[2] = 0x01 << 4; /* Master mode */
|
||||
st->buf[2] = 0x01 << 4; /* Master mode */
|
||||
|
||||
b[3] = 0x00;
|
||||
st->buf[3] = 0x00;
|
||||
|
||||
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
|
||||
|
||||
|
@ -499,20 +544,23 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
st->channel_state |= 1 << (3-adap->stream.props.endpoint);
|
||||
}
|
||||
|
||||
b[2] |= st->channel_state;
|
||||
st->buf[2] |= st->channel_state;
|
||||
|
||||
deb_info("data for streaming: %x %x\n", b[1], b[2]);
|
||||
deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
|
||||
|
||||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
return dib0700_ctrl_wr(adap->dev, st->buf, 4);
|
||||
}
|
||||
|
||||
int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
||||
{
|
||||
struct dvb_usb_device *d = rc->priv;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
|
||||
int new_proto, ret;
|
||||
|
||||
st->buf[0] = REQUEST_SET_RC;
|
||||
st->buf[1] = 0;
|
||||
st->buf[2] = 0;
|
||||
|
||||
/* Set the IR mode */
|
||||
if (rc_type == RC_TYPE_RC5)
|
||||
new_proto = 1;
|
||||
|
@ -526,9 +574,9 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
|||
} else
|
||||
return -EINVAL;
|
||||
|
||||
rc_setup[1] = new_proto;
|
||||
st->buf[1] = new_proto;
|
||||
|
||||
ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
if (ret < 0) {
|
||||
err("ir protocol setup failed");
|
||||
return ret;
|
||||
|
@ -561,7 +609,6 @@ struct dib0700_rc_response {
|
|||
static void dib0700_rc_urb_completion(struct urb *purb)
|
||||
{
|
||||
struct dvb_usb_device *d = purb->context;
|
||||
struct dib0700_state *st;
|
||||
struct dib0700_rc_response *poll_reply;
|
||||
u32 uninitialized_var(keycode);
|
||||
u8 toggle;
|
||||
|
@ -576,7 +623,6 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
return;
|
||||
}
|
||||
|
||||
st = d->priv;
|
||||
poll_reply = purb->transfer_buffer;
|
||||
|
||||
if (purb->status < 0) {
|
||||
|
|
|
@ -2439,7 +2439,6 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
dib0700_set_i2c_speed(adap->dev, 340);
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
|
||||
|
||||
if (adap->fe == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -2802,6 +2801,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
|
|||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) },
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) },
|
||||
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
|
||||
/* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) },
|
||||
{ 0 } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
|
||||
|
@ -3411,7 +3411,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 3,
|
||||
.num_device_descs = 4,
|
||||
.devices = {
|
||||
{ "DiBcom STK7770P reference design",
|
||||
{ &dib0700_usb_id_table[59], NULL },
|
||||
|
@ -3427,6 +3427,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[74], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Medion CTX1921 DVB-T USB",
|
||||
{ &dib0700_usb_id_table[75], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc.core = {
|
||||
|
|
|
@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = {
|
|||
|
||||
{ 0x8008, KEY_DVD },
|
||||
{ 0x8009, KEY_AUDIO },
|
||||
{ 0x800a, KEY_MEDIA }, /* Pictures */
|
||||
{ 0x800a, KEY_IMAGES }, /* Pictures */
|
||||
{ 0x800b, KEY_VIDEO },
|
||||
|
||||
{ 0x800c, KEY_BACK },
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
|
||||
int newfeedcount,ret;
|
||||
int newfeedcount, ret;
|
||||
|
||||
if (adap == NULL)
|
||||
return -ENODEV;
|
||||
|
@ -24,9 +24,13 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
|||
deb_ts("stop feeding\n");
|
||||
usb_urb_kill(&adap->stream);
|
||||
|
||||
if (adap->props.streaming_ctrl != NULL)
|
||||
if ((ret = adap->props.streaming_ctrl(adap,0)))
|
||||
if (adap->props.streaming_ctrl != NULL) {
|
||||
ret = adap->props.streaming_ctrl(adap, 0);
|
||||
if (ret < 0) {
|
||||
err("error while stopping stream.");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adap->feedcount = newfeedcount;
|
||||
|
@ -49,17 +53,24 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
|||
|
||||
deb_ts("controlling pid parser\n");
|
||||
if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
|
||||
adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
|
||||
adap->props.pid_filter_ctrl != NULL)
|
||||
if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0)
|
||||
adap->props.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);
|
||||
if (ret < 0) {
|
||||
err("could not handle pid_parser");
|
||||
|
||||
deb_ts("start feeding\n");
|
||||
if (adap->props.streaming_ctrl != NULL)
|
||||
if (adap->props.streaming_ctrl(adap,1)) {
|
||||
err("error while enabling fifo.");
|
||||
return -ENODEV;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
deb_ts("start feeding\n");
|
||||
if (adap->props.streaming_ctrl != NULL) {
|
||||
ret = adap->props.streaming_ctrl(adap, 1);
|
||||
if (ret < 0) {
|
||||
err("error while enabling fifo.");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
|
||||
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
|
||||
#define USB_PID_CONEXANT_D680_DMB 0x86d6
|
||||
#define USB_PID_CREATIX_CTX1921 0x1921
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||
|
|
|
@ -121,12 +121,16 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
|
|||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
u8 u8buf[len];
|
||||
|
||||
u8 *u8buf;
|
||||
unsigned int pipe = (flags == DW210X_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
if (flags == DW210X_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
|
@ -134,6 +138,8 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
|
|||
|
||||
if (flags == DW210X_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
|
|||
int ret;
|
||||
unsigned int pipe;
|
||||
u8 request, requesttype;
|
||||
u8 buf[req->size];
|
||||
u8 *buf;
|
||||
|
||||
|
||||
|
||||
switch (req->cmd) {
|
||||
case DOWNLOAD_FIRMWARE:
|
||||
|
@ -72,6 +74,12 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
|
|||
goto error;
|
||||
}
|
||||
|
||||
buf = kmalloc(req->size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
|
||||
/* write */
|
||||
memcpy(buf, req->data, req->size);
|
||||
|
@ -84,13 +92,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
|
|||
msleep(1); /* avoid I2C errors */
|
||||
|
||||
ret = usb_control_msg(udev, pipe, request, requesttype, req->value,
|
||||
req->index, buf, sizeof(buf), EC168_USB_TIMEOUT);
|
||||
req->index, buf, req->size, EC168_USB_TIMEOUT);
|
||||
|
||||
ec168_debug_dump(request, requesttype, req->value, req->index, buf,
|
||||
req->size, deb_xfer);
|
||||
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
goto err_dealloc;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
|
@ -98,7 +106,11 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
|
|||
if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
|
||||
memcpy(req->data, buf, req->size);
|
||||
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
||||
err_dealloc:
|
||||
kfree(buf);
|
||||
error:
|
||||
deb_info("%s: failed:%d\n", __func__, ret);
|
||||
return ret;
|
||||
|
|
|
@ -142,17 +142,20 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter)
|
|||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
|
||||
static int friio_ext_ctl(struct dvb_usb_adapter *adap,
|
||||
u32 sat_color, int lnb_on)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
struct i2c_msg msg;
|
||||
u8 buf[2];
|
||||
u8 *buf;
|
||||
u32 mask;
|
||||
u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
|
||||
|
||||
buf = kmalloc(2, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
msg.addr = 0x00;
|
||||
msg.flags = 0;
|
||||
msg.len = 2;
|
||||
|
@ -189,6 +192,7 @@ static int friio_ext_ctl(struct dvb_usb_adapter *adap,
|
|||
buf[1] |= FRIIO_CTL_CLK;
|
||||
ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
|
||||
|
||||
kfree(buf);
|
||||
return (ret == 70);
|
||||
}
|
||||
|
||||
|
@ -219,11 +223,20 @@ static int friio_initialize(struct dvb_usb_device *d)
|
|||
int ret;
|
||||
int i;
|
||||
int retry = 0;
|
||||
u8 rbuf[2];
|
||||
u8 wbuf[3];
|
||||
u8 *rbuf, *wbuf;
|
||||
|
||||
deb_info("%s called.\n", __func__);
|
||||
|
||||
wbuf = kmalloc(3, GFP_KERNEL);
|
||||
if (!wbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
rbuf = kmalloc(2, GFP_KERNEL);
|
||||
if (!rbuf) {
|
||||
kfree(wbuf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
|
||||
/* because the i2c device is not set up yet. */
|
||||
wbuf[0] = 0x11;
|
||||
|
@ -358,6 +371,8 @@ static int friio_initialize(struct dvb_usb_device *d)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
kfree(wbuf);
|
||||
kfree(rbuf);
|
||||
deb_info("%s:ret == %d\n", __func__, ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
@ -62,8 +62,6 @@
|
|||
* LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
|
||||
* with other tuners. After a cold reset streaming will not start.
|
||||
*
|
||||
* PID functions have been removed from this driver version due to
|
||||
* problems with different firmware and application versions.
|
||||
*/
|
||||
#define DVB_USB_LOG_PREFIX "LME2510(C)"
|
||||
#include <linux/usb.h>
|
||||
|
@ -104,6 +102,10 @@ static int dvb_usb_lme2510_firmware;
|
|||
module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
|
||||
MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
|
||||
|
||||
static int pid_filter;
|
||||
module_param_named(pid, pid_filter, int, 0644);
|
||||
MODULE_PARM_DESC(pid, "set default 0=on 1=off");
|
||||
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
|
@ -125,6 +127,7 @@ struct lme2510_state {
|
|||
u8 i2c_tuner_gate_r;
|
||||
u8 i2c_tuner_addr;
|
||||
u8 stream_on;
|
||||
u8 pid_size;
|
||||
void *buffer;
|
||||
struct urb *lme_urb;
|
||||
void *usb_buffer;
|
||||
|
@ -167,14 +170,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
|||
}
|
||||
buff = st->usb_buffer;
|
||||
|
||||
/* the read/write capped at 512 */
|
||||
memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
|
||||
|
||||
ret = mutex_lock_interruptible(&d->usb_mutex);
|
||||
|
||||
if (ret < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
/* the read/write capped at 512 */
|
||||
memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
|
||||
|
||||
ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
|
||||
|
||||
ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
|
||||
|
@ -216,6 +219,37 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
|
||||
{
|
||||
struct lme2510_state *st = d->priv;
|
||||
static u8 pid_buff[] = LME_ZERO_PID;
|
||||
static u8 rbuf[1];
|
||||
u8 pid_no = index * 2;
|
||||
u8 pid_len = pid_no + 2;
|
||||
int ret = 0;
|
||||
deb_info(1, "PID Setting Pid %04x", pid_out);
|
||||
|
||||
if (st->pid_size == 0)
|
||||
ret |= lme2510_stream_restart(d);
|
||||
|
||||
pid_buff[2] = pid_no;
|
||||
pid_buff[3] = (u8)pid_out & 0xff;
|
||||
pid_buff[4] = pid_no + 1;
|
||||
pid_buff[5] = (u8)(pid_out >> 8);
|
||||
|
||||
if (pid_len > st->pid_size)
|
||||
st->pid_size = pid_len;
|
||||
pid_buff[7] = 0x80 + st->pid_size;
|
||||
|
||||
ret |= lme2510_usb_talk(d, pid_buff ,
|
||||
sizeof(pid_buff) , rbuf, sizeof(rbuf));
|
||||
|
||||
if (st->stream_on)
|
||||
ret |= lme2510_stream_restart(d);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lme2510_int_response(struct urb *lme_urb)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = lme_urb->context;
|
||||
|
@ -326,16 +360,68 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
static u8 clear_pid_reg[] = LME_CLEAR_PID;
|
||||
static u8 rbuf[1];
|
||||
int ret;
|
||||
|
||||
deb_info(1, "PID Clearing Filter");
|
||||
|
||||
ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
|
||||
if (ret < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!onoff)
|
||||
ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
|
||||
sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
|
||||
|
||||
st->pid_size = 0;
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
||||
int onoff)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
|
||||
pid, index, onoff);
|
||||
|
||||
if (onoff)
|
||||
if (!pid_filter) {
|
||||
ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
|
||||
if (ret < 0)
|
||||
return -EAGAIN;
|
||||
ret |= lme2510_enable_pid(adap->dev, index, pid);
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int lme2510_return_status(struct usb_device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 data[10] = {0};
|
||||
u8 *data;
|
||||
|
||||
data = kzalloc(10, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
|
||||
info("Firmware Status: %x (%x)", ret , data[2]);
|
||||
|
||||
return (ret < 0) ? -ENODEV : data[2];
|
||||
ret = (ret < 0) ? -ENODEV : data[2];
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lme2510_msg(struct dvb_usb_device *d,
|
||||
|
@ -591,9 +677,10 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
else {
|
||||
deb_info(1, "STM Steam Off");
|
||||
/* mutex is here only to avoid collision with I2C */
|
||||
ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
|
||||
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
|
||||
ret = lme2510_usb_talk(adap->dev, clear_reg_3,
|
||||
sizeof(clear_reg_3), rbuf, rlen);
|
||||
st->stream_on = 0;
|
||||
st->i2c_talk_onoff = 1;
|
||||
|
@ -655,7 +742,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
const struct firmware *fw)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 data[512] = {0};
|
||||
u8 *data;
|
||||
u16 j, wlen, len_in, start, end;
|
||||
u8 packet_size, dlen, i;
|
||||
u8 *fw_data;
|
||||
|
@ -663,6 +750,11 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
packet_size = 0x31;
|
||||
len_in = 1;
|
||||
|
||||
data = kzalloc(512, GFP_KERNEL);
|
||||
if (!data) {
|
||||
info("FRM Could not start Firmware Download (Buffer allocation failed)");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info("FRM Starting Firmware Download");
|
||||
|
||||
|
@ -678,15 +770,15 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
data[0] = i | 0x80;
|
||||
dlen = (u8)(end - j)-1;
|
||||
}
|
||||
data[1] = dlen;
|
||||
memcpy(&data[2], fw_data, dlen+1);
|
||||
wlen = (u8) dlen + 4;
|
||||
data[wlen-1] = check_sum(fw_data, dlen+1);
|
||||
deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
|
||||
data[1] = dlen;
|
||||
memcpy(&data[2], fw_data, dlen+1);
|
||||
wlen = (u8) dlen + 4;
|
||||
data[wlen-1] = check_sum(fw_data, dlen+1);
|
||||
deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
|
||||
data[dlen+2], data[dlen+3]);
|
||||
ret |= lme2510_bulk_write(dev, data, wlen, 1);
|
||||
ret |= lme2510_bulk_read(dev, data, len_in , 1);
|
||||
ret |= (data[0] == 0x88) ? 0 : -1;
|
||||
ret |= lme2510_bulk_write(dev, data, wlen, 1);
|
||||
ret |= lme2510_bulk_read(dev, data, len_in , 1);
|
||||
ret |= (data[0] == 0x88) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +798,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
else
|
||||
info("FRM Firmware Download Completed - Resetting Device");
|
||||
|
||||
|
||||
kfree(data);
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
|
@ -747,7 +839,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
|
|||
fw_lme = fw_s0194;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0) {
|
||||
cold = 0;/*lme2510-s0194 cannot cold reset*/
|
||||
cold = 0;
|
||||
break;
|
||||
}
|
||||
dvb_usb_lme2510_firmware = TUNER_LG;
|
||||
|
@ -769,8 +861,10 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
|
|||
case TUNER_S7395:
|
||||
fw_lme = fw_c_s7395;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
cold = 0;
|
||||
break;
|
||||
}
|
||||
dvb_usb_lme2510_firmware = TUNER_LG;
|
||||
case TUNER_LG:
|
||||
fw_lme = fw_c_lg;
|
||||
|
@ -796,14 +890,14 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
|
|||
ret = lme2510_download_firmware(udev, fw);
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
if (cold) {
|
||||
info("FRM Changing to %s firmware", fw_lme);
|
||||
lme_coldreset(udev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1017,12 +1111,13 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
|
|||
static u8 rbuf[1];
|
||||
int ret, len = 3, rlen = 1;
|
||||
|
||||
ret = mutex_lock_interruptible(&d->i2c_mutex);
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
if (onoff)
|
||||
ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
|
||||
ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
|
||||
else
|
||||
ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
|
||||
ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
|
||||
|
||||
st->i2c_talk_onoff = 1;
|
||||
|
||||
|
@ -1086,7 +1181,13 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.streaming_ctrl = lme2510_streaming_ctrl,
|
||||
.pid_filter_count = 15,
|
||||
.pid_filter = lme2510_pid_filter,
|
||||
.pid_filter_ctrl = lme2510_pid_filter_ctrl,
|
||||
.frontend_attach = dm04_lme2510_frontend_attach,
|
||||
.tuner_attach = dm04_lme2510_tuner,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
@ -1122,7 +1223,13 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.streaming_ctrl = lme2510_streaming_ctrl,
|
||||
.pid_filter_count = 15,
|
||||
.pid_filter = lme2510_pid_filter,
|
||||
.pid_filter_ctrl = lme2510_pid_filter_ctrl,
|
||||
.frontend_attach = dm04_lme2510_frontend_attach,
|
||||
.tuner_attach = dm04_lme2510_tuner,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
@ -1151,7 +1258,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
void *lme2510_exit_int(struct dvb_usb_device *d)
|
||||
static void *lme2510_exit_int(struct dvb_usb_device *d)
|
||||
{
|
||||
struct lme2510_state *st = d->priv;
|
||||
struct dvb_usb_adapter *adap = &d->adapter[0];
|
||||
|
@ -1178,7 +1285,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void lme2510_exit(struct usb_interface *intf)
|
||||
static void lme2510_exit(struct usb_interface *intf)
|
||||
{
|
||||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
void *usb_buffer;
|
||||
|
@ -1220,5 +1327,5 @@ module_exit(lme2510_module_exit);
|
|||
|
||||
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
||||
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
|
||||
MODULE_VERSION("1.80");
|
||||
MODULE_VERSION("1.86");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
*/
|
||||
#define LME_ST_ON_W {0x06, 0x00}
|
||||
#define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0}
|
||||
#define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c}
|
||||
|
||||
/* LNB Voltage
|
||||
* 07 XX XX
|
||||
|
@ -108,14 +109,14 @@ static u8 s7395_inittab[] = {
|
|||
0x3d, 0x30,
|
||||
0x40, 0x63,
|
||||
0x41, 0x04,
|
||||
0x42, 0x60,
|
||||
0x42, 0x20,
|
||||
0x43, 0x00,
|
||||
0x44, 0x00,
|
||||
0x45, 0x00,
|
||||
0x46, 0x00,
|
||||
0x47, 0x00,
|
||||
0x4a, 0x00,
|
||||
0x50, 0x12,
|
||||
0x50, 0x10,
|
||||
0x51, 0x36,
|
||||
0x52, 0x21,
|
||||
0x53, 0x94,
|
||||
|
|
|
@ -134,13 +134,17 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
{
|
||||
struct m920x_state *m = d->priv;
|
||||
int i, ret = 0;
|
||||
u8 rc_state[2];
|
||||
u8 *rc_state;
|
||||
|
||||
rc_state = kmalloc(2, GFP_KERNEL);
|
||||
if (!rc_state)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
|
||||
if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
|
||||
|
@ -149,7 +153,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
switch(rc_state[0]) {
|
||||
case 0x80:
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
case 0x88: /* framing error or "invalid code" */
|
||||
case 0x99:
|
||||
|
@ -157,7 +161,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
case 0xd8:
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
m->rep_count = 0;
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
case 0x93:
|
||||
case 0x92:
|
||||
|
@ -165,7 +169,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
case 0x82:
|
||||
m->rep_count = 0;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
case 0x91:
|
||||
case 0x81: /* pinnacle PCTV310e */
|
||||
|
@ -174,12 +178,12 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*state = REMOTE_KEY_REPEAT;
|
||||
else
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
goto out;
|
||||
|
||||
default:
|
||||
deb("Unexpected rc state %02x\n", rc_state[0]);
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,8 +192,8 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
unlock:
|
||||
|
||||
out:
|
||||
kfree(rc_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -339,13 +343,19 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in
|
|||
static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
|
||||
{
|
||||
u16 value, index, size;
|
||||
u8 read[4], *buff;
|
||||
u8 *read, *buff;
|
||||
int i, pass, ret = 0;
|
||||
|
||||
buff = kmalloc(65536, GFP_KERNEL);
|
||||
if (buff == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
read = kmalloc(4, GFP_KERNEL);
|
||||
if (!read) {
|
||||
kfree(buff);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
|
||||
goto done;
|
||||
deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
|
||||
|
@ -396,6 +406,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
|
|||
deb("firmware uploaded!\n");
|
||||
|
||||
done:
|
||||
kfree(read);
|
||||
kfree(buff);
|
||||
|
||||
return ret;
|
||||
|
@ -632,9 +643,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
|
|||
{ 0x16, KEY_POWER },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
{ 0x48, KEY_MEDIA }, /* preview */
|
||||
{ 0x48, KEY_PROGRAM }, /* preview */
|
||||
{ 0x1c, KEY_EPG },
|
||||
{ 0x04, KEY_LIST }, /* record list */
|
||||
{ 0x04, KEY_LIST }, /* record list */
|
||||
{ 0x03, KEY_1 },
|
||||
{ 0x01, KEY_2 },
|
||||
{ 0x06, KEY_3 },
|
||||
|
@ -674,14 +685,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
|
|||
{ 0x0e, KEY_MUTE },
|
||||
/* { 0x49, KEY_LR }, */ /* L/R */
|
||||
{ 0x07, KEY_SLEEP }, /* Hibernate */
|
||||
{ 0x08, KEY_MEDIA }, /* A/V */
|
||||
{ 0x0e, KEY_MENU }, /* Recall */
|
||||
{ 0x08, KEY_VIDEO }, /* A/V */
|
||||
{ 0x0e, KEY_MENU }, /* Recall */
|
||||
{ 0x45, KEY_ZOOMIN },
|
||||
{ 0x46, KEY_ZOOMOUT },
|
||||
{ 0x18, KEY_TV }, /* Red */
|
||||
{ 0x53, KEY_VCR }, /* Green */
|
||||
{ 0x5e, KEY_SAT }, /* Yellow */
|
||||
{ 0x5f, KEY_PLAYER }, /* Blue */
|
||||
{ 0x18, KEY_RED }, /* Red */
|
||||
{ 0x53, KEY_GREEN }, /* Green */
|
||||
{ 0x5e, KEY_YELLOW }, /* Yellow */
|
||||
{ 0x5f, KEY_BLUE }, /* Blue */
|
||||
};
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
|
|
|
@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = {
|
|||
{ 0x1e17, KEY_RIGHT },
|
||||
{ 0x1e18, KEY_VIDEO },
|
||||
{ 0x1e19, KEY_AUDIO },
|
||||
{ 0x1e1a, KEY_MEDIA },
|
||||
{ 0x1e1a, KEY_IMAGES },
|
||||
{ 0x1e1b, KEY_EPG },
|
||||
{ 0x1e1c, KEY_TV },
|
||||
{ 0x1e1e, KEY_NEXT },
|
||||
|
|
|
@ -53,27 +53,36 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
|
|||
u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
u8 r;
|
||||
u8 u8buf[len];
|
||||
|
||||
u8 tmp;
|
||||
u8 *buf;
|
||||
unsigned int pipe = (flags == OPERA_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == OPERA_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret =
|
||||
usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, 0x0, u8buf, len, 2000);
|
||||
memcpy(buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request,
|
||||
request_type | USB_TYPE_VENDOR, value, 0x0,
|
||||
buf, len, 2000);
|
||||
|
||||
if (request == OPERA_TUNER_REQ) {
|
||||
tmp = buf[0];
|
||||
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0x01, 0x0, &r, 1, 2000)<1 || r!=0x08)
|
||||
return 0;
|
||||
OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
buf[0] = tmp;
|
||||
}
|
||||
if (flags == OPERA_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
memcpy(data, buf, len);
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -189,7 +198,7 @@ static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
|
|||
static u8 opera1_inittab[] = {
|
||||
0x00, 0xa1,
|
||||
0x01, 0x15,
|
||||
0x02, 0x00,
|
||||
0x02, 0x30,
|
||||
0x03, 0x00,
|
||||
0x04, 0x7d,
|
||||
0x05, 0x05,
|
||||
|
|
|
@ -41,14 +41,23 @@ struct vp702x_fe_state {
|
|||
|
||||
static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
|
||||
{
|
||||
u8 buf[10];
|
||||
if (time_after(jiffies,st->next_status_check)) {
|
||||
vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
|
||||
struct vp702x_device_state *dst = st->d->priv;
|
||||
u8 *buf;
|
||||
|
||||
if (time_after(jiffies, st->next_status_check)) {
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
buf = dst->buf;
|
||||
|
||||
vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
|
||||
st->lock = buf[4];
|
||||
vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
|
||||
vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
|
||||
|
||||
vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
|
||||
st->snr = buf[0];
|
||||
|
||||
vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
|
||||
st->sig = buf[0];
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
|
||||
}
|
||||
return 0;
|
||||
|
@ -130,11 +139,17 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
|
|||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
struct vp702x_device_state *dst = st->d->priv;
|
||||
u32 freq = fep->frequency/1000;
|
||||
/*CalFrequency*/
|
||||
/* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
|
||||
u64 sr;
|
||||
u8 cmd[8] = { 0 },ibuf[10];
|
||||
u8 *cmd;
|
||||
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
|
||||
cmd = dst->buf;
|
||||
memset(cmd, 0, 10);
|
||||
|
||||
cmd[0] = (freq >> 8) & 0x7f;
|
||||
cmd[1] = freq & 0xff;
|
||||
|
@ -170,13 +185,15 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
|
|||
st->status_check_interval = 250;
|
||||
st->next_status_check = jiffies;
|
||||
|
||||
vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
|
||||
vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
|
||||
|
||||
if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
if (cmd[2] == 0 && cmd[3] == 0)
|
||||
deb_fe("tuning failed.\n");
|
||||
else
|
||||
deb_fe("tuning succeeded.\n");
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -204,27 +221,32 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
|
|||
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
|
||||
struct dvb_diseqc_master_cmd *m)
|
||||
{
|
||||
u8 *cmd;
|
||||
struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
u8 cmd[8],ibuf[10];
|
||||
memset(cmd,0,8);
|
||||
struct vp702x_device_state *dst = st->d->priv;
|
||||
|
||||
deb_fe("%s\n",__func__);
|
||||
|
||||
if (m->msg_len > 4)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
|
||||
cmd = dst->buf;
|
||||
cmd[1] = SET_DISEQC_CMD;
|
||||
cmd[2] = m->msg_len;
|
||||
memcpy(&cmd[3], m->msg, m->msg_len);
|
||||
cmd[7] = vp702x_chksum(cmd,0,7);
|
||||
cmd[7] = vp702x_chksum(cmd, 0, 7);
|
||||
|
||||
vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
|
||||
vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
|
||||
|
||||
if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
if (cmd[2] == 0 && cmd[3] == 0)
|
||||
deb_fe("diseqc cmd failed.\n");
|
||||
else
|
||||
deb_fe("diseqc cmd succeeded.\n");
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -237,7 +259,9 @@ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd
|
|||
static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
{
|
||||
struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
u8 ibuf[10];
|
||||
struct vp702x_device_state *dst = st->d->priv;
|
||||
u8 *buf;
|
||||
|
||||
deb_fe("%s\n",__func__);
|
||||
|
||||
st->tone_mode = tone;
|
||||
|
@ -247,14 +271,21 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
|||
else
|
||||
st->lnb_buf[2] = 0x00;
|
||||
|
||||
st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
|
||||
st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
|
||||
|
||||
vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
|
||||
if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
|
||||
buf = dst->buf;
|
||||
memcpy(buf, st->lnb_buf, 8);
|
||||
|
||||
vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
|
||||
if (buf[2] == 0 && buf[3] == 0)
|
||||
deb_fe("set_tone cmd failed.\n");
|
||||
else
|
||||
deb_fe("set_tone cmd succeeded.\n");
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -262,7 +293,8 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
|
|||
voltage)
|
||||
{
|
||||
struct vp702x_fe_state *st = fe->demodulator_priv;
|
||||
u8 ibuf[10];
|
||||
struct vp702x_device_state *dst = st->d->priv;
|
||||
u8 *buf;
|
||||
deb_fe("%s\n",__func__);
|
||||
|
||||
st->voltage = voltage;
|
||||
|
@ -272,14 +304,20 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
|
|||
else
|
||||
st->lnb_buf[4] = 0x00;
|
||||
|
||||
st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
|
||||
st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
|
||||
|
||||
vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
|
||||
if (ibuf[2] == 0 && ibuf[3] == 0)
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
|
||||
buf = dst->buf;
|
||||
memcpy(buf, st->lnb_buf, 8);
|
||||
|
||||
vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
|
||||
if (buf[2] == 0 && buf[3] == 0)
|
||||
deb_fe("set_voltage cmd failed.\n");
|
||||
else
|
||||
deb_fe("set_voltage cmd succeeded.\n");
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#include "vp702x.h"
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/* debug */
|
||||
int dvb_usb_vp702x_debug;
|
||||
|
@ -23,27 +24,23 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
|
|||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
struct vp702x_state {
|
||||
struct vp702x_adapter_state {
|
||||
int pid_filter_count;
|
||||
int pid_filter_can_bypass;
|
||||
u8 pid_filter_state;
|
||||
};
|
||||
|
||||
struct vp702x_device_state {
|
||||
u8 power_state;
|
||||
};
|
||||
|
||||
/* check for mutex FIXME */
|
||||
int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
|
||||
static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
|
||||
u16 value, u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev,0),
|
||||
req,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
value,index,b,blen,
|
||||
2000);
|
||||
ret = usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev, 0),
|
||||
req,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
value, index, b, blen,
|
||||
2000);
|
||||
|
||||
if (ret < 0) {
|
||||
warn("usb in operation failed. (%d)", ret);
|
||||
|
@ -58,8 +55,20 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen)
|
||||
int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&d->usb_mutex);
|
||||
ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret;
|
||||
deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
|
||||
|
@ -77,6 +86,18 @@ static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&d->usb_mutex);
|
||||
ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
|
||||
{
|
||||
int ret;
|
||||
|
@ -84,50 +105,93 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il
|
|||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen);
|
||||
ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen);
|
||||
msleep(msec);
|
||||
ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
|
||||
ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen);
|
||||
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
|
||||
int olen, u8 *i, int ilen, int msec)
|
||||
{
|
||||
u8 bout[olen+2];
|
||||
u8 bin[ilen+1];
|
||||
struct vp702x_device_state *st = d->priv;
|
||||
int ret = 0;
|
||||
u8 *buf;
|
||||
int buflen = max(olen + 2, ilen + 1);
|
||||
|
||||
bout[0] = 0x00;
|
||||
bout[1] = cmd;
|
||||
memcpy(&bout[2],o,olen);
|
||||
ret = mutex_lock_interruptible(&st->buf_mutex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
|
||||
if (buflen > st->buf_len) {
|
||||
buf = kmalloc(buflen, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info("successfully reallocated a bigger buffer");
|
||||
kfree(st->buf);
|
||||
st->buf = buf;
|
||||
st->buf_len = buflen;
|
||||
} else {
|
||||
buf = st->buf;
|
||||
}
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = cmd;
|
||||
memcpy(&buf[2], o, olen);
|
||||
|
||||
ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec);
|
||||
|
||||
if (ret == 0)
|
||||
memcpy(i,&bin[1],ilen);
|
||||
memcpy(i, &buf[1], ilen);
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
|
||||
{
|
||||
u8 buf[16] = { 0 };
|
||||
return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16);
|
||||
int ret;
|
||||
struct vp702x_device_state *st = adap->dev->priv;
|
||||
u8 *buf;
|
||||
|
||||
mutex_lock(&st->buf_mutex);
|
||||
|
||||
buf = st->buf;
|
||||
memset(buf, 0, 16);
|
||||
|
||||
ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e,
|
||||
0, buf, 16);
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
|
||||
{
|
||||
u8 buf[16] = { 0 };
|
||||
return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16);
|
||||
int ret;
|
||||
struct vp702x_device_state *st = adap->dev->priv;
|
||||
u8 *buf;
|
||||
|
||||
mutex_lock(&st->buf_mutex);
|
||||
|
||||
buf = st->buf;
|
||||
memset(buf, 0, 16);
|
||||
ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f,
|
||||
0, buf, 16);
|
||||
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
|
||||
{
|
||||
struct vp702x_state *st = adap->priv;
|
||||
u8 buf[16] = { 0 };
|
||||
struct vp702x_adapter_state *st = adap->priv;
|
||||
struct vp702x_device_state *dst = adap->dev->priv;
|
||||
u8 *buf;
|
||||
|
||||
if (onoff)
|
||||
st->pid_filter_state |= (1 << id);
|
||||
|
@ -139,32 +203,45 @@ static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onof
|
|||
id = 0x10 + id*2;
|
||||
|
||||
vp702x_set_pld_state(adap, st->pid_filter_state);
|
||||
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
|
||||
buf = dst->buf;
|
||||
memset(buf, 0, 16);
|
||||
vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
|
||||
vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16);
|
||||
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct vp702x_state *st = adap->priv;
|
||||
struct vp702x_adapter_state *st = adap->priv;
|
||||
struct vp702x_device_state *dst = adap->dev->priv;
|
||||
int i;
|
||||
u8 b[10] = { 0 };
|
||||
u8 *b;
|
||||
|
||||
st->pid_filter_count = 8;
|
||||
st->pid_filter_can_bypass = 1;
|
||||
st->pid_filter_state = 0x00;
|
||||
|
||||
vp702x_set_pld_mode(adap, 1); // bypass
|
||||
vp702x_set_pld_mode(adap, 1); /* bypass */
|
||||
|
||||
for (i = 0; i < st->pid_filter_count; i++)
|
||||
vp702x_set_pid(adap, 0xffff, i, 1);
|
||||
|
||||
mutex_lock(&dst->buf_mutex);
|
||||
b = dst->buf;
|
||||
memset(b, 0, 10);
|
||||
vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
|
||||
vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
|
||||
vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
|
||||
mutex_unlock(&dst->buf_mutex);
|
||||
/*vp702x_set_pld_mode(d, 0); // filter */
|
||||
|
||||
//vp702x_set_pld_mode(d, 0); // filter
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -182,18 +259,23 @@ static struct rc_map_table rc_map_vp702x_table[] = {
|
|||
/* remote control stuff (does not work with my box) */
|
||||
static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
u8 key[10];
|
||||
u8 *key;
|
||||
int i;
|
||||
|
||||
/* remove the following return to enabled remote querying */
|
||||
return 0;
|
||||
|
||||
key = kmalloc(10, GFP_KERNEL);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
|
||||
|
||||
deb_rc("remote query key: %x %d\n",key[1],key[1]);
|
||||
|
||||
if (key[1] == 0x44) {
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
kfree(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -203,15 +285,23 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = rc_map_vp702x_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
kfree(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
|
||||
{
|
||||
u8 i;
|
||||
u8 i, *buf;
|
||||
struct vp702x_device_state *st = d->priv;
|
||||
|
||||
mutex_lock(&st->buf_mutex);
|
||||
buf = st->buf;
|
||||
for (i = 6; i < 12; i++)
|
||||
vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1);
|
||||
vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
|
||||
|
||||
memcpy(mac, buf, 6);
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -221,7 +311,8 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
|
||||
|
||||
if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10))
|
||||
if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0,
|
||||
buf, 10, 10))
|
||||
return -EIO;
|
||||
|
||||
buf[9] = '\0';
|
||||
|
@ -240,8 +331,38 @@ static struct dvb_usb_device_properties vp702x_properties;
|
|||
static int vp702x_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return dvb_usb_device_init(intf, &vp702x_properties,
|
||||
THIS_MODULE, NULL, adapter_nr);
|
||||
struct dvb_usb_device *d;
|
||||
struct vp702x_device_state *st;
|
||||
int ret;
|
||||
|
||||
ret = dvb_usb_device_init(intf, &vp702x_properties,
|
||||
THIS_MODULE, &d, adapter_nr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
st = d->priv;
|
||||
st->buf_len = 16;
|
||||
st->buf = kmalloc(st->buf_len, GFP_KERNEL);
|
||||
if (!st->buf) {
|
||||
ret = -ENOMEM;
|
||||
dvb_usb_device_exit(intf);
|
||||
goto out;
|
||||
}
|
||||
mutex_init(&st->buf_mutex);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void vp702x_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
struct vp702x_device_state *st = d->priv;
|
||||
mutex_lock(&st->buf_mutex);
|
||||
kfree(st->buf);
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
dvb_usb_device_exit(intf);
|
||||
}
|
||||
|
||||
static struct usb_device_id vp702x_usb_table [] = {
|
||||
|
@ -278,7 +399,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct vp702x_state),
|
||||
.size_of_priv = sizeof(struct vp702x_adapter_state),
|
||||
}
|
||||
},
|
||||
.read_mac_address = vp702x_read_mac_addr,
|
||||
|
@ -307,9 +428,9 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver vp702x_usb_driver = {
|
||||
.name = "dvb_usb_vp702x",
|
||||
.probe = vp702x_usb_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = vp702x_usb_table,
|
||||
.probe = vp702x_usb_probe,
|
||||
.disconnect = vp702x_usb_disconnect,
|
||||
.id_table = vp702x_usb_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
|
|
|
@ -98,6 +98,13 @@ extern int dvb_usb_vp702x_debug;
|
|||
#define RESET_TUNER 0xBE
|
||||
/* IN i: 0, v: 0, no extra buffer */
|
||||
|
||||
struct vp702x_device_state {
|
||||
struct mutex buf_mutex;
|
||||
int buf_len;
|
||||
u8 *buf;
|
||||
};
|
||||
|
||||
|
||||
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
|
||||
|
||||
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
|
||||
|
|
|
@ -28,9 +28,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
|
||||
u8 *buf = d->priv;
|
||||
|
||||
outbuf[0] = cmd;
|
||||
buf[0] = cmd;
|
||||
|
||||
if (outlen > 19)
|
||||
outlen = 19;
|
||||
|
@ -38,19 +38,21 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
|
|||
if (inlen > 11)
|
||||
inlen = 11;
|
||||
|
||||
ret = mutex_lock_interruptible(&d->usb_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (out != NULL && outlen > 0)
|
||||
memcpy(&outbuf[1], out, outlen);
|
||||
memcpy(&buf[1], out, outlen);
|
||||
|
||||
deb_xfer("out buffer: ");
|
||||
debug_dump(outbuf,outlen+1,deb_xfer);
|
||||
debug_dump(buf, outlen+1, deb_xfer);
|
||||
|
||||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
if (usb_control_msg(d->udev,
|
||||
usb_sndctrlpipe(d->udev,0),
|
||||
TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
|
||||
outbuf, 20, 2000) != 20) {
|
||||
buf, 20, 2000) != 20) {
|
||||
err("USB control message 'out' went wrong.");
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
|
@ -61,17 +63,17 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
|
|||
if (usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev,0),
|
||||
TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
inbuf, 12, 2000) != 12) {
|
||||
buf, 12, 2000) != 12) {
|
||||
err("USB control message 'in' went wrong.");
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
deb_xfer("in buffer: ");
|
||||
debug_dump(inbuf,12,deb_xfer);
|
||||
debug_dump(buf, 12, deb_xfer);
|
||||
|
||||
if (in != NULL && inlen > 0)
|
||||
memcpy(in,&inbuf[1],inlen);
|
||||
memcpy(in, &buf[1], inlen);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
@ -222,8 +224,26 @@ static struct dvb_usb_device_properties vp7045_properties;
|
|||
static int vp7045_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return dvb_usb_device_init(intf, &vp7045_properties,
|
||||
THIS_MODULE, NULL, adapter_nr);
|
||||
struct dvb_usb_device *d;
|
||||
int ret = dvb_usb_device_init(intf, &vp7045_properties,
|
||||
THIS_MODULE, &d, adapter_nr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
d->priv = kmalloc(20, GFP_KERNEL);
|
||||
if (!d->priv) {
|
||||
dvb_usb_device_exit(intf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vp7045_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
kfree(d->priv);
|
||||
dvb_usb_device_exit(intf);
|
||||
}
|
||||
|
||||
static struct usb_device_id vp7045_usb_table [] = {
|
||||
|
@ -238,6 +258,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
|
|||
static struct dvb_usb_device_properties vp7045_properties = {
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-vp7045-01.fw",
|
||||
.size_of_priv = sizeof(u8 *),
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -284,7 +305,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
|||
static struct usb_driver vp7045_usb_driver = {
|
||||
.name = "dvb_usb_vp7045",
|
||||
.probe = vp7045_usb_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.disconnect = vp7045_usb_disconnect,
|
||||
.id_table = vp7045_usb_table,
|
||||
};
|
||||
|
||||
|
|
|
@ -263,18 +263,16 @@ config DVB_S5H1432
|
|||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DRX397XD
|
||||
tristate "Micronas DRX3975D/DRX3977D based"
|
||||
config DVB_DRXD
|
||||
tristate "Micronas DRXD driver"
|
||||
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.
|
||||
|
||||
TODO:
|
||||
This driver needs external firmware. Please use the command
|
||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
|
||||
download/extract them, and then copy them to /usr/lib/hotplug/firmware
|
||||
or /lib/firmware (depending on configuration of firmware hotplug).
|
||||
Note: this driver was based on vendor driver reference code (released
|
||||
under the GPL) as opposed to the existing drx397xd driver, which
|
||||
was written via reverse engineering.
|
||||
|
||||
config DVB_L64781
|
||||
tristate "LSI L64781"
|
||||
|
@ -385,6 +383,13 @@ config DVB_STV0367
|
|||
help
|
||||
A DVB-T/C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CXD2820R
|
||||
tristate "Sony CXD2820R"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
|||
stb0899-objs = stb0899_drv.o stb0899_algo.o
|
||||
stv0900-objs = stv0900_core.o stv0900_sw.o
|
||||
au8522-objs = au8522_dig.o au8522_decoder.o
|
||||
drxd-objs = drxd_firm.o drxd_hard.o
|
||||
cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
|
||||
|
||||
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
|
||||
obj-$(CONFIG_DVB_STV0299) += stv0299.o
|
||||
|
@ -36,7 +38,7 @@ obj-$(CONFIG_DVB_ZL10036) += zl10036.o
|
|||
obj-$(CONFIG_DVB_ZL10039) += zl10039.o
|
||||
obj-$(CONFIG_DVB_ZL10353) += zl10353.o
|
||||
obj-$(CONFIG_DVB_CX22702) += cx22702.o
|
||||
obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
|
||||
obj-$(CONFIG_DVB_DRXD) += drxd.o
|
||||
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
|
||||
obj-$(CONFIG_DVB_TDA10023) += tda10023.o
|
||||
obj-$(CONFIG_DVB_STV0297) += stv0297.o
|
||||
|
@ -85,3 +87,5 @@ obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
|
|||
obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
|
||||
obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
|
||||
obj-$(CONFIG_DVB_STV0367) += stv0367.o
|
||||
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* bsbe1-d01a.h - ALPS BSBE1-D01A tuner support
|
||||
*
|
||||
* Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*
|
||||
* the project's page is at http://www.linuxtv.org
|
||||
*/
|
||||
|
||||
#ifndef BSBE1_D01A_H
|
||||
#define BSBE1_D01A_H
|
||||
|
||||
#include "stb6000.h"
|
||||
#include "stv0288.h"
|
||||
|
||||
static u8 stv0288_bsbe1_d01a_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x20,
|
||||
0x09, 0x0,
|
||||
0x0a, 0x4,
|
||||
0x0b, 0x0,
|
||||
0x0c, 0x0,
|
||||
0x0d, 0x0,
|
||||
0x0e, 0xd4,
|
||||
0x0f, 0x30,
|
||||
0x11, 0x80,
|
||||
0x12, 0x03,
|
||||
0x13, 0x48,
|
||||
0x14, 0x84,
|
||||
0x15, 0x45,
|
||||
0x16, 0xb7,
|
||||
0x17, 0x9c,
|
||||
0x18, 0x0,
|
||||
0x19, 0xa6,
|
||||
0x1a, 0x88,
|
||||
0x1b, 0x8f,
|
||||
0x1c, 0xf0,
|
||||
0x20, 0x0b,
|
||||
0x21, 0x54,
|
||||
0x22, 0x0,
|
||||
0x23, 0x0,
|
||||
0x2b, 0xff,
|
||||
0x2c, 0xf7,
|
||||
0x30, 0x0,
|
||||
0x31, 0x1e,
|
||||
0x32, 0x14,
|
||||
0x33, 0x0f,
|
||||
0x34, 0x09,
|
||||
0x35, 0x0c,
|
||||
0x36, 0x05,
|
||||
0x37, 0x2f,
|
||||
0x38, 0x16,
|
||||
0x39, 0xbd,
|
||||
0x3a, 0x03,
|
||||
0x3b, 0x13,
|
||||
0x3c, 0x11,
|
||||
0x3d, 0x30,
|
||||
0x40, 0x63,
|
||||
0x41, 0x04,
|
||||
0x42, 0x60,
|
||||
0x43, 0x00,
|
||||
0x44, 0x00,
|
||||
0x45, 0x00,
|
||||
0x46, 0x00,
|
||||
0x47, 0x00,
|
||||
0x4a, 0x00,
|
||||
0x50, 0x10,
|
||||
0x51, 0x36,
|
||||
0x52, 0x09,
|
||||
0x53, 0x94,
|
||||
0x54, 0x62,
|
||||
0x55, 0x29,
|
||||
0x56, 0x64,
|
||||
0x57, 0x2b,
|
||||
0x58, 0x54,
|
||||
0x59, 0x86,
|
||||
0x5a, 0x0,
|
||||
0x5b, 0x9b,
|
||||
0x5c, 0x08,
|
||||
0x5d, 0x7f,
|
||||
0x5e, 0x0,
|
||||
0x5f, 0xff,
|
||||
0x70, 0x0,
|
||||
0x71, 0x0,
|
||||
0x72, 0x0,
|
||||
0x74, 0x0,
|
||||
0x75, 0x0,
|
||||
0x76, 0x0,
|
||||
0x81, 0x0,
|
||||
0x82, 0x3f,
|
||||
0x83, 0x3f,
|
||||
0x84, 0x0,
|
||||
0x85, 0x0,
|
||||
0x88, 0x0,
|
||||
0x89, 0x0,
|
||||
0x8a, 0x0,
|
||||
0x8b, 0x0,
|
||||
0x8c, 0x0,
|
||||
0x90, 0x0,
|
||||
0x91, 0x0,
|
||||
0x92, 0x0,
|
||||
0x93, 0x0,
|
||||
0x94, 0x1c,
|
||||
0x97, 0x0,
|
||||
0xa0, 0x48,
|
||||
0xa1, 0x0,
|
||||
0xb0, 0xb8,
|
||||
0xb1, 0x3a,
|
||||
0xb2, 0x10,
|
||||
0xb3, 0x82,
|
||||
0xb4, 0x80,
|
||||
0xb5, 0x82,
|
||||
0xb6, 0x82,
|
||||
0xb7, 0x82,
|
||||
0xb8, 0x20,
|
||||
0xb9, 0x0,
|
||||
0xf0, 0x0,
|
||||
0xf1, 0x0,
|
||||
0xf2, 0xc0,
|
||||
0xff, 0xff,
|
||||
};
|
||||
|
||||
static struct stv0288_config stv0288_bsbe1_d01a_config = {
|
||||
.demod_address = 0x68,
|
||||
.min_delay_ms = 100,
|
||||
.inittab = stv0288_bsbe1_d01a_inittab,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static u8 alps_bsru6_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x00,
|
||||
0x02, 0x30,
|
||||
0x03, 0x00,
|
||||
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
|
||||
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
|
||||
|
|
|
@ -137,7 +137,7 @@ MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
|
|||
/* SNR measurements */
|
||||
static int esno_snr;
|
||||
module_param(esno_snr, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
|
||||
MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
|
||||
"1=ESNO(db * 10) (default:0)");
|
||||
|
||||
enum cmds {
|
||||
|
@ -566,7 +566,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
|
|||
{
|
||||
struct cx24116_state *state = fe->demodulator_priv;
|
||||
struct cx24116_cmd cmd;
|
||||
int i, ret;
|
||||
int i, ret, len, max, remaining;
|
||||
unsigned char vers[4];
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
@ -603,8 +603,21 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
|
|||
cx24116_writereg(state, 0xF5, 0x00);
|
||||
cx24116_writereg(state, 0xF6, 0x00);
|
||||
|
||||
/* write the entire firmware as one transaction */
|
||||
cx24116_writeregN(state, 0xF7, fw->data, fw->size);
|
||||
/* Split firmware to the max I2C write len and write.
|
||||
* Writes whole firmware as one write when i2c_wr_max is set to 0. */
|
||||
if (state->config->i2c_wr_max)
|
||||
max = state->config->i2c_wr_max;
|
||||
else
|
||||
max = INT_MAX; /* enough for 32k firmware */
|
||||
|
||||
for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
|
||||
len = remaining;
|
||||
if (len > max - 1)
|
||||
len = max - 1;
|
||||
|
||||
cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
|
||||
len);
|
||||
}
|
||||
|
||||
cx24116_writereg(state, 0xF4, 0x10);
|
||||
cx24116_writereg(state, 0xF0, 0x00);
|
||||
|
|
|
@ -35,6 +35,9 @@ struct cx24116_config {
|
|||
|
||||
/* Need to set MPEG parameters */
|
||||
u8 mpg_clk_pos_pol:0x02;
|
||||
|
||||
/* max bytes I2C provider can write at once */
|
||||
u16 i2c_wr_max;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CX24116) || \
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CXD2820R_H
|
||||
#define CXD2820R_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
#define CXD2820R_GPIO_D (0 << 0) /* disable */
|
||||
#define CXD2820R_GPIO_E (1 << 0) /* enable */
|
||||
#define CXD2820R_GPIO_O (0 << 1) /* output */
|
||||
#define CXD2820R_GPIO_I (1 << 1) /* input */
|
||||
#define CXD2820R_GPIO_L (0 << 2) /* output low */
|
||||
#define CXD2820R_GPIO_H (1 << 2) /* output high */
|
||||
|
||||
#define CXD2820R_TS_SERIAL 0x08
|
||||
#define CXD2820R_TS_SERIAL_MSB 0x28
|
||||
#define CXD2820R_TS_PARALLEL 0x30
|
||||
#define CXD2820R_TS_PARALLEL_MSB 0x70
|
||||
|
||||
struct cxd2820r_config {
|
||||
/* Demodulator I2C address.
|
||||
* Driver determines DVB-C slave I2C address automatically from master
|
||||
* address.
|
||||
* Default: none, must set
|
||||
* Values: 0x6c, 0x6d
|
||||
*/
|
||||
u8 i2c_address;
|
||||
|
||||
/* TS output mode.
|
||||
* Default: none, must set.
|
||||
* Values:
|
||||
*/
|
||||
u8 ts_mode;
|
||||
|
||||
/* IF AGC polarity.
|
||||
* Default: 0
|
||||
* Values: 0, 1
|
||||
*/
|
||||
int if_agc_polarity:1;
|
||||
|
||||
/* Spectrum inversion.
|
||||
* Default: 0
|
||||
* Values: 0, 1
|
||||
*/
|
||||
int spec_inv:1;
|
||||
|
||||
/* IFs for all used modes.
|
||||
* Default: none, must set
|
||||
* Values: <kHz>
|
||||
*/
|
||||
u16 if_dvbt_6;
|
||||
u16 if_dvbt_7;
|
||||
u16 if_dvbt_8;
|
||||
u16 if_dvbt2_5;
|
||||
u16 if_dvbt2_6;
|
||||
u16 if_dvbt2_7;
|
||||
u16 if_dvbt2_8;
|
||||
u16 if_dvbc;
|
||||
|
||||
/* GPIOs for all used modes.
|
||||
* Default: none, disabled
|
||||
* Values: <see above>
|
||||
*/
|
||||
u8 gpio_dvbt[3];
|
||||
u8 gpio_dvbt2[3];
|
||||
u8 gpio_dvbc[3];
|
||||
};
|
||||
|
||||
|
||||
#if defined(CONFIG_DVB_CXD2820R) || \
|
||||
(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *cxd2820r_attach(
|
||||
const struct cxd2820r_config *config,
|
||||
struct i2c_adapter *i2c,
|
||||
struct dvb_frontend *fe
|
||||
);
|
||||
extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
|
||||
struct dvb_frontend *fe
|
||||
);
|
||||
#else
|
||||
static inline struct dvb_frontend *cxd2820r_attach(
|
||||
const struct cxd2820r_config *config,
|
||||
struct i2c_adapter *i2c,
|
||||
struct dvb_frontend *fe
|
||||
)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
|
||||
struct dvb_frontend *fe
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CXD2820R_H */
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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 "cxd2820r_priv.h"
|
||||
|
||||
int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i;
|
||||
u8 buf[2];
|
||||
u16 if_ctl;
|
||||
u64 num;
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x00080, 0x01, 0xff },
|
||||
{ 0x00081, 0x05, 0xff },
|
||||
{ 0x00085, 0x07, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
|
||||
{ 0x00082, 0x20, 0x60 },
|
||||
{ 0x1016a, 0x48, 0xff },
|
||||
{ 0x100a5, 0x00, 0x01 },
|
||||
{ 0x10020, 0x06, 0x07 },
|
||||
{ 0x10059, 0x50, 0xff },
|
||||
{ 0x10087, 0x0c, 0x3c },
|
||||
{ 0x1008b, 0x07, 0xff },
|
||||
{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
|
||||
{ 0x10070, priv->cfg.ts_mode, 0xff },
|
||||
};
|
||||
|
||||
dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
|
||||
|
||||
/* update GPIOs */
|
||||
ret = cxd2820r_gpio(fe);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
if (priv->delivery_system != SYS_DVBC_ANNEX_AC) {
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
|
||||
tab[i].val, tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_DVBC_ANNEX_AC;
|
||||
priv->ber_running = 0; /* tune stops BER counter */
|
||||
|
||||
num = priv->cfg.if_dvbc;
|
||||
num *= 0x4000;
|
||||
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
|
||||
buf[0] = (if_ctl >> 8) & 0x3f;
|
||||
buf[1] = (if_ctl >> 0) & 0xff;
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 0) & 0x03) {
|
||||
case 0:
|
||||
c->modulation = QAM_16;
|
||||
break;
|
||||
case 1:
|
||||
c->modulation = QAM_32;
|
||||
break;
|
||||
case 2:
|
||||
c->modulation = QAM_64;
|
||||
break;
|
||||
case 3:
|
||||
c->modulation = QAM_128;
|
||||
break;
|
||||
case 4:
|
||||
c->modulation = QAM_256;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[0] >> 7) & 0x01) {
|
||||
case 0:
|
||||
c->inversion = INVERSION_OFF;
|
||||
break;
|
||||
case 1:
|
||||
c->inversion = INVERSION_ON;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[3], start_ber = 0;
|
||||
*ber = 0;
|
||||
|
||||
if (priv->ber_running) {
|
||||
ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
|
||||
*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
|
||||
start_ber = 1;
|
||||
}
|
||||
} else {
|
||||
priv->ber_running = 1;
|
||||
start_ber = 1;
|
||||
}
|
||||
|
||||
if (start_ber) {
|
||||
/* (re)start BER */
|
||||
ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
|
||||
u16 *strength)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
u16 tmp;
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
tmp = (buf[0] & 0x03) << 8 | buf[1];
|
||||
tmp = (~tmp & 0x03ff);
|
||||
|
||||
if (tmp == 512)
|
||||
/* ~no signal */
|
||||
tmp = 0;
|
||||
else if (tmp > 350)
|
||||
tmp = 350;
|
||||
|
||||
/* scale value to 0x0000-0xffff */
|
||||
*strength = tmp * 0xffff / (350-0);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 tmp;
|
||||
unsigned int A, B;
|
||||
/* report SNR in dB * 10 */
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (((tmp >> 0) & 0x03) % 2) {
|
||||
A = 875;
|
||||
B = 650;
|
||||
} else {
|
||||
A = 950;
|
||||
B = 760;
|
||||
}
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
#define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
|
||||
if (tmp)
|
||||
*snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
|
||||
/ 10;
|
||||
else
|
||||
*snr = 0;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
*ucblocks = 0;
|
||||
/* no way to read ? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
*status = 0;
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (((buf[0] >> 0) & 0x01) == 1) {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC;
|
||||
|
||||
if (((buf[1] >> 3) & 0x01) == 1) {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_init_c(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_sleep_c(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x000ff, 0x1f, 0xff },
|
||||
{ 0x00085, 0x00, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
{ 0x00081, 0x00, 0xff },
|
||||
{ 0x00080, 0x00, 0xff },
|
||||
};
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
|
||||
tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s)
|
||||
{
|
||||
s->min_delay_ms = 500;
|
||||
s->step_size = 0; /* no zigzag */
|
||||
s->max_drift = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,915 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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 "cxd2820r_priv.h"
|
||||
|
||||
int cxd2820r_debug;
|
||||
module_param_named(debug, cxd2820r_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||
|
||||
/* write multiple registers */
|
||||
static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
|
||||
u8 *val, int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[len+1];
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = i2c,
|
||||
.flags = 0,
|
||||
.len = sizeof(buf),
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
buf[0] = reg;
|
||||
memcpy(&buf[1], val, len);
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 1);
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read multiple registers */
|
||||
static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
|
||||
u8 *val, int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[len];
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = i2c,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = ®,
|
||||
}, {
|
||||
.addr = i2c,
|
||||
.flags = I2C_M_RD,
|
||||
.len = sizeof(buf),
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||
if (ret == 2) {
|
||||
memcpy(val, buf, len);
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write multiple registers */
|
||||
int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
u8 i2c_addr;
|
||||
u8 reg = (reginfo >> 0) & 0xff;
|
||||
u8 bank = (reginfo >> 8) & 0xff;
|
||||
u8 i2c = (reginfo >> 16) & 0x01;
|
||||
|
||||
/* select I2C */
|
||||
if (i2c)
|
||||
i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
|
||||
else
|
||||
i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
|
||||
|
||||
/* switch bank if needed */
|
||||
if (bank != priv->bank[i2c]) {
|
||||
ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->bank[i2c] = bank;
|
||||
}
|
||||
return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);
|
||||
}
|
||||
|
||||
/* read multiple registers */
|
||||
int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
u8 i2c_addr;
|
||||
u8 reg = (reginfo >> 0) & 0xff;
|
||||
u8 bank = (reginfo >> 8) & 0xff;
|
||||
u8 i2c = (reginfo >> 16) & 0x01;
|
||||
|
||||
/* select I2C */
|
||||
if (i2c)
|
||||
i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
|
||||
else
|
||||
i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
|
||||
|
||||
/* switch bank if needed */
|
||||
if (bank != priv->bank[i2c]) {
|
||||
ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
priv->bank[i2c] = bank;
|
||||
}
|
||||
return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);
|
||||
}
|
||||
|
||||
/* write single register */
|
||||
int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)
|
||||
{
|
||||
return cxd2820r_wr_regs(priv, reg, &val, 1);
|
||||
}
|
||||
|
||||
/* read single register */
|
||||
int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)
|
||||
{
|
||||
return cxd2820r_rd_regs(priv, reg, val, 1);
|
||||
}
|
||||
|
||||
/* write single register with mask */
|
||||
int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
|
||||
u8 mask)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
/* no need for read if whole reg is written */
|
||||
if (mask != 0xff) {
|
||||
ret = cxd2820r_rd_reg(priv, reg, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= mask;
|
||||
tmp &= ~mask;
|
||||
val |= tmp;
|
||||
}
|
||||
|
||||
return cxd2820r_wr_reg(priv, reg, val);
|
||||
}
|
||||
|
||||
int cxd2820r_gpio(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
u8 *gpio, tmp0, tmp1;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
gpio = priv->cfg.gpio_dvbt;
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
gpio = priv->cfg.gpio_dvbt2;
|
||||
break;
|
||||
case SYS_DVBC_ANNEX_AC:
|
||||
gpio = priv->cfg.gpio_dvbc;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* update GPIOs only when needed */
|
||||
if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
|
||||
return 0;
|
||||
|
||||
tmp0 = 0x00;
|
||||
tmp1 = 0x00;
|
||||
for (i = 0; i < sizeof(priv->gpio); i++) {
|
||||
/* enable / disable */
|
||||
if (gpio[i] & CXD2820R_GPIO_E)
|
||||
tmp0 |= (2 << 6) >> (2 * i);
|
||||
else
|
||||
tmp0 |= (1 << 6) >> (2 * i);
|
||||
|
||||
/* input / output */
|
||||
if (gpio[i] & CXD2820R_GPIO_I)
|
||||
tmp1 |= (1 << (3 + i));
|
||||
else
|
||||
tmp1 |= (0 << (3 + i));
|
||||
|
||||
/* high / low */
|
||||
if (gpio[i] & CXD2820R_GPIO_H)
|
||||
tmp1 |= (1 << (0 + i));
|
||||
else
|
||||
tmp1 |= (0 << (0 + i));
|
||||
|
||||
dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
|
||||
}
|
||||
|
||||
dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
|
||||
|
||||
/* write bits [7:2] */
|
||||
ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* write bits [5:0] */
|
||||
ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
memcpy(priv->gpio, gpio, sizeof(priv->gpio));
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* lock FE */
|
||||
static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)
|
||||
{
|
||||
int ret = 0;
|
||||
dbg("%s: active_fe=%d", __func__, active_fe);
|
||||
|
||||
mutex_lock(&priv->fe_lock);
|
||||
|
||||
/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
|
||||
if (priv->active_fe == active_fe)
|
||||
;
|
||||
else if (priv->active_fe == -1)
|
||||
priv->active_fe = active_fe;
|
||||
else
|
||||
ret = -EBUSY;
|
||||
|
||||
mutex_unlock(&priv->fe_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* unlock FE */
|
||||
static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)
|
||||
{
|
||||
dbg("%s: active_fe=%d", __func__, active_fe);
|
||||
|
||||
mutex_lock(&priv->fe_lock);
|
||||
|
||||
/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
|
||||
if (priv->active_fe == active_fe)
|
||||
priv->active_fe = -1;
|
||||
|
||||
mutex_unlock(&priv->fe_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
|
||||
u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
|
||||
{
|
||||
return div_u64(dividend + (divisor / 2), divisor);
|
||||
}
|
||||
|
||||
static int cxd2820r_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (priv->delivery_system) {
|
||||
case SYS_UNDEFINED:
|
||||
if (c->delivery_system == SYS_DVBT) {
|
||||
/* SLEEP => DVB-T */
|
||||
ret = cxd2820r_set_frontend_t(fe, p);
|
||||
} else {
|
||||
/* SLEEP => DVB-T2 */
|
||||
ret = cxd2820r_set_frontend_t2(fe, p);
|
||||
}
|
||||
break;
|
||||
case SYS_DVBT:
|
||||
if (c->delivery_system == SYS_DVBT) {
|
||||
/* DVB-T => DVB-T */
|
||||
ret = cxd2820r_set_frontend_t(fe, p);
|
||||
} else if (c->delivery_system == SYS_DVBT2) {
|
||||
/* DVB-T => DVB-T2 */
|
||||
ret = cxd2820r_sleep_t(fe);
|
||||
ret = cxd2820r_set_frontend_t2(fe, p);
|
||||
}
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
if (c->delivery_system == SYS_DVBT2) {
|
||||
/* DVB-T2 => DVB-T2 */
|
||||
ret = cxd2820r_set_frontend_t2(fe, p);
|
||||
} else if (c->delivery_system == SYS_DVBT) {
|
||||
/* DVB-T2 => DVB-T */
|
||||
ret = cxd2820r_sleep_t2(fe);
|
||||
ret = cxd2820r_set_frontend_t(fe, p);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dbg("%s: error state=%d", __func__,
|
||||
priv->delivery_system);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_set_frontend_c(fe, p);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_read_status_t(fe, status);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_read_status_t2(fe, status);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_read_status_c(fe, status);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_get_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_get_frontend_t(fe, p);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_get_frontend_t2(fe, p);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_get_frontend_c(fe, p);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_read_ber_t(fe, ber);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_read_ber_t2(fe, ber);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_read_ber_c(fe, ber);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_read_signal_strength_t(fe, strength);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_read_signal_strength_t2(fe, strength);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_read_signal_strength_c(fe, strength);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_read_snr_t(fe, snr);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_read_snr_t2(fe, snr);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_read_snr_c(fe, snr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
/* delivery system is unknown at that (init) phase */
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_init_t(fe);
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_init_c(fe);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_sleep_t(fe);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_sleep_t2(fe);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
cxd2820r_unlock(priv, 0);
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_sleep_c(fe);
|
||||
|
||||
cxd2820r_unlock(priv, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
/* DVB-T/T2 */
|
||||
ret = cxd2820r_lock(priv, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fe->dtv_property_cache.delivery_system) {
|
||||
case SYS_DVBT:
|
||||
ret = cxd2820r_get_tune_settings_t(fe, s);
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
ret = cxd2820r_get_tune_settings_t2(fe, s);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* DVB-C */
|
||||
ret = cxd2820r_lock(priv, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cxd2820r_get_tune_settings_c(fe, s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i;
|
||||
fe_status_t status = 0;
|
||||
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
|
||||
|
||||
/* switch between DVB-T and DVB-T2 when tune fails */
|
||||
if (priv->last_tune_failed) {
|
||||
if (priv->delivery_system == SYS_DVBT)
|
||||
c->delivery_system = SYS_DVBT2;
|
||||
else
|
||||
c->delivery_system = SYS_DVBT;
|
||||
}
|
||||
|
||||
/* set frontend */
|
||||
ret = cxd2820r_set_frontend(fe, p);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
||||
/* frontend lock wait loop count */
|
||||
switch (priv->delivery_system) {
|
||||
case SYS_DVBT:
|
||||
i = 20;
|
||||
break;
|
||||
case SYS_DVBT2:
|
||||
i = 40;
|
||||
break;
|
||||
case SYS_UNDEFINED:
|
||||
default:
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait frontend lock */
|
||||
for (; i > 0; i--) {
|
||||
dbg("%s: LOOP=%d", __func__, i);
|
||||
msleep(50);
|
||||
ret = cxd2820r_read_status(fe, &status);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (status & FE_HAS_SIGNAL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if we have a valid signal */
|
||||
if (status) {
|
||||
priv->last_tune_failed = 0;
|
||||
return DVBFE_ALGO_SEARCH_SUCCESS;
|
||||
} else {
|
||||
priv->last_tune_failed = 1;
|
||||
return DVBFE_ALGO_SEARCH_AGAIN;
|
||||
}
|
||||
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return DVBFE_ALGO_SEARCH_ERROR;
|
||||
}
|
||||
|
||||
static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return DVBFE_ALGO_CUSTOM;
|
||||
}
|
||||
|
||||
static void cxd2820r_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
dbg("%s", __func__);
|
||||
|
||||
if (fe->ops.info.type == FE_OFDM) {
|
||||
i2c_del_adapter(&priv->tuner_i2c_adapter);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
|
||||
u8 obuf[msg[0].len + 2];
|
||||
struct i2c_msg msg2[2] = {
|
||||
{
|
||||
.addr = priv->cfg.i2c_address,
|
||||
.flags = 0,
|
||||
.len = sizeof(obuf),
|
||||
.buf = obuf,
|
||||
}, {
|
||||
.addr = priv->cfg.i2c_address,
|
||||
.flags = I2C_M_RD,
|
||||
.len = msg[1].len,
|
||||
.buf = msg[1].buf,
|
||||
}
|
||||
};
|
||||
|
||||
obuf[0] = 0x09;
|
||||
obuf[1] = (msg[0].addr << 1);
|
||||
if (num == 2) { /* I2C read */
|
||||
obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
|
||||
msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */
|
||||
}
|
||||
memcpy(&obuf[2], msg[0].buf, msg[0].len);
|
||||
|
||||
return i2c_transfer(priv->i2c, msg2, num);
|
||||
}
|
||||
|
||||
static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
|
||||
.master_xfer = cxd2820r_tuner_i2c_xfer,
|
||||
.functionality = cxd2820r_tuner_i2c_func,
|
||||
};
|
||||
|
||||
struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
return &priv->tuner_i2c_adapter;
|
||||
}
|
||||
EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
|
||||
|
||||
static struct dvb_frontend_ops cxd2820r_ops[2];
|
||||
|
||||
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
|
||||
struct i2c_adapter *i2c, struct dvb_frontend *fe)
|
||||
{
|
||||
int ret;
|
||||
struct cxd2820r_priv *priv = NULL;
|
||||
u8 tmp;
|
||||
|
||||
if (fe == NULL) {
|
||||
/* FE0 */
|
||||
/* allocate memory for the internal priv */
|
||||
priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
goto error;
|
||||
|
||||
/* setup the priv */
|
||||
priv->i2c = i2c;
|
||||
memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
|
||||
mutex_init(&priv->fe_lock);
|
||||
|
||||
priv->active_fe = -1; /* NONE */
|
||||
|
||||
/* check if the demod is there */
|
||||
priv->bank[0] = priv->bank[1] = 0xff;
|
||||
ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
|
||||
dbg("%s: chip id=%02x", __func__, tmp);
|
||||
if (ret || tmp != 0xe1)
|
||||
goto error;
|
||||
|
||||
/* create frontends */
|
||||
memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
|
||||
priv->fe[0].demodulator_priv = priv;
|
||||
priv->fe[1].demodulator_priv = priv;
|
||||
|
||||
/* create tuner i2c adapter */
|
||||
strlcpy(priv->tuner_i2c_adapter.name,
|
||||
"CXD2820R tuner I2C adapter",
|
||||
sizeof(priv->tuner_i2c_adapter.name));
|
||||
priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
|
||||
priv->tuner_i2c_adapter.algo_data = NULL;
|
||||
i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
|
||||
if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
|
||||
err("tuner I2C bus could not be initialized");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return &priv->fe[0];
|
||||
|
||||
} else {
|
||||
/* FE1: FE0 given as pointer, just return FE1 we have
|
||||
* already created */
|
||||
priv = fe->demodulator_priv;
|
||||
return &priv->fe[1];
|
||||
}
|
||||
|
||||
error:
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(cxd2820r_attach);
|
||||
|
||||
static struct dvb_frontend_ops cxd2820r_ops[2] = {
|
||||
{
|
||||
/* DVB-T/T2 */
|
||||
.info = {
|
||||
.name = "Sony CXD2820R (DVB-T/T2)",
|
||||
.type = FE_OFDM,
|
||||
.caps =
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
|
||||
FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
|
||||
FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16 |
|
||||
FE_CAN_QAM_64 | FE_CAN_QAM_256 |
|
||||
FE_CAN_QAM_AUTO |
|
||||
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||
FE_CAN_GUARD_INTERVAL_AUTO |
|
||||
FE_CAN_HIERARCHY_AUTO |
|
||||
FE_CAN_MUTE_TS |
|
||||
FE_CAN_2G_MODULATION
|
||||
},
|
||||
|
||||
.release = cxd2820r_release,
|
||||
.init = cxd2820r_init,
|
||||
.sleep = cxd2820r_sleep,
|
||||
|
||||
.get_tune_settings = cxd2820r_get_tune_settings,
|
||||
|
||||
.get_frontend = cxd2820r_get_frontend,
|
||||
|
||||
.get_frontend_algo = cxd2820r_get_frontend_algo,
|
||||
.search = cxd2820r_search,
|
||||
|
||||
.read_status = cxd2820r_read_status,
|
||||
.read_snr = cxd2820r_read_snr,
|
||||
.read_ber = cxd2820r_read_ber,
|
||||
.read_ucblocks = cxd2820r_read_ucblocks,
|
||||
.read_signal_strength = cxd2820r_read_signal_strength,
|
||||
},
|
||||
{
|
||||
/* DVB-C */
|
||||
.info = {
|
||||
.name = "Sony CXD2820R (DVB-C)",
|
||||
.type = FE_QAM,
|
||||
.caps =
|
||||
FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
|
||||
FE_CAN_QAM_128 | FE_CAN_QAM_256 |
|
||||
FE_CAN_FEC_AUTO
|
||||
},
|
||||
|
||||
.release = cxd2820r_release,
|
||||
.init = cxd2820r_init,
|
||||
.sleep = cxd2820r_sleep,
|
||||
|
||||
.get_tune_settings = cxd2820r_get_tune_settings,
|
||||
|
||||
.set_frontend = cxd2820r_set_frontend,
|
||||
.get_frontend = cxd2820r_get_frontend,
|
||||
|
||||
.read_status = cxd2820r_read_status,
|
||||
.read_snr = cxd2820r_read_snr,
|
||||
.read_ber = cxd2820r_read_ber,
|
||||
.read_ucblocks = cxd2820r_read_ucblocks,
|
||||
.read_signal_strength = cxd2820r_read_signal_strength,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CXD2820R_PRIV_H
|
||||
#define CXD2820R_PRIV_H
|
||||
|
||||
#include <linux/dvb/version.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
#include "cxd2820r.h"
|
||||
|
||||
#define LOG_PREFIX "cxd2820r"
|
||||
|
||||
#undef dbg
|
||||
#define dbg(f, arg...) \
|
||||
if (cxd2820r_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 reg_val_mask {
|
||||
u32 reg;
|
||||
u8 val;
|
||||
u8 mask;
|
||||
};
|
||||
|
||||
struct cxd2820r_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
struct dvb_frontend fe[2];
|
||||
struct cxd2820r_config cfg;
|
||||
struct i2c_adapter tuner_i2c_adapter;
|
||||
|
||||
struct mutex fe_lock; /* FE lock */
|
||||
int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
|
||||
|
||||
int ber_running:1;
|
||||
|
||||
u8 bank[2];
|
||||
u8 gpio[3];
|
||||
|
||||
fe_delivery_system_t delivery_system;
|
||||
int last_tune_failed:1; /* for switch between T and T2 tune */
|
||||
};
|
||||
|
||||
/* cxd2820r_core.c */
|
||||
|
||||
extern int cxd2820r_debug;
|
||||
|
||||
int cxd2820r_gpio(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
|
||||
u8 mask);
|
||||
|
||||
int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
|
||||
int len);
|
||||
|
||||
u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor);
|
||||
|
||||
int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
|
||||
int len);
|
||||
|
||||
int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
|
||||
int len);
|
||||
|
||||
int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val);
|
||||
|
||||
int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
|
||||
|
||||
/* cxd2820r_c.c */
|
||||
|
||||
int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p);
|
||||
|
||||
int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params);
|
||||
|
||||
int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
|
||||
|
||||
int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber);
|
||||
|
||||
int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength);
|
||||
|
||||
int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr);
|
||||
|
||||
int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks);
|
||||
|
||||
int cxd2820r_init_c(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_sleep_c(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s);
|
||||
|
||||
/* cxd2820r_t.c */
|
||||
|
||||
int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p);
|
||||
|
||||
int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params);
|
||||
|
||||
int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
|
||||
|
||||
int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber);
|
||||
|
||||
int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength);
|
||||
|
||||
int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr);
|
||||
|
||||
int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks);
|
||||
|
||||
int cxd2820r_init_t(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_sleep_t(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s);
|
||||
|
||||
/* cxd2820r_t2.c */
|
||||
|
||||
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p);
|
||||
|
||||
int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params);
|
||||
|
||||
int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
|
||||
|
||||
int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber);
|
||||
|
||||
int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength);
|
||||
|
||||
int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr);
|
||||
|
||||
int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks);
|
||||
|
||||
int cxd2820r_init_t2(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_sleep_t2(struct dvb_frontend *fe);
|
||||
|
||||
int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s);
|
||||
|
||||
#endif /* CXD2820R_PRIV_H */
|
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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 "cxd2820r_priv.h"
|
||||
|
||||
int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i;
|
||||
u32 if_khz, if_ctl;
|
||||
u64 num;
|
||||
u8 buf[3], bw_param;
|
||||
u8 bw_params1[][5] = {
|
||||
{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
|
||||
{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
|
||||
{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
|
||||
};
|
||||
u8 bw_params2[][2] = {
|
||||
{ 0x1f, 0xdc }, /* 6 MHz */
|
||||
{ 0x12, 0xf8 }, /* 7 MHz */
|
||||
{ 0x01, 0xe0 }, /* 8 MHz */
|
||||
};
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x00080, 0x00, 0xff },
|
||||
{ 0x00081, 0x03, 0xff },
|
||||
{ 0x00085, 0x07, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
|
||||
{ 0x00070, priv->cfg.ts_mode, 0xff },
|
||||
{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
|
||||
{ 0x000a5, 0x00, 0x01 },
|
||||
{ 0x00082, 0x20, 0x60 },
|
||||
{ 0x000c2, 0xc3, 0xff },
|
||||
{ 0x0016a, 0x50, 0xff },
|
||||
{ 0x00427, 0x41, 0xff },
|
||||
};
|
||||
|
||||
dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
|
||||
|
||||
/* update GPIOs */
|
||||
ret = cxd2820r_gpio(fe);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
|
||||
if (priv->delivery_system != SYS_DVBT) {
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
|
||||
tab[i].val, tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_DVBT;
|
||||
priv->ber_running = 0; /* tune stops BER counter */
|
||||
|
||||
switch (c->bandwidth_hz) {
|
||||
case 6000000:
|
||||
if_khz = priv->cfg.if_dvbt_6;
|
||||
i = 0;
|
||||
bw_param = 2;
|
||||
break;
|
||||
case 7000000:
|
||||
if_khz = priv->cfg.if_dvbt_7;
|
||||
i = 1;
|
||||
bw_param = 1;
|
||||
break;
|
||||
case 8000000:
|
||||
if_khz = priv->cfg.if_dvbt_8;
|
||||
i = 2;
|
||||
bw_param = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num = if_khz;
|
||||
num *= 0x1000000;
|
||||
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
|
||||
buf[0] = ((if_ctl >> 16) & 0xff);
|
||||
buf[1] = ((if_ctl >> 8) & 0xff);
|
||||
buf[2] = ((if_ctl >> 0) & 0xff);
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 6) & 0x03) {
|
||||
case 0:
|
||||
c->modulation = QPSK;
|
||||
break;
|
||||
case 1:
|
||||
c->modulation = QAM_16;
|
||||
break;
|
||||
case 2:
|
||||
c->modulation = QAM_64;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[1] >> 1) & 0x03) {
|
||||
case 0:
|
||||
c->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
case 1:
|
||||
c->transmission_mode = TRANSMISSION_MODE_8K;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[1] >> 3) & 0x03) {
|
||||
case 0:
|
||||
c->guard_interval = GUARD_INTERVAL_1_32;
|
||||
break;
|
||||
case 1:
|
||||
c->guard_interval = GUARD_INTERVAL_1_16;
|
||||
break;
|
||||
case 2:
|
||||
c->guard_interval = GUARD_INTERVAL_1_8;
|
||||
break;
|
||||
case 3:
|
||||
c->guard_interval = GUARD_INTERVAL_1_4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[0] >> 3) & 0x07) {
|
||||
case 0:
|
||||
c->hierarchy = HIERARCHY_NONE;
|
||||
break;
|
||||
case 1:
|
||||
c->hierarchy = HIERARCHY_1;
|
||||
break;
|
||||
case 2:
|
||||
c->hierarchy = HIERARCHY_2;
|
||||
break;
|
||||
case 3:
|
||||
c->hierarchy = HIERARCHY_4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[0] >> 0) & 0x07) {
|
||||
case 0:
|
||||
c->code_rate_HP = FEC_1_2;
|
||||
break;
|
||||
case 1:
|
||||
c->code_rate_HP = FEC_2_3;
|
||||
break;
|
||||
case 2:
|
||||
c->code_rate_HP = FEC_3_4;
|
||||
break;
|
||||
case 3:
|
||||
c->code_rate_HP = FEC_5_6;
|
||||
break;
|
||||
case 4:
|
||||
c->code_rate_HP = FEC_7_8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[1] >> 5) & 0x07) {
|
||||
case 0:
|
||||
c->code_rate_LP = FEC_1_2;
|
||||
break;
|
||||
case 1:
|
||||
c->code_rate_LP = FEC_2_3;
|
||||
break;
|
||||
case 2:
|
||||
c->code_rate_LP = FEC_3_4;
|
||||
break;
|
||||
case 3:
|
||||
c->code_rate_LP = FEC_5_6;
|
||||
break;
|
||||
case 4:
|
||||
c->code_rate_LP = FEC_7_8;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 0) & 0x01) {
|
||||
case 0:
|
||||
c->inversion = INVERSION_OFF;
|
||||
break;
|
||||
case 1:
|
||||
c->inversion = INVERSION_ON;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[3], start_ber = 0;
|
||||
*ber = 0;
|
||||
|
||||
if (priv->ber_running) {
|
||||
ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
|
||||
*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
|
||||
start_ber = 1;
|
||||
}
|
||||
} else {
|
||||
priv->ber_running = 1;
|
||||
start_ber = 1;
|
||||
}
|
||||
|
||||
if (start_ber) {
|
||||
/* (re)start BER */
|
||||
ret = cxd2820r_wr_reg(priv, 0x00079, 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe,
|
||||
u16 *strength)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
u16 tmp;
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
tmp = (buf[0] & 0x0f) << 8 | buf[1];
|
||||
tmp = ~tmp & 0x0fff;
|
||||
|
||||
/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
|
||||
*strength = tmp * 0xffff / 0x0fff;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
u16 tmp;
|
||||
/* report SNR in dB * 10 */
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
tmp = (buf[0] & 0x1f) << 8 | buf[1];
|
||||
#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
|
||||
if (tmp)
|
||||
*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
|
||||
/ 100);
|
||||
else
|
||||
*snr = 0;
|
||||
|
||||
dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
*ucblocks = 0;
|
||||
/* no way to read ? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[4];
|
||||
*status = 0;
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[0] & 0x07) == 6) {
|
||||
ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (((buf[1] >> 3) & 0x01) == 1) {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
} else {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC;
|
||||
}
|
||||
} else {
|
||||
ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[2] & 0x0f) >= 4) {
|
||||
ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (((buf[3] >> 4) & 0x01) == 1)
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
}
|
||||
}
|
||||
|
||||
dbg("%s: lock=%02x %02x %02x %02x", __func__,
|
||||
buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_init_t(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_sleep_t(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x000ff, 0x1f, 0xff },
|
||||
{ 0x00085, 0x00, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
{ 0x00081, 0x00, 0xff },
|
||||
{ 0x00080, 0x00, 0xff },
|
||||
};
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
|
||||
tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s)
|
||||
{
|
||||
s->min_delay_ms = 500;
|
||||
s->step_size = fe->ops.info.frequency_stepsize * 2;
|
||||
s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
* Sony CXD2820R demodulator driver
|
||||
*
|
||||
* Copyright (C) 2010 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 "cxd2820r_priv.h"
|
||||
|
||||
int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret, i;
|
||||
u32 if_khz, if_ctl;
|
||||
u64 num;
|
||||
u8 buf[3], bw_param;
|
||||
u8 bw_params1[][5] = {
|
||||
{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
|
||||
{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
|
||||
{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
|
||||
{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
|
||||
};
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x00080, 0x02, 0xff },
|
||||
{ 0x00081, 0x20, 0xff },
|
||||
{ 0x00085, 0x07, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
{ 0x02069, 0x01, 0xff },
|
||||
|
||||
{ 0x0207f, 0x2a, 0xff },
|
||||
{ 0x02082, 0x0a, 0xff },
|
||||
{ 0x02083, 0x0a, 0xff },
|
||||
{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
|
||||
{ 0x02070, priv->cfg.ts_mode, 0xff },
|
||||
{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
|
||||
{ 0x02567, 0x07, 0x0f },
|
||||
{ 0x02569, 0x03, 0x03 },
|
||||
{ 0x02595, 0x1a, 0xff },
|
||||
{ 0x02596, 0x50, 0xff },
|
||||
{ 0x02a8c, 0x00, 0xff },
|
||||
{ 0x02a8d, 0x34, 0xff },
|
||||
{ 0x02a45, 0x06, 0x07 },
|
||||
{ 0x03f10, 0x0d, 0xff },
|
||||
{ 0x03f11, 0x02, 0xff },
|
||||
{ 0x03f12, 0x01, 0xff },
|
||||
{ 0x03f23, 0x2c, 0xff },
|
||||
{ 0x03f51, 0x13, 0xff },
|
||||
{ 0x03f52, 0x01, 0xff },
|
||||
{ 0x03f53, 0x00, 0xff },
|
||||
{ 0x027e6, 0x14, 0xff },
|
||||
{ 0x02786, 0x02, 0x07 },
|
||||
{ 0x02787, 0x40, 0xe0 },
|
||||
{ 0x027ef, 0x10, 0x18 },
|
||||
};
|
||||
|
||||
dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
|
||||
|
||||
/* update GPIOs */
|
||||
ret = cxd2820r_gpio(fe);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
if (priv->delivery_system != SYS_DVBT2) {
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
|
||||
tab[i].val, tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_DVBT2;
|
||||
|
||||
switch (c->bandwidth_hz) {
|
||||
case 5000000:
|
||||
if_khz = priv->cfg.if_dvbt2_5;
|
||||
i = 0;
|
||||
bw_param = 3;
|
||||
break;
|
||||
case 6000000:
|
||||
if_khz = priv->cfg.if_dvbt2_6;
|
||||
i = 1;
|
||||
bw_param = 2;
|
||||
break;
|
||||
case 7000000:
|
||||
if_khz = priv->cfg.if_dvbt2_7;
|
||||
i = 2;
|
||||
bw_param = 1;
|
||||
break;
|
||||
case 8000000:
|
||||
if_khz = priv->cfg.if_dvbt2_8;
|
||||
i = 3;
|
||||
bw_param = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num = if_khz;
|
||||
num *= 0x1000000;
|
||||
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
|
||||
buf[0] = ((if_ctl >> 16) & 0xff);
|
||||
buf[1] = ((if_ctl >> 8) & 0xff);
|
||||
buf[2] = ((if_ctl >> 0) & 0xff);
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 0) & 0x07) {
|
||||
case 0:
|
||||
c->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
case 1:
|
||||
c->transmission_mode = TRANSMISSION_MODE_8K;
|
||||
break;
|
||||
case 2:
|
||||
c->transmission_mode = TRANSMISSION_MODE_4K;
|
||||
break;
|
||||
case 3:
|
||||
c->transmission_mode = TRANSMISSION_MODE_1K;
|
||||
break;
|
||||
case 4:
|
||||
c->transmission_mode = TRANSMISSION_MODE_16K;
|
||||
break;
|
||||
case 5:
|
||||
c->transmission_mode = TRANSMISSION_MODE_32K;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[1] >> 4) & 0x07) {
|
||||
case 0:
|
||||
c->guard_interval = GUARD_INTERVAL_1_32;
|
||||
break;
|
||||
case 1:
|
||||
c->guard_interval = GUARD_INTERVAL_1_16;
|
||||
break;
|
||||
case 2:
|
||||
c->guard_interval = GUARD_INTERVAL_1_8;
|
||||
break;
|
||||
case 3:
|
||||
c->guard_interval = GUARD_INTERVAL_1_4;
|
||||
break;
|
||||
case 4:
|
||||
c->guard_interval = GUARD_INTERVAL_1_128;
|
||||
break;
|
||||
case 5:
|
||||
c->guard_interval = GUARD_INTERVAL_19_128;
|
||||
break;
|
||||
case 6:
|
||||
c->guard_interval = GUARD_INTERVAL_19_256;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 0) & 0x07) {
|
||||
case 0:
|
||||
c->fec_inner = FEC_1_2;
|
||||
break;
|
||||
case 1:
|
||||
c->fec_inner = FEC_3_5;
|
||||
break;
|
||||
case 2:
|
||||
c->fec_inner = FEC_2_3;
|
||||
break;
|
||||
case 3:
|
||||
c->fec_inner = FEC_3_4;
|
||||
break;
|
||||
case 4:
|
||||
c->fec_inner = FEC_4_5;
|
||||
break;
|
||||
case 5:
|
||||
c->fec_inner = FEC_5_6;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((buf[1] >> 0) & 0x07) {
|
||||
case 0:
|
||||
c->modulation = QPSK;
|
||||
break;
|
||||
case 1:
|
||||
c->modulation = QAM_16;
|
||||
break;
|
||||
case 2:
|
||||
c->modulation = QAM_64;
|
||||
break;
|
||||
case 3:
|
||||
c->modulation = QAM_256;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
switch ((buf[0] >> 4) & 0x01) {
|
||||
case 0:
|
||||
c->inversion = INVERSION_OFF;
|
||||
break;
|
||||
case 1:
|
||||
c->inversion = INVERSION_ON;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[1];
|
||||
*status = 0;
|
||||
|
||||
ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[0] & 0x07) == 6) {
|
||||
if (((buf[0] >> 5) & 0x01) == 1) {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
} else {
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI | FE_HAS_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
dbg("%s: lock=%02x", __func__, buf[0]);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[4];
|
||||
unsigned int errbits;
|
||||
*ber = 0;
|
||||
/* FIXME: correct calculation */
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if ((buf[0] >> 4) & 0x01) {
|
||||
errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 |
|
||||
buf[2] << 8 | buf[3];
|
||||
|
||||
if (errbits)
|
||||
*ber = errbits * 64 / 16588800;
|
||||
}
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe,
|
||||
u16 *strength)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
u16 tmp;
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
tmp = (buf[0] & 0x0f) << 8 | buf[1];
|
||||
tmp = ~tmp & 0x0fff;
|
||||
|
||||
/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
|
||||
*strength = tmp * 0xffff / 0x0fff;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[2];
|
||||
u16 tmp;
|
||||
/* report SNR in dB * 10 */
|
||||
|
||||
ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
tmp = (buf[0] & 0x0f) << 8 | buf[1];
|
||||
#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
|
||||
if (tmp)
|
||||
*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
|
||||
/ 100);
|
||||
else
|
||||
*snr = 0;
|
||||
|
||||
dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
*ucblocks = 0;
|
||||
/* no way to read ? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cxd2820r_sleep_t2(struct dvb_frontend *fe)
|
||||
{
|
||||
struct cxd2820r_priv *priv = fe->demodulator_priv;
|
||||
int ret, i;
|
||||
struct reg_val_mask tab[] = {
|
||||
{ 0x000ff, 0x1f, 0xff },
|
||||
{ 0x00085, 0x00, 0xff },
|
||||
{ 0x00088, 0x01, 0xff },
|
||||
{ 0x02069, 0x00, 0xff },
|
||||
{ 0x00081, 0x00, 0xff },
|
||||
{ 0x00080, 0x00, 0xff },
|
||||
};
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
|
||||
tab[i].mask);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_tune_settings *s)
|
||||
{
|
||||
s->min_delay_ms = 1500;
|
||||
s->step_size = fe->ops.info.frequency_stepsize * 2;
|
||||
s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -73,27 +73,47 @@ struct dib0070_state {
|
|||
|
||||
u8 wbd_gain_current;
|
||||
u16 wbd_offset_3_3[2];
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[3];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
|
||||
};
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->cfg->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 1;
|
||||
state->msg[1].addr = state->cfg->i2c_address;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
|
||||
printk(KERN_WARNING "DiB0070 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
|
||||
{
|
||||
u8 b[3] = { reg, val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
state->i2c_write_buffer[1] = val >> 8;
|
||||
state->i2c_write_buffer[2] = val & 0xff;
|
||||
|
||||
memset(state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->cfg->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 3;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0070 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
|
|
@ -191,6 +191,11 @@ struct dib0090_state {
|
|||
u8 wbd_calibration_gain;
|
||||
const struct dib0090_wbd_slope *current_wbd_table;
|
||||
u16 wbdmux;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[3];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
struct dib0090_fw_state {
|
||||
|
@ -198,27 +203,48 @@ struct dib0090_fw_state {
|
|||
struct dvb_frontend *fe;
|
||||
struct dib0090_identity identity;
|
||||
const struct dib0090_config *config;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg;
|
||||
u8 i2c_write_buffer[2];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1},
|
||||
{.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
|
||||
};
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->config->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 1;
|
||||
state->msg[1].addr = state->config->i2c_address;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
|
||||
printk(KERN_WARNING "DiB0090 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
|
||||
{
|
||||
u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg & 0xff;
|
||||
state->i2c_write_buffer[1] = val >> 8;
|
||||
state->i2c_write_buffer[2] = val & 0xff;
|
||||
|
||||
memset(state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->config->i2c_address;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 3;
|
||||
|
||||
if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
|
|||
|
||||
static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = reg;
|
||||
|
||||
memset(&state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg.addr = reg;
|
||||
state->msg.flags = I2C_M_RD;
|
||||
state->msg.buf = state->i2c_read_buffer;
|
||||
state->msg.len = 2;
|
||||
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
|
||||
{
|
||||
u8 b[2] = { val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
state->i2c_write_buffer[0] = val >> 8;
|
||||
state->i2c_write_buffer[1] = val & 0xff;
|
||||
|
||||
memset(&state->msg, 0, sizeof(struct i2c_msg));
|
||||
state->msg.addr = reg;
|
||||
state->msg.flags = 0;
|
||||
state->msg.buf = state->i2c_write_buffer;
|
||||
state->msg.len = 2;
|
||||
if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0090 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@ struct dib7000m_state {
|
|||
u16 revision;
|
||||
|
||||
u8 agc_state;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib7000m_power_mode {
|
||||
|
@ -64,29 +69,39 @@ enum dib7000m_power_mode {
|
|||
|
||||
static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
|
||||
{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
|
||||
};
|
||||
state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d",reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
};
|
||||
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
|
||||
{
|
||||
|
|
|
@ -63,6 +63,11 @@ struct dib7000p_state {
|
|||
|
||||
u16 tuner_enable;
|
||||
struct i2c_adapter dib7090_tuner_adap;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib7000p_power_mode {
|
||||
|
@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
|
|||
|
||||
static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
|
||||
};
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
};
|
||||
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
|
||||
|
@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_frontend *demod)
|
|||
|
||||
int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
{
|
||||
u8 tx[2], rx[2];
|
||||
u8 *tx, *rx;
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = 0, .len = 2},
|
||||
{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
|
||||
if (!tx)
|
||||
return -ENOMEM;
|
||||
rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
|
||||
if (!rx) {
|
||||
goto rx_memory_error;
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
msg[0].buf = tx;
|
||||
msg[1].buf = rx;
|
||||
|
||||
tx[0] = 0x03;
|
||||
tx[1] = 0x00;
|
||||
|
@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
|||
}
|
||||
|
||||
dprintk("-D- DiB7000PC not detected");
|
||||
return 0;
|
||||
|
||||
kfree(rx);
|
||||
rx_memory_error:
|
||||
kfree(tx);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dib7000pc_detection);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
|||
struct i2c_device {
|
||||
struct i2c_adapter *adap;
|
||||
u8 addr;
|
||||
u8 *i2c_write_buffer;
|
||||
u8 *i2c_read_buffer;
|
||||
};
|
||||
|
||||
struct dib8000_state {
|
||||
|
@ -70,6 +72,11 @@ struct dib8000_state {
|
|||
u32 status;
|
||||
|
||||
struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[4];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
enum dib8000_power_mode {
|
||||
|
@ -79,22 +86,41 @@ enum dib8000_power_mode {
|
|||
|
||||
static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2},
|
||||
{.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
|
||||
{.addr = i2c->addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 2},
|
||||
{.addr = i2c->addr >> 1, .flags = I2C_M_RD,
|
||||
.buf = i2c->i2c_read_buffer, .len = 2},
|
||||
};
|
||||
|
||||
msg[0].buf[0] = reg >> 8;
|
||||
msg[0].buf[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(i2c->adap, msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (msg[1].buf[0] << 8) | msg[1].buf[1];
|
||||
}
|
||||
|
||||
static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
|
||||
{
|
||||
return dib8000_i2c_read16(&state->i2c, reg);
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c.addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = state->i2c_read_buffer;
|
||||
state->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
|
||||
|
@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
|
|||
|
||||
static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4
|
||||
};
|
||||
return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 4};
|
||||
int ret = 0;
|
||||
|
||||
msg.buf[0] = (reg >> 8) & 0xff;
|
||||
msg.buf[1] = reg & 0xff;
|
||||
msg.buf[2] = (val >> 8) & 0xff;
|
||||
msg.buf[3] = val & 0xff;
|
||||
|
||||
ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
|
||||
{
|
||||
return dib8000_i2c_write16(&state->i2c, reg, val);
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
state->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
state->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
|
||||
|
@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct dib8000_state *state)
|
|||
dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
|
||||
}
|
||||
|
||||
static const u16 adc_target_16dB[11] = {
|
||||
(1 << 13) - 825 - 117,
|
||||
(1 << 13) - 837 - 117,
|
||||
(1 << 13) - 811 - 117,
|
||||
(1 << 13) - 766 - 117,
|
||||
(1 << 13) - 737 - 117,
|
||||
(1 << 13) - 693 - 117,
|
||||
(1 << 13) - 648 - 117,
|
||||
(1 << 13) - 619 - 117,
|
||||
(1 << 13) - 575 - 117,
|
||||
(1 << 13) - 531 - 117,
|
||||
(1 << 13) - 501 - 117
|
||||
};
|
||||
static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
|
||||
|
||||
static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
|
||||
{
|
||||
u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
|
||||
u8 guard, crate, constellation, timeI;
|
||||
u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
|
||||
u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled
|
||||
const s16 *ncoeff = NULL, *ana_fe;
|
||||
u16 tmcc_pow = 0;
|
||||
u16 coff_pow = 0x2800;
|
||||
u16 init_prbs = 0xfff;
|
||||
u16 ana_gain = 0;
|
||||
u16 adc_target_16dB[11] = {
|
||||
(1 << 13) - 825 - 117,
|
||||
(1 << 13) - 837 - 117,
|
||||
(1 << 13) - 811 - 117,
|
||||
(1 << 13) - 766 - 117,
|
||||
(1 << 13) - 737 - 117,
|
||||
(1 << 13) - 693 - 117,
|
||||
(1 << 13) - 648 - 117,
|
||||
(1 << 13) - 619 - 117,
|
||||
(1 << 13) - 575 - 117,
|
||||
(1 << 13) - 531 - 117,
|
||||
(1 << 13) - 501 - 117
|
||||
};
|
||||
|
||||
if (state->ber_monitored_layer != LAYER_ALL)
|
||||
dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
|
||||
|
@ -2379,10 +2421,22 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend);
|
|||
|
||||
int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
|
||||
{
|
||||
int k = 0;
|
||||
int k = 0, ret = 0;
|
||||
u8 new_addr = 0;
|
||||
struct i2c_device client = {.adap = host };
|
||||
|
||||
client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_write_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_read_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto error_memory;
|
||||
}
|
||||
|
||||
for (k = no_of_demods - 1; k >= 0; k--) {
|
||||
/* designated i2c address */
|
||||
new_addr = first_addr + (k << 1);
|
||||
|
@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
|
|||
client.addr = default_addr;
|
||||
if (dib8000_identify(&client) == 0) {
|
||||
dprintk("#%d: not identified", k);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
|
|||
dib8000_i2c_write16(&client, 1286, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(client.i2c_read_buffer);
|
||||
error_memory:
|
||||
kfree(client.i2c_write_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dib8000_i2c_enumeration);
|
||||
|
@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
|
|||
memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
|
||||
state->i2c.adap = i2c_adap;
|
||||
state->i2c.addr = i2c_addr;
|
||||
state->i2c.i2c_write_buffer = state->i2c_write_buffer;
|
||||
state->i2c.i2c_read_buffer = state->i2c_read_buffer;
|
||||
state->gpio_val = cfg->gpio_val;
|
||||
state->gpio_dir = cfg->gpio_dir;
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
|||
struct i2c_device {
|
||||
struct i2c_adapter *i2c_adap;
|
||||
u8 i2c_addr;
|
||||
u8 *i2c_read_buffer;
|
||||
u8 *i2c_write_buffer;
|
||||
};
|
||||
|
||||
/* lock */
|
||||
|
@ -92,11 +94,16 @@ struct dib9000_state {
|
|||
|
||||
struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
|
||||
u16 component_bus_speed;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[2];
|
||||
u8 i2c_write_buffer[255];
|
||||
u8 i2c_read_buffer[255];
|
||||
};
|
||||
|
||||
u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
enum dib9000_power_mode {
|
||||
|
@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
|
|||
u32 chunk_size = 126;
|
||||
u32 l;
|
||||
int ret;
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
|
||||
};
|
||||
|
||||
if (state->platform.risc.fw_is_running && (reg < 1024))
|
||||
return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
|
||||
|
||||
memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = 2;
|
||||
state->msg[1].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[1].flags = I2C_M_RD;
|
||||
state->msg[1].buf = b;
|
||||
state->msg[1].len = len;
|
||||
|
||||
state->i2c_write_buffer[0] = reg >> 8;
|
||||
state->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
|
||||
wb[0] |= (1 << 5);
|
||||
state->i2c_write_buffer[0] |= (1 << 5);
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
wb[0] |= (1 << 4);
|
||||
state->i2c_write_buffer[0] |= (1 << 4);
|
||||
|
||||
do {
|
||||
l = len < chunk_size ? len : chunk_size;
|
||||
msg[1].len = l;
|
||||
msg[1].buf = b;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
|
||||
state->msg[1].len = l;
|
||||
state->msg[1].buf = b;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
|
||||
if (ret != 0) {
|
||||
dprintk("i2c read error on %d", reg);
|
||||
return -EREMOTEIO;
|
||||
|
@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
|
|||
|
||||
static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 2},
|
||||
{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
|
||||
.buf = i2c->i2c_read_buffer, .len = 2},
|
||||
};
|
||||
|
||||
i2c->i2c_write_buffer[0] = reg >> 8;
|
||||
i2c->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
|
||||
dprintk("read register %x error", reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (b[0] << 8) | b[1];
|
||||
return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
|
||||
if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
|
||||
return 0;
|
||||
return (b[0] << 8 | b[1]);
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
|
||||
{
|
||||
u8 b[2];
|
||||
if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
|
||||
if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
|
||||
attribute) != 0)
|
||||
return 0;
|
||||
return (b[0] << 8 | b[1]);
|
||||
return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
|
||||
static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
|
||||
{
|
||||
u8 b[255];
|
||||
u32 chunk_size = 126;
|
||||
u32 l;
|
||||
int ret;
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
|
||||
};
|
||||
|
||||
if (state->platform.risc.fw_is_running && (reg < 1024)) {
|
||||
if (dib9000_risc_apb_access_write
|
||||
(state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
|
||||
|
@ -304,20 +316,26 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
|
|||
return 0;
|
||||
}
|
||||
|
||||
b[0] = (reg >> 8) & 0xff;
|
||||
b[1] = (reg) & 0xff;
|
||||
memset(&state->msg[0], 0, sizeof(struct i2c_msg));
|
||||
state->msg[0].addr = state->i2c.i2c_addr >> 1;
|
||||
state->msg[0].flags = 0;
|
||||
state->msg[0].buf = state->i2c_write_buffer;
|
||||
state->msg[0].len = len + 2;
|
||||
|
||||
state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
state->i2c_write_buffer[1] = (reg) & 0xff;
|
||||
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
|
||||
b[0] |= (1 << 5);
|
||||
state->i2c_write_buffer[0] |= (1 << 5);
|
||||
if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
|
||||
b[0] |= (1 << 4);
|
||||
state->i2c_write_buffer[0] |= (1 << 4);
|
||||
|
||||
do {
|
||||
l = len < chunk_size ? len : chunk_size;
|
||||
msg.len = l + 2;
|
||||
memcpy(&b[2], buf, l);
|
||||
state->msg[0].len = l + 2;
|
||||
memcpy(&state->i2c_write_buffer[2], buf, l);
|
||||
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
|
||||
buf += l;
|
||||
len -= l;
|
||||
|
@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
|
|||
|
||||
static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
|
||||
struct i2c_msg msg = {
|
||||
.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
|
||||
.addr = i2c->i2c_addr >> 1, .flags = 0,
|
||||
.buf = i2c->i2c_write_buffer, .len = 4
|
||||
};
|
||||
|
||||
i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
i2c->i2c_write_buffer[1] = reg & 0xff;
|
||||
i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
i2c->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
|
@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
|
|||
return 0;
|
||||
dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
|
||||
do {
|
||||
dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
|
||||
} while (i && index_loop--);
|
||||
dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
|
||||
} while (state->i2c_read_buffer[0] && index_loop--);
|
||||
|
||||
if (index_loop > 0)
|
||||
return 0;
|
||||
|
@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
|
||||
s8 intlv_native;
|
||||
};
|
||||
struct dibDVBTChannel ch;
|
||||
struct dibDVBTChannel *ch;
|
||||
int ret = 0;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
@ -1148,9 +1171,12 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
ret = -EIO;
|
||||
}
|
||||
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
|
||||
state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
|
||||
ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
|
||||
|
||||
switch (ch.spectrum_inversion & 0x7) {
|
||||
|
||||
switch (ch->spectrum_inversion & 0x7) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
|
||||
break;
|
||||
|
@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.nfft) {
|
||||
switch (ch->nfft) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
|
@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.guard) {
|
||||
switch (ch->guard) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
|
||||
break;
|
||||
|
@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.constellation) {
|
||||
switch (ch->constellation) {
|
||||
case 2:
|
||||
state->fe[0]->dtv_property_cache.modulation = QAM_64;
|
||||
break;
|
||||
|
@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.hrch) {
|
||||
switch (ch->hrch) {
|
||||
case 0:
|
||||
state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
|
||||
break;
|
||||
|
@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.code_rate_hp) {
|
||||
switch (ch->code_rate_hp) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
|
||||
break;
|
||||
|
@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
|
|||
state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
|
||||
break;
|
||||
}
|
||||
switch (ch.code_rate_lp) {
|
||||
switch (ch->code_rate_lp) {
|
||||
case 1:
|
||||
state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
|
||||
break;
|
||||
|
@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
|
|||
break;
|
||||
case CT_DEMOD_STEP_1:
|
||||
if (search)
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
|
||||
else
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
|
||||
dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
|
||||
i = (s8)state->i2c_read_buffer[0];
|
||||
switch (i) { /* something happened */
|
||||
case 0:
|
||||
break;
|
||||
|
@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
|
|||
static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
|
||||
state->i2c_read_buffer, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
c = (u16 *)state->i2c_read_buffer;
|
||||
|
||||
*ber = c[10] << 16 | c[11];
|
||||
return 0;
|
||||
}
|
||||
|
@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
|||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u8 index_frontend;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
u16 val;
|
||||
|
||||
*strength = 0;
|
||||
|
@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
|||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
val = 65535 - c[4];
|
||||
|
@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
|
|||
static u32 dib9000_get_snr(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
u32 n, s, exp;
|
||||
u16 val;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
val = c[7];
|
||||
|
@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
|
|||
static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
|
||||
{
|
||||
struct dib9000_state *state = fe->demodulator_priv;
|
||||
u16 c[16];
|
||||
u16 *c = (u16 *)state->i2c_read_buffer;
|
||||
|
||||
DibAcquireLock(&state->platform.risc.mem_mbx_lock);
|
||||
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
|
||||
return -EIO;
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
|
||||
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
|
||||
DibReleaseLock(&state->platform.risc.mem_mbx_lock);
|
||||
|
||||
*unc = c[12];
|
||||
|
@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
|
|||
|
||||
int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
|
||||
{
|
||||
int k = 0;
|
||||
int k = 0, ret = 0;
|
||||
u8 new_addr = 0;
|
||||
struct i2c_device client = {.i2c_adap = i2c };
|
||||
|
||||
client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_write_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
|
||||
if (!client.i2c_read_buffer) {
|
||||
dprintk("%s: not enough memory", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto error_memory;
|
||||
}
|
||||
|
||||
client.i2c_addr = default_addr + 16;
|
||||
dib9000_i2c_write16(&client, 1796, 0x0);
|
||||
|
||||
|
@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
|
|||
client.i2c_addr = default_addr;
|
||||
if (dib9000_identify(&client) == 0) {
|
||||
dprintk("DiB9000 #%d: not identified", k);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
|
|||
dib9000_i2c_write16(&client, 1795, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
kfree(client.i2c_read_buffer);
|
||||
error_memory:
|
||||
kfree(client.i2c_write_buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dib9000_i2c_enumeration);
|
||||
|
||||
|
@ -2255,12 +2303,16 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
|
|||
if (st == NULL)
|
||||
return NULL;
|
||||
fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
|
||||
if (fe == NULL)
|
||||
if (fe == NULL) {
|
||||
kfree(st);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
|
||||
st->i2c.i2c_adap = i2c_adap;
|
||||
st->i2c.i2c_addr = i2c_addr;
|
||||
st->i2c.i2c_write_buffer = st->i2c_write_buffer;
|
||||
st->i2c.i2c_read_buffer = st->i2c_read_buffer;
|
||||
|
||||
st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
|
||||
st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
|
||||
|
|
|
@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
|||
|
||||
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
|
||||
};
|
||||
mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
|
||||
mst->i2c_write_buffer[1] = reg & 0xff;
|
||||
mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
|
||||
mst->i2c_write_buffer[3] = val & 0xff;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg));
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].flags = 0;
|
||||
mst->msg[0].buf = mst->i2c_write_buffer;
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
|
||||
{
|
||||
u8 wb[2] = { reg >> 8, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
|
||||
{.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
|
||||
};
|
||||
mst->i2c_write_buffer[0] = reg >> 8;
|
||||
mst->i2c_write_buffer[1] = reg & 0xff;
|
||||
|
||||
if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
|
||||
memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].flags = 0;
|
||||
mst->msg[0].buf = mst->i2c_write_buffer;
|
||||
mst->msg[0].len = 2;
|
||||
mst->msg[1].addr = mst->i2c_addr;
|
||||
mst->msg[1].flags = I2C_M_RD;
|
||||
mst->msg[1].buf = mst->i2c_read_buffer;
|
||||
mst->msg[1].len = 2;
|
||||
|
||||
if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
|
||||
dprintk("i2c read error on %d", reg);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
|
||||
}
|
||||
|
||||
static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
|
||||
|
@ -248,26 +257,32 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
|
|||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
|
||||
struct i2c_msg m[2 + num];
|
||||
u8 tx_open[4], tx_close[4];
|
||||
|
||||
memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
if (num > 32) {
|
||||
dprintk("%s: too much I2C message to be transmitted (%i).\
|
||||
Maximum is 32", __func__, num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
|
||||
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
|
||||
m[0].addr = mst->i2c_addr;
|
||||
m[0].buf = tx_open;
|
||||
m[0].len = 4;
|
||||
/* open the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].buf = &mst->i2c_write_buffer[0];
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
|
||||
memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
|
||||
m[num + 1].addr = mst->i2c_addr;
|
||||
m[num + 1].buf = tx_close;
|
||||
m[num + 1].len = 4;
|
||||
/* close the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
|
||||
mst->msg[num + 1].addr = mst->i2c_addr;
|
||||
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
|
||||
mst->msg[num + 1].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
|
||||
|
@ -279,26 +294,32 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
|
|||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
|
||||
struct i2c_msg m[2 + num];
|
||||
u8 tx_open[4], tx_close[4];
|
||||
|
||||
memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
if (num > 32) {
|
||||
dprintk("%s: too much I2C message to be transmitted (%i).\
|
||||
Maximum is 32", __func__, num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
|
||||
|
||||
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
|
||||
m[0].addr = mst->i2c_addr;
|
||||
m[0].buf = tx_open;
|
||||
m[0].len = 4;
|
||||
/* open the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
|
||||
mst->msg[0].addr = mst->i2c_addr;
|
||||
mst->msg[0].buf = &mst->i2c_write_buffer[0];
|
||||
mst->msg[0].len = 4;
|
||||
|
||||
memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
|
||||
memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
|
||||
m[num + 1].addr = mst->i2c_addr;
|
||||
m[num + 1].buf = tx_close;
|
||||
m[num + 1].len = 4;
|
||||
/* close the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
|
||||
mst->msg[num + 1].addr = mst->i2c_addr;
|
||||
mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
|
||||
mst->msg[num + 1].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
|
||||
return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
|
||||
|
|
|
@ -28,6 +28,11 @@ struct dibx000_i2c_master {
|
|||
u8 i2c_addr;
|
||||
|
||||
u16 base_reg;
|
||||
|
||||
/* for the I2C transfer */
|
||||
struct i2c_msg msg[34];
|
||||
u8 i2c_write_buffer[8];
|
||||
u8 i2c_read_buffer[2];
|
||||
};
|
||||
|
||||
extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* Driver for Micronas DVB-T drx397xD demodulator
|
||||
*
|
||||
* Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
|
||||
*/
|
||||
|
||||
#ifndef _DRX397XD_H_INCLUDED
|
||||
#define _DRX397XD_H_INCLUDED
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
#define DRX_F_STEPSIZE 166667
|
||||
#define DRX_F_OFFSET 36000000
|
||||
|
||||
#define I2C_ADR_C0(x) \
|
||||
( cpu_to_le32( \
|
||||
(u32)( \
|
||||
(((u32)(x) & (u32)0x000000ffUL) ) | \
|
||||
(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
|
||||
(((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
|
||||
( (u32)0x00c00000UL) \
|
||||
)) \
|
||||
)
|
||||
|
||||
#define I2C_ADR_E0(x) \
|
||||
( cpu_to_le32( \
|
||||
(u32)( \
|
||||
(((u32)(x) & (u32)0x000000ffUL) ) | \
|
||||
(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
|
||||
(((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
|
||||
( (u32)0x00e00000UL) \
|
||||
)) \
|
||||
)
|
||||
|
||||
struct drx397xD_CfgRfAgc /* 0x7c */
|
||||
{
|
||||
int d00; /* 2 */
|
||||
u16 w04;
|
||||
u16 w06;
|
||||
};
|
||||
|
||||
struct drx397xD_CfgIfAgc /* 0x68 */
|
||||
{
|
||||
int d00; /* 0 */
|
||||
u16 w04; /* 0 */
|
||||
u16 w06;
|
||||
u16 w08;
|
||||
u16 w0A;
|
||||
u16 w0C;
|
||||
};
|
||||
|
||||
struct drx397xD_s20 {
|
||||
int d04;
|
||||
u32 d18;
|
||||
u32 d1C;
|
||||
u32 d20;
|
||||
u32 d14;
|
||||
u32 d24;
|
||||
u32 d0C;
|
||||
u32 d08;
|
||||
};
|
||||
|
||||
struct drx397xD_config
|
||||
{
|
||||
/* demodulator's I2C address */
|
||||
u8 demod_address; /* 0x0f */
|
||||
|
||||
struct drx397xD_CfgIfAgc ifagc; /* 0x68 */
|
||||
struct drx397xD_CfgRfAgc rfagc; /* 0x7c */
|
||||
u32 s20d24;
|
||||
|
||||
/* HI_CfgCommand parameters */
|
||||
u16 w50, w52, /* w54, */ w56;
|
||||
|
||||
int d5C;
|
||||
int d60;
|
||||
int d48;
|
||||
int d28;
|
||||
|
||||
u32 f_if; /* d14: intermediate frequency [Hz] */
|
||||
/* 36000000 on Cinergy 2400i DT */
|
||||
/* 42800000 on Pinnacle Hybrid PRO 330e */
|
||||
|
||||
u16 f_osc; /* s66: 48000 oscillator frequency [kHz] */
|
||||
|
||||
u16 w92; /* 20000 */
|
||||
|
||||
u16 wA0;
|
||||
u16 w98;
|
||||
u16 w9A;
|
||||
|
||||
u16 w9C; /* 0xe0 */
|
||||
u16 w9E; /* 0x00 */
|
||||
|
||||
/* used for signal strength calculations in
|
||||
drx397x_read_signal_strength
|
||||
*/
|
||||
u16 ss78; // 2200
|
||||
u16 ss7A; // 150
|
||||
u16 ss76; // 820
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_DRX397XD */
|
||||
|
||||
#endif /* _DRX397XD_H_INCLUDED */
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Firmware definitions for Micronas drx397xD
|
||||
*
|
||||
* Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef _FW_ENTRY
|
||||
_FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0, DRXD_FW_A2 ),
|
||||
_FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1, DRXD_FW_B1 ),
|
||||
#undef _FW_ENTRY
|
||||
#endif /* _FW_ENTRY */
|
||||
|
||||
#ifdef _BLOB_ENTRY
|
||||
_BLOB_ENTRY("InitAtomicRead", DRXD_InitAtomicRead = 0 ),
|
||||
_BLOB_ENTRY("InitCE", DRXD_InitCE ),
|
||||
_BLOB_ENTRY("InitCP", DRXD_InitCP ),
|
||||
_BLOB_ENTRY("InitEC", DRXD_InitEC ),
|
||||
_BLOB_ENTRY("InitEQ", DRXD_InitEQ ),
|
||||
_BLOB_ENTRY("InitFE_1", DRXD_InitFE_1 ),
|
||||
_BLOB_ENTRY("InitFE_2", DRXD_InitFE_2 ),
|
||||
_BLOB_ENTRY("InitFT", DRXD_InitFT ),
|
||||
_BLOB_ENTRY("InitSC", DRXD_InitSC ),
|
||||
_BLOB_ENTRY("ResetCEFR", DRXD_ResetCEFR ),
|
||||
_BLOB_ENTRY("ResetECRAM", DRXD_ResetECRAM ),
|
||||
_BLOB_ENTRY("microcode", DRXD_microcode ),
|
||||
#undef _BLOB_ENTRY
|
||||
#endif /* _BLOB_ENTRY */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* drxd.h: DRXD DVB-T demodulator driver
|
||||
*
|
||||
* Copyright (C) 2005-2007 Micronas
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 only, 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#ifndef _DRXD_H_
|
||||
#define _DRXD_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
struct drxd_config {
|
||||
u8 index;
|
||||
|
||||
u8 pll_address;
|
||||
u8 pll_type;
|
||||
#define DRXD_PLL_NONE 0
|
||||
#define DRXD_PLL_DTT7520X 1
|
||||
#define DRXD_PLL_MT3X0823 2
|
||||
|
||||
u32 clock;
|
||||
u8 insert_rs_byte;
|
||||
|
||||
u8 demod_address;
|
||||
u8 demoda_address;
|
||||
u8 demod_revision;
|
||||
|
||||
/* If the tuner is not behind an i2c gate, be sure to flip this bit
|
||||
or else the i2c bus could get wedged */
|
||||
u8 disable_i2c_gate_ctrl;
|
||||
|
||||
u32 IF;
|
||||
int (*pll_set) (void *priv, void *priv_params,
|
||||
u8 pll_addr, u8 demoda_addr, s32 *off);
|
||||
s16(*osc_deviation) (void *priv, s16 dev, int flag);
|
||||
};
|
||||
|
||||
extern
|
||||
struct dvb_frontend *drxd_attach(const struct drxd_config *config,
|
||||
void *priv, struct i2c_adapter *i2c,
|
||||
struct device *dev);
|
||||
extern int drxd_config_i2c(struct dvb_frontend *, int);
|
||||
#endif
|
|
@ -0,0 +1,929 @@
|
|||
/*
|
||||
* drxd_firm.c : DRXD firmware tables
|
||||
*
|
||||
* Copyright (C) 2006-2007 Micronas
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 only, 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/* TODO: generate this file with a script from a settings file */
|
||||
|
||||
/* Contains A2 firmware version: 1.4.2
|
||||
* Contains B1 firmware version: 3.3.33
|
||||
* Contains settings from driver 1.4.23
|
||||
*/
|
||||
|
||||
#include "drxd_firm.h"
|
||||
|
||||
#define ADDRESS(x) ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF)
|
||||
#define LENGTH(x) ((x) & 0xFF), (((x)>>8) & 0xFF)
|
||||
|
||||
/* Is written via block write, must be little endian */
|
||||
#define DATA16(x) ((x) & 0xFF), (((x)>>8) & 0xFF)
|
||||
|
||||
#define WRBLOCK(a, l) ADDRESS(a), LENGTH(l)
|
||||
#define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d)
|
||||
|
||||
#define END_OF_TABLE 0xFF, 0xFF, 0xFF, 0xFF
|
||||
|
||||
/* HI firmware patches */
|
||||
|
||||
#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
|
||||
#define HI_TR_FUNC_SIZE 9 /* size of this function in instruction words */
|
||||
|
||||
u8 DRXD_InitAtomicRead[] = {
|
||||
WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE),
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x60, 0x04, /* r0rami.dt -> ring.xba; */
|
||||
0x61, 0x04, /* r0rami.dt -> ring.xad; */
|
||||
0xE3, 0x07, /* HI_RA_RAM_USR_BEGIN -> ring.iad; */
|
||||
0x40, 0x00, /* (long immediate) */
|
||||
0x64, 0x04, /* r0rami.dt -> ring.len; */
|
||||
0x65, 0x04, /* r0rami.dt -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x38, 0x00, /* 0 -> jumps.ad; */
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
/* Pins D0 and D1 of the parallel MPEG output can be used
|
||||
to set the I2C address of a device. */
|
||||
|
||||
#define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE)
|
||||
#define HI_RST_FUNC_SIZE 54 /* size of this function in instruction words */
|
||||
|
||||
/* D0 Version */
|
||||
u8 DRXD_HiI2cPatch_1[] = {
|
||||
WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
|
||||
0xC8, 0x07, 0x01, 0x00, /* MASK -> reg0.dt; */
|
||||
0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
|
||||
0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */
|
||||
0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */
|
||||
0x23, 0x00, /* &data -> ring.iad; */
|
||||
0x24, 0x00, /* 0 -> ring.len; */
|
||||
0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x42, 0x00, /* &data+1 -> w0ram.ad; */
|
||||
0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */
|
||||
0x63, 0x00, /* &data+1 -> ring.iad; */
|
||||
0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */
|
||||
0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */
|
||||
0x23, 0x00, /* &data -> ring.iad; */
|
||||
0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x42, 0x00, /* &data+1 -> w0ram.ad; */
|
||||
0x0F, 0x04, /* r0ram.dt -> and.op; */
|
||||
0x1C, 0x06, /* reg0.dt -> and.tr; */
|
||||
0xCF, 0x04, /* and.rs -> add.op; */
|
||||
0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */
|
||||
0xD0, 0x04, /* add.rs -> add.tr; */
|
||||
0xC8, 0x04, /* add.rs -> reg0.dt; */
|
||||
0x60, 0x00, /* reg0.dt -> w0ram.dt; */
|
||||
0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x06, /* reg0.dt -> w0rami.dt; */
|
||||
0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x06, /* reg0.dt -> w0rami.dt; */
|
||||
0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */
|
||||
0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */
|
||||
0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */
|
||||
0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */
|
||||
0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */
|
||||
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
|
||||
/* Force quick and dirty reset */
|
||||
WR16(B_HI_CT_REG_COMM_STATE__A, 0),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
/* D0,D1 Version */
|
||||
u8 DRXD_HiI2cPatch_3[] = {
|
||||
WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
|
||||
0xC8, 0x07, 0x03, 0x00, /* MASK -> reg0.dt; */
|
||||
0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
|
||||
0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */
|
||||
0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */
|
||||
0x23, 0x00, /* &data -> ring.iad; */
|
||||
0x24, 0x00, /* 0 -> ring.len; */
|
||||
0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x42, 0x00, /* &data+1 -> w0ram.ad; */
|
||||
0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */
|
||||
0x63, 0x00, /* &data+1 -> ring.iad; */
|
||||
0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */
|
||||
0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */
|
||||
0x23, 0x00, /* &data -> ring.iad; */
|
||||
0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */
|
||||
0x26, 0x00, /* 0 -> ring.rdy; */
|
||||
0x42, 0x00, /* &data+1 -> w0ram.ad; */
|
||||
0x0F, 0x04, /* r0ram.dt -> and.op; */
|
||||
0x1C, 0x06, /* reg0.dt -> and.tr; */
|
||||
0xCF, 0x04, /* and.rs -> add.op; */
|
||||
0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */
|
||||
0xD0, 0x04, /* add.rs -> add.tr; */
|
||||
0xC8, 0x04, /* add.rs -> reg0.dt; */
|
||||
0x60, 0x00, /* reg0.dt -> w0ram.dt; */
|
||||
0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x06, /* reg0.dt -> w0rami.dt; */
|
||||
0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x06, /* reg0.dt -> w0rami.dt; */
|
||||
0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x01, 0x00, /* 0 -> w0rami.dt; */
|
||||
0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */
|
||||
0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */
|
||||
0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */
|
||||
0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */
|
||||
0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */
|
||||
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
|
||||
(u16) (HI_RST_FUNC_ADDR & 0x3FF)),
|
||||
|
||||
/* Force quick and dirty reset */
|
||||
WR16(B_HI_CT_REG_COMM_STATE__A, 0),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_ResetCEFR[] = {
|
||||
WRBLOCK(CE_REG_FR_TREAL00__A, 57),
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL00__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG00__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL01__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG01__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL02__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG02__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL03__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG03__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL04__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG04__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL05__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG05__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL06__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG06__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL07__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG07__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL08__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG08__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL09__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG09__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL10__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG10__A */
|
||||
0x52, 0x00, /* CE_REG_FR_TREAL11__A */
|
||||
0x00, 0x00, /* CE_REG_FR_TIMAG11__A */
|
||||
|
||||
0x52, 0x00, /* CE_REG_FR_MID_TAP__A */
|
||||
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G00__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G01__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G02__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G03__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G04__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G05__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G06__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G07__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G08__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G09__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G10__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G11__A */
|
||||
0x0B, 0x00, /* CE_REG_FR_SQS_G12__A */
|
||||
|
||||
0xFF, 0x01, /* CE_REG_FR_RIO_G00__A */
|
||||
0x90, 0x01, /* CE_REG_FR_RIO_G01__A */
|
||||
0x0B, 0x01, /* CE_REG_FR_RIO_G02__A */
|
||||
0xC8, 0x00, /* CE_REG_FR_RIO_G03__A */
|
||||
0xA0, 0x00, /* CE_REG_FR_RIO_G04__A */
|
||||
0x85, 0x00, /* CE_REG_FR_RIO_G05__A */
|
||||
0x72, 0x00, /* CE_REG_FR_RIO_G06__A */
|
||||
0x64, 0x00, /* CE_REG_FR_RIO_G07__A */
|
||||
0x59, 0x00, /* CE_REG_FR_RIO_G08__A */
|
||||
0x50, 0x00, /* CE_REG_FR_RIO_G09__A */
|
||||
0x49, 0x00, /* CE_REG_FR_RIO_G10__A */
|
||||
|
||||
0x10, 0x00, /* CE_REG_FR_MODE__A */
|
||||
0x78, 0x00, /* CE_REG_FR_SQS_TRH__A */
|
||||
0x00, 0x00, /* CE_REG_FR_RIO_GAIN__A */
|
||||
0x00, 0x02, /* CE_REG_FR_BYPASS__A */
|
||||
0x0D, 0x00, /* CE_REG_FR_PM_SET__A */
|
||||
0x07, 0x00, /* CE_REG_FR_ERR_SH__A */
|
||||
0x04, 0x00, /* CE_REG_FR_MAN_SH__A */
|
||||
0x06, 0x00, /* CE_REG_FR_TAP_SH__A */
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitFEA2_1[] = {
|
||||
WRBLOCK(FE_AD_REG_PD__A, 3),
|
||||
0x00, 0x00, /* FE_AD_REG_PD__A */
|
||||
0x01, 0x00, /* FE_AD_REG_INVEXT__A */
|
||||
0x00, 0x00, /* FE_AD_REG_CLKNEG__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2),
|
||||
0x10, 0x00, /* FE_AG_REG_DCE_AUR_CNT__A */
|
||||
0x10, 0x00, /* FE_AG_REG_DCE_RUR_CNT__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2),
|
||||
0x0E, 0x00, /* FE_AG_REG_ACE_AUR_CNT__A */
|
||||
0x00, 0x00, /* FE_AG_REG_ACE_RUR_CNT__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5),
|
||||
0x04, 0x00, /* FE_AG_REG_EGC_FLA_RGN__A */
|
||||
0x1F, 0x00, /* FE_AG_REG_EGC_SLO_RGN__A */
|
||||
0x00, 0x00, /* FE_AG_REG_EGC_JMP_PSN__A */
|
||||
0x00, 0x00, /* FE_AG_REG_EGC_FLA_INC__A */
|
||||
0x00, 0x00, /* FE_AG_REG_EGC_FLA_DEC__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2),
|
||||
0xFF, 0x01, /* FE_AG_REG_GC1_AGC_MAX__A */
|
||||
0x00, 0xFE, /* FE_AG_REG_GC1_AGC_MIN__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_IND_WIN__A, 29),
|
||||
0x00, 0x00, /* FE_AG_REG_IND_WIN__A */
|
||||
0x05, 0x00, /* FE_AG_REG_IND_THD_LOL__A */
|
||||
0x0F, 0x00, /* FE_AG_REG_IND_THD_HIL__A */
|
||||
0x00, 0x00, /* FE_AG_REG_IND_DEL__A don't care */
|
||||
0x1E, 0x00, /* FE_AG_REG_IND_PD1_WRI__A */
|
||||
0x0C, 0x00, /* FE_AG_REG_PDA_AUR_CNT__A */
|
||||
0x00, 0x00, /* FE_AG_REG_PDA_RUR_CNT__A */
|
||||
0x00, 0x00, /* FE_AG_REG_PDA_AVE_DAT__A don't care */
|
||||
0x00, 0x00, /* FE_AG_REG_PDC_RUR_CNT__A */
|
||||
0x01, 0x00, /* FE_AG_REG_PDC_SET_LVL__A */
|
||||
0x02, 0x00, /* FE_AG_REG_PDC_FLA_RGN__A */
|
||||
0x00, 0x00, /* FE_AG_REG_PDC_JMP_PSN__A don't care */
|
||||
0xFF, 0xFF, /* FE_AG_REG_PDC_FLA_STP__A */
|
||||
0xFF, 0xFF, /* FE_AG_REG_PDC_SLO_STP__A */
|
||||
0x00, 0x1F, /* FE_AG_REG_PDC_PD2_WRI__A don't care */
|
||||
0x00, 0x00, /* FE_AG_REG_PDC_MAP_DAT__A don't care */
|
||||
0x02, 0x00, /* FE_AG_REG_PDC_MAX__A */
|
||||
0x0C, 0x00, /* FE_AG_REG_TGA_AUR_CNT__A */
|
||||
0x00, 0x00, /* FE_AG_REG_TGA_RUR_CNT__A */
|
||||
0x00, 0x00, /* FE_AG_REG_TGA_AVE_DAT__A don't care */
|
||||
0x00, 0x00, /* FE_AG_REG_TGC_RUR_CNT__A */
|
||||
0x22, 0x00, /* FE_AG_REG_TGC_SET_LVL__A */
|
||||
0x15, 0x00, /* FE_AG_REG_TGC_FLA_RGN__A */
|
||||
0x00, 0x00, /* FE_AG_REG_TGC_JMP_PSN__A don't care */
|
||||
0x01, 0x00, /* FE_AG_REG_TGC_FLA_STP__A */
|
||||
0x0A, 0x00, /* FE_AG_REG_TGC_SLO_STP__A */
|
||||
0x00, 0x00, /* FE_AG_REG_TGC_MAP_DAT__A don't care */
|
||||
0x10, 0x00, /* FE_AG_REG_FGA_AUR_CNT__A */
|
||||
0x10, 0x00, /* FE_AG_REG_FGA_RUR_CNT__A */
|
||||
|
||||
WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2),
|
||||
0x00, 0x00, /* FE_AG_REG_BGC_FGC_WRI__A */
|
||||
0x00, 0x00, /* FE_AG_REG_BGC_CGC_WRI__A */
|
||||
|
||||
WRBLOCK(FE_FD_REG_SCL__A, 3),
|
||||
0x05, 0x00, /* FE_FD_REG_SCL__A */
|
||||
0x03, 0x00, /* FE_FD_REG_MAX_LEV__A */
|
||||
0x05, 0x00, /* FE_FD_REG_NR__A */
|
||||
|
||||
WRBLOCK(FE_CF_REG_SCL__A, 5),
|
||||
0x16, 0x00, /* FE_CF_REG_SCL__A */
|
||||
0x04, 0x00, /* FE_CF_REG_MAX_LEV__A */
|
||||
0x06, 0x00, /* FE_CF_REG_NR__A */
|
||||
0x00, 0x00, /* FE_CF_REG_IMP_VAL__A */
|
||||
0x01, 0x00, /* FE_CF_REG_MEAS_VAL__A */
|
||||
|
||||
WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2),
|
||||
0x00, 0x08, /* FE_CU_REG_FRM_CNT_RST__A */
|
||||
0x00, 0x00, /* FE_CU_REG_FRM_CNT_STR__A */
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
/* with PGA */
|
||||
/* WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0004), */
|
||||
/* without PGA */
|
||||
/* WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0001), */
|
||||
/* WR16(FE_AG_REG_AG_AGC_SIO__A, (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/
|
||||
/* WR16(FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
|
||||
|
||||
u8 DRXD_InitFEA2_2[] = {
|
||||
WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010),
|
||||
WR16(FE_AG_REG_FGM_WRI__A, 48),
|
||||
/* Activate measurement, activate scale */
|
||||
WR16(FE_FD_REG_MEAS_VAL__A, 0x0001),
|
||||
|
||||
WR16(FE_CU_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_CF_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_IF_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_FD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_FS_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_AD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_AG_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E),
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitFEB1_1[] = {
|
||||
WR16(B_FE_AD_REG_PD__A, 0x0000),
|
||||
WR16(B_FE_AD_REG_CLKNEG__A, 0x0000),
|
||||
WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000),
|
||||
WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000),
|
||||
WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a),
|
||||
WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35),
|
||||
WR16(B_FE_AG_REG_IND_WIN__A, 0),
|
||||
WR16(B_FE_AG_REG_IND_THD_LOL__A, 8),
|
||||
WR16(B_FE_AG_REG_IND_THD_HIL__A, 8),
|
||||
WR16(B_FE_CF_REG_IMP_VAL__A, 1),
|
||||
WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
/* with PGA */
|
||||
/* WR16(B_FE_AG_REG_AG_PGA_MODE__A , 0x0000, 0x0000); */
|
||||
/* without PGA */
|
||||
/* WR16(B_FE_AG_REG_AG_PGA_MODE__A ,
|
||||
B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/
|
||||
/* WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */
|
||||
/* WR16(B_FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
|
||||
|
||||
u8 DRXD_InitFEB1_2[] = {
|
||||
WR16(B_FE_COMM_EXEC__A, 0x0001),
|
||||
|
||||
/* RF-AGC setup */
|
||||
WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C),
|
||||
WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01),
|
||||
WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02),
|
||||
WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF),
|
||||
WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF),
|
||||
WR16(B_FE_AG_REG_PDC_MAX__A, 0x02),
|
||||
WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C),
|
||||
WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22),
|
||||
WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15),
|
||||
WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01),
|
||||
WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A),
|
||||
|
||||
WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0),
|
||||
WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000),
|
||||
WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitCPA2[] = {
|
||||
WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2),
|
||||
0x07, 0x00, /* CP_REG_BR_SPL_OFFSET__A */
|
||||
0x0A, 0x00, /* CP_REG_BR_STR_DEL__A */
|
||||
|
||||
WRBLOCK(CP_REG_RT_ANG_INC0__A, 4),
|
||||
0x00, 0x00, /* CP_REG_RT_ANG_INC0__A */
|
||||
0x00, 0x00, /* CP_REG_RT_ANG_INC1__A */
|
||||
0x03, 0x00, /* CP_REG_RT_DETECT_ENA__A */
|
||||
0x03, 0x00, /* CP_REG_RT_DETECT_TRH__A */
|
||||
|
||||
WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5),
|
||||
0x32, 0x00, /* CP_REG_AC_NEXP_OFFS__A */
|
||||
0x62, 0x00, /* CP_REG_AC_AVER_POW__A */
|
||||
0x82, 0x00, /* CP_REG_AC_MAX_POW__A */
|
||||
0x26, 0x00, /* CP_REG_AC_WEIGHT_MAN__A */
|
||||
0x0F, 0x00, /* CP_REG_AC_WEIGHT_EXP__A */
|
||||
|
||||
WRBLOCK(CP_REG_AC_AMP_MODE__A, 2),
|
||||
0x02, 0x00, /* CP_REG_AC_AMP_MODE__A */
|
||||
0x01, 0x00, /* CP_REG_AC_AMP_FIX__A */
|
||||
|
||||
WR16(CP_REG_INTERVAL__A, 0x0005),
|
||||
WR16(CP_REG_RT_EXP_MARG__A, 0x0004),
|
||||
WR16(CP_REG_AC_ANG_MODE__A, 0x0003),
|
||||
|
||||
WR16(CP_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitCPB1[] = {
|
||||
WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008),
|
||||
WR16(B_CP_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitCEA2[] = {
|
||||
WRBLOCK(CE_REG_AVG_POW__A, 4),
|
||||
0x62, 0x00, /* CE_REG_AVG_POW__A */
|
||||
0x78, 0x00, /* CE_REG_MAX_POW__A */
|
||||
0x62, 0x00, /* CE_REG_ATT__A */
|
||||
0x17, 0x00, /* CE_REG_NRED__A */
|
||||
|
||||
WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2),
|
||||
0x07, 0x00, /* CE_REG_NE_ERR_SELECT__A */
|
||||
0xEB, 0xFF, /* CE_REG_NE_TD_CAL__A */
|
||||
|
||||
WRBLOCK(CE_REG_NE_MIXAVG__A, 2),
|
||||
0x06, 0x00, /* CE_REG_NE_MIXAVG__A */
|
||||
0x00, 0x00, /* CE_REG_NE_NUPD_OFS__A */
|
||||
|
||||
WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2),
|
||||
0x00, 0x00, /* CE_REG_PE_NEXP_OFFS__A */
|
||||
0x00, 0x00, /* CE_REG_PE_TIMESHIFT__A */
|
||||
|
||||
WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3),
|
||||
0x00, 0x01, /* CE_REG_TP_A0_TAP_NEW__A */
|
||||
0x01, 0x00, /* CE_REG_TP_A0_TAP_NEW_VALID__A */
|
||||
0x0E, 0x00, /* CE_REG_TP_A0_MU_LMS_STEP__A */
|
||||
|
||||
WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3),
|
||||
0x00, 0x00, /* CE_REG_TP_A1_TAP_NEW__A */
|
||||
0x01, 0x00, /* CE_REG_TP_A1_TAP_NEW_VALID__A */
|
||||
0x0A, 0x00, /* CE_REG_TP_A1_MU_LMS_STEP__A */
|
||||
|
||||
WRBLOCK(CE_REG_FI_SHT_INCR__A, 2),
|
||||
0x12, 0x00, /* CE_REG_FI_SHT_INCR__A */
|
||||
0x0C, 0x00, /* CE_REG_FI_EXP_NORM__A */
|
||||
|
||||
WRBLOCK(CE_REG_IR_INPUTSEL__A, 3),
|
||||
0x00, 0x00, /* CE_REG_IR_INPUTSEL__A */
|
||||
0x00, 0x00, /* CE_REG_IR_STARTPOS__A */
|
||||
0xFF, 0x00, /* CE_REG_IR_NEXP_THRES__A */
|
||||
|
||||
WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000),
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitCEB1[] = {
|
||||
WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001),
|
||||
WR16(B_CE_REG_FR_PM_SET__A, 0x000D),
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitEQA2[] = {
|
||||
WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4),
|
||||
0x1E, 0x00, /* EQ_REG_OT_QNT_THRES0__A */
|
||||
0x1F, 0x00, /* EQ_REG_OT_QNT_THRES1__A */
|
||||
0x06, 0x00, /* EQ_REG_OT_CSI_STEP__A */
|
||||
0x02, 0x00, /* EQ_REG_OT_CSI_OFFSET__A */
|
||||
|
||||
WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200),
|
||||
WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F),
|
||||
WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)),
|
||||
WR16(EQ_REG_RC_SEL_CAR__A, 0x0002),
|
||||
WR16(EQ_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitEQB1[] = {
|
||||
WR16(B_EQ_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_ResetECRAM[] = {
|
||||
/* Reset packet sync bytes in EC_VD ram */
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
|
||||
|
||||
/* Reset packet sync bytes in EC_RS ram */
|
||||
WR16(EC_RS_EC_RAM__A, 0x0000),
|
||||
WR16(EC_RS_EC_RAM__A + 204, 0x0000),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitECA2[] = {
|
||||
WRBLOCK(EC_SB_REG_CSI_HI__A, 6),
|
||||
0x1F, 0x00, /* EC_SB_REG_CSI_HI__A */
|
||||
0x1E, 0x00, /* EC_SB_REG_CSI_LO__A */
|
||||
0x01, 0x00, /* EC_SB_REG_SMB_TGL__A */
|
||||
0x7F, 0x00, /* EC_SB_REG_SNR_HI__A */
|
||||
0x7F, 0x00, /* EC_SB_REG_SNR_MID__A */
|
||||
0x7F, 0x00, /* EC_SB_REG_SNR_LO__A */
|
||||
|
||||
WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2),
|
||||
0x00, 0x10, /* EC_RS_REG_REQ_PCK_CNT__A */
|
||||
DATA16(EC_RS_REG_VAL_PCK), /* EC_RS_REG_VAL__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
|
||||
0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */
|
||||
0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */
|
||||
0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */
|
||||
0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */
|
||||
0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
|
||||
0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */
|
||||
0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
|
||||
0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */
|
||||
0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */
|
||||
0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */
|
||||
0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */
|
||||
0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */
|
||||
0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */
|
||||
|
||||
WR16(EC_SB_REG_CSI_OFS__A, 0x0001),
|
||||
WR16(EC_VD_REG_FORCE__A, 0x0002),
|
||||
WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001),
|
||||
WR16(EC_VD_REG_RLK_ENA__A, 0x0001),
|
||||
WR16(EC_OD_REG_SYNC__A, 0x0664),
|
||||
WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
|
||||
WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
|
||||
/* Output zero on monitorbus pads, power saving */
|
||||
WR16(EC_OC_REG_OCR_MON_UOS__A,
|
||||
(EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
|
||||
WR16(EC_OC_REG_OCR_MON_WRI__A,
|
||||
EC_OC_REG_OCR_MON_WRI_INIT),
|
||||
|
||||
/* CHK_ERROR(ResetECRAM(demod)); */
|
||||
/* Reset packet sync bytes in EC_VD ram */
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
|
||||
|
||||
/* Reset packet sync bytes in EC_RS ram */
|
||||
WR16(EC_RS_EC_RAM__A, 0x0000),
|
||||
WR16(EC_RS_EC_RAM__A + 204, 0x0000),
|
||||
|
||||
WR16(EC_SB_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(EC_VD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(EC_RS_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitECB1[] = {
|
||||
WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001),
|
||||
WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001),
|
||||
WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001),
|
||||
WR16(B_EC_SB_REG_CSI_LO__A, 0x000c),
|
||||
WR16(B_EC_SB_REG_CSI_HI__A, 0x0018),
|
||||
WR16(B_EC_SB_REG_SNR_HI__A, 0x007f),
|
||||
WR16(B_EC_SB_REG_SNR_MID__A, 0x007f),
|
||||
WR16(B_EC_SB_REG_SNR_LO__A, 0x007f),
|
||||
|
||||
WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002),
|
||||
WR16(B_EC_OC_REG_DTO_PER__A, 0x0006),
|
||||
WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001),
|
||||
WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000),
|
||||
WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D),
|
||||
WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000),
|
||||
|
||||
/* Needed because shadow registers do not have correct default value */
|
||||
WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000),
|
||||
WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000),
|
||||
WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000),
|
||||
WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0),
|
||||
WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000),
|
||||
WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0),
|
||||
WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000),
|
||||
WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0),
|
||||
|
||||
WR16(B_EC_OD_REG_SYNC__A, 0x0664),
|
||||
WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000),
|
||||
|
||||
/* CHK_ERROR(ResetECRAM(demod)); */
|
||||
/* Reset packet sync bytes in EC_VD ram */
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
|
||||
|
||||
/* Reset packet sync bytes in EC_RS ram */
|
||||
WR16(EC_RS_EC_RAM__A, 0x0000),
|
||||
WR16(EC_RS_EC_RAM__A + 204, 0x0000),
|
||||
|
||||
WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001),
|
||||
WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_ResetECA2[] = {
|
||||
|
||||
WR16(EC_OC_REG_COMM_EXEC__A, 0x0000),
|
||||
WR16(EC_OD_REG_COMM_EXEC__A, 0x0000),
|
||||
|
||||
WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
|
||||
0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */
|
||||
0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */
|
||||
0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */
|
||||
0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */
|
||||
0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
|
||||
0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */
|
||||
0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
|
||||
0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */
|
||||
0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */
|
||||
0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */
|
||||
0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */
|
||||
0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */
|
||||
|
||||
WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
|
||||
0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */
|
||||
0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */
|
||||
|
||||
WR16(EC_OD_REG_SYNC__A, 0x0664),
|
||||
WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
|
||||
WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
|
||||
/* Output zero on monitorbus pads, power saving */
|
||||
WR16(EC_OC_REG_OCR_MON_UOS__A,
|
||||
(EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
|
||||
EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
|
||||
WR16(EC_OC_REG_OCR_MON_WRI__A,
|
||||
EC_OC_REG_OCR_MON_WRI_INIT),
|
||||
|
||||
/* CHK_ERROR(ResetECRAM(demod)); */
|
||||
/* Reset packet sync bytes in EC_VD ram */
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
|
||||
WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
|
||||
|
||||
/* Reset packet sync bytes in EC_RS ram */
|
||||
WR16(EC_RS_EC_RAM__A, 0x0000),
|
||||
WR16(EC_RS_EC_RAM__A + 204, 0x0000),
|
||||
|
||||
WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitSC[] = {
|
||||
WR16(SC_COMM_EXEC__A, 0),
|
||||
WR16(SC_COMM_STATE__A, 0),
|
||||
|
||||
#ifdef COMPILE_FOR_QT
|
||||
WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100),
|
||||
#endif
|
||||
|
||||
/* SC is not started, this is done in SetChannels() */
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
/* Diversity settings */
|
||||
|
||||
u8 DRXD_InitDiversityFront[] = {
|
||||
/* Start demod ********* RF in , diversity out **************************** */
|
||||
WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
|
||||
B_SC_RA_RAM_CONFIG_FREQSCAN__M),
|
||||
|
||||
WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7),
|
||||
WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
|
||||
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
|
||||
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
|
||||
WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
|
||||
|
||||
WR16(B_CC_REG_DIVERSITY__A, 0x0001),
|
||||
WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010),
|
||||
WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |
|
||||
B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
|
||||
|
||||
/* 0x2a ), *//* CE to PASS mux */
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_InitDiversityEnd[] = {
|
||||
/* End demod *********** combining RF in and diversity in, MPEG TS out **** */
|
||||
/* disable near/far; switch on timing slave mode */
|
||||
WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
|
||||
B_SC_RA_RAM_CONFIG_FREQSCAN__M |
|
||||
B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M |
|
||||
B_SC_RA_RAM_CONFIG_SLAVE__M |
|
||||
B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M
|
||||
/* MV from CtrlDiversity */
|
||||
),
|
||||
#ifdef DRXDDIV_SRMM_SLAVING
|
||||
WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7),
|
||||
WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7),
|
||||
#else
|
||||
WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7),
|
||||
WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7),
|
||||
#endif
|
||||
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
|
||||
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
|
||||
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
|
||||
WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
|
||||
|
||||
WR16(B_CC_REG_DIVERSITY__A, 0x0001),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_DisableDiversity[] = {
|
||||
WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE),
|
||||
WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A,
|
||||
B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A,
|
||||
B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A,
|
||||
B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A,
|
||||
B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A,
|
||||
B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A,
|
||||
B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE),
|
||||
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A,
|
||||
B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A,
|
||||
B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A,
|
||||
B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A,
|
||||
B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A,
|
||||
B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE),
|
||||
WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A,
|
||||
B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE),
|
||||
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE),
|
||||
WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE),
|
||||
WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE),
|
||||
WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE),
|
||||
|
||||
WR16(B_CC_REG_DIVERSITY__A, 0x0000),
|
||||
WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT), /* combining disabled */
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_StartDiversityFront[] = {
|
||||
/* Start demod, RF in and diversity out, no combining */
|
||||
WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),
|
||||
WR16(B_FE_AD_REG_FDB_IN__A, 0x0),
|
||||
WR16(B_FE_AD_REG_INVEXT__A, 0x0),
|
||||
WR16(B_EQ_REG_COMM_MB__A, 0x12), /* EQ to MB out */
|
||||
WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE | /* CE to PASS mux */
|
||||
B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
|
||||
|
||||
WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2),
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_StartDiversityEnd[] = {
|
||||
/* End demod, combining RF in and diversity in, MPEG TS out */
|
||||
WR16(B_FE_CF_REG_IMP_VAL__A, 0x0), /* disable impulse noise cruncher */
|
||||
WR16(B_FE_AD_REG_INVEXT__A, 0x0), /* clock inversion (for sohard board) */
|
||||
WR16(B_CP_REG_BR_STR_DEL__A, 10), /* apperently no mb delay matching is best */
|
||||
|
||||
WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON | /* org = 0x81 combining enabled */
|
||||
B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
|
||||
B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC),
|
||||
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_DiversityDelay8MHZ[] = {
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
u8 DRXD_DiversityDelay6MHZ[] = /* also used ok for 7 MHz */
|
||||
{
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50),
|
||||
WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50),
|
||||
END_OF_TABLE
|
||||
};
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* drxd_firm.h
|
||||
*
|
||||
* Copyright (C) 2006-2007 Micronas
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 only, 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#ifndef _DRXD_FIRM_H_
|
||||
#define _DRXD_FIRM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "drxd_map_firm.h"
|
||||
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 4
|
||||
#define VERSION_PATCH 23
|
||||
|
||||
#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
|
||||
|
||||
#define DRXD_MAX_RETRIES (1000)
|
||||
#define HI_I2C_DELAY 84
|
||||
#define HI_I2C_BRIDGE_DELAY 750
|
||||
|
||||
#define EQ_TD_TPS_PWR_UNKNOWN 0x00C0 /* Unknown configurations */
|
||||
#define EQ_TD_TPS_PWR_QPSK 0x016a
|
||||
#define EQ_TD_TPS_PWR_QAM16_ALPHAN 0x0195
|
||||
#define EQ_TD_TPS_PWR_QAM16_ALPHA1 0x0195
|
||||
#define EQ_TD_TPS_PWR_QAM16_ALPHA2 0x011E
|
||||
#define EQ_TD_TPS_PWR_QAM16_ALPHA4 0x01CE
|
||||
#define EQ_TD_TPS_PWR_QAM64_ALPHAN 0x019F
|
||||
#define EQ_TD_TPS_PWR_QAM64_ALPHA1 0x019F
|
||||
#define EQ_TD_TPS_PWR_QAM64_ALPHA2 0x00F8
|
||||
#define EQ_TD_TPS_PWR_QAM64_ALPHA4 0x014D
|
||||
|
||||
#define DRXD_DEF_AG_PWD_CONSUMER 0x000E
|
||||
#define DRXD_DEF_AG_PWD_PRO 0x0000
|
||||
#define DRXD_DEF_AG_AGC_SIO 0x0000
|
||||
|
||||
#define DRXD_FE_CTRL_MAX 1023
|
||||
|
||||
#define DRXD_OSCDEV_DO_SCAN (16)
|
||||
|
||||
#define DRXD_OSCDEV_DONT_SCAN (0)
|
||||
|
||||
#define DRXD_OSCDEV_STEP (275)
|
||||
|
||||
#define DRXD_SCAN_TIMEOUT (650)
|
||||
|
||||
#define DRXD_BANDWIDTH_8MHZ_IN_HZ (0x8B8249L)
|
||||
#define DRXD_BANDWIDTH_7MHZ_IN_HZ (0x7A1200L)
|
||||
#define DRXD_BANDWIDTH_6MHZ_IN_HZ (0x68A1B6L)
|
||||
|
||||
#define IRLEN_COARSE_8K (10)
|
||||
#define IRLEN_FINE_8K (10)
|
||||
#define IRLEN_COARSE_2K (7)
|
||||
#define IRLEN_FINE_2K (9)
|
||||
#define DIFF_INVALID (511)
|
||||
#define DIFF_TARGET (4)
|
||||
#define DIFF_MARGIN (1)
|
||||
|
||||
extern u8 DRXD_InitAtomicRead[];
|
||||
extern u8 DRXD_HiI2cPatch_1[];
|
||||
extern u8 DRXD_HiI2cPatch_3[];
|
||||
|
||||
extern u8 DRXD_InitSC[];
|
||||
|
||||
extern u8 DRXD_ResetCEFR[];
|
||||
extern u8 DRXD_InitFEA2_1[];
|
||||
extern u8 DRXD_InitFEA2_2[];
|
||||
extern u8 DRXD_InitCPA2[];
|
||||
extern u8 DRXD_InitCEA2[];
|
||||
extern u8 DRXD_InitEQA2[];
|
||||
extern u8 DRXD_InitECA2[];
|
||||
extern u8 DRXD_ResetECA2[];
|
||||
extern u8 DRXD_ResetECRAM[];
|
||||
|
||||
extern u8 DRXD_A2_microcode[];
|
||||
extern u32 DRXD_A2_microcode_length;
|
||||
|
||||
extern u8 DRXD_InitFEB1_1[];
|
||||
extern u8 DRXD_InitFEB1_2[];
|
||||
extern u8 DRXD_InitCPB1[];
|
||||
extern u8 DRXD_InitCEB1[];
|
||||
extern u8 DRXD_InitEQB1[];
|
||||
extern u8 DRXD_InitECB1[];
|
||||
|
||||
extern u8 DRXD_InitDiversityFront[];
|
||||
extern u8 DRXD_InitDiversityEnd[];
|
||||
extern u8 DRXD_DisableDiversity[];
|
||||
extern u8 DRXD_StartDiversityFront[];
|
||||
extern u8 DRXD_StartDiversityEnd[];
|
||||
|
||||
extern u8 DRXD_DiversityDelay8MHZ[];
|
||||
extern u8 DRXD_DiversityDelay6MHZ[];
|
||||
|
||||
extern u8 DRXD_B1_microcode[];
|
||||
extern u32 DRXD_B1_microcode_length;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -61,7 +61,7 @@ static u8 stv0288_earda_inittab[] = {
|
|||
0x3d, 0x30,
|
||||
0x40, 0x63,
|
||||
0x41, 0x04,
|
||||
0x42, 0x60,
|
||||
0x42, 0x20,
|
||||
0x43, 0x00,
|
||||
0x44, 0x00,
|
||||
0x45, 0x00,
|
||||
|
|
|
@ -218,11 +218,13 @@ static int ix2505v_set_params(struct dvb_frontend *fe,
|
|||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
len = sizeof(data);
|
||||
|
||||
ret |= ix2505v_write(state, data, len);
|
||||
|
||||
data[2] |= 0x4; /* set TM = 1 other bits same */
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
len = 1;
|
||||
ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */
|
||||
|
||||
|
@ -233,12 +235,12 @@ static int ix2505v_set_params(struct dvb_frontend *fe,
|
|||
|
||||
deb_info("Data 2=[%x%x]\n", data[2], data[3]);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
len = 2;
|
||||
ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (state->config->min_delay_ms)
|
||||
msleep(state->config->min_delay_ms);
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ static u8 stv0288_inittab[] = {
|
|||
0x3d, 0x30,
|
||||
0x40, 0x63,
|
||||
0x41, 0x04,
|
||||
0x42, 0x60,
|
||||
0x42, 0x20,
|
||||
0x43, 0x00,
|
||||
0x44, 0x00,
|
||||
0x45, 0x00,
|
||||
|
|
|
@ -64,6 +64,7 @@ struct stv0299_state {
|
|||
fe_code_rate_t fec_inner;
|
||||
int errmode;
|
||||
u32 ucblocks;
|
||||
u8 mcr_reg;
|
||||
};
|
||||
|
||||
#define STATUS_BER 0
|
||||
|
@ -457,6 +458,9 @@ static int stv0299_init (struct dvb_frontend* fe)
|
|||
|
||||
dprintk("stv0299: init chip\n");
|
||||
|
||||
stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg);
|
||||
msleep(50);
|
||||
|
||||
for (i = 0; ; i += 2) {
|
||||
reg = state->config->inittab[i];
|
||||
val = state->config->inittab[i+1];
|
||||
|
@ -464,6 +468,8 @@ static int stv0299_init (struct dvb_frontend* fe)
|
|||
break;
|
||||
if (reg == 0x0c && state->config->op0_off)
|
||||
val &= ~0x10;
|
||||
if (reg == 0x2)
|
||||
state->mcr_reg = val & 0xf;
|
||||
stv0299_writeregI(state, reg, val);
|
||||
}
|
||||
|
||||
|
@ -618,7 +624,7 @@ static int stv0299_sleep(struct dvb_frontend* fe)
|
|||
{
|
||||
struct stv0299_state* state = fe->demodulator_priv;
|
||||
|
||||
stv0299_writeregI(state, 0x02, 0x80);
|
||||
stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg);
|
||||
state->initialised = 0;
|
||||
|
||||
return 0;
|
||||
|
@ -680,7 +686,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
|
|||
state->errmode = STATUS_BER;
|
||||
|
||||
/* check if the demod is there */
|
||||
stv0299_writeregI(state, 0x02, 0x34); /* standby off */
|
||||
stv0299_writeregI(state, 0x02, 0x30); /* standby off */
|
||||
msleep(200);
|
||||
id = stv0299_readreg(state, 0x00);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
|
|||
|
||||
static u8 sharp_z0194a_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x00,
|
||||
0x02, 0x30,
|
||||
0x03, 0x00,
|
||||
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
|
||||
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
static unsigned int verbose;
|
||||
module_param(verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
|
||||
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
|
||||
|
||||
#define DRIVER_NAME "Hopper"
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
static unsigned int verbose;
|
||||
module_param(verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
|
||||
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
|
||||
|
||||
static int devs;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
int __devinit mantis_pci_init(struct mantis_pci *mantis)
|
||||
{
|
||||
u8 revision, latency;
|
||||
u8 latency;
|
||||
struct mantis_hwconfig *config = mantis->hwconfig;
|
||||
struct pci_dev *pdev = mantis->pdev;
|
||||
int err, ret = 0;
|
||||
|
@ -95,9 +95,8 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis)
|
|||
}
|
||||
|
||||
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
|
||||
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
|
||||
mantis->latency = latency;
|
||||
mantis->revision = revision;
|
||||
mantis->revision = pdev->revision;
|
||||
|
||||
dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ",
|
||||
mantis->revision,
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
u8 lgtdqcs001f_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x00,
|
||||
0x02, 0x30,
|
||||
0x03, 0x00,
|
||||
0x04, 0x2a,
|
||||
0x05, 0x85,
|
||||
|
|
|
@ -1090,6 +1090,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
i2c_adap->algo = &pt1_i2c_algo;
|
||||
i2c_adap->algo_data = NULL;
|
||||
i2c_adap->dev.parent = &pdev->dev;
|
||||
strcpy(i2c_adap->name, DRIVER_NAME);
|
||||
i2c_set_adapdata(i2c_adap, pt1);
|
||||
ret = i2c_add_adapter(i2c_adap);
|
||||
if (ret < 0)
|
||||
|
@ -1156,10 +1157,10 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
pt1->power = 0;
|
||||
pt1->reset = 1;
|
||||
pt1_update_power(pt1);
|
||||
err_pt1_cleanup_adapters:
|
||||
pt1_cleanup_adapters(pt1);
|
||||
err_i2c_del_adapter:
|
||||
i2c_del_adapter(i2c_adap);
|
||||
err_pt1_cleanup_adapters:
|
||||
pt1_cleanup_adapters(pt1);
|
||||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(pt1);
|
||||
|
|
|
@ -297,9 +297,8 @@ static void smsusb_term_device(struct usb_interface *intf)
|
|||
if (dev->coredev)
|
||||
smscore_unregister_device(dev->coredev);
|
||||
|
||||
kfree(dev);
|
||||
|
||||
sms_info("device %p destroyed", dev);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
|
|
@ -95,6 +95,8 @@ config DVB_BUDGET_CI
|
|||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0288 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
|
||||
depends on RC_CORE
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "bsru6.h"
|
||||
#include "tda1002x.h"
|
||||
#include "tda827x.h"
|
||||
#include "bsbe1-d01a.h"
|
||||
|
||||
#define MODULE_NAME "budget_ci"
|
||||
|
||||
|
@ -224,6 +225,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
|
|||
case 0x1017:
|
||||
case 0x1019:
|
||||
case 0x101a:
|
||||
case 0x101b:
|
||||
/* for the Technotrend 1500 bundled remote */
|
||||
dev->map_name = RC_MAP_TT_1500;
|
||||
break;
|
||||
|
@ -1388,6 +1390,23 @@ static void frontend_init(struct budget_ci *budget_ci)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */
|
||||
budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);
|
||||
if (budget_ci->budget.dvb_frontend) {
|
||||
if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {
|
||||
if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
|
||||
printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);
|
||||
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
|
||||
budget_ci->budget.dvb_frontend = NULL;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "%s: No STB6000 found!\n", __func__);
|
||||
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
|
||||
budget_ci->budget.dvb_frontend = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1019: // TT S2-3200 PCI
|
||||
/*
|
||||
* NOTE! on some STB0899 versions, the internal PLL takes a longer time
|
||||
|
@ -1518,6 +1537,7 @@ MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
|
|||
MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
|
||||
MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
|
||||
MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
|
||||
MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);
|
||||
|
||||
static struct pci_device_id pci_tbl[] = {
|
||||
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
|
||||
|
@ -1528,6 +1548,7 @@ static struct pci_device_id pci_tbl[] = {
|
|||
MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
|
||||
MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
|
||||
MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
|
||||
MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),
|
||||
{
|
||||
.vendor = 0,
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
my TTUSB, so let it undef'd unless you want to implement another
|
||||
frontend. never tested.
|
||||
|
||||
DEBUG:
|
||||
debug:
|
||||
define it to > 3 for really hardcore debugging. you probably don't want
|
||||
this unless the device doesn't load at all. > 2 for bandwidth statistics.
|
||||
*/
|
||||
|
@ -134,20 +134,19 @@ struct ttusb {
|
|||
/* ugly workaround ... don't know why it's necessary to read */
|
||||
/* all result codes. */
|
||||
|
||||
#define DEBUG 0
|
||||
static int ttusb_cmd(struct ttusb *ttusb,
|
||||
const u8 * data, int len, int needresult)
|
||||
{
|
||||
int actual_len;
|
||||
int err;
|
||||
#if DEBUG >= 3
|
||||
int i;
|
||||
|
||||
printk(">");
|
||||
for (i = 0; i < len; ++i)
|
||||
printk(" %02x", data[i]);
|
||||
printk("\n");
|
||||
#endif
|
||||
if (debug >= 3) {
|
||||
printk(KERN_DEBUG ">");
|
||||
for (i = 0; i < len; ++i)
|
||||
printk(KERN_CONT " %02x", data[i]);
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&ttusb->semusb) < 0)
|
||||
return -EAGAIN;
|
||||
|
@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb,
|
|||
mutex_unlock(&ttusb->semusb);
|
||||
return err;
|
||||
}
|
||||
#if DEBUG >= 3
|
||||
actual_len = ttusb->last_result[3] + 4;
|
||||
printk("<");
|
||||
for (i = 0; i < actual_len; ++i)
|
||||
printk(" %02x", ttusb->last_result[i]);
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
if (debug >= 3) {
|
||||
actual_len = ttusb->last_result[3] + 4;
|
||||
printk(KERN_DEBUG "<");
|
||||
for (i = 0; i < actual_len; ++i)
|
||||
printk(KERN_CONT " %02x", ttusb->last_result[i]);
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
||||
if (!needresult)
|
||||
mutex_unlock(&ttusb->semusb);
|
||||
return 0;
|
||||
|
@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
|
|||
++ttusb->mux_state;
|
||||
else {
|
||||
ttusb->mux_state = 0;
|
||||
#if DEBUG > 3
|
||||
if (ttusb->insync)
|
||||
printk("%02x ", data[-1]);
|
||||
#else
|
||||
if (ttusb->insync) {
|
||||
printk("%s: lost sync.\n",
|
||||
dprintk("%s: %02x\n",
|
||||
__func__, data[-1]);
|
||||
printk(KERN_INFO "%s: lost sync.\n",
|
||||
__func__);
|
||||
ttusb->insync = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
|
|||
static void ttusb_iso_irq(struct urb *urb)
|
||||
{
|
||||
struct ttusb *ttusb = urb->context;
|
||||
struct usb_iso_packet_descriptor *d;
|
||||
u8 *data;
|
||||
int len, i;
|
||||
|
||||
if (!ttusb->iso_streaming)
|
||||
return;
|
||||
|
@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb)
|
|||
#endif
|
||||
|
||||
if (!urb->status) {
|
||||
int i;
|
||||
for (i = 0; i < urb->number_of_packets; ++i) {
|
||||
struct usb_iso_packet_descriptor *d;
|
||||
u8 *data;
|
||||
int len;
|
||||
numpkt++;
|
||||
if (time_after_eq(jiffies, lastj + HZ)) {
|
||||
#if DEBUG > 2
|
||||
printk
|
||||
("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
|
||||
numpkt * HZ / (jiffies - lastj),
|
||||
numts, numstuff, numsec, numinvalid,
|
||||
numts + numstuff + numsec +
|
||||
numinvalid);
|
||||
#endif
|
||||
dprintk("frames/s: %lu (ts: %d, stuff %d, "
|
||||
"sec: %d, invalid: %d, all: %d)\n",
|
||||
numpkt * HZ / (jiffies - lastj),
|
||||
numts, numstuff, numsec, numinvalid,
|
||||
numts + numstuff + numsec + numinvalid);
|
||||
numts = numstuff = numsec = numinvalid = 0;
|
||||
lastj = jiffies;
|
||||
numpkt = 0;
|
||||
|
|
|
@ -174,15 +174,27 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
|
|||
if (retval < 0)
|
||||
goto done;
|
||||
|
||||
/* wait till tune operation has completed */
|
||||
timeout = jiffies + msecs_to_jiffies(tune_timeout);
|
||||
do {
|
||||
retval = si470x_get_register(radio, STATUSRSSI);
|
||||
if (retval < 0)
|
||||
goto stop;
|
||||
timed_out = time_after(jiffies, timeout);
|
||||
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
|
||||
(!timed_out));
|
||||
/* currently I2C driver only uses interrupt way to tune */
|
||||
if (radio->stci_enabled) {
|
||||
INIT_COMPLETION(radio->completion);
|
||||
|
||||
/* wait till tune operation has completed */
|
||||
retval = wait_for_completion_timeout(&radio->completion,
|
||||
msecs_to_jiffies(tune_timeout));
|
||||
if (!retval)
|
||||
timed_out = true;
|
||||
} else {
|
||||
/* wait till tune operation has completed */
|
||||
timeout = jiffies + msecs_to_jiffies(tune_timeout);
|
||||
do {
|
||||
retval = si470x_get_register(radio, STATUSRSSI);
|
||||
if (retval < 0)
|
||||
goto stop;
|
||||
timed_out = time_after(jiffies, timeout);
|
||||
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
|
||||
&& (!timed_out));
|
||||
}
|
||||
|
||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
|
||||
dev_warn(&radio->videodev->dev, "tune does not complete\n");
|
||||
if (timed_out)
|
||||
|
@ -310,15 +322,27 @@ static int si470x_set_seek(struct si470x_device *radio,
|
|||
if (retval < 0)
|
||||
goto done;
|
||||
|
||||
/* wait till seek operation has completed */
|
||||
timeout = jiffies + msecs_to_jiffies(seek_timeout);
|
||||
do {
|
||||
retval = si470x_get_register(radio, STATUSRSSI);
|
||||
if (retval < 0)
|
||||
goto stop;
|
||||
timed_out = time_after(jiffies, timeout);
|
||||
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
|
||||
(!timed_out));
|
||||
/* currently I2C driver only uses interrupt way to seek */
|
||||
if (radio->stci_enabled) {
|
||||
INIT_COMPLETION(radio->completion);
|
||||
|
||||
/* wait till seek operation has completed */
|
||||
retval = wait_for_completion_timeout(&radio->completion,
|
||||
msecs_to_jiffies(seek_timeout));
|
||||
if (!retval)
|
||||
timed_out = true;
|
||||
} else {
|
||||
/* wait till seek operation has completed */
|
||||
timeout = jiffies + msecs_to_jiffies(seek_timeout);
|
||||
do {
|
||||
retval = si470x_get_register(radio, STATUSRSSI);
|
||||
if (retval < 0)
|
||||
goto stop;
|
||||
timed_out = time_after(jiffies, timeout);
|
||||
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
|
||||
&& (!timed_out));
|
||||
}
|
||||
|
||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
|
||||
dev_warn(&radio->videodev->dev, "seek does not complete\n");
|
||||
if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
|
||||
|
|
|
@ -197,8 +197,9 @@ int si470x_fops_open(struct file *file)
|
|||
if (retval < 0)
|
||||
goto done;
|
||||
|
||||
/* enable RDS interrupt */
|
||||
/* enable RDS / STC interrupt */
|
||||
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
|
||||
radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
|
||||
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
|
||||
radio->registers[SYSCONFIG1] |= 0x1 << 2;
|
||||
retval = si470x_set_register(radio, SYSCONFIG1);
|
||||
|
@ -261,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
|
|||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* si470x_i2c_interrupt_work - rds processing function
|
||||
* si470x_i2c_interrupt - interrupt handler
|
||||
*/
|
||||
static void si470x_i2c_interrupt_work(struct work_struct *work)
|
||||
static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct si470x_device *radio = container_of(work,
|
||||
struct si470x_device, radio_work);
|
||||
struct si470x_device *radio = dev_id;
|
||||
unsigned char regnr;
|
||||
unsigned char blocknum;
|
||||
unsigned short bler; /* rds block errors */
|
||||
|
@ -274,21 +274,29 @@ static void si470x_i2c_interrupt_work(struct work_struct *work)
|
|||
unsigned char tmpbuf[3];
|
||||
int retval = 0;
|
||||
|
||||
/* check Seek/Tune Complete */
|
||||
retval = si470x_get_register(radio, STATUSRSSI);
|
||||
if (retval < 0)
|
||||
goto end;
|
||||
|
||||
if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
|
||||
complete(&radio->completion);
|
||||
|
||||
/* safety checks */
|
||||
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
|
||||
return;
|
||||
goto end;
|
||||
|
||||
/* Update RDS registers */
|
||||
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) {
|
||||
for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
|
||||
retval = si470x_get_register(radio, STATUSRSSI + regnr);
|
||||
if (retval < 0)
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* get rds blocks */
|
||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
|
||||
/* No RDS group ready, better luck next time */
|
||||
return;
|
||||
goto end;
|
||||
|
||||
for (blocknum = 0; blocknum < 4; blocknum++) {
|
||||
switch (blocknum) {
|
||||
|
@ -342,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work)
|
|||
|
||||
if (radio->wr_index != radio->rd_index)
|
||||
wake_up_interruptible(&radio->read_queue);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* si470x_i2c_interrupt - interrupt handler
|
||||
*/
|
||||
static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct si470x_device *radio = dev_id;
|
||||
|
||||
if (!work_pending(&radio->radio_work))
|
||||
schedule_work(&radio->radio_work);
|
||||
|
||||
end:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -376,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
|
|||
goto err_initial;
|
||||
}
|
||||
|
||||
INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work);
|
||||
radio->users = 0;
|
||||
radio->client = client;
|
||||
mutex_init(&radio->lock);
|
||||
|
@ -441,7 +437,11 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
|
|||
radio->rd_index = 0;
|
||||
init_waitqueue_head(&radio->read_queue);
|
||||
|
||||
retval = request_irq(client->irq, si470x_i2c_interrupt,
|
||||
/* mark Seek/Tune Complete Interrupt enabled */
|
||||
radio->stci_enabled = true;
|
||||
init_completion(&radio->completion);
|
||||
|
||||
retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
|
||||
IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
|
||||
if (retval) {
|
||||
dev_err(&client->dev, "Failed to register interrupt\n");
|
||||
|
@ -479,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
|
|||
struct si470x_device *radio = i2c_get_clientdata(client);
|
||||
|
||||
free_irq(client->irq, radio);
|
||||
cancel_work_sync(&radio->radio_work);
|
||||
video_unregister_device(radio->videodev);
|
||||
kfree(radio);
|
||||
|
||||
|
@ -491,8 +490,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
|
|||
/*
|
||||
* si470x_i2c_suspend - suspend the device
|
||||
*/
|
||||
static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
static int si470x_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct si470x_device *radio = i2c_get_clientdata(client);
|
||||
|
||||
/* power down */
|
||||
|
@ -507,8 +507,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
|
|||
/*
|
||||
* si470x_i2c_resume - resume the device
|
||||
*/
|
||||
static int si470x_i2c_resume(struct i2c_client *client)
|
||||
static int si470x_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct si470x_device *radio = i2c_get_clientdata(client);
|
||||
|
||||
/* power up : need 110ms */
|
||||
|
@ -519,9 +520,8 @@ static int si470x_i2c_resume(struct i2c_client *client)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define si470x_i2c_suspend NULL
|
||||
#define si470x_i2c_resume NULL
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -532,11 +532,12 @@ static struct i2c_driver si470x_i2c_driver = {
|
|||
.driver = {
|
||||
.name = "si470x",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &si470x_i2c_pm,
|
||||
#endif
|
||||
},
|
||||
.probe = si470x_i2c_probe,
|
||||
.remove = __devexit_p(si470x_i2c_remove),
|
||||
.suspend = si470x_i2c_suspend,
|
||||
.resume = si470x_i2c_resume,
|
||||
.id_table = si470x_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -158,6 +158,9 @@ struct si470x_device {
|
|||
unsigned int rd_index;
|
||||
unsigned int wr_index;
|
||||
|
||||
struct completion completion;
|
||||
bool stci_enabled; /* Seek/Tune Complete Interrupt */
|
||||
|
||||
#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
|
||||
/* reference to USB and video device */
|
||||
struct usb_device *usbdev;
|
||||
|
@ -179,7 +182,6 @@ struct si470x_device {
|
|||
|
||||
#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
|
||||
struct i2c_client *client;
|
||||
struct work_struct radio_work;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -55,8 +55,6 @@
|
|||
#define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */
|
||||
#define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */
|
||||
|
||||
#define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define fmerr(format, ...) \
|
||||
printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__)
|
||||
#define fmwarn(format, ...) \
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue