aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-10-24 14:06:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-29 14:53:13 -0500
commitf71f11ed46df2f29daf928eb5fd8c6c2d1455f36 (patch)
tree400a792ed015bf31a22911183fc44cfd43a94261 /drivers/media/dvb/frontends
parentc2e591fcb7aa5300cf6967edb29960628cf1831d (diff)
V4L/DVB (9367): Move lgdt3304 driver to the proper place and allow it to compile
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r--drivers/media/dvb/frontends/Kconfig8
-rw-r--r--drivers/media/dvb/frontends/Makefile2
-rw-r--r--drivers/media/dvb/frontends/lgdt3304.c378
-rw-r--r--drivers/media/dvb/frontends/lgdt3304.h45
4 files changed, 433 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 8da1e81668e7..69eb1f8eb4a9 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -345,6 +345,14 @@ config DVB_LGDT330X
345 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want 345 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
346 to support this frontend. 346 to support this frontend.
347 347
348config DVB_LGDT3304
349 tristate "LG Electronics LGDT3304"
350 depends on DVB_CORE && I2C
351 default m if DVB_FE_CUSTOMISE
352 help
353 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
354 to support this frontend.
355
348config DVB_S5H1409 356config DVB_S5H1409
349 tristate "Samsung S5H1409 based" 357 tristate "Samsung S5H1409 based"
350 depends on DVB_CORE && I2C 358 depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 11a5407ecdb7..651c9e889a66 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
37obj-$(CONFIG_DVB_BCM3510) += bcm3510.o 37obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
38obj-$(CONFIG_DVB_S5H1420) += s5h1420.o 38obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
39obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o 39obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
40obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
40obj-$(CONFIG_DVB_CX24123) += cx24123.o 41obj-$(CONFIG_DVB_CX24123) += cx24123.o
41obj-$(CONFIG_DVB_LNBP21) += lnbp21.o 42obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
42obj-$(CONFIG_DVB_ISL6405) += isl6405.o 43obj-$(CONFIG_DVB_ISL6405) += isl6405.o
@@ -58,3 +59,4 @@ obj-$(CONFIG_DVB_SI21XX) += si21xx.o
58obj-$(CONFIG_DVB_STV0288) += stv0288.o 59obj-$(CONFIG_DVB_STV0288) += stv0288.o
59obj-$(CONFIG_DVB_STB6000) += stb6000.o 60obj-$(CONFIG_DVB_STB6000) += stb6000.o
60obj-$(CONFIG_DVB_S921) += s921.o 61obj-$(CONFIG_DVB_S921) += s921.o
62
diff --git a/drivers/media/dvb/frontends/lgdt3304.c b/drivers/media/dvb/frontends/lgdt3304.c
new file mode 100644
index 000000000000..469ace5692c6
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgdt3304.c
@@ -0,0 +1,378 @@
1/*
2 * Driver for LG ATSC lgdt3304 driver
3 *
4 * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
5 *
6 */
7
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/delay.h>
11#include "dvb_frontend.h"
12#include "lgdt3304.h"
13
14static unsigned int debug = 0;
15module_param(debug, int, 0644);
16MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)");
17
18#define dprintk(fmt, args...) if (debug) do {\
19 printk("lgdt3304 debug: " fmt, ##args); } while (0)
20
21struct lgdt3304_state
22{
23 struct dvb_frontend frontend;
24 fe_modulation_t current_modulation;
25 __u32 snr;
26 __u32 current_frequency;
27 __u8 addr;
28 struct i2c_adapter *i2c;
29};
30
31static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len)
32{
33 struct lgdt3304_state *state = fe->demodulator_priv;
34 struct i2c_msg i2cmsgs = {
35 .addr = state->addr,
36 .flags = 0,
37 .len = 3,
38 .buf = buf
39 };
40 int i;
41 int err;
42
43 for (i=0; i<len-1; i+=3){
44 if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
45 printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
46 if (err < 0)
47 return err;
48 else
49 return -EREMOTEIO;
50 }
51 i2cmsgs.buf += 3;
52 }
53 return 0;
54}
55
56static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg)
57{
58 struct lgdt3304_state *state = fe->demodulator_priv;
59 struct i2c_msg i2cmsgs[2];
60 int ret;
61 __u8 buf;
62
63 __u8 regbuf[2] = { reg>>8, reg&0xff };
64
65 i2cmsgs[0].addr = state->addr;
66 i2cmsgs[0].flags = 0;
67 i2cmsgs[0].len = 2;
68 i2cmsgs[0].buf = regbuf;
69
70 i2cmsgs[1].addr = state->addr;
71 i2cmsgs[1].flags = I2C_M_RD;
72 i2cmsgs[1].len = 1;
73 i2cmsgs[1].buf = &buf;
74
75 if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
76 printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
77 return ret;
78 }
79
80 return buf;
81}
82
83static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val)
84{
85 struct lgdt3304_state *state = fe->demodulator_priv;
86 char buffer[3] = { reg>>8, reg&0xff, val };
87 int ret;
88
89 struct i2c_msg i2cmsgs = {
90 .addr = state->addr,
91 .flags = 0,
92 .len = 3,
93 .buf=buffer
94 };
95 ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
96 if (ret != 1) {
97 printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
98 return ret;
99 }
100
101 return 0;
102}
103
104
105static int lgdt3304_soft_Reset(struct dvb_frontend *fe)
106{
107 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a);
108 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b);
109 mdelay(200);
110 return 0;
111}
112
113static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
114 int err = 0;
115
116 static __u8 lgdt3304_vsb8_data[] = {
117 /* 16bit , 8bit */
118 /* regs , val */
119 0x00, 0x00, 0x02,
120 0x00, 0x00, 0x13,
121 0x00, 0x0d, 0x02,
122 0x00, 0x0e, 0x02,
123 0x00, 0x12, 0x32,
124 0x00, 0x13, 0xc4,
125 0x01, 0x12, 0x17,
126 0x01, 0x13, 0x15,
127 0x01, 0x14, 0x18,
128 0x01, 0x15, 0xff,
129 0x01, 0x16, 0x2c,
130 0x02, 0x14, 0x67,
131 0x02, 0x24, 0x8d,
132 0x04, 0x27, 0x12,
133 0x04, 0x28, 0x4f,
134 0x03, 0x08, 0x80,
135 0x03, 0x09, 0x00,
136 0x03, 0x0d, 0x00,
137 0x03, 0x0e, 0x1c,
138 0x03, 0x14, 0xe1,
139 0x05, 0x0e, 0x5b,
140 };
141
142 /* not yet tested .. */
143 static __u8 lgdt3304_qam64_data[] = {
144 /* 16bit , 8bit */
145 /* regs , val */
146 0x00, 0x00, 0x18,
147 0x00, 0x0d, 0x02,
148 //0x00, 0x0e, 0x02,
149 0x00, 0x12, 0x2a,
150 0x00, 0x13, 0x00,
151 0x03, 0x14, 0xe3,
152 0x03, 0x0e, 0x1c,
153 0x03, 0x08, 0x66,
154 0x03, 0x09, 0x66,
155 0x03, 0x0a, 0x08,
156 0x03, 0x0b, 0x9b,
157 0x05, 0x0e, 0x5b,
158 };
159
160
161 /* tested with KWorld a340 */
162 static __u8 lgdt3304_qam256_data[] = {
163 /* 16bit , 8bit */
164 /* regs , val */
165 0x00, 0x00, 0x01, //0x19,
166 0x00, 0x12, 0x2a,
167 0x00, 0x13, 0x80,
168 0x00, 0x0d, 0x02,
169 0x03, 0x14, 0xe3,
170
171 0x03, 0x0e, 0x1c,
172 0x03, 0x08, 0x66,
173 0x03, 0x09, 0x66,
174 0x03, 0x0a, 0x08,
175 0x03, 0x0b, 0x9b,
176
177 0x03, 0x0d, 0x14,
178 //0x05, 0x0e, 0x5b,
179 0x01, 0x06, 0x4a,
180 0x01, 0x07, 0x3d,
181 0x01, 0x08, 0x70,
182 0x01, 0x09, 0xa3,
183
184 0x05, 0x04, 0xfd,
185
186 0x00, 0x0d, 0x82,
187
188 0x05, 0x0e, 0x5b,
189
190 0x05, 0x0e, 0x5b,
191
192 0x00, 0x02, 0x9a,
193
194 0x00, 0x02, 0x9b,
195
196 0x00, 0x00, 0x01,
197 0x00, 0x12, 0x2a,
198 0x00, 0x13, 0x80,
199 0x00, 0x0d, 0x02,
200 0x03, 0x14, 0xe3,
201
202 0x03, 0x0e, 0x1c,
203 0x03, 0x08, 0x66,
204 0x03, 0x09, 0x66,
205 0x03, 0x0a, 0x08,
206 0x03, 0x0b, 0x9b,
207
208 0x03, 0x0d, 0x14,
209 0x01, 0x06, 0x4a,
210 0x01, 0x07, 0x3d,
211 0x01, 0x08, 0x70,
212 0x01, 0x09, 0xa3,
213
214 0x05, 0x04, 0xfd,
215
216 0x00, 0x0d, 0x82,
217
218 0x05, 0x0e, 0x5b,
219 };
220
221 struct lgdt3304_state *state = fe->demodulator_priv;
222 if (state->current_modulation != param->u.vsb.modulation) {
223 switch(param->u.vsb.modulation) {
224 case VSB_8:
225 err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data,
226 sizeof(lgdt3304_vsb8_data));
227 break;
228 case QAM_64:
229 err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data,
230 sizeof(lgdt3304_qam64_data));
231 break;
232 case QAM_256:
233 err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data,
234 sizeof(lgdt3304_qam256_data));
235 break;
236 default:
237 break;
238 }
239
240 if (err) {
241 printk("%s error setting modulation\n", __FUNCTION__);
242 } else {
243 state->current_modulation = param->u.vsb.modulation;
244 }
245 }
246 state->current_frequency = param->frequency;
247
248 lgdt3304_soft_Reset(fe);
249
250
251 if (fe->ops.tuner_ops.set_params)
252 fe->ops.tuner_ops.set_params(fe, param);
253
254 return 0;
255}
256
257static int lgdt3304_init(struct dvb_frontend *fe) {
258 return 0;
259}
260
261static int lgdt3304_sleep(struct dvb_frontend *fe) {
262 return 0;
263}
264
265
266static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
267{
268 struct lgdt3304_state *state = fe->demodulator_priv;
269 int r011d;
270 int qam_lck;
271
272 *status = 0;
273 dprintk("lgdt read status\n");
274
275 r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
276
277 dprintk("%02x\n", r011d);
278
279 switch(state->current_modulation) {
280 case VSB_8:
281 if (r011d & 0x80) {
282 dprintk("VSB Locked\n");
283 *status |= FE_HAS_CARRIER;
284 *status |= FE_HAS_LOCK;
285 *status |= FE_HAS_SYNC;
286 *status |= FE_HAS_SIGNAL;
287 }
288 break;
289 case QAM_64:
290 case QAM_256:
291 qam_lck = r011d & 0x7;
292 switch(qam_lck) {
293 case 0x0: dprintk("Unlock\n");
294 break;
295 case 0x4: dprintk("1st Lock in acquisition state\n");
296 break;
297 case 0x6: dprintk("2nd Lock in acquisition state\n");
298 break;
299 case 0x7: dprintk("Final Lock in good reception state\n");
300 *status |= FE_HAS_CARRIER;
301 *status |= FE_HAS_LOCK;
302 *status |= FE_HAS_SYNC;
303 *status |= FE_HAS_SIGNAL;
304 break;
305 }
306 break;
307 default:
308 printk("%s unhandled modulation\n", __FUNCTION__);
309 }
310
311
312 return 0;
313}
314
315static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
316{
317 dprintk("read ber\n");
318 return 0;
319}
320
321static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
322{
323 dprintk("read snr\n");
324 return 0;
325}
326
327static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
328{
329 dprintk("read ucblocks\n");
330 return 0;
331}
332
333static void lgdt3304_release(struct dvb_frontend *fe)
334{
335 struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
336 kfree(state);
337}
338
339static struct dvb_frontend_ops demod_lgdt3304={
340 .info = {
341 .name = "LG 3304",
342 .type = FE_ATSC,
343 .frequency_min = 54000000,
344 .frequency_max = 858000000,
345 .frequency_stepsize = 62500,
346 .symbol_rate_min = 5056941,
347 .symbol_rate_max = 10762000,
348 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
349 },
350 .init = lgdt3304_init,
351 .sleep = lgdt3304_sleep,
352 .set_frontend = lgdt3304_set_parameters,
353 .read_snr = lgdt3304_read_snr,
354 .read_ber = lgdt3304_read_ber,
355 .read_status = lgdt3304_read_status,
356 .read_ucblocks = lgdt3304_read_ucblocks,
357 .release = lgdt3304_release,
358};
359
360struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
361 struct i2c_adapter *i2c)
362{
363
364 struct lgdt3304_state *state;
365 state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
366 memset(state, 0x0, sizeof(struct lgdt3304_state));
367 state->addr = config->i2c_address;
368 state->i2c = i2c;
369
370 memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops));
371 state->frontend.demodulator_priv = state;
372 return &state->frontend;
373}
374
375EXPORT_SYMBOL_GPL(lgdt3304_attach);
376MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
377MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver");
378MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lgdt3304.h b/drivers/media/dvb/frontends/lgdt3304.h
new file mode 100644
index 000000000000..fc409fe59acb
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgdt3304.h
@@ -0,0 +1,45 @@
1/*
2 * Driver for DVB-T lgdt3304 demodulator
3 *
4 * Copyright (C) 2008 Markus Rechberger <mrechberger@gmail.com>
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 *
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
20 */
21
22#ifndef LGDT3304_H
23#define LGDT3304_H
24
25#include <linux/dvb/frontend.h>
26
27struct lgdt3304_config
28{
29 /* demodulator's I2C address */
30 u8 i2c_address;
31};
32
33#if defined(CONFIG_DVB_LGDT3304) || (defined(CONFIG_DVB_LGDT3304_MODULE) && defined(MODULE))
34extern struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
35 struct i2c_adapter *i2c);
36#else
37static inline struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
38 struct i2c_adapter *i2c)
39{
40 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
41 return NULL;
42}
43#endif /* CONFIG_DVB_LGDT */
44
45#endif /* LGDT3304_H */