aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Boettcher <pboettcher@dibcom.fr>2006-12-02 18:15:51 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 05:50:46 -0500
commit91bb9be6ff4101652bb104f9f083f340e73ba6dd (patch)
tree936eca628fde8a7da3103bf75dc5e768ef49fbb1
parent902fc997adb7b917e1bd06ad6f2f0d38aa482578 (diff)
V4L/DVB (4524): Initial commit for the DiB7000M-demod
Initial commit for the driver for the DiB7000M COFDM demodulator. Signed-off-by: Francois KANOUNNIKOFF <fkanounnikoff@dibcom.fr> Signed-off-by: Patrick Boettcher <pboettcher@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig1
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c1
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c242
-rw-r--r--drivers/media/dvb/frontends/dib7000m.h50
4 files changed, 294 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index a263b3f3c21d..a0aeaf4bbb37 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -69,6 +69,7 @@ config DVB_USB_DIBUSB_MC
69config DVB_USB_DIB0700 69config DVB_USB_DIB0700
70 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" 70 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
71 depends on DVB_USB 71 depends on DVB_USB
72 select DVB_DIB7000M
72 select DVB_DIB3000MC 73 select DVB_DIB3000MC
73 select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE 74 select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
74 help 75 help
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index e473bfed226b..b4e339df72e5 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -9,6 +9,7 @@
9#include "dib0700.h" 9#include "dib0700.h"
10 10
11#include "dib3000mc.h" 11#include "dib3000mc.h"
12#include "dib7000m.h"
12#include "mt2060.h" 13#include "mt2060.h"
13 14
14static int force_lna_activation; 15static int force_lna_activation;
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
new file mode 100644
index 000000000000..c9a57678fa34
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -0,0 +1,242 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB7000M and
3 * first generation DiB7000P-demodulator-family.
4 *
5 * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2.
10 */
11#include <linux/kernel.h>
12#include <linux/i2c.h>
13
14#include "dvb_frontend.h"
15
16#include "dib7000m.h"
17
18static int debug;
19module_param(debug, int, 0644);
20MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
21
22#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
23
24struct dib7000m_state {
25 struct dvb_frontend demod;
26 struct dib7000m_config cfg;
27
28 u8 i2c_addr;
29 struct i2c_adapter *i2c_adap;
30
31 struct dibx000_i2c_master i2c_master;
32
33/* offset is 1 in case of the 7000MC */
34 u8 reg_offs;
35
36 u16 wbd_ref;
37
38 u8 current_band;
39 fe_bandwidth_t current_bandwidth;
40 struct dibx000_agc_config *current_agc;
41 u32 timf[9];
42
43 u16 revision;
44};
45
46static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
47{
48 u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
49 u8 rb[2];
50 struct i2c_msg msg[2] = {
51 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
52 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
53 };
54
55 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
56 dprintk("i2c read error on %d\n",reg);
57
58 return (rb[0] << 8) | rb[1];
59}
60
61/*
62static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
63{
64 u8 b[4] = {
65 (reg >> 8) & 0xff, reg & 0xff,
66 (val >> 8) & 0xff, val & 0xff,
67 };
68 struct i2c_msg msg = {
69 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
70 };
71 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
72}
73*/
74
75static int dib7000m_get_frontend(struct dvb_frontend* fe,
76 struct dvb_frontend_parameters *fep)
77{
78 struct dib7000m_state *state = fe->demodulator_priv;
79 u16 tps = dib7000m_read_word(state,480);
80
81 fep->inversion = INVERSION_AUTO;
82
83 fep->u.ofdm.bandwidth = state->current_bandwidth;
84
85 switch ((tps >> 8) & 0x2) {
86 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
87 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
88 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
89 }
90
91 switch (tps & 0x3) {
92 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
93 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
94 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
95 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
96 }
97
98 switch ((tps >> 14) & 0x3) {
99 case 0: fep->u.ofdm.constellation = QPSK; break;
100 case 1: fep->u.ofdm.constellation = QAM_16; break;
101 case 2:
102 default: fep->u.ofdm.constellation = QAM_64; break;
103 }
104
105 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
106 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
107
108 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
109 switch ((tps >> 5) & 0x7) {
110 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
111 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
112 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
113 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
114 case 7:
115 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
116
117 }
118
119 switch ((tps >> 2) & 0x7) {
120 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
121 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
122 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
123 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
124 case 7:
125 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
126 }
127
128 /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
129
130 return 0;
131}
132
133static int dib7000m_set_frontend(struct dvb_frontend* fe,
134 struct dvb_frontend_parameters *fep)
135{
136 return 0;
137}
138
139static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
140{
141 struct dib7000m_state *state = fe->demodulator_priv;
142 u16 lock = dib7000m_read_word(state, 509);
143
144 *stat = 0;
145
146 if (lock & 0x8000)
147 *stat |= FE_HAS_SIGNAL;
148 if (lock & 0x3000)
149 *stat |= FE_HAS_CARRIER;
150 if (lock & 0x0100)
151 *stat |= FE_HAS_VITERBI;
152 if (lock & 0x0010)
153 *stat |= FE_HAS_SYNC;
154 if (lock & 0x0008)
155 *stat |= FE_HAS_LOCK;
156
157 return 0;
158}
159
160static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
161{
162 struct dib7000m_state *state = fe->demodulator_priv;
163 *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
164 return 0;
165}
166
167static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
168{
169 struct dib7000m_state *state = fe->demodulator_priv;
170 *unc = dib7000m_read_word(state, 534);
171 return 0;
172}
173
174static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
175{
176 struct dib7000m_state *state = fe->demodulator_priv;
177 u16 val = dib7000m_read_word(state, 390);
178 *strength = 65535 - val;
179 return 0;
180}
181
182static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
183{
184 *snr = 0x0000;
185 return 0;
186}
187
188static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
189{
190 tune->min_delay_ms = 1000;
191 return 0;
192}
193
194static int dib7000m_init(struct dvb_frontend *fe)
195{
196 return 0;
197}
198
199static int dib7000m_sleep(struct dvb_frontend *fe)
200{
201 return 0;
202}
203
204static void dib7000m_release(struct dvb_frontend *fe)
205{ }
206
207static struct dvb_frontend_ops dib7000m_ops = {
208 .info = {
209 .name = "DiBcom 7000MA/MB/PA/PB/MC",
210 .type = FE_OFDM,
211 .frequency_min = 44250000,
212 .frequency_max = 867250000,
213 .frequency_stepsize = 62500,
214 .caps = FE_CAN_INVERSION_AUTO |
215 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
216 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
217 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
218 FE_CAN_TRANSMISSION_MODE_AUTO |
219 FE_CAN_GUARD_INTERVAL_AUTO |
220 FE_CAN_RECOVER |
221 FE_CAN_HIERARCHY_AUTO,
222 },
223
224 .release = dib7000m_release,
225
226 .init = dib7000m_init,
227 .sleep = dib7000m_sleep,
228
229 .set_frontend = dib7000m_set_frontend,
230 .get_tune_settings = dib7000m_fe_get_tune_settings,
231 .get_frontend = dib7000m_get_frontend,
232
233 .read_status = dib7000m_read_status,
234 .read_ber = dib7000m_read_ber,
235 .read_signal_strength = dib7000m_read_signal_strength,
236 .read_snr = dib7000m_read_snr,
237 .read_ucblocks = dib7000m_read_unc_blocks,
238};
239
240MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
241MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
242MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h
new file mode 100644
index 000000000000..45990e3a5cee
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000m.h
@@ -0,0 +1,50 @@
1#ifndef DIB7000M_H
2#define DIB7000M_H
3
4#include "dibx000_common.h"
5
6struct dib7000m_config {
7 u8 dvbt_mode;
8 u8 output_mpeg2_in_188_bytes;
9 u8 hostbus_diversity;
10 u8 tuner_is_baseband;
11 u8 mobile_mode;
12 int (*update_lna) (struct dvb_frontend *, u16 agc_global);
13
14 u8 agc_config_count;
15 struct dibx000_agc_config *agc;
16
17 struct dibx000_bandwidth_config *bw;
18
19#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
20 u16 gpio_dir;
21#define DIB7000M_GPIO_DEFAULT_VALUES 0x0000
22 u16 gpio_val;
23#define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
24#define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
25#define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
26#define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf)
27#define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff
28 u16 gpio_pwm_pos;
29
30 u16 pwm_freq_div;
31
32 u8 quartz_direct;
33
34 u8 input_clk_is_div_2;
35};
36
37#define DEFAULT_DIB7000M_I2C_ADDRESS 18
38
39extern int dib7000m_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr , u8 do_i2c_enum, struct dib7000m_config[], struct dvb_frontend*[]);
40
41extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
42
43/* TODO
44extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
45extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
46extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
47extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
48*/
49
50#endif