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/slab.h> 11#include <linux/delay.h> 12#include "dvb_frontend.h" 13#include "lgdt3304.h" 14 15static unsigned int debug = 0; 16module_param(debug, int, 0644); 17MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)"); 18 19#define dprintk(fmt, args...) if (debug) do {\ 20 printk("lgdt3304 debug: " fmt, ##args); } while (0) 21 22struct lgdt3304_state 23{ 24 struct dvb_frontend frontend; 25 fe_modulation_t current_modulation; 26 __u32 snr; 27 __u32 current_frequency; 28 __u8 addr; 29 struct i2c_adapter *i2c; 30}; 31 32static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len) 33{ 34 struct lgdt3304_state *state = fe->demodulator_priv; 35 struct i2c_msg i2cmsgs = { 36 .addr = state->addr, 37 .flags = 0, 38 .len = 3, 39 .buf = buf 40 }; 41 int i; 42 int err; 43 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); 47 if (err < 0) 48 return err; 49 else 50 return -EREMOTEIO; 51 } 52 i2cmsgs.buf += 3; 53 } 54 return 0; 55} 56 57static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg) 58{ 59 struct lgdt3304_state *state = fe->demodulator_priv; 60 struct i2c_msg i2cmsgs[2]; 61 int ret; 62 __u8 buf; 63 64 __u8 regbuf[2] = { reg>>8, reg&0xff }; 65 66 i2cmsgs[0].addr = state->addr; 67 i2cmsgs[0].flags = 0; 68 i2cmsgs[0].len = 2; 69 i2cmsgs[0].buf = regbuf; 70 71 i2cmsgs[1].addr = state->addr; 72 i2cmsgs[1].flags = I2C_M_RD; 73 i2cmsgs[1].len = 1; 74 i2cmsgs[1].buf = &buf; 75 76 if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) { 77 printk("%s i2c_transfer error %d\n", __func__, ret); 78 return ret; 79 } 80 81 return buf; 82} 83 84static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val) 85{ 86 struct lgdt3304_state *state = fe->demodulator_priv; 87 char buffer[3] = { reg>>8, reg&0xff, val }; 88 int ret; 89 90 struct i2c_msg i2cmsgs = { 91 .addr = state->addr, 92 .flags = 0, 93 .len = 3, 94 .buf=buffer 95 }; 96 ret = i2c_transfer(state->i2c, &i2cmsgs, 1); 97 if (ret != 1) { 98 printk("%s i2c_transfer error %d\n", __func__, ret); 99 return ret; 100 } 101 102 return 0; 103} 104 105 106static int lgdt3304_soft_Reset(struct dvb_frontend *fe) 107{ 108 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a); 109 lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b); 110 mdelay(200); 111 return 0; 112} 113 114static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { 115 int err = 0; 116 117 static __u8 lgdt3304_vsb8_data[] = { 118 /* 16bit , 8bit */ 119 /* regs , val */ 120 0x00, 0x00, 0x02, 121 0x00, 0x00, 0x13, 122 0x00, 0x0d, 0x02, 123 0x00, 0x0e, 0x02, 124 0x00, 0x12, 0x32, 125 0x00, 0x13, 0xc4, 126 0x01, 0x12, 0x17, 127 0x01, 0x13, 0x15, 128 0x01, 0x14, 0x18, 129 0x01, 0x15, 0xff, 130 0x01, 0x16, 0x2c, 131 0x02, 0x14, 0x67, 132 0x02, 0x24, 0x8d, 133 0x04, 0x27, 0x12, 134 0x04, 0x28, 0x4f, 135 0x03, 0x08, 0x80, 136 0x03, 0x09, 0x00, 137 0x03, 0x0d, 0x00, 138 0x03, 0x0e, 0x1c, 139 0x03, 0x14, 0xe1, 140 0x05, 0x0e, 0x5b, 141 }; 142 143 /* not yet tested .. */ 144 static __u8 lgdt3304_qam64_data[] = { 145 /* 16bit , 8bit */ 146 /* regs , val */ 147 0x00, 0x00, 0x18, 148 0x00, 0x0d, 0x02, 149 //0x00, 0x0e, 0x02, 150 0x00, 0x12, 0x2a, 151 0x00, 0x13, 0x00, 152 0x03, 0x14, 0xe3, 153 0x03, 0x0e, 0x1c, 154 0x03, 0x08, 0x66, 155 0x03, 0x09, 0x66, 156 0x03, 0x0a, 0x08, 157 0x03, 0x0b, 0x9b, 158 0x05, 0x0e, 0x5b, 159 }; 160 161 162 /* tested with KWorld a340 */ 163 static __u8 lgdt3304_qam256_data[] = { 164 /* 16bit , 8bit */ 165 /* regs , val */ 166 0x00, 0x00, 0x01, //0x19, 167 0x00, 0x12, 0x2a, 168 0x00, 0x13, 0x80, 169 0x00, 0x0d, 0x02, 170 0x03, 0x14, 0xe3, 171 172 0x03, 0x0e, 0x1c, 173 0x03, 0x08, 0x66, 174 0x03, 0x09, 0x66, 175 0x03, 0x0a, 0x08, 176 0x03, 0x0b, 0x9b, 177 178 0x03, 0x0d, 0x14, 179 //0x05, 0x0e, 0x5b, 180 0x01, 0x06, 0x4a, 181 0x01, 0x07, 0x3d, 182 0x01, 0x08, 0x70, 183 0x01, 0x09, 0xa3, 184 185 0x05, 0x04, 0xfd, 186 187 0x00, 0x0d, 0x82, 188 189 0x05, 0x0e, 0x5b, 190 191 0x05, 0x0e, 0x5b, 192 193 0x00, 0x02, 0x9a, 194 195 0x00, 0x02, 0x9b, 196 197 0x00, 0x00, 0x01, 198 0x00, 0x12, 0x2a, 199 0x00, 0x13, 0x80, 200 0x00, 0x0d, 0x02, 201 0x03, 0x14, 0xe3, 202 203 0x03, 0x0e, 0x1c, 204 0x03, 0x08, 0x66, 205 0x03, 0x09, 0x66, 206 0x03, 0x0a, 0x08, 207 0x03, 0x0b, 0x9b, 208 209 0x03, 0x0d, 0x14, 210 0x01, 0x06, 0x4a, 211 0x01, 0x07, 0x3d, 212 0x01, 0x08, 0x70, 213 0x01, 0x09, 0xa3, 214 215 0x05, 0x04, 0xfd, 216 217 0x00, 0x0d, 0x82, 218 219 0x05, 0x0e, 0x5b, 220 }; 221 222 struct lgdt3304_state *state = fe->demodulator_priv; 223 if (state->current_modulation != param->u.vsb.modulation) { 224 switch(param->u.vsb.modulation) { 225 case VSB_8: 226 err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data, 227 sizeof(lgdt3304_vsb8_data)); 228 break; 229 case QAM_64: 230 err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data, 231 sizeof(lgdt3304_qam64_data)); 232 break; 233 case QAM_256: 234 err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data, 235 sizeof(lgdt3304_qam256_data)); 236 break; 237 default: 238 break; 239 } 240 241 if (err) { 242 printk("%s error setting modulation\n", __func__); 243 } else { 244 state->current_modulation = param->u.vsb.modulation; 245 } 246 } 247 state->current_frequency = param->frequency; 248 249 lgdt3304_soft_Reset(fe); 250 251 252 if (fe->ops.tuner_ops.set_params) 253 fe->ops.tuner_ops.set_params(fe, param); 254 255 return 0; 256} 257 258static int lgdt3304_init(struct dvb_frontend *fe) { 259 return 0; 260} 261 262static int lgdt3304_sleep(struct dvb_frontend *fe) { 263 return 0; 264} 265 266 267static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status) 268{ 269 struct lgdt3304_state *state = fe->demodulator_priv; 270 int r011d; 271 int qam_lck; 272 273 *status = 0; 274 dprintk("lgdt read status\n"); 275 276 r011d = lgdt3304_i2c_read_reg(fe, 0x011d); 277 278 dprintk("%02x\n", r011d); 279 280 switch(state->current_modulation) { 281 case VSB_8: 282 if (r011d & 0x80) { 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; 288 } 289 break; 290 case QAM_64: 291 case QAM_256: 292 qam_lck = r011d & 0x7; 293 switch(qam_lck) { 294 case 0x0: dprintk("Unlock\n"); 295 break; 296 case 0x4: dprintk("1st Lock in acquisition state\n"); 297 break; 298 case 0x6: dprintk("2nd Lock in acquisition state\n"); 299 break; 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; 305 break; 306 } 307 break; 308 default: 309 printk("%s unhandled modulation\n", __func__); 310 } 311 312 313 return 0; 314} 315 316static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber) 317{ 318 dprintk("read ber\n"); 319 return 0; 320} 321 322static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr) 323{ 324 dprintk("read snr\n"); 325 return 0; 326} 327 328static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks) 329{ 330 dprintk("read ucblocks\n"); 331 return 0; 332} 333 334static void lgdt3304_release(struct dvb_frontend *fe) 335{ 336 struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv; 337 kfree(state); 338} 339 340static struct dvb_frontend_ops demod_lgdt3304={ 341 .info = { 342 .name = "LG 3304", 343 .type = FE_ATSC, 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 350 }, 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, 359}; 360 361struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config, 362 struct i2c_adapter *i2c) 363{ 364 365 struct lgdt3304_state *state; 366 state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL); 367 if (state == NULL) 368 return NULL; 369 state->addr = config->i2c_address; 370 state->i2c = i2c; 371 372 memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops)); 373 state->frontend.demodulator_priv = state; 374 return &state->frontend; 375} 376 377EXPORT_SYMBOL_GPL(lgdt3304_attach); 378MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>"); 379MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver"); 380MODULE_LICENSE("GPL"); 381