blob: 56d1109b90a2b7e14e29d6df102852d865b8309a [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;
57 struct dvb_frontend_ops ops;
58
59 /* Configuration settings */
60 const struct or51132_config* config;
61
62 struct dvb_frontend frontend;
63
64 /* Demodulator private data */
65 fe_modulation_t current_modulation;
66
67 /* Tuner private data */
68 u32 current_frequency;
69};
70
71static int i2c_writebytes (struct or51132_state* state, u8 reg, u8 *buf, int len)
72{
73 int err;
74 struct i2c_msg msg;
75 msg.addr = reg;
76 msg.flags = 0;
77 msg.len = len;
78 msg.buf = buf;
79
80 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
81 printk(KERN_WARNING "or51132: i2c_writebytes error (addr %02x, err == %i)\n", reg, err);
82 return -EREMOTEIO;
83 }
84
85 return 0;
86}
87
88static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len)
89{
90 int err;
91 struct i2c_msg msg;
92 msg.addr = reg;
93 msg.flags = I2C_M_RD;
94 msg.len = len;
95 msg.buf = buf;
96
97 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
98 printk(KERN_WARNING "or51132: i2c_readbytes error (addr %02x, err == %i)\n", reg, err);
99 return -EREMOTEIO;
100 }
101
102 return 0;
103}
104
105static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
106{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700107 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 static u8 run_buf[] = {0x7F,0x01};
Trent Piepho0ead0912006-04-02 20:40:33 -0300109 u8 rec_buf[8];
110 u8 cmd_buf[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 u32 firmwareAsize, firmwareBsize;
112 int i,ret;
113
114 dprintk("Firmware is %Zd bytes\n",fw->size);
115
116 /* Get size of firmware A and B */
117 firmwareAsize = le32_to_cpu(*((u32*)fw->data));
118 dprintk("FirmwareA is %i bytes\n",firmwareAsize);
119 firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
120 dprintk("FirmwareB is %i bytes\n",firmwareBsize);
121
122 /* Upload firmware */
123 if ((ret = i2c_writebytes(state,state->config->demod_address,
124 &fw->data[8],firmwareAsize))) {
125 printk(KERN_WARNING "or51132: load_firmware error 1\n");
126 return ret;
127 }
128 msleep(1); /* 1ms */
129 if ((ret = i2c_writebytes(state,state->config->demod_address,
130 &fw->data[8+firmwareAsize],firmwareBsize))) {
131 printk(KERN_WARNING "or51132: load_firmware error 2\n");
132 return ret;
133 }
134 msleep(1); /* 1ms */
135
136 if ((ret = i2c_writebytes(state,state->config->demod_address,
137 run_buf,2))) {
138 printk(KERN_WARNING "or51132: load_firmware error 3\n");
139 return ret;
140 }
141
142 /* Wait at least 5 msec */
143 msleep(20); /* 10ms */
144
145 if ((ret = i2c_writebytes(state,state->config->demod_address,
146 run_buf,2))) {
147 printk(KERN_WARNING "or51132: load_firmware error 4\n");
148 return ret;
149 }
150
151 /* 50ms for operation to begin */
152 msleep(50);
153
154 /* Read back ucode version to besure we loaded correctly and are really up and running */
155 /* Get uCode version */
156 cmd_buf[0] = 0x10;
157 cmd_buf[1] = 0x10;
158 cmd_buf[2] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 msleep(20); /* 20ms */
160 if ((ret = i2c_writebytes(state,state->config->demod_address,
161 cmd_buf,3))) {
162 printk(KERN_WARNING "or51132: load_firmware error a\n");
163 return ret;
164 }
165
166 cmd_buf[0] = 0x04;
167 cmd_buf[1] = 0x17;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 msleep(20); /* 20ms */
169 if ((ret = i2c_writebytes(state,state->config->demod_address,
170 cmd_buf,2))) {
171 printk(KERN_WARNING "or51132: load_firmware error b\n");
172 return ret;
173 }
174
175 cmd_buf[0] = 0x00;
176 cmd_buf[1] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 msleep(20); /* 20ms */
178 if ((ret = i2c_writebytes(state,state->config->demod_address,
179 cmd_buf,2))) {
180 printk(KERN_WARNING "or51132: load_firmware error c\n");
181 return ret;
182 }
183
184 for(i=0;i<4;i++) {
185 msleep(20); /* 20ms */
Michael Krufkyd147ed22006-04-03 01:29:09 -0300186 /* Once upon a time, this command might have had something
Trent Piepho0ead0912006-04-02 20:40:33 -0300187 to do with getting the firmware version, but it's
188 not used anymore:
189 {0x04,0x00,0x30,0x00,i+1} */
190 /* Read 8 bytes, two bytes at a time */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 if ((ret = i2c_readbytes(state,state->config->demod_address,
192 &rec_buf[i*2],2))) {
193 printk(KERN_WARNING
194 "or51132: load_firmware error d - %d\n",i);
195 return ret;
196 }
197 }
198
199 printk(KERN_WARNING
200 "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
201 rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
202 rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
203 rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
204 rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
205
206 cmd_buf[0] = 0x10;
207 cmd_buf[1] = 0x00;
208 cmd_buf[2] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 msleep(20); /* 20ms */
210 if ((ret = i2c_writebytes(state,state->config->demod_address,
211 cmd_buf,3))) {
212 printk(KERN_WARNING "or51132: load_firmware error e\n");
213 return ret;
214 }
215 return 0;
216};
217
218static int or51132_init(struct dvb_frontend* fe)
219{
220 return 0;
221}
222
223static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
224{
225 *ber = 0;
226 return 0;
227}
228
229static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
230{
231 *ucblocks = 0;
232 return 0;
233}
234
235static int or51132_sleep(struct dvb_frontend* fe)
236{
237 return 0;
238}
239
240static int or51132_setmode(struct dvb_frontend* fe)
241{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700242 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 unsigned char cmd_buf[4];
244
245 dprintk("setmode %d\n",(int)state->current_modulation);
246 /* set operation mode in Receiver 1 register; */
247 cmd_buf[0] = 0x04;
248 cmd_buf[1] = 0x01;
249 switch (state->current_modulation) {
250 case QAM_256:
251 case QAM_64:
252 case QAM_AUTO:
253 /* Auto-deinterleave; MPEG ser, MPEG2tr, phase noise-high*/
254 cmd_buf[2] = 0x5F;
255 break;
256 case VSB_8:
257 /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high*/
258 cmd_buf[2] = 0x50;
259 break;
260 default:
261 printk("setmode:Modulation set to unsupported value\n");
262 };
263 cmd_buf[3] = 0x00;
264 if (i2c_writebytes(state,state->config->demod_address,
265 cmd_buf,3)) {
266 printk(KERN_WARNING "or51132: set_mode error 1\n");
267 return -1;
268 }
269 dprintk("or51132: set #1 to %02x\n", cmd_buf[2]);
270
271 /* Set operation mode in Receiver 6 register */
272 cmd_buf[0] = 0x1C;
273 switch (state->current_modulation) {
274 case QAM_AUTO:
275 /* REC MODE Normal Carrier Lock */
276 cmd_buf[1] = 0x00;
277 /* Channel MODE Auto QAM64/256 */
278 cmd_buf[2] = 0x4f;
279 break;
280 case QAM_256:
281 /* REC MODE Normal Carrier Lock */
282 cmd_buf[1] = 0x00;
283 /* Channel MODE QAM256 */
284 cmd_buf[2] = 0x45;
285 break;
286 case QAM_64:
287 /* REC MODE Normal Carrier Lock */
288 cmd_buf[1] = 0x00;
289 /* Channel MODE QAM64 */
290 cmd_buf[2] = 0x43;
291 break;
292 case VSB_8:
293 /* REC MODE inv IF spectrum, Normal */
294 cmd_buf[1] = 0x03;
295 /* Channel MODE ATSC/VSB8 */
296 cmd_buf[2] = 0x06;
297 break;
298 default:
299 printk("setmode: Modulation set to unsupported value\n");
300 };
301 cmd_buf[3] = 0x00;
302 msleep(20); /* 20ms */
303 if (i2c_writebytes(state,state->config->demod_address,
304 cmd_buf,3)) {
305 printk(KERN_WARNING "or51132: set_mode error 2\n");
306 return -1;
307 }
308 dprintk("or51132: set #6 to 0x%02x%02x\n", cmd_buf[1], cmd_buf[2]);
309
310 return 0;
311}
312
Trent Piepho87184552006-04-04 09:30:29 -0300313/* Some modulations use the same firmware. This classifies modulations
314 by the firmware they use. */
315#define MOD_FWCLASS_UNKNOWN 0
316#define MOD_FWCLASS_VSB 1
317#define MOD_FWCLASS_QAM 2
318static int modulation_fw_class(fe_modulation_t modulation)
319{
320 switch(modulation) {
321 case VSB_8:
322 return MOD_FWCLASS_VSB;
323 case QAM_AUTO:
324 case QAM_64:
325 case QAM_256:
326 return MOD_FWCLASS_QAM;
327 default:
328 return MOD_FWCLASS_UNKNOWN;
329 }
330}
331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332static int or51132_set_parameters(struct dvb_frontend* fe,
333 struct dvb_frontend_parameters *param)
334{
335 int ret;
336 u8 buf[4];
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700337 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 const struct firmware *fw;
Trent Piepho87184552006-04-04 09:30:29 -0300339 const char *fwname;
340 int clock_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Trent Piepho87184552006-04-04 09:30:29 -0300342 /* Upload new firmware only if we need a different one */
343 if (modulation_fw_class(state->current_modulation) !=
344 modulation_fw_class(param->u.vsb.modulation)) {
345 switch(modulation_fw_class(param->u.vsb.modulation)) {
346 case MOD_FWCLASS_VSB:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 dprintk("set_parameters VSB MODE\n");
Trent Piepho87184552006-04-04 09:30:29 -0300348 fwname = OR51132_VSB_FIRMWARE;
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 /* Set non-punctured clock for VSB */
Trent Piepho87184552006-04-04 09:30:29 -0300351 clock_mode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 break;
Trent Piepho87184552006-04-04 09:30:29 -0300353 case MOD_FWCLASS_QAM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 dprintk("set_parameters QAM MODE\n");
Trent Piepho87184552006-04-04 09:30:29 -0300355 fwname = OR51132_QAM_FIRMWARE;
356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* Set punctured clock for QAM */
Trent Piepho87184552006-04-04 09:30:29 -0300358 clock_mode = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 break;
360 default:
Trent Piepho87184552006-04-04 09:30:29 -0300361 printk("or51132: Modulation type(%d) UNSUPPORTED\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 param->u.vsb.modulation);
363 return -1;
Trent Piepho87184552006-04-04 09:30:29 -0300364 }
365 printk("or51132: Waiting for firmware upload(%s)...\n",
366 fwname);
367 ret = request_firmware(&fw, fwname, &state->i2c->dev);
368 if (ret) {
369 printk(KERN_WARNING "or51132: No firmware up"
370 "loaded(timeout or file not found?)\n");
371 return ret;
372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 ret = or51132_load_firmware(fe, fw);
374 release_firmware(fw);
375 if (ret) {
376 printk(KERN_WARNING "or51132: Writing firmware to "
377 "device failed!\n");
378 return ret;
379 }
380 printk("or51132: Firmware upload complete.\n");
Trent Piepho87184552006-04-04 09:30:29 -0300381 state->config->set_ts_params(fe, clock_mode);
382 }
383 /* Change only if we are actually changing the modulation */
384 if (state->current_modulation != param->u.vsb.modulation) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 state->current_modulation = param->u.vsb.modulation;
386 or51132_setmode(fe);
387 }
388
Mac Michaels80e27e22005-09-09 13:02:40 -0700389 dvb_pll_configure(state->config->pll_desc, buf,
390 param->frequency, 0);
391 dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
392 "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
Trent Piepho87184552006-04-04 09:30:29 -0300393 if (i2c_writebytes(state, state->config->pll_address, buf, 4))
Mac Michaels80e27e22005-09-09 13:02:40 -0700394 printk(KERN_WARNING "or51132: set_parameters error "
395 "writing to tuner\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Mac Michaels80e27e22005-09-09 13:02:40 -0700397 /* Set to current mode */
398 or51132_setmode(fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
Mac Michaels80e27e22005-09-09 13:02:40 -0700400 /* Update current frequency */
401 state->current_frequency = param->frequency;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 return 0;
403}
404
405static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
406{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700407 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 unsigned char rec_buf[2];
409 unsigned char snd_buf[2];
410 *status = 0;
411
412 /* Receiver Status */
413 snd_buf[0]=0x04;
414 snd_buf[1]=0x00;
415 msleep(30); /* 30ms */
416 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
417 printk(KERN_WARNING "or51132: read_status write error\n");
418 return -1;
419 }
420 msleep(30); /* 30ms */
421 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
422 printk(KERN_WARNING "or51132: read_status read error\n");
423 return -1;
424 }
425 dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
426
427 if (rec_buf[1] & 0x01) { /* Receiver Lock */
428 *status |= FE_HAS_SIGNAL;
429 *status |= FE_HAS_CARRIER;
430 *status |= FE_HAS_VITERBI;
431 *status |= FE_HAS_SYNC;
432 *status |= FE_HAS_LOCK;
433 }
434 return 0;
435}
436
437/* log10-1 table at .5 increments from 1 to 100.5 */
438static unsigned int i100x20log10[] = {
439 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
440 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
441 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
442 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
443 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
444 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
445 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
446 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
447 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
448 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
449 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
450 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
451 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
452 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
453 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
454 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
455 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
456 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
457 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
458 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
459};
460
461static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
462
463static unsigned int i20Log10(unsigned short val)
464{
465 unsigned int rntval = 100;
466 unsigned int tmp = val;
467 unsigned int exp = 1;
468
469 while(tmp > 100) {tmp /= 100; exp++;}
470
471 val = (2 * val)/denom[exp];
472 if (exp > 1) rntval = 2000*exp;
473
474 rntval += i100x20log10[val];
475 return rntval;
476}
477
478static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
479{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700480 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 unsigned char rec_buf[2];
482 unsigned char snd_buf[2];
483 u8 rcvr_stat;
484 u16 snr_equ;
Johannes Stezenbachb90ed912005-11-08 21:35:25 -0800485 u32 signal_strength;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 int usK;
487
488 snd_buf[0]=0x04;
489 snd_buf[1]=0x02; /* SNR after Equalizer */
490 msleep(30); /* 30ms */
491 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
492 printk(KERN_WARNING "or51132: read_status write error\n");
493 return -1;
494 }
495 msleep(30); /* 30ms */
496 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
497 printk(KERN_WARNING "or51132: read_status read error\n");
498 return -1;
499 }
500 snr_equ = rec_buf[0] | (rec_buf[1] << 8);
501 dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
502
503 /* Receiver Status */
504 snd_buf[0]=0x04;
505 snd_buf[1]=0x00;
506 msleep(30); /* 30ms */
507 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
508 printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n");
509 return -1;
510 }
511 msleep(30); /* 30ms */
512 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
513 printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n");
514 return -1;
515 }
516 dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
517 rcvr_stat = rec_buf[1];
518 usK = (rcvr_stat & 0x10) ? 3 : 0;
519
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800520 /* The value reported back from the frontend will be FFFF=100% 0000=0% */
Johannes Stezenbachb90ed912005-11-08 21:35:25 -0800521 signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
522 if (signal_strength > 0xffff)
523 *strength = 0xffff;
524 else
525 *strength = signal_strength;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 dprintk("read_signal_strength %i\n",*strength);
527
528 return 0;
529}
530
531static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
532{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700533 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 unsigned char rec_buf[2];
535 unsigned char snd_buf[2];
536 u16 snr_equ;
537
538 snd_buf[0]=0x04;
539 snd_buf[1]=0x02; /* SNR after Equalizer */
540 msleep(30); /* 30ms */
541 if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
542 printk(KERN_WARNING "or51132: read_snr write error\n");
543 return -1;
544 }
545 msleep(30); /* 30ms */
546 if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
547 printk(KERN_WARNING "or51132: read_snr dvr read error\n");
548 return -1;
549 }
550 snr_equ = rec_buf[0] | (rec_buf[1] << 8);
551 dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
552
553 *snr = 0xFFFF - snr_equ;
554 dprintk("read_snr %i\n",*snr);
555
556 return 0;
557}
558
559static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
560{
561 fe_tune_settings->min_delay_ms = 500;
562 fe_tune_settings->step_size = 0;
563 fe_tune_settings->max_drift = 0;
564
565 return 0;
566}
567
568static void or51132_release(struct dvb_frontend* fe)
569{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700570 struct or51132_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 kfree(state);
572}
573
574static struct dvb_frontend_ops or51132_ops;
575
576struct dvb_frontend* or51132_attach(const struct or51132_config* config,
577 struct i2c_adapter* i2c)
578{
579 struct or51132_state* state = NULL;
580
581 /* Allocate memory for the internal state */
582 state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
583 if (state == NULL)
584 goto error;
585
586 /* Setup the state */
587 state->config = config;
588 state->i2c = i2c;
589 memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
590 state->current_frequency = -1;
591 state->current_modulation = -1;
592
593 /* Create dvb_frontend */
594 state->frontend.ops = &state->ops;
595 state->frontend.demodulator_priv = state;
596 return &state->frontend;
597
598error:
Jesper Juhl2ea75332005-11-07 01:01:31 -0800599 kfree(state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 return NULL;
601}
602
603static struct dvb_frontend_ops or51132_ops = {
604
605 .info = {
606 .name = "Oren OR51132 VSB/QAM Frontend",
607 .type = FE_ATSC,
608 .frequency_min = 44000000,
609 .frequency_max = 958000000,
610 .frequency_stepsize = 166666,
611 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
612 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
613 FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
614 FE_CAN_8VSB
615 },
616
617 .release = or51132_release,
618
619 .init = or51132_init,
620 .sleep = or51132_sleep,
621
622 .set_frontend = or51132_set_parameters,
623 .get_tune_settings = or51132_get_tune_settings,
624
625 .read_status = or51132_read_status,
626 .read_ber = or51132_read_ber,
627 .read_signal_strength = or51132_read_signal_strength,
628 .read_snr = or51132_read_snr,
629 .read_ucblocks = or51132_read_ucblocks,
630};
631
632module_param(debug, int, 0644);
633MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
634
635MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
636MODULE_AUTHOR("Kirk Lapray");
637MODULE_LICENSE("GPL");
638
639EXPORT_SYMBOL(or51132_attach);
640
641/*
642 * Local variables:
643 * c-basic-offset: 8
644 * End:
645 */