Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
7d208bb2
Commit
7d208bb2
authored
Apr 07, 2003
by
Alan Cox
Committed by
Linus Torvalds
Apr 07, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] update the dvb front end chips
(Again all DVB is Martin Hunold)
parent
28003225
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2657 additions
and
504 deletions
+2657
-504
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Kconfig
+27
-11
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/Makefile
+2
-1
drivers/media/dvb/frontends/alps_bsrv2.c
drivers/media/dvb/frontends/alps_bsrv2.c
+21
-22
drivers/media/dvb/frontends/alps_tdlb7.c
drivers/media/dvb/frontends/alps_tdlb7.c
+130
-74
drivers/media/dvb/frontends/alps_tdmb7.c
drivers/media/dvb/frontends/alps_tdmb7.c
+23
-15
drivers/media/dvb/frontends/at76c651.c
drivers/media/dvb/frontends/at76c651.c
+542
-0
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/dvb_dummy_fe.c
+219
-0
drivers/media/dvb/frontends/grundig_29504-401.c
drivers/media/dvb/frontends/grundig_29504-401.c
+28
-36
drivers/media/dvb/frontends/grundig_29504-491.c
drivers/media/dvb/frontends/grundig_29504-491.c
+20
-19
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/nxt6000.c
+869
-0
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/nxt6000.h
+301
-0
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.c
+256
-121
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1820.c
+219
-205
No files found.
drivers/media/dvb/frontends/Kconfig
View file @
7d208bb2
comment "Supported Frontend Modules"
depends on DVB
config DVB_
ALPS_BSRU6
tristate "
Alps BSRU6
(QPSK)"
config DVB_
STV0299
tristate "
STV0299 based DVB-S frontend
(QPSK)"
depends on DVB_CORE
help
A DVB-S tuner module.
Say Y when you want to support this frontend.
Say Y when you want to support frontend based on this
demodulator.
Some examples are the Alps BSRU6, the Philips SU1278 and
the LG TDQB-S00x.
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
...
...
@@ -29,22 +33,34 @@ config DVB_ALPS_TDLB7
help
A DVB-T tuner module. Say Y when you want to support this frontend.
This tuner module needs some microcode located in a file called
This tuner module needs some microcode located in a file called
"Sc_main.mc" in the windows driver. Please pass the module parameter
mcfile="/PATH/FILENAME" when loading alps_tdlb7.
mcfile="/PATH/FILENAME" when loading alps_tdlb7.
o.
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
right one will get autodetected.
config DVB_ALPS_TDMB7
tristate "Alps
BSRV2
(OFDM)"
tristate "Alps
TDMB7
(OFDM)"
depends on DVB_CORE
help
A DVB-
S
tuner module. Say Y when you want to support this frontend.
A DVB-
T
tuner module. Say Y when you want to support this frontend.
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
right one will get autodetected.
config DVB_ATMEL_AT76C651
tristate "Atmel AT76C651 (QAM)"
depends on DVB_CORE
help
The AT76C651 Demodulator is used in some DVB-C SetTopBoxes. Say Y
when you see this demodulator chip near your tuner module.
If you don't know what tuner module is soldered on your
DVB adapter simply enable all supported frontends, the
right one will get autodetected.
config DVB_GRUNDIG_29504_491
...
...
drivers/media/dvb/frontends/Makefile
View file @
7d208bb2
...
...
@@ -4,10 +4,11 @@
EXTRA_CFLAGS
=
-Idrivers
/media/dvb/dvb-core/
obj-$(CONFIG_DVB_
ALPS_BSRU6)
+=
alps_bsru6
.o
obj-$(CONFIG_DVB_
STV0299)
+=
stv0299
.o
obj-$(CONFIG_DVB_ALPS_BSRV2)
+=
alps_bsrv2.o
obj-$(CONFIG_DVB_ALPS_TDLB7)
+=
alps_tdlb7.o
obj-$(CONFIG_DVB_ALPS_TDMB7)
+=
alps_tdmb7.o
obj-$(CONFIG_DVB_ATMEL_AT76C651)
+=
at76c651.o
obj-$(CONFIG_DVB_GRUNDIG_29504_491)
+=
grundig_29504-491.o
obj-$(CONFIG_DVB_GRUNDIG_29504_401)
+=
grundig_29504-401.o
obj-$(CONFIG_DVB_VES1820)
+=
ves1820.o
drivers/media/dvb/frontends/alps_bsrv2.c
View file @
7d208bb2
...
...
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
...
...
@@ -32,20 +31,20 @@ static int debug = 0;
static
struct
dvb_frontend_info
bsrv2_info
=
{
.
name
=
"Alps BSRV2"
,
.
type
=
FE_QPSK
,
.
frequency_min
=
950000
,
.
frequency_max
=
2150000
,
.
frequency_stepsize
=
250
,
/* kHz for QPSK frontends */
.
frequency_tolerance
=
29500
,
.
symbol_rate_min
=
1000000
,
.
symbol_rate_max
=
45000000
,
.
notifier_delay
=
50
,
/* 1/20 s
*/
.
caps
=
FE_CAN_INVERSION_AUTO
|
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
name:
"Alps BSRV2"
,
type:
FE_QPSK
,
frequency_min:
950000
,
frequency_max:
2150000
,
frequency_stepsize:
250
,
/* kHz for QPSK frontends */
frequency_tolerance:
29500
,
symbol_rate_min:
1000000
,
symbol_rate_max:
45000000
,
/* symbol_rate_tolerance: ???,
*/
notifier_delay:
50
,
/* 1/20 s */
caps:
FE_CAN_INVERSION_AUTO
|
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
};
...
...
@@ -73,10 +72,10 @@ u8 init_1893_wtab[] =
static
int
ves1893_writereg
(
struct
dvb_i2c_bus
*
i2c
,
int
reg
,
int
data
)
int
ves1893_writereg
(
struct
dvb_i2c_bus
*
i2c
,
u8
reg
,
u8
data
)
{
u8
buf
[]
=
{
0x00
,
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x08
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
3
};
struct
i2c_msg
msg
=
{
addr
:
0x08
,
flags
:
0
,
buf
:
buf
,
len
:
3
};
int
err
;
if
((
err
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
{
...
...
@@ -94,8 +93,8 @@ u8 ves1893_readreg (struct dvb_i2c_bus *i2c, u8 reg)
int
ret
;
u8
b0
[]
=
{
0x00
,
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x08
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
2
},
{
.
addr
=
0x08
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x08
,
flags
:
0
,
buf
:
b0
,
len
:
2
},
{
addr
:
0x08
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -110,7 +109,7 @@ static
int
sp5659_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
])
{
int
ret
;
struct
i2c_msg
msg
=
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x61
,
flags
:
0
,
buf
:
data
,
len
:
4
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
@@ -297,7 +296,7 @@ int ves1893_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
return
ves1893_writereg
(
i2c
,
0x1f
,
0x30
);
default:
return
-
EINVAL
;
}
;
}
}
...
...
@@ -314,7 +313,7 @@ int bsrv2_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case
FE_READ_STATUS
:
{
fe_status_t
*
status
=
arg
;
int
sync
=
ves1893_readreg
(
i2c
,
0x0e
);
u8
sync
=
ves1893_readreg
(
i2c
,
0x0e
);
*
status
=
0
;
...
...
drivers/media/dvb/frontends/alps_tdlb7.c
View file @
7d208bb2
...
...
@@ -51,7 +51,6 @@
#include <linux/fs.h>
#include <linux/unistd.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
...
...
@@ -63,7 +62,7 @@ static char * mcfile = "/usr/lib/DVB/driver/frontends/Sc_main.mc";
#define dprintk if (debug) printk
/* microcode size for sp8870 */
#define SP8870_CODE_SIZE 1638
4
#define SP8870_CODE_SIZE 1638
2
/* starting point for microcode in file 'Sc_main.mc' */
#define SP8870_CODE_OFFSET 0x0A
...
...
@@ -73,15 +72,21 @@ static int errno;
static
struct
dvb_frontend_info
tdlb7_info
=
{
.
name
=
"Alps TDLB7"
,
.
type
=
FE_OFDM
,
.
frequency_min
=
470000000
,
.
frequency_max
=
860000000
,
.
frequency_stepsize
=
166666
,
.
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
name:
"Alps TDLB7"
,
type:
FE_OFDM
,
frequency_min:
470000000
,
frequency_max:
860000000
,
frequency_stepsize:
166666
,
#if 0
frequency_tolerance: ???,
symbol_rate_min: ???,
symbol_rate_max: ???,
symbol_rate_tolerance: ???,
notifier_delay: 0,
#endif
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
};
...
...
@@ -89,7 +94,7 @@ static
int
sp8870_writereg
(
struct
dvb_i2c_bus
*
i2c
,
u16
reg
,
u16
data
)
{
u8
buf
[]
=
{
reg
>>
8
,
reg
&
0xff
,
data
>>
8
,
data
&
0xff
};
struct
i2c_msg
msg
=
{
.
addr
=
0x71
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x71
,
flags
:
0
,
buf
:
buf
,
len
:
4
};
int
err
;
if
((
err
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
{
...
...
@@ -107,8 +112,8 @@ u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
int
ret
;
u8
b0
[]
=
{
reg
>>
8
,
reg
&
0xff
};
u8
b1
[]
=
{
0
,
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x71
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
2
},
{
.
addr
=
0x71
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
2
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x71
,
flags
:
0
,
buf
:
b0
,
len
:
2
},
{
addr
:
0x71
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
2
}
};
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -123,7 +128,7 @@ static
int
sp5659_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
])
{
int
ret
;
struct
i2c_msg
msg
=
{
.
addr
=
0x60
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x60
,
flags
:
0
,
buf
:
data
,
len
:
4
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
@@ -135,10 +140,21 @@ int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
static
int
sp5659_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
u8
pwr
)
int
sp5659_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
)
{
u32
div
=
(
freq
+
36200000
)
/
166666
;
u8
buf
[
4
]
=
{
(
div
>>
8
)
&
0x7f
,
div
&
0xff
,
0x85
,
(
pwr
<<
5
)
|
0x30
};
u8
buf
[
4
];
int
pwr
;
if
(
freq
<=
782000000
)
pwr
=
1
;
else
pwr
=
2
;
buf
[
0
]
=
(
div
>>
8
)
&
0x7f
;
buf
[
1
]
=
div
&
0xff
;
buf
[
2
]
=
0x85
;
buf
[
3
]
=
pwr
<<
6
;
return
sp5659_write
(
i2c
,
buf
);
}
...
...
@@ -193,8 +209,14 @@ int sp8870_load_code(struct dvb_i2c_bus *i2c)
int
c
;
mm_segment_t
fs
=
get_fs
();
sp8870_writereg
(
i2c
,
0x8F08
,
0x1FFF
);
sp8870_writereg
(
i2c
,
0x8F0A
,
0x0000
);
// system controller stop
sp8870_writereg
(
i2c
,
0x0F00
,
0x0000
);
// instruction RAM register hiword
sp8870_writereg
(
i2c
,
0x8F08
,((
SP8870_CODE_SIZE
/
2
)
&
0xFFFF
));
// instruction RAM MWR
sp8870_writereg
(
i2c
,
0x8F0A
,((
SP8870_CODE_SIZE
/
2
)
>>
16
));
set_fs
(
get_ds
());
if
(
sp8870_read_code
(
mcfile
,(
char
**
)
&
lcode
)
<
0
)
return
-
1
;
...
...
@@ -210,7 +232,8 @@ int sp8870_load_code(struct dvb_i2c_bus *i2c)
msg
.
buf
=
buf
;
msg
.
len
=
c
;
if
((
err
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
{
dprintk
(
"%s: i2c error (err == %i)
\n
"
,
__FUNCTION__
,
err
);
dprintk
(
"%s: i2c error (err == %i)
\n
"
,
__FUNCTION__
,
err
);
vfree
(
lcode
);
return
-
EREMOTEIO
;
}
...
...
@@ -228,49 +251,40 @@ int sp8870_init (struct dvb_i2c_bus *i2c)
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
sp8870_readreg
(
i2c
,
0x200
);
sp8870_readreg
(
i2c
,
0x200
);
sp8870_readreg
(
i2c
,
0x0F00
);
/* system controller stop */
sp8870_readreg
(
i2c
,
0x0301
);
/* ???????? */
sp8870_readreg
(
i2c
,
0x0309
);
/* integer carrier offset */
sp8870_readreg
(
i2c
,
0x030A
);
/* fractional carrier offset */
sp8870_readreg
(
i2c
,
0x0311
);
/* filter for 8 Mhz channel */
sp8870_readreg
(
i2c
,
0x0319
);
/* sample rate correction bit [23..17] */
sp8870_readreg
(
i2c
,
0x031A
);
/* sample rate correction bit [16..0] */
sp8870_readreg
(
i2c
,
0x0338
);
/* ???????? */
sp8870_readreg
(
i2c
,
0x0F00
);
sp8870_readreg
(
i2c
,
0x0200
);
// system controller stop
sp8870_writereg
(
i2c
,
0x0F00
,
0x0000
);
if
(
loadcode
)
{
dprintk
(
"%s: loading mcfile '%s' !
\n
"
,
__FUNCTION__
,
mcfile
);
if
(
sp8870_load_code
(
i2c
)
==
0
)
dprintk
(
"%s: microcode loaded!
\n
"
,
__FUNCTION__
);
}
else
{
dprintk
(
"%s: without loading mcfile!
\n
"
,
__FUNCTION__
);
}
// ADC mode: 2 for MT8872, 3 for MT8870/8871
sp8870_writereg
(
i2c
,
0x0301
,
0x0003
);
return
0
;
}
// Reed Solomon parity bytes passed to output
sp8870_writereg
(
i2c
,
0x0C13
,
0x0001
);
// MPEG clock is suppressed if no valid data
sp8870_writereg
(
i2c
,
0x0C14
,
0x0001
);
static
int
sp8870_reset
(
struct
dvb_i2c_bus
*
i2c
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
sp8870_writereg
(
i2c
,
0x0F00
,
0x0000
);
/* system controller stop */
sp8870_writereg
(
i2c
,
0x0301
,
0x0003
);
/* ???????? */
sp8870_writereg
(
i2c
,
0x0309
,
0x0400
);
/* integer carrier offset */
sp8870_writereg
(
i2c
,
0x030A
,
0x0000
);
/* fractional carrier offset */
sp8870_writereg
(
i2c
,
0x0311
,
0x0000
);
/* filter for 8 Mhz channel */
sp8870_writereg
(
i2c
,
0x0319
,
0x000A
);
/* sample rate correction bit [23..17] */
sp8870_writereg
(
i2c
,
0x031A
,
0x0AAB
);
/* sample rate correction bit [16..0] */
sp8870_writereg
(
i2c
,
0x0338
,
0x0000
);
/* ???????? */
sp8870_writereg
(
i2c
,
0x0201
,
0x0000
);
/* interrupts for change of lock or tuner adjustment disabled */
sp8870_writereg
(
i2c
,
0x0F00
,
0x0001
);
/* system controller start */
// sample rate correction bit [23..17]
sp8870_writereg
(
i2c
,
0x0319
,
0x000A
);
return
0
;
// sample rate correction bit [16..0]
sp8870_writereg
(
i2c
,
0x031A
,
0x0AAB
);
// integer carrier offset
sp8870_writereg
(
i2c
,
0x0309
,
0x0400
);
// fractional carrier offset
sp8870_writereg
(
i2c
,
0x030A
,
0x0000
);
// filter for 8 Mhz channel
sp8870_writereg
(
i2c
,
0x0311
,
0x0000
);
// scan order: 2k first = 0x0000, 8k first = 0x0001
sp8870_writereg
(
i2c
,
0x0338
,
0x0000
);
return
0
;
}
static
int
tdlb7_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
...
...
@@ -285,10 +299,10 @@ int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
fe_status_t
*
status
=
arg
;
int
sync
=
sp8870_readreg
(
i2c
,
0x0200
);
int
signal
=
0xff
-
sp8870_readreg
(
i2c
,
0x303
);
*
status
=
0
;
if
(
sync
&
0x04
)
// FIXME: find criteria for having signal
if
(
signal
>
10
)
// FIXME: is 10 the right value ?
*
status
|=
FE_HAS_SIGNAL
;
if
(
sync
&
0x04
)
// FIXME: find criteria
...
...
@@ -309,15 +323,15 @@ int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case
FE_READ_BER
:
{
u32
*
ber
=
(
u32
*
)
arg
;
*
ber
=
sp8870_readreg
(
i2c
,
0x0C07
);
// bit error rate before Viterbi
// bit error rate before Viterbi
*
ber
=
sp8870_readreg
(
i2c
,
0x0C07
);
break
;
}
case
FE_READ_SIGNAL_STRENGTH
:
//
not supported by hardware
?
case
FE_READ_SIGNAL_STRENGTH
:
//
FIXME: correct registers
?
{
s32
*
signal
=
(
s32
*
)
arg
;
*
signal
=
0
;
*
((
u16
*
)
arg
)
=
0xffff
-
((
sp8870_readreg
(
i2c
,
0x306
)
<<
8
)
|
sp8870_readreg
(
i2c
,
0x303
));
break
;
}
...
...
@@ -325,27 +339,64 @@ int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
s32
*
snr
=
(
s32
*
)
arg
;
*
snr
=
0
;
break
;
return
-
EOPNOTSUPP
;
}
case
FE_READ_UNCORRECTED_BLOCKS
:
// not supported by hardware?
{
u32
*
ublocks
=
(
u32
*
)
arg
;
*
ublocks
=
0
;
break
;
return
-
EOPNOTSUPP
;
}
case
FE_SET_FRONTEND
:
{
struct
dvb_frontend_parameters
*
p
=
arg
;
sp5659_set_tv_freq
(
i2c
,
p
->
frequency
,
0
);
// all other parameters are set by the on card
// system controller. Don't know how to pass
// distinct values to the card.
break
;
// system controller stop
sp8870_writereg
(
i2c
,
0x0F00
,
0x0000
);
sp5659_set_tv_freq
(
i2c
,
p
->
frequency
);
// sample rate correction bit [23..17]
sp8870_writereg
(
i2c
,
0x0319
,
0x000A
);
// sample rate correction bit [16..0]
sp8870_writereg
(
i2c
,
0x031A
,
0x0AAB
);
// integer carrier offset
sp8870_writereg
(
i2c
,
0x0309
,
0x0400
);
// fractional carrier offset
sp8870_writereg
(
i2c
,
0x030A
,
0x0000
);
// filter for 6/7/8 Mhz channel
if
(
p
->
u
.
ofdm
.
bandwidth
==
BANDWIDTH_6_MHZ
)
sp8870_writereg
(
i2c
,
0x0311
,
0x0002
);
else
if
(
p
->
u
.
ofdm
.
bandwidth
==
BANDWIDTH_7_MHZ
)
sp8870_writereg
(
i2c
,
0x0311
,
0x0001
);
else
sp8870_writereg
(
i2c
,
0x0311
,
0x0000
);
// scan order: 2k first = 0x0000, 8k first = 0x0001
if
(
p
->
u
.
ofdm
.
transmission_mode
==
TRANSMISSION_MODE_2K
)
sp8870_writereg
(
i2c
,
0x0338
,
0x0000
);
else
sp8870_writereg
(
i2c
,
0x0338
,
0x0001
);
// instruction RAM register loword
sp8870_writereg
(
i2c
,
0x0F09
,
0x0000
);
// instruction RAM register hiword
sp8870_writereg
(
i2c
,
0x0F08
,
0x0000
);
// system controller start
sp8870_writereg
(
i2c
,
0x0F00
,
0x0001
);
break
;
}
case
FE_GET_FRONTEND
:
// how to do this?
case
FE_GET_FRONTEND
:
// FIXME: read known values back from Hardware...
{
break
;
}
...
...
@@ -356,9 +407,6 @@ int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case
FE_INIT
:
return
sp8870_init
(
i2c
);
case
FE_RESET
:
return
sp8870_reset
(
i2c
);
default:
return
-
EOPNOTSUPP
;
};
...
...
@@ -371,13 +419,21 @@ static
int
tdlb7_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
struct
i2c_msg
msg
=
{
.
addr
=
0x71
,
.
flags
=
0
,
.
buf
=
NULL
,
.
len
=
0
};
struct
i2c_msg
msg
=
{
addr
:
0x71
,
flags
:
0
,
buf
:
NULL
,
len
:
0
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
i2c
->
xfer
(
i2c
,
&
msg
,
1
)
!=
1
)
return
-
ENODEV
;
if
(
loadcode
)
{
dprintk
(
"%s: loading mcfile '%s' !
\n
"
,
__FUNCTION__
,
mcfile
);
if
(
sp8870_load_code
(
i2c
)
==
0
)
dprintk
(
"%s: microcode loaded!
\n
"
,
__FUNCTION__
);
}
else
{
dprintk
(
"%s: without loading mcfile!
\n
"
,
__FUNCTION__
);
}
dvb_register_frontend
(
tdlb7_ioctl
,
i2c
,
NULL
,
&
tdlb7_info
);
return
0
;
...
...
drivers/media/dvb/frontends/alps_tdmb7.c
View file @
7d208bb2
...
...
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include "compat.h"
#include "dvb_frontend.h"
...
...
@@ -33,15 +32,22 @@ static int debug = 0;
static
struct
dvb_frontend_info
tdmb7_info
=
{
.
name
=
"Alps TDMB7"
,
.
type
=
FE_OFDM
,
.
frequency_min
=
470000000
,
.
frequency_max
=
860000000
,
.
frequency_stepsize
=
166667
,
.
caps
=
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_AUTO
|
FE_CAN_QPSK
|
FE_CAN_QAM_16
|
FE_CAN_QAM_64
name:
"Alps TDMB7"
,
type:
FE_OFDM
,
frequency_min:
470000000
,
frequency_max:
860000000
,
frequency_stepsize:
166667
,
#if 0
frequency_tolerance: ???,
symbol_rate_min: ???,
symbol_rate_max: ???,
symbol_rate_tolerance: 500, /* ppm */
notifier_delay: 0,
#endif
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_CLEAN_SETUP
|
FE_CAN_RECOVER
};
...
...
@@ -81,7 +87,7 @@ int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{
int
ret
;
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x43
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
2
};
struct
i2c_msg
msg
=
{
addr
:
0x43
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
@@ -101,8 +107,8 @@ u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg)
int
ret
;
u8
b0
[]
=
{
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x43
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
1
},
{
.
addr
=
0x43
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x43
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
0x43
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
@@ -118,7 +124,7 @@ u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg)
static
int
pll_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
])
{
struct
i2c_msg
msg
=
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x61
,
flags
:
0
,
buf
:
data
,
len
:
4
};
int
ret
;
cx22700_writereg
(
i2c
,
0x0a
,
0x00
);
/* open i2c bus switch */
...
...
@@ -350,6 +356,7 @@ int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
case
FE_READ_BER
:
*
((
uint32_t
*
)
arg
)
=
cx22700_readreg
(
i2c
,
0x0c
)
&
0x7f
;
cx22700_writereg
(
i2c
,
0x0c
,
0x00
);
break
;
case
FE_READ_SIGNAL_STRENGTH
:
...
...
@@ -368,6 +375,7 @@ int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
}
case
FE_READ_UNCORRECTED_BLOCKS
:
*
((
uint32_t
*
)
arg
)
=
cx22700_readreg
(
i2c
,
0x0f
);
cx22700_writereg
(
i2c
,
0x0f
,
0x00
);
break
;
case
FE_SET_FRONTEND
:
...
...
@@ -412,7 +420,7 @@ int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
static
int
tdmb7_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
struct
i2c_msg
msg
=
{
.
addr
=
0x43
,
.
flags
=
0
,
.
buf
=
NULL
,
.
len
=
0
};
struct
i2c_msg
msg
=
{
addr
:
0x43
,
flags
:
0
,
buf
:
NULL
,
len
:
0
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
drivers/media/dvb/frontends/at76c651.c
0 → 100644
View file @
7d208bb2
/*
* at76c651.c
*
* Atmel DVB-C Frontend Driver (at76c651/dat7021)
*
* Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
* & 2002 Andreas Oberritter <andreas@oberritter.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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#if defined(__powerpc__)
#include <asm/bitops.h>
#endif
#include "dvb_frontend.h"
#include "dvb_i2c.h"
static
int
debug
=
0
;
#define dprintk if (debug) printk
/*
* DAT7021
* -------
* Input Frequency Range (RF): 48.25 MHz to 863.25 MHz
* Band Width: 8 MHz
* Level Input (Range for Digital Signals): -61 dBm to -41 dBm
* Output Frequency (IF): 36 MHz
*
* (see http://www.atmel.com/atmel/acrobat/doc1320.pdf)
*/
static
struct
dvb_frontend_info
at76c651_info
=
{
.
name
=
"Atmel AT76c651(B) with DAT7021"
,
.
type
=
FE_QAM
,
.
frequency_min
=
48250000
,
.
frequency_max
=
863250000
,
.
frequency_stepsize
=
62500
,
/*.frequency_tolerance = */
/* FIXME: 12% of SR */
.
symbol_rate_min
=
0
,
/* FIXME */
.
symbol_rate_max
=
9360000
,
/* FIXME */
.
symbol_rate_tolerance
=
4000
,
.
notifier_delay
=
0
,
.
caps
=
FE_CAN_INVERSION_AUTO
|
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_4_5
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_6_7
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_8_9
|
FE_CAN_FEC_AUTO
|
FE_CAN_QAM_16
|
FE_CAN_QAM_32
|
FE_CAN_QAM_64
|
FE_CAN_QAM_128
|
FE_CAN_QAM_256
,
/* FE_CAN_QAM_512 | FE_CAN_QAM_1024 | */
};
#if ! defined(__powerpc__)
static
__inline__
int
__ilog2
(
unsigned
long
x
)
{
int
i
;
if
(
x
==
0
)
return
-
1
;
for
(
i
=
0
;
x
!=
0
;
i
++
)
x
>>=
1
;
return
i
-
1
;
}
#endif
static
int
at76c651_writereg
(
struct
dvb_i2c_bus
*
i2c
,
u8
reg
,
u8
data
)
{
int
ret
;
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
addr
:
0x1a
>>
1
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
if
(
ret
!=
1
)
dprintk
(
"%s: writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)
\n
"
,
__FUNCTION__
,
reg
,
data
,
ret
);
mdelay
(
10
);
return
(
ret
!=
1
)
?
-
EREMOTEIO
:
0
;
}
static
u8
at76c651_readreg
(
struct
dvb_i2c_bus
*
i2c
,
u8
reg
)
{
int
ret
;
u8
b0
[]
=
{
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x1a
>>
1
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
0x1a
>>
1
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
if
(
ret
!=
2
)
dprintk
(
"%s: readreg error (ret == %i)
\n
"
,
__FUNCTION__
,
ret
);
return
b1
[
0
];
}
static
int
at76c651_set_auto_config
(
struct
dvb_i2c_bus
*
i2c
)
{
at76c651_writereg
(
i2c
,
0x06
,
0x01
);
/*
* performance optimizations
*/
at76c651_writereg
(
i2c
,
0x10
,
0x06
);
at76c651_writereg
(
i2c
,
0x11
,
0x10
);
at76c651_writereg
(
i2c
,
0x15
,
0x28
);
at76c651_writereg
(
i2c
,
0x20
,
0x09
);
at76c651_writereg
(
i2c
,
0x24
,
0x90
);
return
0
;
}
static
int
at76c651_set_bbfreq
(
struct
dvb_i2c_bus
*
i2c
)
{
at76c651_writereg
(
i2c
,
0x04
,
0x3f
);
at76c651_writereg
(
i2c
,
0x05
,
0xee
);
return
0
;
}
static
int
at76c651_reset
(
struct
dvb_i2c_bus
*
i2c
)
{
return
at76c651_writereg
(
i2c
,
0x07
,
0x01
);
}
static
int
at76c651_disable_interrupts
(
struct
dvb_i2c_bus
*
i2c
)
{
return
at76c651_writereg
(
i2c
,
0x0b
,
0x00
);
}
static
int
at76c651_switch_tuner_i2c
(
struct
dvb_i2c_bus
*
i2c
,
u8
enable
)
{
if
(
enable
)
return
at76c651_writereg
(
i2c
,
0x0c
,
0xc2
|
0x01
);
else
return
at76c651_writereg
(
i2c
,
0x0c
,
0xc2
);
}
static
int
dat7021_write
(
struct
dvb_i2c_bus
*
i2c
,
u32
tw
)
{
int
ret
;
struct
i2c_msg
msg
=
{
addr
:
0xc2
>>
1
,
flags
:
0
,
buf
:
(
u8
*
)
&
tw
,
len
:
sizeof
(
tw
)
};
at76c651_switch_tuner_i2c
(
i2c
,
1
);
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
at76c651_switch_tuner_i2c
(
i2c
,
0
);
if
(
ret
!=
4
)
return
-
EFAULT
;
at76c651_reset
(
i2c
);
return
0
;
}
static
int
dat7021_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
)
{
u32
dw
;
freq
/=
1000
;
if
((
freq
<
48250
)
||
(
freq
>
863250
))
return
-
EINVAL
;
/*
* formula: dw=0x17e28e06+(freq-346000UL)/8000UL*0x800000
* or: dw=0x4E28E06+(freq-42000) / 125 * 0x20000
*/
dw
=
(
freq
-
42000
)
*
4096
;
dw
=
dw
/
125
;
dw
=
dw
*
32
;
if
(
freq
>
394000
)
dw
+=
0x4E28E85
;
else
dw
+=
0x4E28E06
;
return
dat7021_write
(
i2c
,
dw
);
}
static
int
at76c651_set_symbolrate
(
struct
dvb_i2c_bus
*
i2c
,
u32
symbolrate
)
{
u8
exponent
;
u32
mantissa
;
if
(
symbolrate
>
9360000
)
return
-
1
;
/*
* FREF = 57800 kHz
* exponent = 10 + floor ( log2 ( symbolrate / FREF ) )
* mantissa = ( symbolrate / FREF) * ( 1 << ( 30 - exponent ) )
*/
exponent
=
__ilog2
((
symbolrate
<<
4
)
/
903125
);
mantissa
=
((
symbolrate
/
3125
)
*
(
1
<<
(
24
-
exponent
)))
/
289
;
at76c651_writereg
(
i2c
,
0x00
,
mantissa
>>
13
);
at76c651_writereg
(
i2c
,
0x01
,
mantissa
>>
5
);
at76c651_writereg
(
i2c
,
0x02
,
(
mantissa
<<
3
)
|
exponent
);
return
0
;
}
static
int
at76c651_set_qam
(
struct
dvb_i2c_bus
*
i2c
,
fe_modulation_t
qam
)
{
u8
qamsel
=
0
;
switch
(
qam
)
{
case
QPSK
:
qamsel
=
0x02
;
break
;
case
QAM_16
:
qamsel
=
0x04
;
break
;
case
QAM_32
:
qamsel
=
0x05
;
break
;
case
QAM_64
:
qamsel
=
0x06
;
break
;
case
QAM_128
:
qamsel
=
0x07
;
break
;
case
QAM_256
:
qamsel
=
0x08
;
break
;
#if 0
case QAM_512:
qamsel = 0x09;
break;
case QAM_1024:
qamsel = 0x0A;
break;
#endif
default:
return
-
EINVAL
;
}
return
at76c651_writereg
(
i2c
,
0x03
,
qamsel
);
}
static
int
at76c651_set_inversion
(
struct
dvb_i2c_bus
*
i2c
,
fe_spectral_inversion_t
inversion
)
{
u8
feciqinv
=
at76c651_readreg
(
i2c
,
0x60
);
switch
(
inversion
)
{
case
INVERSION_OFF
:
feciqinv
|=
0x02
;
feciqinv
&=
0xFE
;
break
;
case
INVERSION_ON
:
feciqinv
|=
0x03
;
break
;
case
INVERSION_AUTO
:
feciqinv
&=
0xFC
;
break
;
default:
return
-
EINVAL
;
}
return
at76c651_writereg
(
i2c
,
0x60
,
feciqinv
);
}
static
int
at76c651_set_parameters
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_frontend_parameters
*
p
)
{
dat7021_set_tv_freq
(
i2c
,
p
->
frequency
);
at76c651_set_symbolrate
(
i2c
,
p
->
u
.
qam
.
symbol_rate
);
at76c651_set_inversion
(
i2c
,
p
->
inversion
);
at76c651_set_auto_config
(
i2c
);
return
0
;
}
static
int
at76c651_set_defaults
(
struct
dvb_i2c_bus
*
i2c
)
{
at76c651_set_symbolrate
(
i2c
,
6900000
);
at76c651_set_qam
(
i2c
,
QAM_64
);
at76c651_set_bbfreq
(
i2c
);
at76c651_set_auto_config
(
i2c
);
at76c651_disable_interrupts
(
i2c
);
return
0
;
}
static
int
at76c651_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
switch
(
cmd
)
{
case
FE_GET_INFO
:
memcpy
(
arg
,
&
at76c651_info
,
sizeof
(
struct
dvb_frontend_info
));
break
;
case
FE_READ_STATUS
:
{
fe_status_t
*
status
=
(
fe_status_t
*
)
arg
;
u8
sync
;
/*
* Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
*/
sync
=
at76c651_readreg
(
fe
->
i2c
,
0x80
);
*
status
=
0
;
if
(
sync
&
(
0x04
|
0x10
))
/* AGC1 || TIM */
*
status
|=
FE_HAS_SIGNAL
;
if
(
sync
&
0x10
)
/* TIM */
*
status
|=
FE_HAS_CARRIER
;
if
(
sync
&
0x80
)
/* FEC */
*
status
|=
FE_HAS_VITERBI
;
if
(
sync
&
0x40
)
/* CAR */
*
status
|=
FE_HAS_SYNC
;
if
((
sync
&
0xF0
)
==
0xF0
)
/* TIM && EQU && CAR && FEC */
*
status
|=
FE_HAS_LOCK
;
break
;
}
case
FE_READ_BER
:
{
u32
*
ber
=
(
u32
*
)
arg
;
*
ber
=
(
at76c651_readreg
(
fe
->
i2c
,
0x81
)
&
0x0F
)
<<
16
;
*
ber
|=
at76c651_readreg
(
fe
->
i2c
,
0x82
)
<<
8
;
*
ber
|=
at76c651_readreg
(
fe
->
i2c
,
0x83
);
*
ber
*=
10
;
break
;
}
case
FE_READ_SIGNAL_STRENGTH
:
{
u8
gain
=
~
at76c651_readreg
(
fe
->
i2c
,
0x91
);
*
(
s32
*
)
arg
=
(
gain
<<
8
)
|
gain
;
*
(
s32
*
)
arg
=
0x0FFF
;
break
;
}
case
FE_READ_SNR
:
*
(
s32
*
)
arg
=
0xFFFF
-
((
at76c651_readreg
(
fe
->
i2c
,
0x8F
)
<<
8
)
|
at76c651_readreg
(
fe
->
i2c
,
0x90
));
break
;
case
FE_READ_UNCORRECTED_BLOCKS
:
*
(
u32
*
)
arg
=
at76c651_readreg
(
fe
->
i2c
,
0x82
);
break
;
case
FE_SET_FRONTEND
:
return
at76c651_set_parameters
(
fe
->
i2c
,
arg
);
case
FE_GET_FRONTEND
:
break
;
case
FE_SLEEP
:
break
;
case
FE_INIT
:
return
at76c651_set_defaults
(
fe
->
i2c
);
case
FE_RESET
:
return
at76c651_reset
(
fe
->
i2c
);
default:
return
-
ENOSYS
;
}
return
0
;
}
static
int
at76c651_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
if
(
at76c651_readreg
(
i2c
,
0x0e
)
!=
0x65
)
{
dprintk
(
"no AT76C651(B) found
\n
"
);
return
-
ENODEV
;
}
if
(
at76c651_readreg
(
i2c
,
0x0F
)
!=
0x10
)
{
if
(
at76c651_readreg
(
i2c
,
0x0F
)
==
0x11
)
{
dprintk
(
"AT76C651B found
\n
"
);
}
else
{
dprintk
(
"no AT76C651(B) found
\n
"
);
return
-
ENODEV
;
}
}
else
{
dprintk
(
"AT76C651B found
\n
"
);
}
at76c651_set_defaults
(
i2c
);
dvb_register_frontend
(
at76c651_ioctl
,
i2c
,
NULL
,
&
at76c651_info
);
return
0
;
}
static
void
at76c651_detach
(
struct
dvb_i2c_bus
*
i2c
)
{
dvb_unregister_frontend
(
at76c651_ioctl
,
i2c
);
at76c651_disable_interrupts
(
i2c
);
}
static
int
__init
at76c651_init
(
void
)
{
return
dvb_register_i2c_device
(
THIS_MODULE
,
at76c651_attach
,
at76c651_detach
);
}
static
void
__exit
at76c651_exit
(
void
)
{
dvb_unregister_i2c_device
(
at76c651_attach
);
}
module_init
(
at76c651_init
);
module_exit
(
at76c651_exit
);
#ifdef MODULE
MODULE_DESCRIPTION
(
"at76c651/dat7021 dvb-c frontend driver"
);
MODULE_AUTHOR
(
"Andreas Oberritter <andreas@oberritter.de>"
);
#ifdef MODULE_LICENSE
MODULE_LICENSE
(
"GPL"
);
#endif
MODULE_PARM
(
debug
,
"i"
);
#endif
drivers/media/dvb/frontends/dvb_dummy_fe.c
0 → 100644
View file @
7d208bb2
/*
* Driver for Dummy Frontend
*
* Written by Emard <emard@softhome.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#include <linux/module.h>
#include <linux/init.h>
#include "dvb_frontend.h"
static
int
sct
=
0
;
/* depending on module parameter sct deliver different infos
*/
static
struct
dvb_frontend_info
dvb_s_dummyfe_info
=
{
name:
"DVB-S dummy frontend"
,
type:
FE_QPSK
,
frequency_min:
950000
,
frequency_max:
2150000
,
frequency_stepsize:
250
,
/* kHz for QPSK frontends */
frequency_tolerance:
29500
,
symbol_rate_min:
1000000
,
symbol_rate_max:
45000000
,
/* symbol_rate_tolerance: ???,*/
notifier_delay:
50
,
/* 1/20 s */
caps:
FE_CAN_INVERSION_AUTO
|
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
};
static
struct
dvb_frontend_info
dvb_c_dummyfe_info
=
{
.
name
=
"DVB-C dummy frontend"
,
.
type
=
FE_QAM
,
.
frequency_stepsize
=
62500
,
.
frequency_min
=
51000000
,
.
frequency_max
=
858000000
,
.
symbol_rate_min
=
(
57840000
/
2
)
/
64
,
/* SACLK/64 == (XIN/2)/64 */
.
symbol_rate_max
=
(
57840000
/
2
)
/
4
,
/* SACLK/4 */
#if 0
frequency_tolerance: ???,
symbol_rate_tolerance: ???, /* ppm */ /* == 8% (spec p. 5) */
notifier_delay: ?,
#endif
.
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
|
FE_CAN_INVERSION_AUTO
|
FE_CAN_CLEAN_SETUP
};
static
struct
dvb_frontend_info
dvb_t_dummyfe_info
=
{
.
name
=
"DVB-T dummy frontend"
,
.
type
=
FE_OFDM
,
.
frequency_min
=
0
,
.
frequency_max
=
863250000
,
.
frequency_stepsize
=
62500
,
/*.frequency_tolerance = */
/* FIXME: 12% of SR */
.
symbol_rate_min
=
0
,
/* FIXME */
.
symbol_rate_max
=
9360000
,
/* FIXME */
.
symbol_rate_tolerance
=
4000
,
.
notifier_delay
=
0
,
.
caps
=
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_4_5
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_6_7
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_8_9
|
FE_CAN_FEC_AUTO
|
FE_CAN_QAM_16
|
FE_CAN_QAM_64
|
FE_CAN_QAM_AUTO
|
FE_CAN_TRANSMISSION_MODE_AUTO
|
FE_CAN_GUARD_INTERVAL_AUTO
|
FE_CAN_HIERARCHY_AUTO
,
};
struct
dvb_frontend_info
*
frontend_info
(
void
)
{
switch
(
sct
)
{
case
2
:
return
&
dvb_t_dummyfe_info
;
case
1
:
return
&
dvb_c_dummyfe_info
;
case
0
:
default:
return
&
dvb_s_dummyfe_info
;
}
}
static
int
dvbdummyfe_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
switch
(
cmd
)
{
case
FE_GET_INFO
:
memcpy
(
arg
,
frontend_info
(),
sizeof
(
struct
dvb_frontend_info
));
break
;
case
FE_READ_STATUS
:
{
fe_status_t
*
status
=
arg
;
*
status
=
FE_HAS_SIGNAL
|
FE_HAS_CARRIER
|
FE_HAS_VITERBI
|
FE_HAS_SYNC
|
FE_HAS_LOCK
;
break
;
}
case
FE_READ_BER
:
{
u32
*
ber
=
(
u32
*
)
arg
;
*
ber
=
0
;
break
;
}
case
FE_READ_SIGNAL_STRENGTH
:
{
u8
signal
=
0xff
;
*
((
u16
*
)
arg
)
=
(
signal
<<
8
)
|
signal
;
break
;
}
case
FE_READ_SNR
:
{
u8
snr
=
0xf0
;
*
(
u16
*
)
arg
=
(
snr
<<
8
)
|
snr
;
break
;
}
case
FE_READ_UNCORRECTED_BLOCKS
:
*
(
u32
*
)
arg
=
0
;
break
;
case
FE_SET_FRONTEND
:
break
;
case
FE_GET_FRONTEND
:
break
;
case
FE_SLEEP
:
return
0
;
case
FE_INIT
:
return
0
;
case
FE_RESET
:
return
0
;
case
FE_SET_TONE
:
return
-
EOPNOTSUPP
;
case
FE_SET_VOLTAGE
:
return
0
;
default:
return
-
EOPNOTSUPP
;
}
return
0
;
}
static
int
dvbdummyfe_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
dvb_register_frontend
(
dvbdummyfe_ioctl
,
i2c
,
NULL
,
frontend_info
());
return
0
;
}
static
void
dvbdummyfe_detach
(
struct
dvb_i2c_bus
*
i2c
)
{
dvb_unregister_frontend
(
dvbdummyfe_ioctl
,
i2c
);
}
static
int
__init
init_dvbdummyfe
(
void
)
{
return
dvb_register_i2c_device
(
THIS_MODULE
,
dvbdummyfe_attach
,
dvbdummyfe_detach
);
return
0
;
}
static
void
__exit
exit_dvbdummyfe
(
void
)
{
dvb_unregister_i2c_device
(
dvbdummyfe_attach
);
return
;
}
module_init
(
init_dvbdummyfe
);
module_exit
(
exit_dvbdummyfe
);
MODULE_DESCRIPTION
(
"DVB DUMMY Frontend"
);
MODULE_AUTHOR
(
"Emard"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
sct
,
"i"
);
drivers/media/dvb/frontends/grundig_29504-401.c
View file @
7d208bb2
...
...
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
...
...
@@ -34,14 +33,18 @@ static int debug = 0;
struct
dvb_frontend_info
grundig_29504_401_info
=
{
.
name
=
"Grundig 29504-401"
,
.
type
=
FE_OFDM
,
.
frequency_stepsize
=
166666
,
.
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_QPSK
|
FE_CAN_QAM_16
|
FE_CAN_QAM_64
|
FE_CAN_MUTE_TS
name:
"Grundig 29504-401"
,
type:
FE_OFDM
,
/* frequency_min: ???,*/
/* frequency_max: ???,*/
frequency_stepsize:
166666
,
/* frequency_tolerance: ???,*/
/* symbol_rate_tolerance: ???,*/
notifier_delay:
0
,
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_QPSK
|
FE_CAN_QAM_16
|
FE_CAN_QAM_64
|
FE_CAN_MUTE_TS
/*| FE_CAN_CLEAN_SETUP*/
};
...
...
@@ -50,7 +53,7 @@ int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{
int
ret
;
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x55
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
2
};
struct
i2c_msg
msg
=
{
addr
:
0x55
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
if
((
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
dprintk
(
"%s: write_reg error (reg == %02x) = %02x!
\n
"
,
...
...
@@ -66,8 +69,8 @@ u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg)
int
ret
;
u8
b0
[]
=
{
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x55
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
1
},
{
.
addr
=
0x55
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x55
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
0x55
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -82,7 +85,7 @@ static
int
tsa5060_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
])
{
int
ret
;
struct
i2c_msg
msg
=
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x61
,
flags
:
0
,
buf
:
data
,
len
:
4
};
if
((
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
dprintk
(
"%s: write_reg error == %02x!
\n
"
,
__FUNCTION__
,
ret
);
...
...
@@ -97,24 +100,19 @@ int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4])
* frequency offset is 36000000 Hz.
*/
static
int
tsa5060_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
u8
pwr
)
int
tsa5060_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
)
{
u32
div
;
u8
buf
[
4
];
u8
cfg
;
if
(
freq
<
700000000
)
{
div
=
(
36000000
+
freq
)
/
31250
;
cfg
=
0x86
;
}
else
{
div
=
(
36000000
+
freq
)
/
166666
;
cfg
=
0x88
;
}
div
=
(
36000000
+
freq
)
/
166666
;
cfg
=
0x88
;
buf
[
0
]
=
(
div
>>
8
)
&
0x7f
;
buf
[
1
]
=
div
&
0xff
;
buf
[
2
]
=
((
div
>>
10
)
&
0x60
)
|
cfg
;
buf
[
3
]
=
pwr
<<
6
;
buf
[
3
]
=
0xc0
;
return
tsa5060_write
(
i2c
,
buf
);
}
...
...
@@ -175,12 +173,13 @@ int apply_frontend_param (struct dvb_i2c_bus *i2c,
u8
val0x04
;
u8
val0x05
;
u8
val0x06
;
int
bw
=
p
->
bandwidth
-
BANDWIDTH_8_MHZ
;
if
(
param
->
inversion
!=
INVERSION_ON
&&
param
->
inversion
!=
INVERSION_OFF
)
return
-
EINVAL
;
if
(
p
->
bandwidth
<
BANDWIDTH_8_MHZ
||
p
->
bandwidth
>
BANDWIDTH_6_MHZ
)
if
(
bw
<
0
||
bw
>
2
)
return
-
EINVAL
;
if
(
p
->
code_rate_HP
!=
FEC_1_2
&&
p
->
code_rate_HP
!=
FEC_2_3
&&
...
...
@@ -230,6 +229,7 @@ int apply_frontend_param (struct dvb_i2c_bus *i2c,
val0x04
=
(
p
->
transmission_mode
<<
2
)
|
p
->
guard_interval
;
val0x05
=
fec_tab
[
p
->
code_rate_HP
];
if
(
p
->
hierarchy_information
!=
HIERARCHY_NONE
)
val0x05
|=
(
p
->
code_rate_LP
-
FEC_1_2
)
<<
3
;
...
...
@@ -269,7 +269,7 @@ static
void
reset_and_configure
(
struct
dvb_i2c_bus
*
i2c
)
{
u8
buf
[]
=
{
0x06
};
struct
i2c_msg
msg
=
{
.
addr
=
0x00
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
1
};
struct
i2c_msg
msg
=
{
addr
:
0x00
,
flags
:
0
,
buf
:
buf
,
len
:
1
};
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
}
...
...
@@ -307,7 +307,7 @@ int init (struct dvb_i2c_bus *i2c)
/*l64781_writereg (i2c, 0x19, 0x92);*/
/* Everything is two's complement, soft bit and CSI_OUT too */
l64781_writereg
(
i2c
,
0x1e
,
0x
4
9
);
l64781_writereg
(
i2c
,
0x1e
,
0x
0
9
);
return
0
;
}
...
...
@@ -390,9 +390,8 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
{
struct
dvb_frontend_parameters
*
p
=
arg
;
tsa5060_set_tv_freq
(
i2c
,
p
->
frequency
,
3
);
tsa5060_set_tv_freq
(
i2c
,
p
->
frequency
);
apply_frontend_param
(
i2c
,
p
);
// tsa5060_set_tv_freq (i2c, p->frequency, 0);
}
case
FE_GET_FRONTEND
:
/* we could correct the frequency here, but...
...
...
@@ -407,13 +406,6 @@ int grundig_29504_401_ioctl (struct dvb_frontend *fe,
case
FE_INIT
:
return
init
(
i2c
);
case
FE_RESET
:
//reset_afc (i2c);
apply_tps
(
i2c
);
l64781_readreg
(
i2c
,
0x00
);
/* clear interrupt registers... */
l64781_readreg
(
i2c
,
0x01
);
/* dto. */
break
;
default:
dprintk
(
"%s: unknown command !!!
\n
"
,
__FUNCTION__
);
return
-
EINVAL
;
...
...
@@ -428,8 +420,8 @@ int l64781_attach (struct dvb_i2c_bus *i2c)
{
u8
b0
[]
=
{
0x1a
};
u8
b1
[]
=
{
0x00
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x55
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
1
},
{
.
addr
=
0x55
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x55
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
0x55
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
if
(
i2c
->
xfer
(
i2c
,
msg
,
2
)
==
2
)
/* probably an EEPROM... */
return
-
ENODEV
;
...
...
drivers/media/dvb/frontends/grundig_29504-491.c
View file @
7d208bb2
...
...
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
...
...
@@ -36,20 +35,22 @@ static int debug = 0;
static
struct
dvb_frontend_info
grundig_29504_491_info
=
{
.
name
=
"Grundig 29504-491, (TDA8083 based)"
,
.
type
=
FE_QPSK
,
.
frequency_min
=
950000
,
/* FIXME: guessed! */
.
frequency_max
=
1400000
,
/* FIXME: guessed! */
.
frequency_stepsize
=
125
,
/* kHz for QPSK frontends */
.
symbol_rate_min
=
1000000
,
/* FIXME: guessed! */
.
symbol_rate_max
=
45000000
,
/* FIXME: guessed! */
.
caps
=
FE_CAN_INVERSION_AUTO
|
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_4_5
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_6_7
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_8_9
|
FE_CAN_FEC_AUTO
|
FE_CAN_QPSK
|
FE_CAN_MUTE_TS
name:
"Grundig 29504-491, (TDA8083 based)"
,
type:
FE_QPSK
,
frequency_min:
950000
,
/* FIXME: guessed! */
frequency_max:
1400000
,
/* FIXME: guessed! */
frequency_stepsize:
125
,
/* kHz for QPSK frontends */
/* frequency_tolerance: ???,*/
symbol_rate_min:
1000000
,
/* FIXME: guessed! */
symbol_rate_max:
45000000
,
/* FIXME: guessed! */
/* symbol_rate_tolerance: ???,*/
notifier_delay:
0
,
caps:
FE_CAN_INVERSION_AUTO
|
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_4_5
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_6_7
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_8_9
|
FE_CAN_FEC_AUTO
|
FE_CAN_QPSK
|
FE_CAN_MUTE_TS
|
FE_CAN_CLEAN_SETUP
};
...
...
@@ -71,7 +72,7 @@ int tda8083_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{
int
ret
;
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
2
};
struct
i2c_msg
msg
=
{
addr
:
0x68
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
@@ -87,8 +88,8 @@ static
int
tda8083_readregs
(
struct
dvb_i2c_bus
*
i2c
,
u8
reg1
,
u8
*
b
,
u8
len
)
{
int
ret
;
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
&
reg1
,
.
len
=
1
},
{
.
addr
=
0x68
,
.
flags
=
I2C_M_RD
,
.
buf
=
b
,
.
len
=
len
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x68
,
flags
:
0
,
buf
:
&
reg1
,
len
:
1
},
{
addr
:
0x68
,
flags
:
I2C_M_RD
,
buf
:
b
,
len
:
len
}
};
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -115,7 +116,7 @@ static
int
tsa5522_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
])
{
int
ret
;
struct
i2c_msg
msg
=
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
0x61
,
flags
:
0
,
buf
:
data
,
len
:
4
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
drivers/media/dvb/frontends/nxt6000.c
0 → 100644
View file @
7d208bb2
/*
NxtWave Communications - NXT6000 demodulator driver
This driver currently supports:
Alps TDME7 (Tuner: MITEL SP5659)
Alps TDED4 (Tuner: TI ALP510, external Nxt6000)
Copyright (C) 2002-2003 Florian Schirmer <schirmer@taytron.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <asm/io.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "nxt6000.h"
static
int
debug
=
0
;
MODULE_DESCRIPTION
(
"NxtWave NXT6000 DVB demodulator driver"
);
MODULE_AUTHOR
(
"Florian Schirmer"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
debug
,
"i"
);
static
struct
dvb_frontend_info
nxt6000_info
=
{
.
name
=
"NxtWave NXT6000"
,
.
type
=
FE_OFDM
,
.
frequency_min
=
0
,
.
frequency_max
=
863250000
,
.
frequency_stepsize
=
62500
,
/*.frequency_tolerance = */
/* FIXME: 12% of SR */
.
symbol_rate_min
=
0
,
/* FIXME */
.
symbol_rate_max
=
9360000
,
/* FIXME */
.
symbol_rate_tolerance
=
4000
,
.
notifier_delay
=
0
,
.
caps
=
FE_CAN_FEC_1_2
|
FE_CAN_FEC_2_3
|
FE_CAN_FEC_3_4
|
FE_CAN_FEC_4_5
|
FE_CAN_FEC_5_6
|
FE_CAN_FEC_6_7
|
FE_CAN_FEC_7_8
|
FE_CAN_FEC_8_9
|
FE_CAN_FEC_AUTO
|
FE_CAN_QAM_16
|
FE_CAN_QAM_64
|
FE_CAN_QAM_AUTO
|
FE_CAN_TRANSMISSION_MODE_AUTO
|
FE_CAN_GUARD_INTERVAL_AUTO
|
FE_CAN_HIERARCHY_AUTO
,
};
#pragma pack(1)
struct
nxt6000_config
{
u8
demod_addr
;
u8
tuner_addr
;
u8
tuner_type
;
u8
clock_inversion
;
};
#pragma pack()
#define TUNER_TYPE_ALP510 0
#define TUNER_TYPE_SP5659 1
#define FE2NXT(fe) ((struct nxt6000_config *)&(fe->data))
#define FREQ2DIV(freq) ((freq + 36166667) / 166667)
#define dprintk if (debug) printk
static
int
nxt6000_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
addr
,
u8
reg
,
u8
data
)
{
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
addr
:
addr
>>
1
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
int
ret
;
if
((
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
))
!=
1
)
dprintk
(
"nxt6000: nxt6000_write error (addr: 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)
\n
"
,
addr
,
reg
,
data
,
ret
);
return
(
ret
!=
1
)
?
-
EFAULT
:
0
;
}
static
u8
nxt6000_writereg
(
struct
dvb_frontend
*
fe
,
u8
reg
,
u8
data
)
{
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
return
nxt6000_write
(
fe
->
i2c
,
nxt
->
demod_addr
,
reg
,
data
);
}
static
u8
nxt6000_read
(
struct
dvb_i2c_bus
*
i2c
,
u8
addr
,
u8
reg
)
{
int
ret
;
u8
b0
[]
=
{
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msgs
[]
=
{{
addr
:
addr
>>
1
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
addr
>>
1
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}};
ret
=
i2c
->
xfer
(
i2c
,
msgs
,
2
);
if
(
ret
!=
2
)
dprintk
(
"nxt6000: nxt6000_read error (addr: 0x%02X, reg: 0x%02X, ret: %d)
\n
"
,
addr
,
reg
,
ret
);
return
b1
[
0
];
}
static
u8
nxt6000_readreg
(
struct
dvb_frontend
*
fe
,
u8
reg
)
{
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
return
nxt6000_read
(
fe
->
i2c
,
nxt
->
demod_addr
,
reg
);
}
static
int
pll_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
demod_addr
,
u8
tuner_addr
,
u8
*
buf
,
u8
len
)
{
struct
i2c_msg
msg
=
{
addr
:
tuner_addr
>>
1
,
flags
:
0
,
buf
:
buf
,
len
:
len
};
int
ret
;
nxt6000_write
(
i2c
,
demod_addr
,
ENABLE_TUNER_IIC
,
0x01
);
/* open i2c bus switch */
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
nxt6000_write
(
i2c
,
demod_addr
,
ENABLE_TUNER_IIC
,
0x00
);
/* close i2c bus switch */
if
(
ret
!=
1
)
dprintk
(
"nxt6000: pll_write error %d
\n
"
,
ret
);
return
(
ret
!=
1
)
?
-
EFAULT
:
0
;
}
static
int
sp5659_set_tv_freq
(
struct
dvb_frontend
*
fe
,
u32
freq
)
{
u8
buf
[
4
];
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
buf
[
0
]
=
(
FREQ2DIV
(
freq
)
>>
8
)
&
0x7F
;
buf
[
1
]
=
FREQ2DIV
(
freq
)
&
0xFF
;
buf
[
2
]
=
(((
FREQ2DIV
(
freq
)
>>
15
)
&
0x03
)
<<
5
)
|
0x85
;
if
((
freq
>=
174000000
)
&&
(
freq
<
230000000
))
buf
[
3
]
=
0x82
;
else
if
((
freq
>=
470000000
)
&&
(
freq
<
782000000
))
buf
[
3
]
=
0x85
;
else
if
((
freq
>=
782000000
)
&&
(
freq
<
863000000
))
buf
[
3
]
=
0xC5
;
else
return
-
EINVAL
;
return
pll_write
(
fe
->
i2c
,
nxt
->
demod_addr
,
nxt
->
tuner_addr
,
buf
,
4
);
}
static
int
alp510_set_tv_freq
(
struct
dvb_frontend
*
fe
,
u32
freq
)
{
u8
buf
[
4
];
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
buf
[
0
]
=
(
FREQ2DIV
(
freq
)
>>
8
)
&
0x7F
;
buf
[
1
]
=
FREQ2DIV
(
freq
)
&
0xFF
;
buf
[
2
]
=
0x85
;
#if 0
if ((freq >= 47000000) && (freq < 153000000))
buf[3] = 0x01;
else if ((freq >= 153000000) && (freq < 430000000))
buf[3] = 0x02;
else if ((freq >= 430000000) && (freq < 824000000))
buf[3] = 0x08;
else if ((freq >= 824000000) && (freq < 863000000))
buf[3] = 0x88;
else
return -EINVAL;
#else
if
((
freq
>=
47000000
)
&&
(
freq
<
153000000
))
buf
[
3
]
=
0x01
;
else
if
((
freq
>=
153000000
)
&&
(
freq
<
430000000
))
buf
[
3
]
=
0x02
;
else
if
((
freq
>=
430000000
)
&&
(
freq
<
824000000
))
buf
[
3
]
=
0x0C
;
else
if
((
freq
>=
824000000
)
&&
(
freq
<
863000000
))
buf
[
3
]
=
0x8C
;
else
return
-
EINVAL
;
#endif
return
pll_write
(
fe
->
i2c
,
nxt
->
demod_addr
,
nxt
->
tuner_addr
,
buf
,
4
);
}
static
void
nxt6000_reset
(
struct
dvb_frontend
*
fe
)
{
u8
val
;
val
=
nxt6000_readreg
(
fe
,
OFDM_COR_CTL
);
nxt6000_writereg
(
fe
,
OFDM_COR_CTL
,
val
&
~
COREACT
);
nxt6000_writereg
(
fe
,
OFDM_COR_CTL
,
val
|
COREACT
);
}
static
int
nxt6000_set_bandwidth
(
struct
dvb_frontend
*
fe
,
fe_bandwidth_t
bandwidth
)
{
u16
nominal_rate
;
int
result
;
switch
(
bandwidth
)
{
case
BANDWIDTH_6_MHZ
:
nominal_rate
=
0x55B7
;
break
;
case
BANDWIDTH_7_MHZ
:
nominal_rate
=
0x6400
;
break
;
case
BANDWIDTH_8_MHZ
:
nominal_rate
=
0x7249
;
break
;
default:
return
-
EINVAL
;
}
if
((
result
=
nxt6000_writereg
(
fe
,
OFDM_TRL_NOMINALRATE_1
,
nominal_rate
&
0xFF
))
<
0
)
return
result
;
return
nxt6000_writereg
(
fe
,
OFDM_TRL_NOMINALRATE_2
,
(
nominal_rate
>>
8
)
&
0xFF
);
}
static
int
nxt6000_set_guard_interval
(
struct
dvb_frontend
*
fe
,
fe_guard_interval_t
guard_interval
)
{
switch
(
guard_interval
)
{
case
GUARD_INTERVAL_1_32
:
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
0x00
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x03
));
case
GUARD_INTERVAL_1_16
:
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
0x01
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x03
));
case
GUARD_INTERVAL_AUTO
:
case
GUARD_INTERVAL_1_8
:
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
0x02
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x03
));
case
GUARD_INTERVAL_1_4
:
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
0x03
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x03
));
default:
return
-
EINVAL
;
}
}
static
int
nxt6000_set_inversion
(
struct
dvb_frontend
*
fe
,
fe_spectral_inversion_t
inversion
)
{
switch
(
inversion
)
{
case
INVERSION_OFF
:
return
nxt6000_writereg
(
fe
,
OFDM_ITB_CTL
,
0x00
);
case
INVERSION_ON
:
return
nxt6000_writereg
(
fe
,
OFDM_ITB_CTL
,
ITBINV
);
default:
return
-
EINVAL
;
}
}
static
int
nxt6000_set_transmission_mode
(
struct
dvb_frontend
*
fe
,
fe_transmit_mode_t
transmission_mode
)
{
int
result
;
switch
(
transmission_mode
)
{
case
TRANSMISSION_MODE_2K
:
if
((
result
=
nxt6000_writereg
(
fe
,
EN_DMD_RACQ
,
0x00
|
(
nxt6000_readreg
(
fe
,
EN_DMD_RACQ
)
&
~
0x03
)))
<
0
)
return
result
;
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
(
0x00
<<
2
)
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x04
));
case
TRANSMISSION_MODE_8K
:
case
TRANSMISSION_MODE_AUTO
:
if
((
result
=
nxt6000_writereg
(
fe
,
EN_DMD_RACQ
,
0x02
|
(
nxt6000_readreg
(
fe
,
EN_DMD_RACQ
)
&
~
0x03
)))
<
0
)
return
result
;
return
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
(
0x01
<<
2
)
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_MODEGUARD
)
&
~
0x04
));
default:
return
-
EINVAL
;
}
}
static
void
nxt6000_setup
(
struct
dvb_frontend
*
fe
)
{
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
nxt6000_writereg
(
fe
,
RS_COR_SYNC_PARAM
,
SYNC_PARAM
);
nxt6000_writereg
(
fe
,
BER_CTRL
,
/*(1 << 2) |*/
(
0x01
<<
1
)
|
0x01
);
nxt6000_writereg
(
fe
,
VIT_COR_CTL
,
VIT_COR_RESYNC
);
nxt6000_writereg
(
fe
,
OFDM_COR_CTL
,
(
0x01
<<
5
)
|
(
nxt6000_readreg
(
fe
,
OFDM_COR_CTL
)
&
0x0F
));
nxt6000_writereg
(
fe
,
OFDM_COR_MODEGUARD
,
FORCEMODE8K
|
0x02
);
nxt6000_writereg
(
fe
,
OFDM_AGC_CTL
,
AGCLAST
|
INITIAL_AGC_BW
);
nxt6000_writereg
(
fe
,
OFDM_ITB_FREQ_1
,
0x06
);
nxt6000_writereg
(
fe
,
OFDM_ITB_FREQ_2
,
0x31
);
nxt6000_writereg
(
fe
,
OFDM_CAS_CTL
,
(
0x01
<<
7
)
|
(
0x02
<<
3
)
|
0x04
);
nxt6000_writereg
(
fe
,
CAS_FREQ
,
0xBB
);
// CHECKME
nxt6000_writereg
(
fe
,
OFDM_SYR_CTL
,
1
<<
2
);
nxt6000_writereg
(
fe
,
OFDM_PPM_CTL_1
,
PPM256
);
nxt6000_writereg
(
fe
,
OFDM_TRL_NOMINALRATE_1
,
0x49
);
nxt6000_writereg
(
fe
,
OFDM_TRL_NOMINALRATE_2
,
0x72
);
nxt6000_writereg
(
fe
,
ANALOG_CONTROL_0
,
1
<<
5
);
nxt6000_writereg
(
fe
,
EN_DMD_RACQ
,
(
1
<<
7
)
|
(
3
<<
4
)
|
2
);
nxt6000_writereg
(
fe
,
DIAG_CONFIG
,
TB_SET
);
if
(
nxt
->
clock_inversion
)
nxt6000_writereg
(
fe
,
SUB_DIAG_MODE_SEL
,
CLKINVERSION
);
else
nxt6000_writereg
(
fe
,
SUB_DIAG_MODE_SEL
,
0
);
nxt6000_writereg
(
fe
,
TS_FORMAT
,
0
);
}
static
void
nxt6000_dump_status
(
struct
dvb_frontend
*
fe
)
{
u8
val
;
// printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
// printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
// printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
// printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
// printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
// printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
// printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
// printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
// printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
// printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
printk
(
"NXT6000 status:"
);
val
=
nxt6000_readreg
(
fe
,
RS_COR_STAT
);
printk
(
" DATA DESCR LOCK: %d,"
,
val
&
0x01
);
printk
(
" DATA SYNC LOCK: %d,"
,
(
val
>>
1
)
&
0x01
);
val
=
nxt6000_readreg
(
fe
,
VIT_SYNC_STATUS
);
printk
(
" VITERBI LOCK: %d,"
,
(
val
>>
7
)
&
0x01
);
switch
((
val
>>
4
)
&
0x07
)
{
case
0x00
:
printk
(
" VITERBI CODERATE: 1/2,"
);
break
;
case
0x01
:
printk
(
" VITERBI CODERATE: 2/3,"
);
break
;
case
0x02
:
printk
(
" VITERBI CODERATE: 3/4,"
);
break
;
case
0x03
:
printk
(
" VITERBI CODERATE: 5/6,"
);
case
0x04
:
printk
(
" VITERBI CODERATE: 7/8,"
);
break
;
default:
printk
(
" VITERBI CODERATE: Reserved,"
);
}
val
=
nxt6000_readreg
(
fe
,
OFDM_COR_STAT
);
printk
(
" CHCTrack: %d,"
,
(
val
>>
7
)
&
0x01
);
printk
(
" TPSLock: %d,"
,
(
val
>>
6
)
&
0x01
);
printk
(
" SYRLock: %d,"
,
(
val
>>
5
)
&
0x01
);
printk
(
" AGCLock: %d,"
,
(
val
>>
4
)
&
0x01
);
switch
(
val
&
0x0F
)
{
case
0x00
:
printk
(
" CoreState: IDLE,"
);
break
;
case
0x02
:
printk
(
" CoreState: WAIT_AGC,"
);
break
;
case
0x03
:
printk
(
" CoreState: WAIT_SYR,"
);
break
;
case
0x04
:
printk
(
" CoreState: WAIT_PPM,"
);
case
0x01
:
printk
(
" CoreState: WAIT_TRL,"
);
break
;
case
0x05
:
printk
(
" CoreState: WAIT_TPS,"
);
break
;
case
0x06
:
printk
(
" CoreState: MONITOR_TPS,"
);
break
;
default:
printk
(
" CoreState: Reserved,"
);
}
val
=
nxt6000_readreg
(
fe
,
OFDM_SYR_STAT
);
printk
(
" SYRLock: %d,"
,
(
val
>>
4
)
&
0x01
);
printk
(
" SYRMode: %s,"
,
(
val
>>
2
)
&
0x01
?
"8K"
:
"2K"
);
switch
((
val
>>
4
)
&
0x03
)
{
case
0x00
:
printk
(
" SYRGuard: 1/32,"
);
break
;
case
0x01
:
printk
(
" SYRGuard: 1/16,"
);
break
;
case
0x02
:
printk
(
" SYRGuard: 1/8,"
);
break
;
case
0x03
:
printk
(
" SYRGuard: 1/4,"
);
break
;
}
val
=
nxt6000_readreg
(
fe
,
OFDM_TPS_RCVD_3
);
switch
((
val
>>
4
)
&
0x07
)
{
case
0x00
:
printk
(
" TPSLP: 1/2,"
);
break
;
case
0x01
:
printk
(
" TPSLP: 2/3,"
);
break
;
case
0x02
:
printk
(
" TPSLP: 3/4,"
);
break
;
case
0x03
:
printk
(
" TPSLP: 5/6,"
);
case
0x04
:
printk
(
" TPSLP: 7/8,"
);
break
;
default:
printk
(
" TPSLP: Reserved,"
);
}
switch
(
val
&
0x07
)
{
case
0x00
:
printk
(
" TPSHP: 1/2,"
);
break
;
case
0x01
:
printk
(
" TPSHP: 2/3,"
);
break
;
case
0x02
:
printk
(
" TPSHP: 3/4,"
);
break
;
case
0x03
:
printk
(
" TPSHP: 5/6,"
);
case
0x04
:
printk
(
" TPSHP: 7/8,"
);
break
;
default:
printk
(
" TPSHP: Reserved,"
);
}
val
=
nxt6000_readreg
(
fe
,
OFDM_TPS_RCVD_4
);
printk
(
" TPSMode: %s,"
,
val
&
0x01
?
"8K"
:
"2K"
);
switch
((
val
>>
4
)
&
0x03
)
{
case
0x00
:
printk
(
" TPSGuard: 1/32,"
);
break
;
case
0x01
:
printk
(
" TPSGuard: 1/16,"
);
break
;
case
0x02
:
printk
(
" TPSGuard: 1/8,"
);
break
;
case
0x03
:
printk
(
" TPSGuard: 1/4,"
);
break
;
}
// Strange magic required to gain access to RF_AGC_STATUS
nxt6000_readreg
(
fe
,
RF_AGC_VAL_1
);
val
=
nxt6000_readreg
(
fe
,
RF_AGC_STATUS
);
val
=
nxt6000_readreg
(
fe
,
RF_AGC_STATUS
);
printk
(
" RF AGC LOCK: %d,"
,
(
val
>>
4
)
&
0x01
);
printk
(
"
\n
"
);
}
static
int
nxt6000_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
switch
(
cmd
)
{
case
FE_GET_INFO
:
memcpy
(
arg
,
&
nxt6000_info
,
sizeof
(
struct
dvb_frontend_info
));
return
0
;
case
FE_READ_STATUS
:
{
fe_status_t
*
status
=
(
fe_status_t
*
)
arg
;
u8
core_status
;
*
status
=
0
;
core_status
=
nxt6000_readreg
(
fe
,
OFDM_COR_STAT
);
if
(
core_status
&
AGCLOCKED
)
*
status
|=
FE_HAS_SIGNAL
;
if
(
nxt6000_readreg
(
fe
,
OFDM_SYR_STAT
)
&
GI14_SYR_LOCK
)
*
status
|=
FE_HAS_CARRIER
;
if
(
nxt6000_readreg
(
fe
,
VIT_SYNC_STATUS
)
&
VITINSYNC
)
*
status
|=
FE_HAS_VITERBI
;
if
(
nxt6000_readreg
(
fe
,
RS_COR_STAT
)
&
RSCORESTATUS
)
*
status
|=
FE_HAS_SYNC
;
if
((
core_status
&
TPSLOCKED
)
&&
(
*
status
==
(
FE_HAS_SIGNAL
|
FE_HAS_CARRIER
|
FE_HAS_VITERBI
|
FE_HAS_SYNC
)))
*
status
|=
FE_HAS_LOCK
;
if
(
debug
)
nxt6000_dump_status
(
fe
);
return
0
;
}
case
FE_READ_BER
:
{
u32
*
ber
=
(
u32
*
)
arg
;
*
ber
=
0
;
return
0
;
}
case
FE_READ_SIGNAL_STRENGTH
:
{
// s16 *signal = (s16 *)arg;
// *signal=(((signed char)readreg(client, 0x16))+128)<<8;
return
0
;
}
case
FE_READ_SNR
:
{
// s16 *snr = (s16 *)arg;
// *snr=readreg(client, 0x24)<<8;
// *snr|=readreg(client, 0x25);
break
;
}
case
FE_READ_UNCORRECTED_BLOCKS
:
{
u32
*
ublocks
=
(
u32
*
)
arg
;
*
ublocks
=
0
;
break
;
}
case
FE_INIT
:
case
FE_RESET
:
nxt6000_reset
(
fe
);
nxt6000_setup
(
fe
);
break
;
case
FE_SET_FRONTEND
:
{
struct
nxt6000_config
*
nxt
=
FE2NXT
(
fe
);
struct
dvb_frontend_parameters
*
param
=
(
struct
dvb_frontend_parameters
*
)
arg
;
int
result
;
switch
(
nxt
->
tuner_type
)
{
case
TUNER_TYPE_ALP510
:
if
((
result
=
alp510_set_tv_freq
(
fe
,
param
->
frequency
))
<
0
)
return
result
;
break
;
case
TUNER_TYPE_SP5659
:
if
((
result
=
sp5659_set_tv_freq
(
fe
,
param
->
frequency
))
<
0
)
return
result
;
break
;
default:
return
-
EFAULT
;
}
if
((
result
=
nxt6000_set_bandwidth
(
fe
,
param
->
u
.
ofdm
.
bandwidth
))
<
0
)
return
result
;
if
((
result
=
nxt6000_set_guard_interval
(
fe
,
param
->
u
.
ofdm
.
guard_interval
))
<
0
)
return
result
;
if
((
result
=
nxt6000_set_transmission_mode
(
fe
,
param
->
u
.
ofdm
.
transmission_mode
))
<
0
)
return
result
;
if
((
result
=
nxt6000_set_inversion
(
fe
,
param
->
inversion
))
<
0
)
return
result
;
break
;
}
default:
return
-
EOPNOTSUPP
;
}
return
0
;
}
static
u8
demod_addr_tbl
[]
=
{
0x14
,
0x18
,
0x24
,
0x28
};
static
int
nxt6000_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
u8
addr_nr
;
u8
fe_count
=
0
;
struct
nxt6000_config
nxt
;
dprintk
(
"nxt6000: attach
\n
"
);
for
(
addr_nr
=
0
;
addr_nr
<
sizeof
(
demod_addr_tbl
);
addr_nr
++
)
{
if
(
nxt6000_read
(
i2c
,
demod_addr_tbl
[
addr_nr
],
OFDM_MSC_REV
)
!=
NXT6000ASICDEVICE
)
continue
;
if
(
pll_write
(
i2c
,
demod_addr_tbl
[
addr_nr
],
0xC0
,
NULL
,
0
)
==
0
)
{
nxt
.
tuner_addr
=
0xC0
;
nxt
.
tuner_type
=
TUNER_TYPE_ALP510
;
nxt
.
clock_inversion
=
1
;
dprintk
(
"nxt6000: detected TI ALP510 tuner at 0x%02X
\n
"
,
nxt
.
tuner_addr
);
}
else
if
(
pll_write
(
i2c
,
demod_addr_tbl
[
addr_nr
],
0xC2
,
NULL
,
0
)
==
0
)
{
nxt
.
tuner_addr
=
0xC2
;
nxt
.
tuner_type
=
TUNER_TYPE_SP5659
;
nxt
.
clock_inversion
=
0
;
dprintk
(
"nxt6000: detected MITEL SP5659 tuner at 0x%02X
\n
"
,
nxt
.
tuner_addr
);
}
else
{
printk
(
"nxt6000: unable to detect tuner
\n
"
);
continue
;
}
nxt
.
demod_addr
=
demod_addr_tbl
[
addr_nr
];
dprintk
(
"nxt6000: attached at %d:%d
\n
"
,
i2c
->
adapter
->
num
,
i2c
->
id
);
dvb_register_frontend
(
nxt6000_ioctl
,
i2c
,
(
void
*
)(
*
((
u32
*
)
&
nxt
)),
&
nxt6000_info
);
}
return
(
fe_count
>
0
)
?
0
:
-
ENODEV
;
}
static
void
nxt6000_detach
(
struct
dvb_i2c_bus
*
i2c
)
{
dprintk
(
"nxt6000: detach
\n
"
);
dvb_unregister_frontend
(
nxt6000_ioctl
,
i2c
);
}
static
__init
int
nxt6000_init
(
void
)
{
dprintk
(
"nxt6000: init
\n
"
);
return
dvb_register_i2c_device
(
THIS_MODULE
,
nxt6000_attach
,
nxt6000_detach
);
}
static
__exit
void
nxt6000_exit
(
void
)
{
dprintk
(
"nxt6000: cleanup
\n
"
);
dvb_unregister_i2c_device
(
nxt6000_attach
);
}
module_init
(
nxt6000_init
);
module_exit
(
nxt6000_exit
);
drivers/media/dvb/frontends/nxt6000.h
0 → 100644
View file @
7d208bb2
/**********************************************************************/
*
DRV6000reg
.
H
*
Public
Include
File
for
DRV6000
users
*
*
Copyright
(
C
)
2001
NxtWave
Communications
,
Inc
.
*
*
$
Log
:
nxt6000
.
h
,
v
$
*
Revision
1
.
2
2003
/
01
/
27
12
:
32
:
42
fschirmer
*
Lots
of
bugfixes
and
new
features
*
*
Revision
1
.
1
2003
/
01
/
21
18
:
43
:
09
fschirmer
*
Nxt6000
based
frontend
driver
*
*
Revision
1
.
1
2003
/
01
/
03
02
:
25
:
45
obi
*
alps
tdme7
driver
*
*
*
Rev
1
.
10
Jun
12
2002
11
:
28
:
02
dkoeger
*
Updated
for
SA
in
GUi
work
*
*
Rev
1
.
9
Apr
01
2002
10
:
38
:
46
dkoeger
*
Updated
for
1
.
0
.
31
GUI
*
*
Rev
1
.
8
Mar
11
2002
10
:
04
:
56
dkoeger
*
Updated
for
1
.
0
.
31
GUI
version
*
*
Rev
1
.
5
Dec
07
2001
14
:
40
:
40
dkoeger
*
Updated
for
1
.
0
.
28
GUI
*
*
Rev
1
.
4
Nov
13
2001
11
:
09
:
00
dkoeger
*
No
change
.
*
*
Rev
1
.
3
Aug
23
2001
14
:
21
:
02
dkoeger
*
Updated
for
driver
version
2
.
1
.
9
*
*
Rev
1
.
2
Jul
09
2001
09
:
20
:
04
dkoeger
*
Updated
for
1
.
0
.
18
*
*
Rev
1
.
1
Jun
13
2001
16
:
14
:
24
dkoeger
*
Updated
to
reflect
NXT6000
GUI
BETA
1
.
0
.
11
6
/
13
/
2001
*********************************************************************
*/
/* Nxt6000 Register Addresses and Bit Masks */
/* Maximum Register Number */
#define MAXNXT6000REG (0x9A)
/* 0x1B A_VIT_BER_0 aka 0x3A */
#define A_VIT_BER_0 (0x1B)
/* 0x1D A_VIT_BER_TIMER_0 aka 0x38 */
#define A_VIT_BER_TIMER_0 (0x1D)
/* 0x21 RS_COR_STAT */
#define RS_COR_STAT (0x21)
#define RSCORESTATUS (0x03)
/* 0x22 RS_COR_INTEN */
#define RS_COR_INTEN (0x22)
/* 0x23 RS_COR_INSTAT */
#define RS_COR_INSTAT (0x23)
#define INSTAT_ERROR (0x04)
#define LOCK_LOSS_BITS (0x03)
/* 0x24 RS_COR_SYNC_PARAM */
#define RS_COR_SYNC_PARAM (0x24)
#define SYNC_PARAM (0x03)
/* 0x25 BER_CTRL */
#define BER_CTRL (0x25)
#define BER_ENABLE (0x02)
#define BER_RESET (0x01)
/* 0x26 BER_PAY */
#define BER_PAY (0x26)
/* 0x27 BER_PKT_L */
#define BER_PKT_L (0x27)
#define BER_PKTOVERFLOW (0x80)
/* 0x30 VIT_COR_CTL */
#define VIT_COR_CTL (0x30)
#define BER_CONTROL (0x02)
#define VIT_COR_MASK (0x82)
#define VIT_COR_RESYNC (0x80)
/* 0x32 VIT_SYNC_STATUS */
#define VIT_SYNC_STATUS (0x32)
#define VITINSYNC (0x80)
/* 0x33 VIT_COR_INTEN */
#define VIT_COR_INTEN (0x33)
#define GLOBAL_ENABLE (0x80)
/* 0x34 VIT_COR_INTSTAT */
#define VIT_COR_INTSTAT (0x34)
#define BER_DONE (0x08)
#define BER_OVERFLOW (0x10)
/* 0x38 OFDM_BERTimer */
/* Use the alias registers */
#define A_VIT_BER_TIMER_0 (0x1D)
/* 0x3A VIT_BER_TIMER_0 */
/* Use the alias registers */
#define A_VIT_BER_0 (0x1B)
/* 0x40 OFDM_COR_CTL */
#define OFDM_COR_CTL (0x40)
#define COREACT (0x20)
#define HOLDSM (0x10)
#define WAIT_AGC (0x02)
#define WAIT_SYR (0x03)
/* 0x41 OFDM_COR_STAT */
#define OFDM_COR_STAT (0x41)
#define COR_STATUS (0x0F)
#define MONITOR_TPS (0x06)
#define TPSLOCKED (0x40)
#define AGCLOCKED (0x10)
/* 0x42 OFDM_COR_INTEN */
#define OFDM_COR_INTEN (0x42)
#define TPSRCVBAD (0x04)
#define TPSRCVCHANGED (0x02)
#define TPSRCVUPDATE (0x01)
/* 0x43 OFDM_COR_INSTAT */
#define OFDM_COR_INSTAT (0x43)
/* 0x44 OFDM_COR_MODEGUARD */
#define OFDM_COR_MODEGUARD (0x44)
#define FORCEMODE (0x08)
#define FORCEMODE8K (0x04)
/* 0x45 OFDM_AGC_CTL */
#define OFDM_AGC_CTL (0x45)
#define INITIAL_AGC_BW (0x08)
#define AGCNEG (0x02)
#define AGCLAST (0x10)
/* 0x48 OFDM_AGC_TARGET */
#define OFDM_AGC_TARGET (0x48)
#define OFDM_AGC_TARGET_DEFAULT (0x28)
#define OFDM_AGC_TARGET_IMPULSE (0x38)
/* 0x49 OFDM_AGC_GAIN_1 */
#define OFDM_AGC_GAIN_1 (0x49)
/* 0x4B OFDM_ITB_CTL */
#define OFDM_ITB_CTL (0x4B)
#define ITBINV (0x01)
/* 0x4C OFDM_ITB_FREQ_1 */
#define OFDM_ITB_FREQ_1 (0x4C)
/* 0x4D OFDM_ITB_FREQ_2 */
#define OFDM_ITB_FREQ_2 (0x4D)
/* 0x4E OFDM_CAS_CTL */
#define OFDM_CAS_CTL (0x4E)
#define ACSDIS (0x40)
#define CCSEN (0x80)
/* 0x4F CAS_FREQ */
#define CAS_FREQ (0x4F)
/* 0x51 OFDM_SYR_CTL */
#define OFDM_SYR_CTL (0x51)
#define SIXTH_ENABLE (0x80)
#define SYR_TRACKING_DISABLE (0x01)
/* 0x52 OFDM_SYR_STAT */
#define OFDM_SYR_STAT (0x52)
#define GI14_2K_SYR_LOCK (0x13)
#define GI14_8K_SYR_LOCK (0x17)
#define GI14_SYR_LOCK (0x10)
/* 0x55 OFDM_SYR_OFFSET_1 */
#define OFDM_SYR_OFFSET_1 (0x55)
/* 0x56 OFDM_SYR_OFFSET_2 */
#define OFDM_SYR_OFFSET_2 (0x56)
/* 0x58 OFDM_SCR_CTL */
#define OFDM_SCR_CTL (0x58)
#define SYR_ADJ_DECAY_MASK (0x70)
#define SYR_ADJ_DECAY (0x30)
/* 0x59 OFDM_PPM_CTL_1 */
#define OFDM_PPM_CTL_1 (0x59)
#define PPMMAX_MASK (0x30)
#define PPM256 (0x30)
/* 0x5B OFDM_TRL_NOMINALRATE_1 */
#define OFDM_TRL_NOMINALRATE_1 (0x5B)
/* 0x5C OFDM_TRL_NOMINALRATE_2 */
#define OFDM_TRL_NOMINALRATE_2 (0x5C)
/* 0x5D OFDM_TRL_TIME_1 */
#define OFDM_TRL_TIME_1 (0x5D)
/* 0x60 OFDM_CRL_FREQ_1 */
#define OFDM_CRL_FREQ_1 (0x60)
/* 0x63 OFDM_CHC_CTL_1 */
#define OFDM_CHC_CTL_1 (0x63)
#define MANMEAN1 (0xF0)
;
#define CHCFIR (0x01)
/* 0x64 OFDM_CHC_SNR */
#define OFDM_CHC_SNR (0x64)
/* 0x65 OFDM_BDI_CTL */
#define OFDM_BDI_CTL (0x65)
#define LP_SELECT (0x02)
/* 0x67 OFDM_TPS_RCVD_1 */
#define OFDM_TPS_RCVD_1 (0x67)
#define TPSFRAME (0x03)
/* 0x68 OFDM_TPS_RCVD_2 */
#define OFDM_TPS_RCVD_2 (0x68)
/* 0x69 OFDM_TPS_RCVD_3 */
#define OFDM_TPS_RCVD_3 (0x69)
/* 0x6A OFDM_TPS_RCVD_4 */
#define OFDM_TPS_RCVD_4 (0x6A)
/* 0x6B OFDM_TPS_RESERVED_1 */
#define OFDM_TPS_RESERVED_1 (0x6B)
/* 0x6C OFDM_TPS_RESERVED_2 */
#define OFDM_TPS_RESERVED_2 (0x6C)
/* 0x73 OFDM_MSC_REV */
#define OFDM_MSC_REV (0x73)
/* 0x76 OFDM_SNR_CARRIER_2 */
#define OFDM_SNR_CARRIER_2 (0x76)
#define MEAN_MASK (0x80)
#define MEANBIT (0x80)
/* 0x80 ANALOG_CONTROL_0 */
#define ANALOG_CONTROL_0 (0x80)
#define POWER_DOWN_ADC (0x40)
/* 0x81 ENABLE_TUNER_IIC */
#define ENABLE_TUNER_IIC (0x81)
#define ENABLE_TUNER_BIT (0x01)
/* 0x82 EN_DMD_RACQ */
#define EN_DMD_RACQ (0x82)
#define EN_DMD_RACQ_REG_VAL (0x81)
#define EN_DMD_RACQ_REG_VAL_14 (0x01)
/* 0x84 SNR_COMMAND */
#define SNR_COMMAND (0x84)
#define SNRStat (0x80)
/* 0x85 SNRCARRIERNUMBER_LSB */
#define SNRCARRIERNUMBER_LSB (0x85)
/* 0x87 SNRMINTHRESHOLD_LSB */
#define SNRMINTHRESHOLD_LSB (0x87)
/* 0x89 SNR_PER_CARRIER_LSB */
#define SNR_PER_CARRIER_LSB (0x89)
/* 0x8B SNRBELOWTHRESHOLD_LSB */
#define SNRBELOWTHRESHOLD_LSB (0x8B)
/* 0x91 RF_AGC_VAL_1 */
#define RF_AGC_VAL_1 (0x91)
/* 0x92 RF_AGC_STATUS */
#define RF_AGC_STATUS (0x92)
/* 0x98 DIAG_CONFIG */
#define DIAG_CONFIG (0x98)
#define DIAG_MASK (0x70)
#define TB_SET (0x10)
#define TRAN_SELECT (0x07)
#define SERIAL_SELECT (0x01)
/* 0x99 SUB_DIAG_MODE_SEL */
#define SUB_DIAG_MODE_SEL (0x99)
#define CLKINVERSION (0x01)
/* 0x9A TS_FORMAT */
#define TS_FORMAT (0x9A)
#define ERROR_SENSE (0x08)
#define VALID_SENSE (0x04)
#define SYNC_SENSE (0x02)
#define GATED_CLOCK (0x01)
#define NXT6000ASICDEVICE (0x0b)
drivers/media/dvb/frontends/
alps_bsru6
.c
→
drivers/media/dvb/frontends/
stv0299
.c
View file @
7d208bb2
/*
Alps BSRU6 and LG TDQB-S00x DVB QPSK frontend driver
/*
Universal driver for STV0299/TDA5059/SL1935 based
DVB QPSK frontends
Alps BSRU6, LG TDQB-S00x
Copyright (C) 2001-2002 Convergence Integrated Media GmbH
<ralph@convergence.de>, <holger@convergence.de>,
<ralph@convergence.de>,
<holger@convergence.de>,
<js@convergence.de>
Philips SU1278/SH
Copyright (C) 2002 by Peter Schildmann
<peter.schildmann@web.de>
LG TDQF-S001F
Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
& Andreas Oberritter <andreas@oberritter.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
...
...
@@ -24,67 +38,80 @@
#include <linux/init.h>
#include <linux/module.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
#define dprintk if (debug) printk
/* frontend types */
#define UNKNOWN_FRONTEND -1
#define PHILIPS_SU1278SH 0
#define ALPS_BSRU6 1
#define LG_TDQF_S001F 2
#define M_CLK (88000000UL)
/* M=21, K=0, P=0, f_VCO = 4MHz*4*(M+1)/(K+1) = 352 MHz */
/* Master Clock = 88 MHz */
#define M_CLK (88000000UL)
static
struct
dvb_frontend_info
bsru6_info
=
{
#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X
.
name
=
"LG TDQB-S00x"
,
#else
.
name
=
"Alps BSRU6"
,
#endif
.
type
=
FE_QPSK
,
.
frequency_min
=
950000
,
.
frequency_max
=
2150000
,
.
frequency_stepsize
=
125
,
/* kHz for QPSK frontends */
.
frequency_tolerance
=
M_CLK
/
2000
,
.
symbol_rate_min
=
1000000
,
.
symbol_rate_max
=
45000000
,
.
symbol_rate_tolerance
=
500
,
/* ppm */
.
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
struct
dvb_frontend_info
uni0299_info
=
{
name:
"STV0299/TSA5059/SL1935 based"
,
type:
FE_QPSK
,
frequency_min:
950000
,
frequency_max:
2150000
,
frequency_stepsize:
125
,
/* kHz for QPSK frontends */
frequency_tolerance:
M_CLK
/
2000
,
symbol_rate_min:
1000000
,
symbol_rate_max:
45000000
,
symbol_rate_tolerance:
500
,
/* ppm */
notifier_delay:
0
,
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_QPSK
|
FE_CAN_FEC_AUTO
|
FE_CAN_INVERSION_AUTO
|
FE_CAN_CLEAN_SETUP
};
static
u8
init_tab
[]
=
{
0x01
,
0x15
,
// M: 0x15 DIRCLK: 0 K:0
0x02
,
0x30
,
// P: 0 SERCLK: 0 VCO:ON STDBY:0
0x03
,
0x00
,
0x04
,
0x7d
,
// F22FR, F22=22kHz
0x05
,
0x35
,
// SDAT:0 SCLT:0 I2CT:1
0x06
,
0x00
,
// DAC mode and MSB
0x07
,
0x00
,
// DAC LSB
// 0x08, 0x43, // DiSEqC
0x08
,
0x03
,
// DiSEqC
0x09
,
0x00
,
0x0a
,
0x42
,
0x0c
,
0x51
,
// QPSK reverse:1 Nyquist:0 OP0 val:1 OP0 con:1 OP1 val:1 OP1 con:1
0x0d
,
0x82
,
0x0e
,
0x23
,
0x0f
,
0x52
,
0x10
,
0x3d
,
// AGC2
0x11
,
0x84
,
/* clock registers */
0x01
,
0x15
,
/* K = 0, DIRCLK = 0, M = 0x15 */
0x02
,
0x30
,
/* STDBY = 0, VCO = 0 (ON), SERCLK = 0, P = 0 */
/* f_VCO = 4MHz * 4 * (M+1) / (K+1) = 352 MHz */
0x03
,
0x00
,
/* auxiliary clock not used */
0x04
,
0x7d
,
/* F22FR = 0x7d */
/* F22 = f_VCO / 128 / 0x7d = 22 kHz */
/* I2C bus repeater */
0x05
,
0x35
,
/* I2CT = 0, SCLT = 1, SDAT = 1 */
/* general purpose DAC registers */
0x06
,
0x40
,
/* DAC not used, set to high impendance mode */
0x07
,
0x00
,
/* DAC LSB */
/* DiSEqC registers */
0x08
,
0x40
,
/* DiSEqC off */
0x09
,
0x00
,
/* FIFO */
/* Input/Output configuration register */
0x0c
,
0x51
,
/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
/* OP0 ctl = Normal, OP0 val = 1 (18 V) */
/* Nyquist filter = 00, QPSK reverse = 0 */
/* AGC1 control register */
0x0d
,
0x82
,
/* DC offset compensation = ON, beta_agc1 = 2 */
/* Timing loop register */
0x0e
,
0x23
,
/* alpha_tmg = 2, beta_tmg = 3 */
0x10
,
0x3f
,
// AGC2 0x3d
0x11
,
0x84
,
0x12
,
0xb5
,
// Lock detect: -64 Carrier freq detect:on
0x13
,
0xb6
,
// alpha_car b:4 a:0 noise est:256ks derot:on
0x13
,
0xb6
,
// alpha_car b:4 a:0 noise est:256ks derot:on
0x14
,
0x93
,
// beat carc:0 d:0 e:0xf phase detect algo: 1
0x15
,
0xc9
,
// lock detector threshold
0x16
,
0x1d
,
0x16
,
0x1d
,
/* AGC1 integrator value */
0x17
,
0x00
,
0x18
,
0x14
,
0x19
,
0xf2
,
...
...
@@ -105,7 +132,7 @@ u8 init_tab [] = {
0x25
,
0xff
,
0x26
,
0xff
,
0x28
,
0x00
,
// out imp: normal out type: parallel FEC mode:0
0x28
,
0x00
,
// out imp: normal out type: parallel FEC mode:0
0x29
,
0x1e
,
// 1/2 threshold
0x2a
,
0x14
,
// 2/3 threshold
0x2b
,
0x0f
,
// 3/4 threshold
...
...
@@ -113,13 +140,13 @@ u8 init_tab [] = {
0x2d
,
0x05
,
// 7/8 threshold
0x2e
,
0x01
,
0x31
,
0x1f
,
// test all FECs
0x31
,
0x1f
,
// test all FECs
0x32
,
0x19
,
// viterbi and synchro search
0x33
,
0xfc
,
// rs control
0x34
,
0x93
,
// error control
0x0b
,
0x00
,
0x0b
,
0x00
,
0x27
,
0x00
,
0x2f
,
0x00
,
0x30
,
0x00
,
...
...
@@ -158,7 +185,7 @@ int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{
int
ret
;
u8
buf
[]
=
{
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
2
};
struct
i2c_msg
msg
=
{
addr
:
0x68
,
flags
:
0
,
buf
:
buf
,
len
:
2
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
@@ -178,9 +205,9 @@ u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg)
int
ret
;
u8
b0
[]
=
{
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
1
},
{
.
addr
=
0x68
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x68
,
flags
:
0
,
buf
:
b0
,
len
:
1
},
{
addr
:
0x68
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -196,8 +223,8 @@ static
int
stv0299_readregs
(
struct
dvb_i2c_bus
*
i2c
,
u8
reg1
,
u8
*
b
,
u8
len
)
{
int
ret
;
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
&
reg1
,
.
len
=
1
},
{
.
addr
=
0x68
,
.
flags
=
I2C_M_RD
,
.
buf
=
b
,
.
len
=
len
}
};
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x68
,
flags
:
0
,
buf
:
&
reg1
,
len
:
1
},
{
addr
:
0x68
,
flags
:
I2C_M_RD
,
buf
:
b
,
len
:
len
}
};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
@@ -210,18 +237,25 @@ int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len)
}
static
int
tsa5059_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
]
)
int
pll_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
data
[
4
],
int
ftype
)
{
int
ret
;
u8
rpt1
[]
=
{
0x05
,
0xb5
};
/* enable i2c repeater on stv0299 */
struct
i2c_msg
msg
[]
=
{{
.
addr
=
0x68
,
.
flags
=
0
,
.
buf
=
rpt1
,
.
len
=
2
},
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
}};
/* TSA5059 i2c-bus address */
u8
addr
=
(
ftype
==
PHILIPS_SU1278SH
)
?
0x60
:
0x61
;
struct
i2c_msg
msg
[]
=
{{
addr
:
0x68
,
flags
:
0
,
buf
:
rpt1
,
len
:
2
},
{
addr
:
addr
,
flags
:
0
,
buf
:
data
,
len
:
4
}};
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
if
(
ftype
==
LG_TDQF_S001F
||
ftype
==
ALPS_BSRU6
)
{
ret
=
i2c
->
xfer
(
i2c
,
&
msg
[
0
],
1
);
ret
+=
i2c
->
xfer
(
i2c
,
&
msg
[
1
],
1
);
}
else
{
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
}
if
(
ret
!=
2
)
dprintk
(
"%s: i/o error (ret == %i)
\n
"
,
__FUNCTION__
,
ret
);
...
...
@@ -230,24 +264,90 @@ int tsa5059_write (struct dvb_i2c_bus *i2c, u8 data [4])
}
static
int
sl1935_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
int
ftype
)
{
u8
buf
[
4
];
u32
div
;
u32
ratios
[]
=
{
2000
,
1000
,
500
,
250
,
125
};
u8
ratio
;
for
(
ratio
=
4
;
ratio
>
0
;
ratio
--
)
if
((
freq
/
ratios
[
ratio
])
<=
0x3fff
)
break
;
div
=
freq
/
ratios
[
ratio
];
buf
[
0
]
=
(
freq
>>
8
)
&
0x7f
;
buf
[
1
]
=
freq
&
0xff
;
buf
[
2
]
=
0x80
|
ratio
;
if
(
freq
<
1531000
)
buf
[
3
]
=
0x10
;
else
buf
[
3
]
=
0x00
;
return
pll_write
(
i2c
,
buf
,
ftype
);
}
/**
* set up the downconverter frequency divisor for a
* reference clock comparision frequency of 125 kHz.
*/
static
int
tsa5059_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
u8
pwr
)
int
tsa5059_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
int
ftype
)
{
u32
div
=
freq
/
125
;
u8
buf
[
4
]
=
{
(
div
>>
8
)
&
0x7f
,
div
&
0xff
,
0x84
,
(
pwr
<<
5
)
|
0x20
};
u32
div
=
freq
/
125
;
u8
buf
[
4
]
=
{
(
div
>>
8
)
&
0x7f
,
div
&
0xff
,
0x84
};
if
(
ftype
==
PHILIPS_SU1278SH
)
/* activate f_xtal/f_comp signal output */
/* charge pump current C0/C1 = 00 */
buf
[
3
]
=
0x20
;
else
buf
[
3
]
=
freq
>
1530000
?
0xc0
:
0xc4
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
return
tsa5059_write
(
i2c
,
buf
);
return
pll_write
(
i2c
,
buf
,
ftype
);
}
static
int
pll_set_tv_freq
(
struct
dvb_i2c_bus
*
i2c
,
u32
freq
,
int
ftype
)
{
if
(
ftype
==
LG_TDQF_S001F
)
return
sl1935_set_tv_freq
(
i2c
,
freq
,
ftype
);
else
return
tsa5059_set_tv_freq
(
i2c
,
freq
,
ftype
);
}
#if 0
static
int
stv0299_init
(
struct
dvb_i2c_bus
*
i2c
)
int tsa5059_read_status (struct dvb_i2c_bus *i2c)
{
int ret;
u8 rpt1 [] = { 0x05, 0xb5 };
u8 stat [] = { 0 };
struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 },
{ addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }};
dprintk ("%s\n", __FUNCTION__);
ret = i2c->xfer (i2c, msg, 2);
if (ret != 2)
dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
return stat[0];
}
#endif
static
int
stv0299_init
(
struct
dvb_i2c_bus
*
i2c
,
int
ftype
)
{
int
i
;
...
...
@@ -256,45 +356,27 @@ int stv0299_init (struct dvb_i2c_bus *i2c)
for
(
i
=
0
;
i
<
sizeof
(
init_tab
);
i
+=
2
)
stv0299_writereg
(
i2c
,
init_tab
[
i
],
init_tab
[
i
+
1
]);
/* AGC1 reference register setup */
if
(
ftype
==
PHILIPS_SU1278SH
)
stv0299_writereg
(
i2c
,
0x0f
,
0xd2
);
/* Iagc = Inverse, m1 = 18 */
else
stv0299_writereg
(
i2c
,
0x0f
,
0x52
);
/* Iagc = Normal, m1 = 18 */
return
0
;
}
static
int
stv0299_set_inversion
(
struct
dvb_i2c_bus
*
i2c
,
fe_spectral_inversion_t
inversion
)
int
stv0299_check_inversion
(
struct
dvb_i2c_bus
*
i2c
)
{
u8
val
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X
/* reversed I/Q pins */
switch
(
inversion
)
{
case
INVERSION_AUTO
:
return
-
EOPNOTSUPP
;
case
INVERSION_OFF
:
val
=
stv0299_readreg
(
i2c
,
0x0c
);
return
stv0299_writereg
(
i2c
,
0x0c
,
val
&
0xfe
);
case
INVERSION_ON
:
val
=
stv0299_readreg
(
i2c
,
0x0c
);
return
stv0299_writereg
(
i2c
,
0x0c
,
val
|
0x01
);
default:
return
-
EINVAL
;
};
#else
switch
(
inversion
)
{
case
INVERSION_AUTO
:
return
-
EOPNOTSUPP
;
case
INVERSION_OFF
:
val
=
stv0299_readreg
(
i2c
,
0x0c
);
return
stv0299_writereg
(
i2c
,
0x0c
,
val
|
0x01
);
case
INVERSION_ON
:
val
=
stv0299_readreg
(
i2c
,
0x0c
);
return
stv0299_writereg
(
i2c
,
0x0c
,
val
&
0xfe
);
default:
return
-
EINVAL
;
};
#endif
if
((
stv0299_readreg
(
i2c
,
0x1b
)
&
0x98
)
!=
0x98
)
{
u8
val
=
stv0299_readreg
(
i2c
,
0x0c
);
return
stv0299_writereg
(
i2c
,
0x0c
,
val
^
0x01
);
}
return
0
;
}
...
...
@@ -473,8 +555,8 @@ int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
val
=
stv0299_readreg
(
i2c
,
0x0c
);
val
&=
0x0f
;
val
|=
0x40
;
val
|=
0x40
;
/* LNB power on */
switch
(
voltage
)
{
case
SEC_VOLTAGE_13
:
return
stv0299_writereg
(
i2c
,
0x0c
,
val
);
...
...
@@ -485,7 +567,7 @@ int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage)
};
}
static
int
stv0299_set_symbolrate
(
struct
dvb_i2c_bus
*
i2c
,
u32
srate
)
{
...
...
@@ -558,15 +640,16 @@ int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c)
static
int
bsru6
_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
int
uni0299
_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
int
tuner_type
=
(
int
)
fe
->
data
;
struct
dvb_i2c_bus
*
i2c
=
fe
->
i2c
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
switch
(
cmd
)
{
case
FE_GET_INFO
:
memcpy
(
arg
,
&
bsru6
_info
,
sizeof
(
struct
dvb_frontend_info
));
memcpy
(
arg
,
&
uni0299
_info
,
sizeof
(
struct
dvb_frontend_info
));
break
;
case
FE_READ_STATUS
:
...
...
@@ -575,6 +658,8 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
u8
signal
=
0xff
-
stv0299_readreg
(
i2c
,
0x18
);
u8
sync
=
stv0299_readreg
(
i2c
,
0x1b
);
dprintk
(
"VSTATUS: 0x%02x
\n
"
,
sync
);
*
status
=
0
;
if
(
signal
>
10
)
...
...
@@ -604,6 +689,11 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
s32
signal
=
0xffff
-
((
stv0299_readreg
(
i2c
,
0x18
)
<<
8
)
|
stv0299_readreg
(
i2c
,
0x19
));
dprintk
(
"AGC2I: 0x%02x%02x, signal=0x%04x
\n
"
,
stv0299_readreg
(
i2c
,
0x18
),
stv0299_readreg
(
i2c
,
0x19
),
signal
);
signal
=
signal
*
5
/
4
;
*
((
u16
*
)
arg
)
=
(
signal
>
0xffff
)
?
0xffff
:
(
signal
<
0
)
?
0
:
signal
;
...
...
@@ -626,15 +716,17 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
struct
dvb_frontend_parameters
*
p
=
arg
;
tsa5059_set_tv_freq
(
i2c
,
p
->
frequency
,
3
);
stv0299_set_inversion
(
i2c
,
p
->
inversion
);
pll_set_tv_freq
(
i2c
,
p
->
frequency
,
tuner_type
);
stv0299_set_FEC
(
i2c
,
p
->
u
.
qpsk
.
fec_inner
);
stv0299_set_symbolrate
(
i2c
,
p
->
u
.
qpsk
.
symbol_rate
);
tsa5059_set_tv_freq
(
i2c
,
p
->
frequency
,
0
);
stv0299_check_inversion
(
i2c
);
/* pll_set_tv_freq (i2c, p->frequency, tuner_type); */
stv0299_writereg
(
i2c
,
0x22
,
0x00
);
stv0299_writereg
(
i2c
,
0x23
,
0x00
);
stv0299_readreg
(
i2c
,
0x23
);
stv0299_writereg
(
i2c
,
0x12
,
0xb9
);
/* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */
break
;
}
...
...
@@ -664,7 +756,7 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
break
;
case
FE_INIT
:
return
stv0299_init
(
i2c
);
return
stv0299_init
(
i2c
,
tuner_type
);
case
FE_RESET
:
stv0299_writereg
(
i2c
,
0x22
,
0x00
);
...
...
@@ -692,54 +784,97 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
return
0
;
}
static
int
probe_tuner
(
struct
dvb_i2c_bus
*
i2c
)
{
int
type
;
/* read the status register of TSA5059 */
u8
rpt
[]
=
{
0x05
,
0xb5
};
u8
stat
[]
=
{
0
};
struct
i2c_msg
msg1
[]
=
{{
addr
:
0x68
,
flags
:
0
,
buf
:
rpt
,
len
:
2
},
{
addr
:
0x60
,
flags
:
I2C_M_RD
,
buf
:
stat
,
len
:
1
}};
struct
i2c_msg
msg2
[]
=
{{
addr
:
0x68
,
flags
:
0
,
buf
:
rpt
,
len
:
2
},
{
addr
:
0x61
,
flags
:
I2C_M_RD
,
buf
:
stat
,
len
:
1
}};
if
(
i2c
->
xfer
(
i2c
,
msg1
,
2
)
==
2
)
{
type
=
PHILIPS_SU1278SH
;
printk
(
"%s: setup for tuner SU1278/SH
\n
"
,
__FILE__
);
}
else
if
(
i2c
->
xfer
(
i2c
,
msg2
,
2
)
==
2
)
{
if
(
0
)
{
// if ((stat[0] & 0x3f) == 0) {
type
=
LG_TDQF_S001F
;
printk
(
"%s: setup for tuner TDQF-S001F
\n
"
,
__FILE__
);
}
else
{
type
=
ALPS_BSRU6
;
printk
(
"%s: setup for tuner BSRU6, TDQB-S00x
\n
"
,
__FILE__
);
}
}
else
{
type
=
UNKNOWN_FRONTEND
;
printk
(
"%s: unknown PLL synthesizer, "
"please report to <linuxdvb@linuxtv.org>!!
\n
"
,
__FILE__
);
}
return
type
;
}
static
int
bsru6
_attach
(
struct
dvb_i2c_bus
*
i2c
)
int
uni0299
_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
int
tuner_type
;
u8
id
=
stv0299_readreg
(
i2c
,
0x00
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
((
stv0299_readreg
(
i2c
,
0x00
))
!=
0xa1
)
return
-
ENODEV
;
/* register 0x00 contains 0xa1 for STV0299 and STV0299B */
/* register 0x00 might contain 0x80 when returning from standby */
if
(
id
!=
0xa1
&&
id
!=
0x80
)
return
-
ENODEV
;
dvb_register_frontend
(
bsru6_ioctl
,
i2c
,
NULL
,
&
bsru6_info
);
if
((
tuner_type
=
probe_tuner
(
i2c
))
<
0
)
return
-
ENODEV
;
dvb_register_frontend
(
uni0299_ioctl
,
i2c
,
(
void
*
)
tuner_type
,
&
uni0299_info
);
return
0
;
}
static
void
bsru6
_detach
(
struct
dvb_i2c_bus
*
i2c
)
void
uni0299
_detach
(
struct
dvb_i2c_bus
*
i2c
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dvb_unregister_frontend
(
bsru6
_ioctl
,
i2c
);
dvb_unregister_frontend
(
uni0299
_ioctl
,
i2c
);
}
static
int
__init
init_
bsru6
(
void
)
int
__init
init_
uni0299
(
void
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
return
dvb_register_i2c_device
(
THIS_MODULE
,
bsru6_attach
,
bsru6
_detach
);
return
dvb_register_i2c_device
(
THIS_MODULE
,
uni0299_attach
,
uni0299
_detach
);
}
static
void
__exit
exit_
bsru6
(
void
)
void
__exit
exit_
uni0299
(
void
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dvb_unregister_i2c_device
(
bsru6
_attach
);
dvb_unregister_i2c_device
(
uni0299
_attach
);
}
module_init
(
init_
bsru6
);
module_exit
(
exit_
bsru6
);
module_init
(
init_
uni0299
);
module_exit
(
exit_
uni0299
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"enable verbose debug messages"
);
MODULE_DESCRIPTION
(
"Alps BSRU6/LG TDQB-S00x DVB Frontend driver"
);
MODULE_AUTHOR
(
"Ralph Metzler, Holger Waechtler"
);
MODULE_DESCRIPTION
(
"Universal STV0299/TSA5059/SL1935 DVB Frontend driver"
);
MODULE_AUTHOR
(
"Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter"
);
MODULE_LICENSE
(
"GPL"
);
drivers/media/dvb/frontends/ves1820.c
View file @
7d208bb2
...
...
@@ -23,12 +23,14 @@
#include <linux/module.h>
#include <linux/delay.h>
#include "compat.h"
#include "dvb_frontend.h"
static
int
debug
=
0
;
#define dprintk if (debug) printk
#if 0
#define dprintk(x...) printk(x)
#else
#define dprintk(x...)
#endif
/**
...
...
@@ -36,36 +38,58 @@ static int debug = 0;
* extra memory but use frontend->data as bitfield
*/
#define SET_PWM(
frontend
,pwm) do { \
(int)
frontend->
data &= ~0xff; \
(int)
frontend->
data |= pwm; \
#define SET_PWM(
data
,pwm) do { \
(int) data &= ~0xff; \
(int) data |= pwm; \
} while (0)
#define SET_REG0(
frontend,reg0) do {
\
(int)
frontend->
data &= ~(0xff << 8); \
(int)
frontend->
data |= reg0 << 8; \
#define SET_REG0(
data,reg0) do {
\
(int) data &= ~(0xff << 8); \
(int) data |= reg0 << 8; \
} while (0)
#define SET_TUNER(
frontend,type) do {
\
(int)
frontend->
data &= ~(0xff << 16); \
(int)
frontend->
data |= type << 16; \
#define SET_TUNER(
data,type) do {
\
(int) data &= ~(0xff << 16); \
(int) data |= type << 16; \
} while (0)
#define GET_PWM(frontend) ((u8) ((int) frontend->data & 0xff))
#define GET_REG0(frontend) ((u8) (((int) frontend->data >> 8) & 0xff))
#define GET_TUNER(frontend) ((u8) (((int) frontend->data >> 16) & 0xff))
#define SET_DEMOD_ADDR(data,type) do { \
(int) data &= ~(0xff << 24); \
(int) data |= type << 24; \
} while (0)
#define GET_PWM(data) ((u8) ((int) data & 0xff))
#define GET_REG0(data) ((u8) (((int) data >> 8) & 0xff))
#define GET_TUNER(data) ((u8) (((int) data >> 16) & 0xff))
#define GET_DEMOD_ADDR(data) ((u8) (((int) data >> 24) & 0xff))
static
inline
void
ddelay
(
int
ms
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
((
HZ
*
ms
)
/
1000
);
}
static
struct
dvb_frontend_info
ves1820_info
=
{
.
name
=
"VES1820/Grundig tuner as used on the Siemens DVB-C card"
,
.
type
=
FE_QAM
,
.
frequency_stepsize
=
62500
,
.
frequency_min
=
51000000
,
.
frequency_max
=
858000000
,
.
caps
=
FE_CAN_QAM_16
|
FE_CAN_QAM_32
|
FE_CAN_QAM_64
|
FE_CAN_QAM_128
|
FE_CAN_QAM_256
.
name
=
"VES1820 based DVB-C frontend"
,
.
type
=
FE_QAM
,
.
frequency_stepsize
=
62500
,
.
frequency_min
=
51000000
,
.
frequency_max
=
858000000
,
.
symbol_rate_min
=
(
57840000
/
2
)
/
64
,
/* SACLK/64 == (XIN/2)/64 */
.
symbol_rate_max
=
(
57840000
/
2
)
/
4
,
/* SACLK/4 */
#if 0
frequency_tolerance: ???,
symbol_rate_tolerance: ???, /* ppm */ /* == 8% (spec p. 5) */
notifier_delay: ?,
#endif
.
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
|
FE_CAN_INVERSION_AUTO
|
FE_CAN_CLEAN_SETUP
|
FE_CAN_RECOVER
};
...
...
@@ -73,22 +97,24 @@ struct dvb_frontend_info ves1820_info = {
static
u8
ves1820_inittab
[]
=
{
0x69
,
0x6A
,
0x9B
,
0x0A
,
0x52
,
0x46
,
0x26
,
0x1A
,
0x43
,
0x6A
,
0xAA
,
0xAA
,
0x1E
,
0x85
,
0x43
,
0x28
,
0xE0
,
0x00
,
0xA1
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x40
0x69
,
0x6A
,
0x9B
,
0x0A
,
0x52
,
0x46
,
0x26
,
0x1A
,
0x43
,
0x6A
,
0xAA
,
0xAA
,
0x1E
,
0x85
,
0x43
,
0x28
,
0xE0
,
0x00
,
0xA1
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x40
};
static
int
ves1820_writereg
(
struct
dvb_
i2c_bus
*
i2c
,
u8
reg
,
u8
data
)
int
ves1820_writereg
(
struct
dvb_
frontend
*
fe
,
u8
reg
,
u8
data
)
{
int
ret
;
u8
addr
=
GET_DEMOD_ADDR
(
fe
->
data
)
;
u8
buf
[]
=
{
0x00
,
reg
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
0x09
,
.
flags
=
0
,
.
buf
=
buf
,
.
len
=
3
};
struct
i2c_msg
msg
=
{
addr
:
addr
,
flags
:
0
,
buf
:
buf
,
len
:
3
};
struct
dvb_i2c_bus
*
i2c
=
fe
->
i2c
;
int
ret
;
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
@@ -103,14 +129,15 @@ int ves1820_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
static
u8
ves1820_readreg
(
struct
dvb_
i2c_bus
*
i2c
,
u8
reg
)
u8
ves1820_readreg
(
struct
dvb_
frontend
*
fe
,
u8
reg
)
{
int
ret
;
u8
b0
[]
=
{
0x00
,
reg
};
u8
b1
[]
=
{
0
};
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x09
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
2
},
{
.
addr
=
0x09
,
.
flags
=
I2C_M_RD
,
.
buf
=
b1
,
.
len
=
1
}
};
u8
addr
=
GET_DEMOD_ADDR
(
fe
->
data
);
struct
i2c_msg
msg
[]
=
{
{
addr
:
addr
,
flags
:
0
,
buf
:
b0
,
len
:
2
},
{
addr
:
addr
,
flags
:
I2C_M_RD
,
buf
:
b1
,
len
:
1
}
};
struct
dvb_i2c_bus
*
i2c
=
fe
->
i2c
;
int
ret
;
ret
=
i2c
->
xfer
(
i2c
,
msg
,
2
);
...
...
@@ -125,7 +152,7 @@ static
int
tuner_write
(
struct
dvb_i2c_bus
*
i2c
,
u8
addr
,
u8
data
[
4
])
{
int
ret
;
struct
i2c_msg
msg
=
{
.
addr
=
addr
,
.
flags
=
0
,
.
buf
=
data
,
.
len
=
4
};
struct
i2c_msg
msg
=
{
addr
:
addr
,
flags
:
0
,
buf
:
data
,
len
:
4
};
ret
=
i2c
->
xfer
(
i2c
,
&
msg
,
1
);
...
...
@@ -141,15 +168,18 @@ int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4])
* reference clock comparision frequency of 62.5 kHz.
*/
static
int
tuner_set_tv_freq
(
struct
dvb_frontend
*
f
rontend
,
u32
freq
)
int
tuner_set_tv_freq
(
struct
dvb_frontend
*
f
e
,
u32
freq
)
{
u32
div
;
static
u8
addr
[]
=
{
0x61
,
0x62
};
static
u8
byte3
[]
=
{
0x8e
,
0x85
};
int
tuner_type
=
GET_TUNER
(
f
rontend
);
int
tuner_type
=
GET_TUNER
(
f
e
->
data
);
u8
buf
[
4
];
div
=
(
freq
+
36250000
+
31250
)
/
62500
;
if
(
tuner_type
==
0xff
)
/* PLL not reachable over i2c ... */
return
0
;
div
=
(
freq
+
36125000
+
31250
)
/
62500
;
buf
[
0
]
=
(
div
>>
8
)
&
0x7f
;
buf
[
1
]
=
div
&
0xff
;
buf
[
2
]
=
byte3
[
tuner_type
];
...
...
@@ -163,115 +193,56 @@ int tuner_set_tv_freq (struct dvb_frontend *frontend, u32 freq)
freq
<
454000000
?
0x92
:
0x34
);
}
return
tuner_write
(
f
rontend
->
i2c
,
addr
[
tuner_type
],
buf
);
return
tuner_write
(
f
e
->
i2c
,
addr
[
tuner_type
],
buf
);
}
static
int
probe_tuner
(
struct
dvb_frontend
*
frontend
)
int
ves1820_setup_reg0
(
struct
dvb_frontend
*
fe
,
u8
reg0
)
{
struct
dvb_i2c_bus
*
i2c
=
frontend
->
i2c
;
struct
i2c_msg
msg
=
{
.
addr
=
0x61
,
.
flags
=
0
,
.
buf
=
NULL
,
.
len
=
0
};
if
(
i2c
->
xfer
(
i2c
,
&
msg
,
1
)
==
1
)
{
SET_TUNER
(
frontend
,
0
);
printk
(
"%s: setup for tuner spXXXX
\n
"
,
__FILE__
);
}
else
{
SET_TUNER
(
frontend
,
1
);
printk
(
"%s: setup for tuner sp5659c
\n
"
,
__FILE__
);
reg0
|=
GET_REG0
(
fe
->
data
)
&
0x62
;
ves1820_writereg
(
fe
,
0x00
,
reg0
&
0xfe
);
ves1820_writereg
(
fe
,
0x00
,
reg0
|
0x01
);
/**
* check lock and toggle inversion bit if required...
*/
if
(
!
(
ves1820_readreg
(
fe
,
0x11
)
&
0x08
))
{
ddelay
(
1
);
if
(
!
(
ves1820_readreg
(
fe
,
0x11
)
&
0x08
))
{
reg0
^=
0x20
;
ves1820_writereg
(
fe
,
0x00
,
reg0
&
0xfe
);
ves1820_writereg
(
fe
,
0x00
,
reg0
|
0x01
);
}
}
SET_REG0
(
fe
->
data
,
reg0
);
return
0
;
}
static
int
ves1820_init
(
struct
dvb_frontend
*
f
rontend
)
int
ves1820_init
(
struct
dvb_frontend
*
f
e
)
{
struct
dvb_i2c_bus
*
i2c
=
frontend
->
i2c
;
u8
b0
[]
=
{
0xff
};
u8
pwm
;
int
i
;
struct
i2c_msg
msg
[]
=
{
{
.
addr
=
0x50
,
.
flags
=
0
,
.
buf
=
b0
,
.
len
=
1
},
{
.
addr
=
0x50
,
.
flags
=
I2C_M_RD
,
.
buf
=
&
pwm
,
.
len
=
1
}
};
dprintk
(
"VES1820: init chip
\n
"
);
i2c
->
xfer
(
i2c
,
msg
,
2
);
dprintk
(
"VES1820: pwm=%02x
\n
"
,
pwm
);
if
(
pwm
==
0xff
)
pwm
=
0x48
;
ves1820_writereg
(
i2c
,
0
,
0
);
ves1820_writereg
(
fe
,
0
,
0
);
for
(
i
=
0
;
i
<
53
;
i
++
)
ves1820_writereg
(
i2c
,
i
,
ves1820_inittab
[
i
]);
ves1820_writereg
(
i2c
,
0x34
,
pwm
);
(
int
)
frontend
->
data
=
0
;
SET_PWM
(
frontend
,
pwm
);
probe_tuner
(
frontend
);
return
0
;
}
static
int
ves1820_setup_reg0
(
struct
dvb_frontend
*
frontend
,
u8
real_qam
,
fe_spectral_inversion_t
inversion
)
{
struct
dvb_i2c_bus
*
i2c
=
frontend
->
i2c
;
u8
reg0
=
(
ves1820_inittab
[
0
]
&
0xe3
)
|
(
real_qam
<<
2
);
switch
(
inversion
)
{
case
INVERSION_OFF
:
/* XXX FIXME: reversed?? p. 25 */
reg0
|=
0x20
;
break
;
case
INVERSION_ON
:
reg0
&=
0xdf
;
break
;
default:
return
-
EINVAL
;
}
SET_REG0
(
frontend
,
reg0
);
ves1820_writereg
(
fe
,
i
,
ves1820_inittab
[
i
]);
ves1820_writereg
(
i2c
,
0x00
,
reg0
&
0xfe
);
ves1820_writereg
(
i2c
,
0x00
,
reg0
);
ves1820_writereg
(
fe
,
0x34
,
GET_PWM
(
fe
->
data
));
return
0
;
}
static
int
ves1820_reset
(
struct
dvb_frontend
*
frontend
)
{
struct
dvb_i2c_bus
*
i2c
=
frontend
->
i2c
;
u8
reg0
=
GET_REG0
(
frontend
);
ves1820_writereg
(
i2c
,
0x00
,
reg0
&
0xfe
);
ves1820_writereg
(
i2c
,
0x00
,
reg0
);
return
0
;
}
static
void
ves1820_reset_uncorrected_block_counter
(
struct
dvb_i2c_bus
*
i2c
)
{
ves1820_writereg
(
i2c
,
0x10
,
ves1820_inittab
[
0x10
]
&
0xdf
);
ves1820_writereg
(
i2c
,
0x10
,
ves1820_inittab
[
0x10
]);
}
static
int
ves1820_set_symbolrate
(
struct
dvb_i2c_bus
*
i2c
,
u32
symbolrate
)
int
ves1820_set_symbolrate
(
struct
dvb_frontend
*
fe
,
u32
symbolrate
)
{
s32
BDR
;
s32
BDRI
;
...
...
@@ -280,7 +251,7 @@ int ves1820_set_symbolrate (struct dvb_i2c_bus *i2c, u32 symbolrate)
u32
tmp
,
ratio
;
#define XIN 57840000UL
#define FIN (
57840000UL>>
4)
#define FIN (
XIN >>
4)
if
(
symbolrate
>
XIN
/
2
)
symbolrate
=
XIN
/
2
;
...
...
@@ -317,81 +288,50 @@ int ves1820_set_symbolrate (struct dvb_i2c_bus *i2c, u32 symbolrate)
NDEC
=
(
NDEC
<<
6
)
|
ves1820_inittab
[
0x03
];
ves1820_writereg
(
i2c
,
0x03
,
NDEC
);
ves1820_writereg
(
i2c
,
0x0a
,
BDR
&
0xff
);
ves1820_writereg
(
i2c
,
0x0b
,
(
BDR
>>
8
)
&
0xff
);
ves1820_writereg
(
i2c
,
0x0c
,
(
BDR
>>
16
)
&
0x3f
);
ves1820_writereg
(
fe
,
0x03
,
NDEC
);
ves1820_writereg
(
fe
,
0x0a
,
BDR
&
0xff
);
ves1820_writereg
(
fe
,
0x0b
,
(
BDR
>>
8
)
&
0xff
);
ves1820_writereg
(
fe
,
0x0c
,
(
BDR
>>
16
)
&
0x3f
);
ves1820_writereg
(
i2c
,
0x0d
,
BDRI
);
ves1820_writereg
(
i2c
,
0x0e
,
SFIL
);
ves1820_writereg
(
fe
,
0x0d
,
BDRI
);
ves1820_writereg
(
fe
,
0x0e
,
SFIL
);
return
0
;
}
static
void
ves1820_reset_pwm
(
struct
dvb_frontend
*
frontend
)
{
u8
pwm
=
GET_PWM
(
frontend
);
ves1820_writereg
(
frontend
->
i2c
,
0x34
,
pwm
);
}
typedef
struct
{
fe_modulation_t
QAM_Mode
;
int
NoOfSym
;
u8
Reg1
;
u8
Reg5
;
u8
Reg8
;
u8
Reg9
;
}
QAM_SETTING
;
QAM_SETTING
QAM_Values
[]
=
{
{
QAM_16
,
16
,
140
,
164
,
162
,
145
},
{
QAM_32
,
32
,
140
,
120
,
116
,
150
},
{
QAM_64
,
64
,
106
,
70
,
67
,
106
},
{
QAM_128
,
128
,
120
,
54
,
52
,
126
},
{
QAM_256
,
256
,
92
,
38
,
35
,
107
}
};
static
int
ves1820_set_parameters
(
struct
dvb_frontend
*
frontend
,
int
ves1820_set_parameters
(
struct
dvb_frontend
*
fe
,
struct
dvb_frontend_parameters
*
p
)
{
struct
dvb_i2c_bus
*
i2c
=
frontend
->
i2c
;
int
real_qam
;
switch
(
p
->
u
.
qam
.
modulation
)
{
case
QAM_16
:
real_qam
=
0
;
break
;
case
QAM_32
:
real_qam
=
1
;
break
;
case
QAM_64
:
real_qam
=
2
;
break
;
case
QAM_128
:
real_qam
=
3
;
break
;
case
QAM_256
:
real_qam
=
4
;
break
;
default:
return
-
EINVAL
;
}
static
const
u8
reg0x00
[]
=
{
0x00
,
0x04
,
0x08
,
0x0c
,
0x10
};
static
const
u8
reg0x01
[]
=
{
140
,
140
,
106
,
120
,
92
};
static
const
u8
reg0x05
[]
=
{
135
,
100
,
70
,
54
,
38
};
static
const
u8
reg0x08
[]
=
{
162
,
116
,
67
,
52
,
35
};
static
const
u8
reg0x09
[]
=
{
145
,
150
,
106
,
126
,
107
};
int
real_qam
=
p
->
u
.
qam
.
modulation
-
QAM_16
;
if
(
real_qam
<
0
||
real_qam
>
4
)
return
-
EINVAL
;
tuner_set_tv_freq
(
f
rontend
,
p
->
frequency
);
ves1820_set_symbolrate
(
i2c
,
p
->
u
.
qam
.
symbol_rate
);
ves1820_
reset_pwm
(
frontend
);
tuner_set_tv_freq
(
f
e
,
p
->
frequency
);
ves1820_set_symbolrate
(
fe
,
p
->
u
.
qam
.
symbol_rate
);
ves1820_
writereg
(
fe
,
0x34
,
GET_PWM
(
fe
->
data
)
);
ves1820_writereg
(
i2c
,
0x01
,
QAM_Values
[
real_qam
].
Reg1
);
ves1820_writereg
(
i2c
,
0x05
,
QAM_Values
[
real_qam
].
Reg5
);
ves1820_writereg
(
i2c
,
0x08
,
QAM_Values
[
real_qam
].
Reg8
);
ves1820_writereg
(
i2c
,
0x09
,
QAM_Values
[
real_qam
].
Reg9
);
ves1820_writereg
(
fe
,
0x01
,
reg0x01
[
real_qam
]);
ves1820_writereg
(
fe
,
0x05
,
reg0x05
[
real_qam
]);
ves1820_writereg
(
fe
,
0x08
,
reg0x08
[
real_qam
]);
ves1820_writereg
(
fe
,
0x09
,
reg0x09
[
real_qam
]);
ves1820_setup_reg0
(
fe
,
reg0x00
[
real_qam
]);
ves1820_setup_reg0
(
frontend
,
real_qam
,
p
->
inversion
);
return
0
;
}
static
int
ves1820_ioctl
(
struct
dvb_frontend
*
f
rontend
,
unsigned
int
cmd
,
void
*
arg
)
int
ves1820_ioctl
(
struct
dvb_frontend
*
f
e
,
unsigned
int
cmd
,
void
*
arg
)
{
switch
(
cmd
)
{
case
FE_GET_INFO
:
...
...
@@ -405,7 +345,7 @@ int ves1820_ioctl (struct dvb_frontend *frontend, unsigned int cmd, void *arg)
*
status
=
0
;
sync
=
ves1820_readreg
(
f
rontend
->
i2c
,
0x11
);
sync
=
ves1820_readreg
(
f
e
,
0x11
);
if
(
sync
&
2
)
*
status
|=
FE_HAS_SIGNAL
;
...
...
@@ -427,35 +367,37 @@ int ves1820_ioctl (struct dvb_frontend *frontend, unsigned int cmd, void *arg)
case
FE_READ_BER
:
{
u32
ber
=
ves1820_readreg
(
f
rontend
->
i2c
,
0x14
)
|
(
ves1820_readreg
(
frontend
->
i2c
,
0x15
)
<<
8
)
|
((
ves1820_readreg
(
f
rontend
->
i2c
,
0x16
)
&
0x0f
)
<<
16
);
u32
ber
=
ves1820_readreg
(
f
e
,
0x14
)
|
(
ves1820_readreg
(
fe
,
0x15
)
<<
8
)
|
((
ves1820_readreg
(
f
e
,
0x16
)
&
0x0f
)
<<
16
);
*
((
u32
*
)
arg
)
=
10
*
ber
;
break
;
}
case
FE_READ_SIGNAL_STRENGTH
:
{
u8
gain
=
ves1820_readreg
(
f
rontend
->
i2c
,
0x17
);
u8
gain
=
ves1820_readreg
(
f
e
,
0x17
);
*
((
u16
*
)
arg
)
=
(
gain
<<
8
)
|
gain
;
break
;
}
case
FE_READ_SNR
:
{
u8
quality
=
~
ves1820_readreg
(
f
rontend
->
i2c
,
0x18
);
u8
quality
=
~
ves1820_readreg
(
f
e
,
0x18
);
*
((
u16
*
)
arg
)
=
(
quality
<<
8
)
|
quality
;
break
;
}
case
FE_READ_UNCORRECTED_BLOCKS
:
*
((
u32
*
)
arg
)
=
ves1820_readreg
(
f
rontend
->
i2c
,
0x13
)
&
0x7f
;
*
((
u32
*
)
arg
)
=
ves1820_readreg
(
f
e
,
0x13
)
&
0x7f
;
if
(
*
((
u32
*
)
arg
)
==
0x7f
)
*
((
u32
*
)
arg
)
=
0xffffffff
;
ves1820_reset_uncorrected_block_counter
(
frontend
->
i2c
);
/* reset uncorrected block counter */
ves1820_writereg
(
fe
,
0x10
,
ves1820_inittab
[
0x10
]
&
0xdf
);
ves1820_writereg
(
fe
,
0x10
,
ves1820_inittab
[
0x10
]);
break
;
case
FE_SET_FRONTEND
:
return
ves1820_set_parameters
(
f
rontend
,
arg
);
return
ves1820_set_parameters
(
f
e
,
arg
);
case
FE_GET_FRONTEND
:
/* XXX FIXME: implement! */
...
...
@@ -468,16 +410,12 @@ int ves1820_ioctl (struct dvb_frontend *frontend, unsigned int cmd, void *arg)
break
;
case
FE_SLEEP
:
ves1820_writereg
(
f
rontend
->
i2c
,
0x1b
,
0x02
);
/* pdown ADC */
ves1820_writereg
(
f
rontend
->
i2c
,
0x00
,
0x80
);
/* standby */
ves1820_writereg
(
f
e
,
0x1b
,
0x02
);
/* pdown ADC */
ves1820_writereg
(
f
e
,
0x00
,
0x80
);
/* standby */
break
;
case
FE_INIT
:
return
ves1820_init
(
frontend
);
case
FE_RESET
:
ves1820_reset
(
frontend
);
break
;
return
ves1820_init
(
fe
);
default:
return
-
EINVAL
;
...
...
@@ -487,13 +425,90 @@ int ves1820_ioctl (struct dvb_frontend *frontend, unsigned int cmd, void *arg)
}
static
int
probe_tuner
(
struct
dvb_i2c_bus
*
i2c
)
{
static
const
struct
i2c_msg
msg1
=
{
addr
:
0x61
,
flags
:
0
,
buf
:
NULL
,
len
:
0
};
static
const
struct
i2c_msg
msg2
=
{
addr
:
0x62
,
flags
:
0
,
buf
:
NULL
,
len
:
0
};
int
type
;
if
(
i2c
->
xfer
(
i2c
,
&
msg1
,
1
)
==
1
)
{
type
=
0
;
printk
(
"%s: setup for tuner spXXXX
\n
"
,
__FILE__
);
}
else
if
(
i2c
->
xfer
(
i2c
,
&
msg2
,
1
)
==
1
)
{
type
=
1
;
printk
(
"%s: setup for tuner sp5659c
\n
"
,
__FILE__
);
}
else
{
type
=
-
1
;
printk
(
"%s: unknown PLL, "
"please report to <linuxdvb@linuxtv.org>!!
\n
"
,
__FILE__
);
}
return
type
;
}
static
u8
read_pwm
(
struct
dvb_i2c_bus
*
i2c
)
{
u8
b
=
0xff
;
u8
pwm
;
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x50
,
flags
:
0
,
buf
:
&
b
,
len
:
1
},
{
addr
:
0x50
,
flags
:
I2C_M_RD
,
buf
:
&
pwm
,
len
:
1
}
};
i2c
->
xfer
(
i2c
,
msg
,
2
);
dprintk
(
"VES1820: pwm=%02x
\n
"
,
pwm
);
if
(
pwm
==
0xff
)
pwm
=
0x48
;
return
pwm
;
}
static
int
probe_demod_addr
(
struct
dvb_i2c_bus
*
i2c
)
{
u8
b
[]
=
{
0x00
,
0x1a
};
u8
id
;
struct
i2c_msg
msg
[]
=
{
{
addr
:
0x08
,
flags
:
0
,
buf
:
b
,
len
:
2
},
{
addr
:
0x08
,
flags
:
I2C_M_RD
,
buf
:
&
id
,
len
:
1
}
};
if
(
i2c
->
xfer
(
i2c
,
msg
,
2
)
==
2
&&
(
id
&
0xf0
)
==
0x70
)
return
msg
[
0
].
addr
;
msg
[
0
].
addr
=
msg
[
1
].
addr
=
0x09
;
if
(
i2c
->
xfer
(
i2c
,
msg
,
2
)
==
2
&&
(
id
&
0xf0
)
==
0x70
)
return
msg
[
0
].
addr
;
return
-
1
;
}
static
int
ves1820_attach
(
struct
dvb_i2c_bus
*
i2c
)
{
if
((
ves1820_readreg
(
i2c
,
0x1a
)
&
0xf0
)
!=
0x70
)
return
-
ENODEV
;
dvb_register_frontend
(
ves1820_ioctl
,
i2c
,
NULL
,
&
ves1820_info
);
void
*
data
=
NULL
;
int
demod_addr
;
int
tuner_type
;
if
((
demod_addr
=
probe_demod_addr
(
i2c
))
<
0
)
return
-
ENODEV
;
if
((
tuner_type
=
probe_tuner
(
i2c
))
<
0
)
return
-
ENODEV
;
SET_PWM
(
data
,
read_pwm
(
i2c
));
SET_REG0
(
data
,
ves1820_inittab
[
0
]);
SET_TUNER
(
data
,
tuner_type
);
SET_DEMOD_ADDR
(
data
,
demod_addr
);
dvb_register_frontend
(
ves1820_ioctl
,
i2c
,
data
,
&
ves1820_info
);
return
0
;
}
...
...
@@ -524,8 +539,7 @@ void __exit exit_ves1820 (void)
module_init
(
init_ves1820
);
module_exit
(
exit_ves1820
);
MODULE_DESCRIPTION
(
""
);
MODULE_AUTHOR
(
"Ralph Metzler"
);
MODULE_DESCRIPTION
(
"
VES1820 DVB-C frontend driver
"
);
MODULE_AUTHOR
(
"Ralph Metzler
, Holger Waechtler
"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
debug
,
"i"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment