2 * Driver for LG ATSC lgdt3304 driver
4 * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
12 #include "dvb_frontend.h"
15 static unsigned int debug = 0;
16 module_param(debug, int, 0644);
17 MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)");
19 #define dprintk(fmt, args...) if (debug) do {\
20 printk("lgdt3304 debug: " fmt, ##args); } while (0)
24 struct dvb_frontend frontend;
25 fe_modulation_t current_modulation;
27 __u32 current_frequency;
29 struct i2c_adapter *i2c;
32 static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len)
34 struct lgdt3304_state *state = fe->demodulator_priv;
35 struct i2c_msg i2cmsgs = {
44 for (i=0; i<len-1; i+=3){
45 if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
46 printk("%s i2c_transfer error %d\n", __func__, err);
57 static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg)
59 struct lgdt3304_state *state = fe->demodulator_priv;
60 struct i2c_msg i2cmsgs[2];
64 __u8 regbuf[2] = { reg>>8, reg&0xff };
66 i2cmsgs[0].addr = state->addr;
69 i2cmsgs[0].buf = regbuf;
71 i2cmsgs[1].addr = state->addr;
72 i2cmsgs[1].flags = I2C_M_RD;
74 i2cmsgs[1].buf = &buf;
76 if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
77 printk("%s i2c_transfer error %d\n", __func__, ret);
84 static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val)
86 struct lgdt3304_state *state = fe->demodulator_priv;
87 char buffer[3] = { reg>>8, reg&0xff, val };
90 struct i2c_msg i2cmsgs = {
96 ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
98 printk("%s i2c_transfer error %d\n", __func__, ret);
106 static int lgdt3304_soft_Reset(struct dvb_frontend *fe)
108 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a);
109 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b);
114 static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
117 static __u8 lgdt3304_vsb8_data[] = {
143 /* not yet tested .. */
144 static __u8 lgdt3304_qam64_data[] = {
162 /* tested with KWorld a340 */
163 static __u8 lgdt3304_qam256_data[] = {
166 0x00, 0x00, 0x01, //0x19,
222 struct lgdt3304_state *state = fe->demodulator_priv;
223 if (state->current_modulation != param->u.vsb.modulation) {
224 switch(param->u.vsb.modulation) {
226 err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data,
227 sizeof(lgdt3304_vsb8_data));
230 err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data,
231 sizeof(lgdt3304_qam64_data));
234 err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data,
235 sizeof(lgdt3304_qam256_data));
242 printk("%s error setting modulation\n", __func__);
244 state->current_modulation = param->u.vsb.modulation;
247 state->current_frequency = param->frequency;
249 lgdt3304_soft_Reset(fe);
252 if (fe->ops.tuner_ops.set_params)
253 fe->ops.tuner_ops.set_params(fe, param);
258 static int lgdt3304_init(struct dvb_frontend *fe) {
262 static int lgdt3304_sleep(struct dvb_frontend *fe) {
267 static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
269 struct lgdt3304_state *state = fe->demodulator_priv;
274 dprintk("lgdt read status\n");
276 r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
278 dprintk("%02x\n", r011d);
280 switch(state->current_modulation) {
283 dprintk("VSB Locked\n");
284 *status |= FE_HAS_CARRIER;
285 *status |= FE_HAS_LOCK;
286 *status |= FE_HAS_SYNC;
287 *status |= FE_HAS_SIGNAL;
292 qam_lck = r011d & 0x7;
294 case 0x0: dprintk("Unlock\n");
296 case 0x4: dprintk("1st Lock in acquisition state\n");
298 case 0x6: dprintk("2nd Lock in acquisition state\n");
300 case 0x7: dprintk("Final Lock in good reception state\n");
301 *status |= FE_HAS_CARRIER;
302 *status |= FE_HAS_LOCK;
303 *status |= FE_HAS_SYNC;
304 *status |= FE_HAS_SIGNAL;
309 printk("%s unhandled modulation\n", __func__);
316 static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
318 dprintk("read ber\n");
322 static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
324 dprintk("read snr\n");
328 static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
330 dprintk("read ucblocks\n");
334 static void lgdt3304_release(struct dvb_frontend *fe)
336 struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
340 static struct dvb_frontend_ops demod_lgdt3304={
344 .frequency_min = 54000000,
345 .frequency_max = 858000000,
346 .frequency_stepsize = 62500,
347 .symbol_rate_min = 5056941,
348 .symbol_rate_max = 10762000,
349 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
351 .init = lgdt3304_init,
352 .sleep = lgdt3304_sleep,
353 .set_frontend = lgdt3304_set_parameters,
354 .read_snr = lgdt3304_read_snr,
355 .read_ber = lgdt3304_read_ber,
356 .read_status = lgdt3304_read_status,
357 .read_ucblocks = lgdt3304_read_ucblocks,
358 .release = lgdt3304_release,
361 struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
362 struct i2c_adapter *i2c)
365 struct lgdt3304_state *state;
366 state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
369 state->addr = config->i2c_address;
372 memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops));
373 state->frontend.demodulator_priv = state;
374 return &state->frontend;
377 EXPORT_SYMBOL_GPL(lgdt3304_attach);
378 MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
379 MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver");
380 MODULE_LICENSE("GPL");