aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2009-11-13 20:33:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:41:32 -0500
commita15c7b42b2b8eda719920e93b81be031f2e0b01b (patch)
treefe17b1a3a783746d2873205bda14708b5b1b803a
parentc1426df678c5e9a095ff40285ff3d698d0d25658 (diff)
V4L/DVB (13363): ec100: add new driver for E3C EC100 DVB-T demodulator
E3C EC100 DVB-T demodulator driver Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/Kconfig7
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/ec100.c335
-rw-r--r--drivers/media/dvb/frontends/ec100.h46
-rw-r--r--drivers/media/dvb/frontends/ec100_priv.h39
5 files changed, 428 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index d7c4837fa71c..4f785f549d02 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -342,6 +342,13 @@ config DVB_AF9013
342 help 342 help
343 Say Y when you want to support this frontend. 343 Say Y when you want to support this frontend.
344 344
345config DVB_EC100
346 tristate "E3C EC100"
347 depends on DVB_CORE && I2C
348 default m if DVB_FE_CUSTOMISE
349 help
350 Say Y when you want to support this frontend.
351
345comment "DVB-C (cable) frontends" 352comment "DVB-C (cable) frontends"
346 depends on DVB_CORE 353 depends on DVB_CORE
347 354
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 3523767e7a76..1ca758eeff59 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -76,3 +76,4 @@ obj-$(CONFIG_DVB_STV0900) += stv0900.o
76obj-$(CONFIG_DVB_STV090x) += stv090x.o 76obj-$(CONFIG_DVB_STV090x) += stv090x.o
77obj-$(CONFIG_DVB_STV6110x) += stv6110x.o 77obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
78obj-$(CONFIG_DVB_ISL6423) += isl6423.o 78obj-$(CONFIG_DVB_ISL6423) += isl6423.o
79obj-$(CONFIG_DVB_EC100) += ec100.o
diff --git a/drivers/media/dvb/frontends/ec100.c b/drivers/media/dvb/frontends/ec100.c
new file mode 100644
index 000000000000..2414dc6ee5d9
--- /dev/null
+++ b/drivers/media/dvb/frontends/ec100.c
@@ -0,0 +1,335 @@
1/*
2 * E3C EC100 demodulator driver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22#include "dvb_frontend.h"
23#include "ec100_priv.h"
24#include "ec100.h"
25
26int ec100_debug;
27module_param_named(debug, ec100_debug, int, 0644);
28MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
29
30struct ec100_state {
31 struct i2c_adapter *i2c;
32 struct dvb_frontend frontend;
33 struct ec100_config config;
34
35 u16 ber;
36};
37
38/* write single register */
39static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
40{
41 u8 buf[2] = {reg, val};
42 struct i2c_msg msg = {
43 .addr = state->config.demod_address,
44 .flags = 0,
45 .len = 2,
46 .buf = buf};
47
48 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
49 warn("I2C write failed reg:%02x", reg);
50 return -EREMOTEIO;
51 }
52 return 0;
53}
54
55/* read single register */
56static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
57{
58 struct i2c_msg msg[2] = {
59 {
60 .addr = state->config.demod_address,
61 .flags = 0,
62 .len = 1,
63 .buf = &reg
64 }, {
65 .addr = state->config.demod_address,
66 .flags = I2C_M_RD,
67 .len = 1,
68 .buf = val
69 }
70 };
71
72 if (i2c_transfer(state->i2c, msg, 2) != 2) {
73 warn("I2C read failed reg:%02x", reg);
74 return -EREMOTEIO;
75 }
76 return 0;
77}
78
79static int ec100_set_frontend(struct dvb_frontend *fe,
80 struct dvb_frontend_parameters *params)
81{
82 struct ec100_state *state = fe->demodulator_priv;
83 int ret;
84 u8 tmp, tmp2;
85
86 deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
87 params->u.ofdm.bandwidth);
88
89 /* program tuner */
90 if (fe->ops.tuner_ops.set_params)
91 fe->ops.tuner_ops.set_params(fe, params);
92
93 ret = ec100_write_reg(state, 0x04, 0x06);
94 if (ret)
95 goto error;
96 ret = ec100_write_reg(state, 0x67, 0x58);
97 if (ret)
98 goto error;
99 ret = ec100_write_reg(state, 0x05, 0x18);
100 if (ret)
101 goto error;
102
103 /* reg/bw | 6 | 7 | 8
104 -------+------+------+------
105 A 0x1b | 0xa1 | 0xe7 | 0x2c
106 A 0x1c | 0x55 | 0x63 | 0x72
107 -------+------+------+------
108 B 0x1b | 0xb7 | 0x00 | 0x49
109 B 0x1c | 0x55 | 0x64 | 0x72 */
110
111 switch (params->u.ofdm.bandwidth) {
112 case BANDWIDTH_6_MHZ:
113 tmp = 0xb7;
114 tmp2 = 0x55;
115 break;
116 case BANDWIDTH_7_MHZ:
117 tmp = 0x00;
118 tmp2 = 0x64;
119 break;
120 case BANDWIDTH_8_MHZ:
121 default:
122 tmp = 0x49;
123 tmp2 = 0x72;
124 }
125
126 ret = ec100_write_reg(state, 0x1b, tmp);
127 if (ret)
128 goto error;
129 ret = ec100_write_reg(state, 0x1c, tmp2);
130 if (ret)
131 goto error;
132
133 ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */
134 if (ret)
135 goto error;
136 ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */
137 if (ret)
138 goto error;
139
140 ret = ec100_write_reg(state, 0x08, 0x24);
141 if (ret)
142 goto error;
143
144 ret = ec100_write_reg(state, 0x00, 0x00); /* go */
145 if (ret)
146 goto error;
147 ret = ec100_write_reg(state, 0x00, 0x20); /* go */
148 if (ret)
149 goto error;
150
151 return ret;
152error:
153 deb_info("%s: failed:%d\n", __func__, ret);
154 return ret;
155}
156
157static int ec100_get_tune_settings(struct dvb_frontend *fe,
158 struct dvb_frontend_tune_settings *fesettings)
159{
160 fesettings->min_delay_ms = 300;
161 fesettings->step_size = 0;
162 fesettings->max_drift = 0;
163
164 return 0;
165}
166
167static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
168{
169 struct ec100_state *state = fe->demodulator_priv;
170 int ret;
171 u8 tmp;
172 *status = 0;
173
174 ret = ec100_read_reg(state, 0x42, &tmp);
175 if (ret)
176 goto error;
177
178 if (tmp & 0x80) {
179 /* bit7 set - have lock */
180 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
181 FE_HAS_SYNC | FE_HAS_LOCK;
182 } else {
183 ret = ec100_read_reg(state, 0x01, &tmp);
184 if (ret)
185 goto error;
186
187 if (tmp & 0x10) {
188 /* bit4 set - have signal */
189 *status |= FE_HAS_SIGNAL;
190 if (!(tmp & 0x01)) {
191 /* bit0 clear - have ~valid signal */
192 *status |= FE_HAS_CARRIER | FE_HAS_VITERBI;
193 }
194 }
195 }
196
197 return ret;
198error:
199 deb_info("%s: failed:%d\n", __func__, ret);
200 return ret;
201}
202
203static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
204{
205 struct ec100_state *state = fe->demodulator_priv;
206 int ret;
207 u8 tmp, tmp2;
208 u16 ber2;
209
210 *ber = 0;
211
212 ret = ec100_read_reg(state, 0x65, &tmp);
213 if (ret)
214 goto error;
215 ret = ec100_read_reg(state, 0x66, &tmp2);
216 if (ret)
217 goto error;
218
219 ber2 = (tmp2 << 8) | tmp;
220
221 /* if counter overflow or clear */
222 if (ber2 < state->ber)
223 *ber = ber2;
224 else
225 *ber = ber2 - state->ber;
226
227 state->ber = ber2;
228
229 return ret;
230error:
231 deb_info("%s: failed:%d\n", __func__, ret);
232 return ret;
233}
234
235static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
236{
237 struct ec100_state *state = fe->demodulator_priv;
238 int ret;
239 u8 tmp;
240
241 ret = ec100_read_reg(state, 0x24, &tmp);
242 if (ret) {
243 *strength = 0;
244 goto error;
245 }
246
247 *strength = ((tmp << 8) | tmp);
248
249 return ret;
250error:
251 deb_info("%s: failed:%d\n", __func__, ret);
252 return ret;
253}
254
255static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)
256{
257 *snr = 0;
258 return 0;
259}
260
261static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
262{
263 *ucblocks = 0;
264 return 0;
265}
266
267static void ec100_release(struct dvb_frontend *fe)
268{
269 struct ec100_state *state = fe->demodulator_priv;
270 kfree(state);
271}
272
273static struct dvb_frontend_ops ec100_ops;
274
275struct dvb_frontend *ec100_attach(const struct ec100_config *config,
276 struct i2c_adapter *i2c)
277{
278 int ret;
279 struct ec100_state *state = NULL;
280 u8 tmp;
281
282 /* allocate memory for the internal state */
283 state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);
284 if (state == NULL)
285 goto error;
286
287 /* setup the state */
288 state->i2c = i2c;
289 memcpy(&state->config, config, sizeof(struct ec100_config));
290
291 /* check if the demod is there */
292 ret = ec100_read_reg(state, 0x33, &tmp);
293 if (ret || tmp != 0x0b)
294 goto error;
295
296 /* create dvb_frontend */
297 memcpy(&state->frontend.ops, &ec100_ops,
298 sizeof(struct dvb_frontend_ops));
299 state->frontend.demodulator_priv = state;
300
301 return &state->frontend;
302error:
303 kfree(state);
304 return NULL;
305}
306EXPORT_SYMBOL(ec100_attach);
307
308static struct dvb_frontend_ops ec100_ops = {
309 .info = {
310 .name = "E3C EC100 DVB-T",
311 .type = FE_OFDM,
312 .caps =
313 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
314 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
315 FE_CAN_QPSK | FE_CAN_QAM_16 |
316 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
317 FE_CAN_TRANSMISSION_MODE_AUTO |
318 FE_CAN_GUARD_INTERVAL_AUTO |
319 FE_CAN_HIERARCHY_AUTO |
320 FE_CAN_MUTE_TS
321 },
322
323 .release = ec100_release,
324 .set_frontend = ec100_set_frontend,
325 .get_tune_settings = ec100_get_tune_settings,
326 .read_status = ec100_read_status,
327 .read_ber = ec100_read_ber,
328 .read_signal_strength = ec100_read_signal_strength,
329 .read_snr = ec100_read_snr,
330 .read_ucblocks = ec100_read_ucblocks,
331};
332
333MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
334MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");
335MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/ec100.h b/drivers/media/dvb/frontends/ec100.h
new file mode 100644
index 000000000000..ee8e52417958
--- /dev/null
+++ b/drivers/media/dvb/frontends/ec100.h
@@ -0,0 +1,46 @@
1/*
2 * E3C EC100 demodulator driver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22#ifndef EC100_H
23#define EC100_H
24
25#include <linux/dvb/frontend.h>
26
27struct ec100_config {
28 /* demodulator's I2C address */
29 u8 demod_address;
30};
31
32
33#if defined(CONFIG_DVB_EC100) || \
34 (defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
35extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
36 struct i2c_adapter *i2c);
37#else
38static inline struct dvb_frontend *ec100_attach(
39 const struct ec100_config *config, struct i2c_adapter *i2c)
40{
41 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
42 return NULL;
43}
44#endif
45
46#endif /* EC100_H */
diff --git a/drivers/media/dvb/frontends/ec100_priv.h b/drivers/media/dvb/frontends/ec100_priv.h
new file mode 100644
index 000000000000..5c990144bc47
--- /dev/null
+++ b/drivers/media/dvb/frontends/ec100_priv.h
@@ -0,0 +1,39 @@
1/*
2 * E3C EC100 demodulator driver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22#ifndef EC100_PRIV
23#define EC100_PRIV
24
25#define LOG_PREFIX "ec100"
26
27#define dprintk(var, level, args...) \
28 do { if ((var & level)) printk(args); } while (0)
29
30#define deb_info(args...) dprintk(ec100_debug, 0x01, args)
31
32#undef err
33#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
34#undef info
35#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
36#undef warn
37#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
38
39#endif /* EC100_PRIV */