diff options
author | Patrick Boettcher <pboettcher@dibcom.fr> | 2006-12-02 18:15:51 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 05:50:46 -0500 |
commit | 91bb9be6ff4101652bb104f9f083f340e73ba6dd (patch) | |
tree | 936eca628fde8a7da3103bf75dc5e768ef49fbb1 | |
parent | 902fc997adb7b917e1bd06ad6f2f0d38aa482578 (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_devices.c | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib7000m.c | 242 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib7000m.h | 50 |
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 | |||
69 | config DVB_USB_DIB0700 | 69 | config 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 | ||
14 | static int force_lna_activation; | 15 | static 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 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_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 | |||
24 | struct 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 | |||
46 | static 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 | /* | ||
62 | static 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 | |||
75 | static 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 | |||
133 | static int dib7000m_set_frontend(struct dvb_frontend* fe, | ||
134 | struct dvb_frontend_parameters *fep) | ||
135 | { | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static 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 | |||
160 | static 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 | |||
167 | static 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 | |||
174 | static 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 | |||
182 | static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
183 | { | ||
184 | *snr = 0x0000; | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static 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 | |||
194 | static int dib7000m_init(struct dvb_frontend *fe) | ||
195 | { | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int dib7000m_sleep(struct dvb_frontend *fe) | ||
200 | { | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void dib7000m_release(struct dvb_frontend *fe) | ||
205 | { } | ||
206 | |||
207 | static 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 | |||
240 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
241 | MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); | ||
242 | MODULE_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 | |||
6 | struct 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 | |||
39 | extern 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 | |||
41 | extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
42 | |||
43 | /* TODO | ||
44 | extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); | ||
45 | extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod); | ||
46 | extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); | ||
47 | extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod); | ||
48 | */ | ||
49 | |||
50 | #endif | ||