blob: d20ab30c1e8341d37af3600a41d97bb1ff02a7c1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
3 *
4 * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
5 *
6 * Based on code from Jack Kelliher (kelliher@xmission.com)
7 * Copyright (C) 2002 & pcHDTV, inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23*/
24
25/*
26 * This driver needs two external firmware files. Please copy
27 * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to
28 * /usr/lib/hotplug/firmware/ or /lib/firmware/
29 * (depending on configuration of firmware hotplug).
30 */
31#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"
32#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/init.h>
38#include <linux/delay.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080039#include <linux/string.h>
40#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/byteorder.h>
42
43#include "dvb_frontend.h"
44#include "dvb-pll.h"
45#include "or51132.h"
46
47static int debug;
48#define dprintk(args...) \
49 do { \
50 if (debug) printk(KERN_DEBUG "or51132: " args); \
51 } while (0)
52
53
54struct or51132_state
55{
56 struct i2c_adapter* i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58 /* Configuration settings */
59 const struct or51132_config* config;
60
61 struct dvb_frontend frontend;
62
63 /* Demodulator private data */
64 fe_modulation_t current_modulation;
65
66 /* Tuner private data */
67 u32 current_frequency;
68};
69
70static int i2c_writebytes (struct or51132_state* state, u8 reg, u8 *buf, int len)
71{
72 int err;
73 struct i2c_msg msg;
74 msg.addr = reg;
75 msg.flags = 0;
76 msg.len = len;
77 msg.buf = buf;
78
79 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
80 printk(KERN_WARNING "or51132: i2c_writebytes error (addr %02x, err == %i)\n", reg, err);
81 return -EREMOTEIO;
82 }
83
84 return 0;
85}
86
87static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len)
88{
89 int err;
90 struct i2c_msg msg;
91 msg.addr = reg;
92 msg.flags = I2C_M_RD;
93 msg.len = len;
94 msg.buf = buf;
95
96 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
97 printk(KERN_WARNING "or51132: i2c_readbytes error (addr %02x, err == %i)\n", reg, err);
98 return -EREMOTEIO;
99 }
100
101 return 0;
102}
103
104static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
105{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700106 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 static u8 run_buf[] = {0x7F,0x01};
Trent Piepho0ead0912006-04-02 20:40:33 -0300108 u8 rec_buf[8];
109 u8 cmd_buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 u32 firmwareAsize, firmwareBsize;
111 int i,ret;
112
113 dprintk("Firmware is %Zd bytes\n",fw->size);
114
115 /* Get size of firmware A and B */
116 firmwareAsize = le32_to_cpu(*((u32*)fw->data));
117 dprintk("FirmwareA is %i bytes\n",firmwareAsize);
118 firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
119 dprintk("FirmwareB is %i bytes\n",firmwareBsize);
120
121 /* Upload firmware */
122 if ((ret = i2c_writebytes(state,state->config->demod_address,
123 &fw->data[8],firmwareAsize))) {
124 printk(KERN_WARNING "or51132: load_firmware error 1\n");
125 return ret;
126 }
127 msleep(1); /* 1ms */
128 if ((ret = i2c_writebytes(state,state->config->demod_address,
129 &fw->data[8+firmwareAsize],firmwareBsize))) {
130 printk(KERN_WARNING "or51132: load_firmware error 2\n");
131 return ret;
132 }
133 msleep(1); /* 1ms */
134
135 if ((ret = i2c_writebytes(state,state->config->demod_address,
136 run_buf,2))) {
137 printk(KERN_WARNING "or51132: load_firmware error 3\n");
138 return ret;
139 }
140
141 /* Wait at least 5 msec */
142 msleep(20); /* 10ms */
143
144 if ((ret = i2c_writebytes(state,state->config->demod_address,
145 run_buf,2))) {
146 printk(KERN_WARNING "or51132: load_firmware error 4\n");
147 return ret;
148 }
149
150 /* 50ms for operation to begin */
151 msleep(50);
152
153 /* Read back ucode version to besure we loaded correctly and are really up and running */
154 /* Get uCode version */
155 cmd_buf[0] = 0x10;
156 cmd_buf[1] = 0x10;
157 cmd_buf[2] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 msleep(20); /* 20ms */
159 if ((ret = i2c_writebytes(state,state->config->demod_address,
160 cmd_buf,3))) {
161 printk(KERN_WARNING "or51132: load_firmware error a\n");
162 return ret;
163 }
164
165 cmd_buf[0] = 0x04;
166 cmd_buf[1] = 0x17;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 msleep(20); /* 20ms */
168 if ((ret = i2c_writebytes(state,state->config->demod_address,
169 cmd_buf,2))) {
170 printk(KERN_WARNING "or51132: load_firmware error b\n");
171 return ret;
172 }
173
174 cmd_buf[0] = 0x00;
175 cmd_buf[1] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 msleep(20); /* 20ms */
177 if ((ret = i2c_writebytes(state,state->config->demod_address,
178 cmd_buf,2))) {
179 printk(KERN_WARNING "or51132: load_firmware error c\n");
180 return ret;
181 }
182
183 for(i=0;i<4;i++) {
184 msleep(20); /* 20ms */
Michael Krufkyd147ed22006-04-03 01:29:09 -0300185 /* Once upon a time, this command might have had something
Trent Piepho0ead0912006-04-02 20:40:33 -0300186 to do with getting the firmware version, but it's
187 not used anymore:
188 {0x04,0x00,0x30,0x00,i+1} */
189 /* Read 8 bytes, two bytes at a time */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 if ((ret = i2c_readbytes(state,state->config->demod_address,
191 &rec_buf[i*2],2))) {
192 printk(KERN_WARNING
193 "or51132: load_firmware error d - %d\n",i);
194 return ret;
195 }
196 }
197
198 printk(KERN_WARNING
199 "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
200 rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
201 rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
202 rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
203 rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
204
205 cmd_buf[0] = 0x10;
206 cmd_buf[1] = 0x00;
207 cmd_buf[2] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 msleep(20); /* 20ms */
209 if ((ret = i2c_writebytes(state,state->config->demod_address,
210 cmd_buf,3))) {
211 printk(KERN_WARNING "or51132: load_firmware error e\n");
212 return ret;
213 }
214 return 0;
215};
216
217static int or51132_init(struct dvb_frontend* fe)
218{
219 return 0;
220}
221
222static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
223{
224 *ber = 0;
225 return 0;
226}
227
228static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
229{
230 *ucblocks = 0;
231 return 0;
232}
233
234static int or51132_sleep(struct dvb_frontend* fe)
235{
236 return 0;
237}
238
239static int or51132_setmode(struct dvb_frontend* fe)
240{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700241 struct or51132_state* state = fe->demodulator_priv;
Trent Piepho68ef5052006-04-04 09:30:33 -0300242 unsigned char cmd_buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
244 dprintk("setmode %d\n",(int)state->current_modulation);
245 /* set operation mode in Receiver 1 register; */
246 cmd_buf[0] = 0x04;
247 cmd_buf[1] = 0x01;
248 switch (state->current_modulation) {
249 case QAM_256:
250 case QAM_64:
251 case QAM_AUTO:
252 /* Auto-deinterleave; MPEG ser, MPEG2tr, phase noise-high*/
253 cmd_buf[2] = 0x5F;
254 break;
255 case VSB_8:
256 /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high*/
257 cmd_buf[2] = 0x50;
258 break;
259 default:
260 printk("setmode:Modulation set to unsupported value\n");
261 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 if (i2c_writebytes(state,state->config->demod_address,
263 cmd_buf,3)) {
264 printk(KERN_WARNING "or51132: set_mode error 1\n");
265 return -1;
266 }
267 dprintk("or51132: set #1 to %02x\n", cmd_buf[2]);
268
269 /* Set operation mode in Receiver 6 register */
270 cmd_buf[0] = 0x1C;
271 switch (state->current_modulation) {
272 case QAM_AUTO:
273 /* REC MODE Normal Carrier Lock */
274 cmd_buf[1] = 0x00;
275 /* Channel MODE Auto QAM64/256 */
276 cmd_buf[2] = 0x4f;
277 break;
278 case QAM_256:
279 /* REC MODE Normal Carrier Lock */
280 cmd_buf[1] = 0x00;
281 /* Channel MODE QAM256 */
282 cmd_buf[2] = 0x45;
283 break;
284 case QAM_64:
285 /* REC MODE Normal Carrier Lock */
286 cmd_buf[1] = 0x00;
287 /* Channel MODE QAM64 */
288 cmd_buf[2] = 0x43;
289 break;
290 case VSB_8:
291 /* REC MODE inv IF spectrum, Normal */
292 cmd_buf[1] = 0x03;
293 /* Channel MODE ATSC/VSB8 */
294 cmd_buf[2] = 0x06;
295 break;
296 default:
297 printk("setmode: Modulation set to unsupported value\n");
298 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 msleep(20); /* 20ms */
300 if (i2c_writebytes(state,state->config->demod_address,
301 cmd_buf,3)) {
302 printk(KERN_WARNING "or51132: set_mode error 2\n");
303 return -1;
304 }
305 dprintk("or51132: set #6 to 0x%02x%02x\n", cmd_buf[1], cmd_buf[2]);
306
307 return 0;
308}
309
Trent Piepho87184552006-04-04 09:30:29 -0300310/* Some modulations use the same firmware. This classifies modulations
311 by the firmware they use. */
312#define MOD_FWCLASS_UNKNOWN 0
313#define MOD_FWCLASS_VSB 1
314#define MOD_FWCLASS_QAM 2
315static int modulation_fw_class(fe_modulation_t modulation)
316{
317 switch(modulation) {
318 case VSB_8:
319 return MOD_FWCLASS_VSB;
320 case QAM_AUTO:
321 case QAM_64:
322 case QAM_256:
323 return MOD_FWCLASS_QAM;
324 default:
325 return MOD_FWCLASS_UNKNOWN;
326 }
327}
328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329static int or51132_set_parameters(struct dvb_frontend* fe,
330 struct dvb_frontend_parameters *param)
331{
332 int ret;
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700333 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 const struct firmware *fw;
Trent Piepho87184552006-04-04 09:30:29 -0300335 const char *fwname;
336 int clock_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Trent Piepho87184552006-04-04 09:30:29 -0300338 /* Upload new firmware only if we need a different one */
339 if (modulation_fw_class(state->current_modulation) !=
340 modulation_fw_class(param->u.vsb.modulation)) {
341 switch(modulation_fw_class(param->u.vsb.modulation)) {
342 case MOD_FWCLASS_VSB:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 dprintk("set_parameters VSB MODE\n");
Trent Piepho87184552006-04-04 09:30:29 -0300344 fwname = OR51132_VSB_FIRMWARE;
345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 /* Set non-punctured clock for VSB */
Trent Piepho87184552006-04-04 09:30:29 -0300347 clock_mode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 break;
Trent Piepho87184552006-04-04 09:30:29 -0300349 case MOD_FWCLASS_QAM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 dprintk("set_parameters QAM MODE\n");
Trent Piepho87184552006-04-04 09:30:29 -0300351 fwname = OR51132_QAM_FIRMWARE;
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 /* Set punctured clock for QAM */
Trent Piepho87184552006-04-04 09:30:29 -0300354 clock_mode = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 break;
356 default:
Trent Piepho87184552006-04-04 09:30:29 -0300357 printk("or51132: Modulation type(%d) UNSUPPORTED\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 param->u.vsb.modulation);
359 return -1;
Trent Piepho87184552006-04-04 09:30:29 -0300360 }
361 printk("or51132: Waiting for firmware upload(%s)...\n",
362 fwname);
363 ret = request_firmware(&fw, fwname, &state->i2c->dev);
364 if (ret) {
365 printk(KERN_WARNING "or51132: No firmware up"
366 "loaded(timeout or file not found?)\n");
367 return ret;
368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 ret = or51132_load_firmware(fe, fw);
370 release_firmware(fw);
371 if (ret) {
372 printk(KERN_WARNING "or51132: Writing firmware to "
373 "device failed!\n");
374 return ret;
375 }
376 printk("or51132: Firmware upload complete.\n");
Trent Piepho87184552006-04-04 09:30:29 -0300377 state->config->set_ts_params(fe, clock_mode);
378 }
379 /* Change only if we are actually changing the modulation */
380 if (state->current_modulation != param->u.vsb.modulation) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 state->current_modulation = param->u.vsb.modulation;
382 or51132_setmode(fe);
383 }
384
Patrick Boettcherdea74862006-05-14 05:01:31 -0300385 if (fe->ops.tuner_ops.set_params) {
386 fe->ops.tuner_ops.set_params(fe, param);
387 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quincey44d92aa2006-04-18 17:47:10 -0300388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Mac Michaels80e27e22005-09-09 13:02:40 -0700390 /* Set to current mode */
391 or51132_setmode(fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Mac Michaels80e27e22005-09-09 13:02:40 -0700393 /* Update current frequency */
394 state->current_frequency = param->frequency;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 return 0;
396}
397
Trent Piepho0dbbc0a2006-04-06 06:03:09 -0300398static int or51132_get_parameters(struct dvb_frontend* fe,
399 struct dvb_frontend_parameters *param)
400{
401 struct or51132_state* state = fe->demodulator_priv;
402 u8 buf[2];
403
404 /* Receiver Status */
405 buf[0]=0x04;
406 buf[1]=0x00;
407 msleep(30); /* 30ms */
408 if (i2c_writebytes(state,state->config->demod_address,buf,2)) {
409 printk(KERN_WARNING "or51132: get_parameters write error\n");
410 return -EREMOTEIO;
411 }
412 msleep(30); /* 30ms */
413 if (i2c_readbytes(state,state->config->demod_address,buf,2)) {
414 printk(KERN_WARNING "or51132: get_parameters read error\n");
415 return -EREMOTEIO;
416 }
417 switch(buf[0]) {
418 case 0x06: param->u.vsb.modulation = VSB_8; break;
419 case 0x43: param->u.vsb.modulation = QAM_64; break;
420 case 0x45: param->u.vsb.modulation = QAM_256; break;
421 default:
422 printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
423 buf[0]);
424 return -EREMOTEIO;
425 }
426
427 /* FIXME: Read frequency from frontend, take AFC into account */
428 param->frequency = state->current_frequency;
429
430 /* FIXME: How to read inversion setting? Receiver 6 register? */
431 param->inversion = INVERSION_AUTO;
432
433 return 0;
434}
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
437{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700438 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 unsigned char rec_buf[2];
440 unsigned char snd_buf[2];
441 *status = 0;
442
443 /* Receiver Status */
444 snd_buf[0]=0x04;
445 snd_buf[1]=0x00;
446 msleep(30); /* 30ms */
447 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
448 printk(KERN_WARNING "or51132: read_status write error\n");
449 return -1;
450 }
451 msleep(30); /* 30ms */
452 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
453 printk(KERN_WARNING "or51132: read_status read error\n");
454 return -1;
455 }
456 dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
457
458 if (rec_buf[1] & 0x01) { /* Receiver Lock */
459 *status |= FE_HAS_SIGNAL;
460 *status |= FE_HAS_CARRIER;
461 *status |= FE_HAS_VITERBI;
462 *status |= FE_HAS_SYNC;
463 *status |= FE_HAS_LOCK;
464 }
465 return 0;
466}
467
468/* log10-1 table at .5 increments from 1 to 100.5 */
469static unsigned int i100x20log10[] = {
470 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
471 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
472 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
473 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
474 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
475 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
476 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
477 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
478 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
479 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
480 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
481 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
482 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
483 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
484 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
485 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
486 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
487 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
488 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
489 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
490};
491
492static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
493
494static unsigned int i20Log10(unsigned short val)
495{
496 unsigned int rntval = 100;
497 unsigned int tmp = val;
498 unsigned int exp = 1;
499
500 while(tmp > 100) {tmp /= 100; exp++;}
501
502 val = (2 * val)/denom[exp];
503 if (exp > 1) rntval = 2000*exp;
504
505 rntval += i100x20log10[val];
506 return rntval;
507}
508
509static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
510{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700511 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 unsigned char rec_buf[2];
513 unsigned char snd_buf[2];
514 u8 rcvr_stat;
515 u16 snr_equ;
Johannes Stezenbachb90ed912005-11-08 21:35:25 -0800516 u32 signal_strength;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 int usK;
518
519 snd_buf[0]=0x04;
520 snd_buf[1]=0x02; /* SNR after Equalizer */
521 msleep(30); /* 30ms */
522 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
523 printk(KERN_WARNING "or51132: read_status write error\n");
524 return -1;
525 }
526 msleep(30); /* 30ms */
527 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
528 printk(KERN_WARNING "or51132: read_status read error\n");
529 return -1;
530 }
531 snr_equ = rec_buf[0] | (rec_buf[1] << 8);
532 dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
533
534 /* Receiver Status */
535 snd_buf[0]=0x04;
536 snd_buf[1]=0x00;
537 msleep(30); /* 30ms */
538 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
539 printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n");
540 return -1;
541 }
542 msleep(30); /* 30ms */
543 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
544 printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n");
545 return -1;
546 }
547 dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
548 rcvr_stat = rec_buf[1];
549 usK = (rcvr_stat & 0x10) ? 3 : 0;
550
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800551 /* The value reported back from the frontend will be FFFF=100% 0000=0% */
Johannes Stezenbachb90ed912005-11-08 21:35:25 -0800552 signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
553 if (signal_strength > 0xffff)
554 *strength = 0xffff;
555 else
556 *strength = signal_strength;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 dprintk("read_signal_strength %i\n",*strength);
558
559 return 0;
560}
561
562static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
563{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700564 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 unsigned char rec_buf[2];
566 unsigned char snd_buf[2];
567 u16 snr_equ;
568
569 snd_buf[0]=0x04;
570 snd_buf[1]=0x02; /* SNR after Equalizer */
571 msleep(30); /* 30ms */
572 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
573 printk(KERN_WARNING "or51132: read_snr write error\n");
574 return -1;
575 }
576 msleep(30); /* 30ms */
577 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
578 printk(KERN_WARNING "or51132: read_snr dvr read error\n");
579 return -1;
580 }
581 snr_equ = rec_buf[0] | (rec_buf[1] << 8);
582 dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
583
584 *snr = 0xFFFF - snr_equ;
585 dprintk("read_snr %i\n",*snr);
586
587 return 0;
588}
589
590static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
591{
592 fe_tune_settings->min_delay_ms = 500;
593 fe_tune_settings->step_size = 0;
594 fe_tune_settings->max_drift = 0;
595
596 return 0;
597}
598
599static void or51132_release(struct dvb_frontend* fe)
600{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700601 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 kfree(state);
603}
604
605static struct dvb_frontend_ops or51132_ops;
606
607struct dvb_frontend* or51132_attach(const struct or51132_config* config,
608 struct i2c_adapter* i2c)
609{
610 struct or51132_state* state = NULL;
611
612 /* Allocate memory for the internal state */
613 state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
614 if (state == NULL)
615 goto error;
616
617 /* Setup the state */
618 state->config = config;
619 state->i2c = i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 state->current_frequency = -1;
621 state->current_modulation = -1;
622
623 /* Create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300624 memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 state->frontend.demodulator_priv = state;
626 return &state->frontend;
627
628error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800629 kfree(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 return NULL;
631}
632
633static struct dvb_frontend_ops or51132_ops = {
634
635 .info = {
636 .name = "Oren OR51132 VSB/QAM Frontend",
Patrick Boettcherdea74862006-05-14 05:01:31 -0300637 .type = FE_ATSC,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 .frequency_min = 44000000,
639 .frequency_max = 958000000,
640 .frequency_stepsize = 166666,
641 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
642 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
643 FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
644 FE_CAN_8VSB
645 },
646
647 .release = or51132_release,
648
649 .init = or51132_init,
650 .sleep = or51132_sleep,
651
652 .set_frontend = or51132_set_parameters,
Trent Piepho0dbbc0a2006-04-06 06:03:09 -0300653 .get_frontend = or51132_get_parameters,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 .get_tune_settings = or51132_get_tune_settings,
655
656 .read_status = or51132_read_status,
657 .read_ber = or51132_read_ber,
658 .read_signal_strength = or51132_read_signal_strength,
659 .read_snr = or51132_read_snr,
660 .read_ucblocks = or51132_read_ucblocks,
661};
662
663module_param(debug, int, 0644);
664MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
665
666MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
667MODULE_AUTHOR("Kirk Lapray");
668MODULE_LICENSE("GPL");
669
670EXPORT_SYMBOL(or51132_attach);
671
672/*
673 * Local variables:
674 * c-basic-offset: 8
675 * End:
676 */