• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 static  unsigned int debug = 0;
15 module_param(debug, int, 0644);
16 MODULE_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 
21 struct 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 
i2c_write_demod_bytes(struct dvb_frontend * fe,__u8 * buf,int len)31 static 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", __func__, err);
46 			if (err < 0)
47 				return err;
48 			else
49 				return -EREMOTEIO;
50 		}
51 		i2cmsgs.buf += 3;
52 	}
53 	return 0;
54 }
55 
lgdt3304_i2c_read_reg(struct dvb_frontend * fe,unsigned int reg)56 static 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", __func__, ret);
77 		return ret;
78 	}
79 
80 	return buf;
81 }
82 
lgdt3304_i2c_write_reg(struct dvb_frontend * fe,int reg,int val)83 static 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", __func__, ret);
98 		return ret;
99 	}
100 
101 	return 0;
102 }
103 
104 
lgdt3304_soft_Reset(struct dvb_frontend * fe)105 static 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 
lgdt3304_set_parameters(struct dvb_frontend * fe,struct dvb_frontend_parameters * param)113 static 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", __func__);
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 
lgdt3304_init(struct dvb_frontend * fe)257 static int lgdt3304_init(struct dvb_frontend *fe) {
258 	return 0;
259 }
260 
lgdt3304_sleep(struct dvb_frontend * fe)261 static int lgdt3304_sleep(struct dvb_frontend *fe) {
262 	return 0;
263 }
264 
265 
lgdt3304_read_status(struct dvb_frontend * fe,fe_status_t * status)266 static 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", __func__);
309 	}
310 
311 
312 	return 0;
313 }
314 
lgdt3304_read_ber(struct dvb_frontend * fe,__u32 * ber)315 static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
316 {
317 	dprintk("read ber\n");
318 	return 0;
319 }
320 
lgdt3304_read_snr(struct dvb_frontend * fe,__u16 * snr)321 static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
322 {
323 	dprintk("read snr\n");
324 	return 0;
325 }
326 
lgdt3304_read_ucblocks(struct dvb_frontend * fe,__u32 * ucblocks)327 static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
328 {
329 	dprintk("read ucblocks\n");
330 	return 0;
331 }
332 
lgdt3304_release(struct dvb_frontend * fe)333 static void lgdt3304_release(struct dvb_frontend *fe)
334 {
335 	struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
336 	kfree(state);
337 }
338 
339 static 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 
lgdt3304_attach(const struct lgdt3304_config * config,struct i2c_adapter * i2c)360 struct 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 
375 EXPORT_SYMBOL_GPL(lgdt3304_attach);
376 MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
377 MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver");
378 MODULE_LICENSE("GPL");
379