1*9a0bf528SMauro Carvalho Chehab /* 2*9a0bf528SMauro Carvalho Chehab * Support for OR51211 (pcHDTV HD-2000) - VSB 3*9a0bf528SMauro Carvalho Chehab * 4*9a0bf528SMauro Carvalho Chehab * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com> 5*9a0bf528SMauro Carvalho Chehab * 6*9a0bf528SMauro Carvalho Chehab * Based on code from Jack Kelliher (kelliher@xmission.com) 7*9a0bf528SMauro Carvalho Chehab * Copyright (C) 2002 & pcHDTV, inc. 8*9a0bf528SMauro Carvalho Chehab * 9*9a0bf528SMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 10*9a0bf528SMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 11*9a0bf528SMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 12*9a0bf528SMauro Carvalho Chehab * (at your option) any later version. 13*9a0bf528SMauro Carvalho Chehab * 14*9a0bf528SMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 15*9a0bf528SMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*9a0bf528SMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*9a0bf528SMauro Carvalho Chehab * GNU General Public License for more details. 18*9a0bf528SMauro Carvalho Chehab * 19*9a0bf528SMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 20*9a0bf528SMauro Carvalho Chehab * along with this program; if not, write to the Free Software 21*9a0bf528SMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*9a0bf528SMauro Carvalho Chehab * 23*9a0bf528SMauro Carvalho Chehab */ 24*9a0bf528SMauro Carvalho Chehab 25*9a0bf528SMauro Carvalho Chehab /* 26*9a0bf528SMauro Carvalho Chehab * This driver needs external firmware. Please use the command 27*9a0bf528SMauro Carvalho Chehab * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to 28*9a0bf528SMauro Carvalho Chehab * download/extract it, and then copy it to /usr/lib/hotplug/firmware 29*9a0bf528SMauro Carvalho Chehab * or /lib/firmware (depending on configuration of firmware hotplug). 30*9a0bf528SMauro Carvalho Chehab */ 31*9a0bf528SMauro Carvalho Chehab #define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw" 32*9a0bf528SMauro Carvalho Chehab 33*9a0bf528SMauro Carvalho Chehab #include <linux/kernel.h> 34*9a0bf528SMauro Carvalho Chehab #include <linux/module.h> 35*9a0bf528SMauro Carvalho Chehab #include <linux/device.h> 36*9a0bf528SMauro Carvalho Chehab #include <linux/firmware.h> 37*9a0bf528SMauro Carvalho Chehab #include <linux/string.h> 38*9a0bf528SMauro Carvalho Chehab #include <linux/slab.h> 39*9a0bf528SMauro Carvalho Chehab #include <asm/byteorder.h> 40*9a0bf528SMauro Carvalho Chehab 41*9a0bf528SMauro Carvalho Chehab #include "dvb_math.h" 42*9a0bf528SMauro Carvalho Chehab #include "dvb_frontend.h" 43*9a0bf528SMauro Carvalho Chehab #include "or51211.h" 44*9a0bf528SMauro Carvalho Chehab 45*9a0bf528SMauro Carvalho Chehab static int debug; 46*9a0bf528SMauro Carvalho Chehab #define dprintk(args...) \ 47*9a0bf528SMauro Carvalho Chehab do { \ 48*9a0bf528SMauro Carvalho Chehab if (debug) printk(KERN_DEBUG "or51211: " args); \ 49*9a0bf528SMauro Carvalho Chehab } while (0) 50*9a0bf528SMauro Carvalho Chehab 51*9a0bf528SMauro Carvalho Chehab static u8 run_buf[] = {0x7f,0x01}; 52*9a0bf528SMauro Carvalho Chehab static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC 53*9a0bf528SMauro Carvalho Chehab 54*9a0bf528SMauro Carvalho Chehab struct or51211_state { 55*9a0bf528SMauro Carvalho Chehab 56*9a0bf528SMauro Carvalho Chehab struct i2c_adapter* i2c; 57*9a0bf528SMauro Carvalho Chehab 58*9a0bf528SMauro Carvalho Chehab /* Configuration settings */ 59*9a0bf528SMauro Carvalho Chehab const struct or51211_config* config; 60*9a0bf528SMauro Carvalho Chehab 61*9a0bf528SMauro Carvalho Chehab struct dvb_frontend frontend; 62*9a0bf528SMauro Carvalho Chehab struct bt878* bt; 63*9a0bf528SMauro Carvalho Chehab 64*9a0bf528SMauro Carvalho Chehab /* Demodulator private data */ 65*9a0bf528SMauro Carvalho Chehab u8 initialized:1; 66*9a0bf528SMauro Carvalho Chehab u32 snr; /* Result of last SNR claculation */ 67*9a0bf528SMauro Carvalho Chehab 68*9a0bf528SMauro Carvalho Chehab /* Tuner private data */ 69*9a0bf528SMauro Carvalho Chehab u32 current_frequency; 70*9a0bf528SMauro Carvalho Chehab }; 71*9a0bf528SMauro Carvalho Chehab 72*9a0bf528SMauro Carvalho Chehab static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf, 73*9a0bf528SMauro Carvalho Chehab int len) 74*9a0bf528SMauro Carvalho Chehab { 75*9a0bf528SMauro Carvalho Chehab int err; 76*9a0bf528SMauro Carvalho Chehab struct i2c_msg msg; 77*9a0bf528SMauro Carvalho Chehab msg.addr = reg; 78*9a0bf528SMauro Carvalho Chehab msg.flags = 0; 79*9a0bf528SMauro Carvalho Chehab msg.len = len; 80*9a0bf528SMauro Carvalho Chehab msg.buf = (u8 *)buf; 81*9a0bf528SMauro Carvalho Chehab 82*9a0bf528SMauro Carvalho Chehab if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { 83*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: i2c_writebytes error " 84*9a0bf528SMauro Carvalho Chehab "(addr %02x, err == %i)\n", reg, err); 85*9a0bf528SMauro Carvalho Chehab return -EREMOTEIO; 86*9a0bf528SMauro Carvalho Chehab } 87*9a0bf528SMauro Carvalho Chehab 88*9a0bf528SMauro Carvalho Chehab return 0; 89*9a0bf528SMauro Carvalho Chehab } 90*9a0bf528SMauro Carvalho Chehab 91*9a0bf528SMauro Carvalho Chehab static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len) 92*9a0bf528SMauro Carvalho Chehab { 93*9a0bf528SMauro Carvalho Chehab int err; 94*9a0bf528SMauro Carvalho Chehab struct i2c_msg msg; 95*9a0bf528SMauro Carvalho Chehab msg.addr = reg; 96*9a0bf528SMauro Carvalho Chehab msg.flags = I2C_M_RD; 97*9a0bf528SMauro Carvalho Chehab msg.len = len; 98*9a0bf528SMauro Carvalho Chehab msg.buf = buf; 99*9a0bf528SMauro Carvalho Chehab 100*9a0bf528SMauro Carvalho Chehab if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { 101*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: i2c_readbytes error " 102*9a0bf528SMauro Carvalho Chehab "(addr %02x, err == %i)\n", reg, err); 103*9a0bf528SMauro Carvalho Chehab return -EREMOTEIO; 104*9a0bf528SMauro Carvalho Chehab } 105*9a0bf528SMauro Carvalho Chehab 106*9a0bf528SMauro Carvalho Chehab return 0; 107*9a0bf528SMauro Carvalho Chehab } 108*9a0bf528SMauro Carvalho Chehab 109*9a0bf528SMauro Carvalho Chehab static int or51211_load_firmware (struct dvb_frontend* fe, 110*9a0bf528SMauro Carvalho Chehab const struct firmware *fw) 111*9a0bf528SMauro Carvalho Chehab { 112*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 113*9a0bf528SMauro Carvalho Chehab u8 tudata[585]; 114*9a0bf528SMauro Carvalho Chehab int i; 115*9a0bf528SMauro Carvalho Chehab 116*9a0bf528SMauro Carvalho Chehab dprintk("Firmware is %zd bytes\n",fw->size); 117*9a0bf528SMauro Carvalho Chehab 118*9a0bf528SMauro Carvalho Chehab /* Get eprom data */ 119*9a0bf528SMauro Carvalho Chehab tudata[0] = 17; 120*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,0x50,tudata,1)) { 121*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211:load_firmware error eprom addr\n"); 122*9a0bf528SMauro Carvalho Chehab return -1; 123*9a0bf528SMauro Carvalho Chehab } 124*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,0x50,&tudata[145],192)) { 125*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: load_firmware error eprom\n"); 126*9a0bf528SMauro Carvalho Chehab return -1; 127*9a0bf528SMauro Carvalho Chehab } 128*9a0bf528SMauro Carvalho Chehab 129*9a0bf528SMauro Carvalho Chehab /* Create firmware buffer */ 130*9a0bf528SMauro Carvalho Chehab for (i = 0; i < 145; i++) 131*9a0bf528SMauro Carvalho Chehab tudata[i] = fw->data[i]; 132*9a0bf528SMauro Carvalho Chehab 133*9a0bf528SMauro Carvalho Chehab for (i = 0; i < 248; i++) 134*9a0bf528SMauro Carvalho Chehab tudata[i+337] = fw->data[145+i]; 135*9a0bf528SMauro Carvalho Chehab 136*9a0bf528SMauro Carvalho Chehab state->config->reset(fe); 137*9a0bf528SMauro Carvalho Chehab 138*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,tudata,585)) { 139*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: load_firmware error 1\n"); 140*9a0bf528SMauro Carvalho Chehab return -1; 141*9a0bf528SMauro Carvalho Chehab } 142*9a0bf528SMauro Carvalho Chehab msleep(1); 143*9a0bf528SMauro Carvalho Chehab 144*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 145*9a0bf528SMauro Carvalho Chehab &fw->data[393],8125)) { 146*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: load_firmware error 2\n"); 147*9a0bf528SMauro Carvalho Chehab return -1; 148*9a0bf528SMauro Carvalho Chehab } 149*9a0bf528SMauro Carvalho Chehab msleep(1); 150*9a0bf528SMauro Carvalho Chehab 151*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) { 152*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: load_firmware error 3\n"); 153*9a0bf528SMauro Carvalho Chehab return -1; 154*9a0bf528SMauro Carvalho Chehab } 155*9a0bf528SMauro Carvalho Chehab 156*9a0bf528SMauro Carvalho Chehab /* Wait at least 5 msec */ 157*9a0bf528SMauro Carvalho Chehab msleep(10); 158*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) { 159*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: load_firmware error 4\n"); 160*9a0bf528SMauro Carvalho Chehab return -1; 161*9a0bf528SMauro Carvalho Chehab } 162*9a0bf528SMauro Carvalho Chehab msleep(10); 163*9a0bf528SMauro Carvalho Chehab 164*9a0bf528SMauro Carvalho Chehab printk("or51211: Done.\n"); 165*9a0bf528SMauro Carvalho Chehab return 0; 166*9a0bf528SMauro Carvalho Chehab }; 167*9a0bf528SMauro Carvalho Chehab 168*9a0bf528SMauro Carvalho Chehab static int or51211_setmode(struct dvb_frontend* fe, int mode) 169*9a0bf528SMauro Carvalho Chehab { 170*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 171*9a0bf528SMauro Carvalho Chehab u8 rec_buf[14]; 172*9a0bf528SMauro Carvalho Chehab 173*9a0bf528SMauro Carvalho Chehab state->config->setmode(fe, mode); 174*9a0bf528SMauro Carvalho Chehab 175*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) { 176*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: setmode error 1\n"); 177*9a0bf528SMauro Carvalho Chehab return -1; 178*9a0bf528SMauro Carvalho Chehab } 179*9a0bf528SMauro Carvalho Chehab 180*9a0bf528SMauro Carvalho Chehab /* Wait at least 5 msec */ 181*9a0bf528SMauro Carvalho Chehab msleep(10); 182*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) { 183*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: setmode error 2\n"); 184*9a0bf528SMauro Carvalho Chehab return -1; 185*9a0bf528SMauro Carvalho Chehab } 186*9a0bf528SMauro Carvalho Chehab 187*9a0bf528SMauro Carvalho Chehab msleep(10); 188*9a0bf528SMauro Carvalho Chehab 189*9a0bf528SMauro Carvalho Chehab /* Set operation mode in Receiver 1 register; 190*9a0bf528SMauro Carvalho Chehab * type 1: 191*9a0bf528SMauro Carvalho Chehab * data 0x50h Automatic sets receiver channel conditions 192*9a0bf528SMauro Carvalho Chehab * Automatic NTSC rejection filter 193*9a0bf528SMauro Carvalho Chehab * Enable MPEG serial data output 194*9a0bf528SMauro Carvalho Chehab * MPEG2tr 195*9a0bf528SMauro Carvalho Chehab * High tuner phase noise 196*9a0bf528SMauro Carvalho Chehab * normal +/-150kHz Carrier acquisition range 197*9a0bf528SMauro Carvalho Chehab */ 198*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) { 199*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: setmode error 3\n"); 200*9a0bf528SMauro Carvalho Chehab return -1; 201*9a0bf528SMauro Carvalho Chehab } 202*9a0bf528SMauro Carvalho Chehab 203*9a0bf528SMauro Carvalho Chehab rec_buf[0] = 0x04; 204*9a0bf528SMauro Carvalho Chehab rec_buf[1] = 0x00; 205*9a0bf528SMauro Carvalho Chehab rec_buf[2] = 0x03; 206*9a0bf528SMauro Carvalho Chehab rec_buf[3] = 0x00; 207*9a0bf528SMauro Carvalho Chehab msleep(20); 208*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) { 209*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: setmode error 5\n"); 210*9a0bf528SMauro Carvalho Chehab } 211*9a0bf528SMauro Carvalho Chehab msleep(3); 212*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) { 213*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: setmode error 6"); 214*9a0bf528SMauro Carvalho Chehab return -1; 215*9a0bf528SMauro Carvalho Chehab } 216*9a0bf528SMauro Carvalho Chehab dprintk("setmode rec status %02x %02x\n",rec_buf[10],rec_buf[11]); 217*9a0bf528SMauro Carvalho Chehab 218*9a0bf528SMauro Carvalho Chehab return 0; 219*9a0bf528SMauro Carvalho Chehab } 220*9a0bf528SMauro Carvalho Chehab 221*9a0bf528SMauro Carvalho Chehab static int or51211_set_parameters(struct dvb_frontend *fe) 222*9a0bf528SMauro Carvalho Chehab { 223*9a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *p = &fe->dtv_property_cache; 224*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 225*9a0bf528SMauro Carvalho Chehab 226*9a0bf528SMauro Carvalho Chehab /* Change only if we are actually changing the channel */ 227*9a0bf528SMauro Carvalho Chehab if (state->current_frequency != p->frequency) { 228*9a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.set_params) { 229*9a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 230*9a0bf528SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); 231*9a0bf528SMauro Carvalho Chehab } 232*9a0bf528SMauro Carvalho Chehab 233*9a0bf528SMauro Carvalho Chehab /* Set to ATSC mode */ 234*9a0bf528SMauro Carvalho Chehab or51211_setmode(fe,0); 235*9a0bf528SMauro Carvalho Chehab 236*9a0bf528SMauro Carvalho Chehab /* Update current frequency */ 237*9a0bf528SMauro Carvalho Chehab state->current_frequency = p->frequency; 238*9a0bf528SMauro Carvalho Chehab } 239*9a0bf528SMauro Carvalho Chehab return 0; 240*9a0bf528SMauro Carvalho Chehab } 241*9a0bf528SMauro Carvalho Chehab 242*9a0bf528SMauro Carvalho Chehab static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status) 243*9a0bf528SMauro Carvalho Chehab { 244*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 245*9a0bf528SMauro Carvalho Chehab unsigned char rec_buf[2]; 246*9a0bf528SMauro Carvalho Chehab unsigned char snd_buf[] = {0x04,0x00,0x03,0x00}; 247*9a0bf528SMauro Carvalho Chehab *status = 0; 248*9a0bf528SMauro Carvalho Chehab 249*9a0bf528SMauro Carvalho Chehab /* Receiver Status */ 250*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { 251*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51132: read_status write error\n"); 252*9a0bf528SMauro Carvalho Chehab return -1; 253*9a0bf528SMauro Carvalho Chehab } 254*9a0bf528SMauro Carvalho Chehab msleep(3); 255*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 256*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51132: read_status read error\n"); 257*9a0bf528SMauro Carvalho Chehab return -1; 258*9a0bf528SMauro Carvalho Chehab } 259*9a0bf528SMauro Carvalho Chehab dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]); 260*9a0bf528SMauro Carvalho Chehab 261*9a0bf528SMauro Carvalho Chehab if (rec_buf[0] & 0x01) { /* Receiver Lock */ 262*9a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL; 263*9a0bf528SMauro Carvalho Chehab *status |= FE_HAS_CARRIER; 264*9a0bf528SMauro Carvalho Chehab *status |= FE_HAS_VITERBI; 265*9a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SYNC; 266*9a0bf528SMauro Carvalho Chehab *status |= FE_HAS_LOCK; 267*9a0bf528SMauro Carvalho Chehab } 268*9a0bf528SMauro Carvalho Chehab return 0; 269*9a0bf528SMauro Carvalho Chehab } 270*9a0bf528SMauro Carvalho Chehab 271*9a0bf528SMauro Carvalho Chehab /* Calculate SNR estimation (scaled by 2^24) 272*9a0bf528SMauro Carvalho Chehab 273*9a0bf528SMauro Carvalho Chehab 8-VSB SNR equation from Oren datasheets 274*9a0bf528SMauro Carvalho Chehab 275*9a0bf528SMauro Carvalho Chehab For 8-VSB: 276*9a0bf528SMauro Carvalho Chehab SNR[dB] = 10 * log10(219037.9454 / MSE^2 ) 277*9a0bf528SMauro Carvalho Chehab 278*9a0bf528SMauro Carvalho Chehab We re-write the snr equation as: 279*9a0bf528SMauro Carvalho Chehab SNR * 2^24 = 10*(c - 2*intlog10(MSE)) 280*9a0bf528SMauro Carvalho Chehab Where for 8-VSB, c = log10(219037.9454) * 2^24 */ 281*9a0bf528SMauro Carvalho Chehab 282*9a0bf528SMauro Carvalho Chehab static u32 calculate_snr(u32 mse, u32 c) 283*9a0bf528SMauro Carvalho Chehab { 284*9a0bf528SMauro Carvalho Chehab if (mse == 0) /* No signal */ 285*9a0bf528SMauro Carvalho Chehab return 0; 286*9a0bf528SMauro Carvalho Chehab 287*9a0bf528SMauro Carvalho Chehab mse = 2*intlog10(mse); 288*9a0bf528SMauro Carvalho Chehab if (mse > c) { 289*9a0bf528SMauro Carvalho Chehab /* Negative SNR, which is possible, but realisticly the 290*9a0bf528SMauro Carvalho Chehab demod will lose lock before the signal gets this bad. The 291*9a0bf528SMauro Carvalho Chehab API only allows for unsigned values, so just return 0 */ 292*9a0bf528SMauro Carvalho Chehab return 0; 293*9a0bf528SMauro Carvalho Chehab } 294*9a0bf528SMauro Carvalho Chehab return 10*(c - mse); 295*9a0bf528SMauro Carvalho Chehab } 296*9a0bf528SMauro Carvalho Chehab 297*9a0bf528SMauro Carvalho Chehab static int or51211_read_snr(struct dvb_frontend* fe, u16* snr) 298*9a0bf528SMauro Carvalho Chehab { 299*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 300*9a0bf528SMauro Carvalho Chehab u8 rec_buf[2]; 301*9a0bf528SMauro Carvalho Chehab u8 snd_buf[3]; 302*9a0bf528SMauro Carvalho Chehab 303*9a0bf528SMauro Carvalho Chehab /* SNR after Equalizer */ 304*9a0bf528SMauro Carvalho Chehab snd_buf[0] = 0x04; 305*9a0bf528SMauro Carvalho Chehab snd_buf[1] = 0x00; 306*9a0bf528SMauro Carvalho Chehab snd_buf[2] = 0x04; 307*9a0bf528SMauro Carvalho Chehab 308*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) { 309*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "%s: error writing snr reg\n", 310*9a0bf528SMauro Carvalho Chehab __func__); 311*9a0bf528SMauro Carvalho Chehab return -1; 312*9a0bf528SMauro Carvalho Chehab } 313*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) { 314*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "%s: read_status read error\n", 315*9a0bf528SMauro Carvalho Chehab __func__); 316*9a0bf528SMauro Carvalho Chehab return -1; 317*9a0bf528SMauro Carvalho Chehab } 318*9a0bf528SMauro Carvalho Chehab 319*9a0bf528SMauro Carvalho Chehab state->snr = calculate_snr(rec_buf[0], 89599047); 320*9a0bf528SMauro Carvalho Chehab *snr = (state->snr) >> 16; 321*9a0bf528SMauro Carvalho Chehab 322*9a0bf528SMauro Carvalho Chehab dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0], 323*9a0bf528SMauro Carvalho Chehab state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16); 324*9a0bf528SMauro Carvalho Chehab 325*9a0bf528SMauro Carvalho Chehab return 0; 326*9a0bf528SMauro Carvalho Chehab } 327*9a0bf528SMauro Carvalho Chehab 328*9a0bf528SMauro Carvalho Chehab static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) 329*9a0bf528SMauro Carvalho Chehab { 330*9a0bf528SMauro Carvalho Chehab /* Calculate Strength from SNR up to 35dB */ 331*9a0bf528SMauro Carvalho Chehab /* Even though the SNR can go higher than 35dB, there is some comfort */ 332*9a0bf528SMauro Carvalho Chehab /* factor in having a range of strong signals that can show at 100% */ 333*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv; 334*9a0bf528SMauro Carvalho Chehab u16 snr; 335*9a0bf528SMauro Carvalho Chehab int ret; 336*9a0bf528SMauro Carvalho Chehab 337*9a0bf528SMauro Carvalho Chehab ret = fe->ops.read_snr(fe, &snr); 338*9a0bf528SMauro Carvalho Chehab if (ret != 0) 339*9a0bf528SMauro Carvalho Chehab return ret; 340*9a0bf528SMauro Carvalho Chehab /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ 341*9a0bf528SMauro Carvalho Chehab /* scale the range 0 - 35*2^24 into 0 - 65535 */ 342*9a0bf528SMauro Carvalho Chehab if (state->snr >= 8960 * 0x10000) 343*9a0bf528SMauro Carvalho Chehab *strength = 0xffff; 344*9a0bf528SMauro Carvalho Chehab else 345*9a0bf528SMauro Carvalho Chehab *strength = state->snr / 8960; 346*9a0bf528SMauro Carvalho Chehab 347*9a0bf528SMauro Carvalho Chehab return 0; 348*9a0bf528SMauro Carvalho Chehab } 349*9a0bf528SMauro Carvalho Chehab 350*9a0bf528SMauro Carvalho Chehab static int or51211_read_ber(struct dvb_frontend* fe, u32* ber) 351*9a0bf528SMauro Carvalho Chehab { 352*9a0bf528SMauro Carvalho Chehab *ber = -ENOSYS; 353*9a0bf528SMauro Carvalho Chehab return 0; 354*9a0bf528SMauro Carvalho Chehab } 355*9a0bf528SMauro Carvalho Chehab 356*9a0bf528SMauro Carvalho Chehab static int or51211_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) 357*9a0bf528SMauro Carvalho Chehab { 358*9a0bf528SMauro Carvalho Chehab *ucblocks = -ENOSYS; 359*9a0bf528SMauro Carvalho Chehab return 0; 360*9a0bf528SMauro Carvalho Chehab } 361*9a0bf528SMauro Carvalho Chehab 362*9a0bf528SMauro Carvalho Chehab static int or51211_sleep(struct dvb_frontend* fe) 363*9a0bf528SMauro Carvalho Chehab { 364*9a0bf528SMauro Carvalho Chehab return 0; 365*9a0bf528SMauro Carvalho Chehab } 366*9a0bf528SMauro Carvalho Chehab 367*9a0bf528SMauro Carvalho Chehab static int or51211_init(struct dvb_frontend* fe) 368*9a0bf528SMauro Carvalho Chehab { 369*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 370*9a0bf528SMauro Carvalho Chehab const struct or51211_config* config = state->config; 371*9a0bf528SMauro Carvalho Chehab const struct firmware* fw; 372*9a0bf528SMauro Carvalho Chehab unsigned char get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00}; 373*9a0bf528SMauro Carvalho Chehab unsigned char rec_buf[14]; 374*9a0bf528SMauro Carvalho Chehab int ret,i; 375*9a0bf528SMauro Carvalho Chehab 376*9a0bf528SMauro Carvalho Chehab if (!state->initialized) { 377*9a0bf528SMauro Carvalho Chehab /* Request the firmware, this will block until it uploads */ 378*9a0bf528SMauro Carvalho Chehab printk(KERN_INFO "or51211: Waiting for firmware upload " 379*9a0bf528SMauro Carvalho Chehab "(%s)...\n", OR51211_DEFAULT_FIRMWARE); 380*9a0bf528SMauro Carvalho Chehab ret = config->request_firmware(fe, &fw, 381*9a0bf528SMauro Carvalho Chehab OR51211_DEFAULT_FIRMWARE); 382*9a0bf528SMauro Carvalho Chehab printk(KERN_INFO "or51211:Got Hotplug firmware\n"); 383*9a0bf528SMauro Carvalho Chehab if (ret) { 384*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: No firmware uploaded " 385*9a0bf528SMauro Carvalho Chehab "(timeout or file not found?)\n"); 386*9a0bf528SMauro Carvalho Chehab return ret; 387*9a0bf528SMauro Carvalho Chehab } 388*9a0bf528SMauro Carvalho Chehab 389*9a0bf528SMauro Carvalho Chehab ret = or51211_load_firmware(fe, fw); 390*9a0bf528SMauro Carvalho Chehab release_firmware(fw); 391*9a0bf528SMauro Carvalho Chehab if (ret) { 392*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Writing firmware to " 393*9a0bf528SMauro Carvalho Chehab "device failed!\n"); 394*9a0bf528SMauro Carvalho Chehab return ret; 395*9a0bf528SMauro Carvalho Chehab } 396*9a0bf528SMauro Carvalho Chehab printk(KERN_INFO "or51211: Firmware upload complete.\n"); 397*9a0bf528SMauro Carvalho Chehab 398*9a0bf528SMauro Carvalho Chehab /* Set operation mode in Receiver 1 register; 399*9a0bf528SMauro Carvalho Chehab * type 1: 400*9a0bf528SMauro Carvalho Chehab * data 0x50h Automatic sets receiver channel conditions 401*9a0bf528SMauro Carvalho Chehab * Automatic NTSC rejection filter 402*9a0bf528SMauro Carvalho Chehab * Enable MPEG serial data output 403*9a0bf528SMauro Carvalho Chehab * MPEG2tr 404*9a0bf528SMauro Carvalho Chehab * High tuner phase noise 405*9a0bf528SMauro Carvalho Chehab * normal +/-150kHz Carrier acquisition range 406*9a0bf528SMauro Carvalho Chehab */ 407*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 408*9a0bf528SMauro Carvalho Chehab cmd_buf,3)) { 409*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error 5\n"); 410*9a0bf528SMauro Carvalho Chehab return -1; 411*9a0bf528SMauro Carvalho Chehab } 412*9a0bf528SMauro Carvalho Chehab 413*9a0bf528SMauro Carvalho Chehab /* Read back ucode version to besure we loaded correctly */ 414*9a0bf528SMauro Carvalho Chehab /* and are really up and running */ 415*9a0bf528SMauro Carvalho Chehab rec_buf[0] = 0x04; 416*9a0bf528SMauro Carvalho Chehab rec_buf[1] = 0x00; 417*9a0bf528SMauro Carvalho Chehab rec_buf[2] = 0x03; 418*9a0bf528SMauro Carvalho Chehab rec_buf[3] = 0x00; 419*9a0bf528SMauro Carvalho Chehab msleep(30); 420*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 421*9a0bf528SMauro Carvalho Chehab rec_buf,3)) { 422*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error A\n"); 423*9a0bf528SMauro Carvalho Chehab return -1; 424*9a0bf528SMauro Carvalho Chehab } 425*9a0bf528SMauro Carvalho Chehab msleep(3); 426*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address, 427*9a0bf528SMauro Carvalho Chehab &rec_buf[10],2)) { 428*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error B\n"); 429*9a0bf528SMauro Carvalho Chehab return -1; 430*9a0bf528SMauro Carvalho Chehab } 431*9a0bf528SMauro Carvalho Chehab 432*9a0bf528SMauro Carvalho Chehab rec_buf[0] = 0x04; 433*9a0bf528SMauro Carvalho Chehab rec_buf[1] = 0x00; 434*9a0bf528SMauro Carvalho Chehab rec_buf[2] = 0x01; 435*9a0bf528SMauro Carvalho Chehab rec_buf[3] = 0x00; 436*9a0bf528SMauro Carvalho Chehab msleep(20); 437*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 438*9a0bf528SMauro Carvalho Chehab rec_buf,3)) { 439*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error C\n"); 440*9a0bf528SMauro Carvalho Chehab return -1; 441*9a0bf528SMauro Carvalho Chehab } 442*9a0bf528SMauro Carvalho Chehab msleep(3); 443*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address, 444*9a0bf528SMauro Carvalho Chehab &rec_buf[12],2)) { 445*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error D\n"); 446*9a0bf528SMauro Carvalho Chehab return -1; 447*9a0bf528SMauro Carvalho Chehab } 448*9a0bf528SMauro Carvalho Chehab 449*9a0bf528SMauro Carvalho Chehab for (i = 0; i < 8; i++) 450*9a0bf528SMauro Carvalho Chehab rec_buf[i]=0xed; 451*9a0bf528SMauro Carvalho Chehab 452*9a0bf528SMauro Carvalho Chehab for (i = 0; i < 5; i++) { 453*9a0bf528SMauro Carvalho Chehab msleep(30); 454*9a0bf528SMauro Carvalho Chehab get_ver_buf[4] = i+1; 455*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 456*9a0bf528SMauro Carvalho Chehab get_ver_buf,5)) { 457*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211:Load DVR Error 6" 458*9a0bf528SMauro Carvalho Chehab " - %d\n",i); 459*9a0bf528SMauro Carvalho Chehab return -1; 460*9a0bf528SMauro Carvalho Chehab } 461*9a0bf528SMauro Carvalho Chehab msleep(3); 462*9a0bf528SMauro Carvalho Chehab 463*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address, 464*9a0bf528SMauro Carvalho Chehab &rec_buf[i*2],2)) { 465*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211:Load DVR Error 7" 466*9a0bf528SMauro Carvalho Chehab " - %d\n",i); 467*9a0bf528SMauro Carvalho Chehab return -1; 468*9a0bf528SMauro Carvalho Chehab } 469*9a0bf528SMauro Carvalho Chehab /* If we didn't receive the right index, try again */ 470*9a0bf528SMauro Carvalho Chehab if ((int)rec_buf[i*2+1]!=i+1){ 471*9a0bf528SMauro Carvalho Chehab i--; 472*9a0bf528SMauro Carvalho Chehab } 473*9a0bf528SMauro Carvalho Chehab } 474*9a0bf528SMauro Carvalho Chehab dprintk("read_fwbits %x %x %x %x %x %x %x %x %x %x\n", 475*9a0bf528SMauro Carvalho Chehab rec_buf[0], rec_buf[1], rec_buf[2], rec_buf[3], 476*9a0bf528SMauro Carvalho Chehab rec_buf[4], rec_buf[5], rec_buf[6], rec_buf[7], 477*9a0bf528SMauro Carvalho Chehab rec_buf[8], rec_buf[9]); 478*9a0bf528SMauro Carvalho Chehab 479*9a0bf528SMauro Carvalho Chehab printk(KERN_INFO "or51211: ver TU%02x%02x%02x VSB mode %02x" 480*9a0bf528SMauro Carvalho Chehab " Status %02x\n", 481*9a0bf528SMauro Carvalho Chehab rec_buf[2], rec_buf[4],rec_buf[6], 482*9a0bf528SMauro Carvalho Chehab rec_buf[12],rec_buf[10]); 483*9a0bf528SMauro Carvalho Chehab 484*9a0bf528SMauro Carvalho Chehab rec_buf[0] = 0x04; 485*9a0bf528SMauro Carvalho Chehab rec_buf[1] = 0x00; 486*9a0bf528SMauro Carvalho Chehab rec_buf[2] = 0x03; 487*9a0bf528SMauro Carvalho Chehab rec_buf[3] = 0x00; 488*9a0bf528SMauro Carvalho Chehab msleep(20); 489*9a0bf528SMauro Carvalho Chehab if (i2c_writebytes(state,state->config->demod_address, 490*9a0bf528SMauro Carvalho Chehab rec_buf,3)) { 491*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error 8\n"); 492*9a0bf528SMauro Carvalho Chehab return -1; 493*9a0bf528SMauro Carvalho Chehab } 494*9a0bf528SMauro Carvalho Chehab msleep(20); 495*9a0bf528SMauro Carvalho Chehab if (i2c_readbytes(state,state->config->demod_address, 496*9a0bf528SMauro Carvalho Chehab &rec_buf[8],2)) { 497*9a0bf528SMauro Carvalho Chehab printk(KERN_WARNING "or51211: Load DVR Error 9\n"); 498*9a0bf528SMauro Carvalho Chehab return -1; 499*9a0bf528SMauro Carvalho Chehab } 500*9a0bf528SMauro Carvalho Chehab state->initialized = 1; 501*9a0bf528SMauro Carvalho Chehab } 502*9a0bf528SMauro Carvalho Chehab 503*9a0bf528SMauro Carvalho Chehab return 0; 504*9a0bf528SMauro Carvalho Chehab } 505*9a0bf528SMauro Carvalho Chehab 506*9a0bf528SMauro Carvalho Chehab static int or51211_get_tune_settings(struct dvb_frontend* fe, 507*9a0bf528SMauro Carvalho Chehab struct dvb_frontend_tune_settings* fesettings) 508*9a0bf528SMauro Carvalho Chehab { 509*9a0bf528SMauro Carvalho Chehab fesettings->min_delay_ms = 500; 510*9a0bf528SMauro Carvalho Chehab fesettings->step_size = 0; 511*9a0bf528SMauro Carvalho Chehab fesettings->max_drift = 0; 512*9a0bf528SMauro Carvalho Chehab return 0; 513*9a0bf528SMauro Carvalho Chehab } 514*9a0bf528SMauro Carvalho Chehab 515*9a0bf528SMauro Carvalho Chehab static void or51211_release(struct dvb_frontend* fe) 516*9a0bf528SMauro Carvalho Chehab { 517*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = fe->demodulator_priv; 518*9a0bf528SMauro Carvalho Chehab state->config->sleep(fe); 519*9a0bf528SMauro Carvalho Chehab kfree(state); 520*9a0bf528SMauro Carvalho Chehab } 521*9a0bf528SMauro Carvalho Chehab 522*9a0bf528SMauro Carvalho Chehab static struct dvb_frontend_ops or51211_ops; 523*9a0bf528SMauro Carvalho Chehab 524*9a0bf528SMauro Carvalho Chehab struct dvb_frontend* or51211_attach(const struct or51211_config* config, 525*9a0bf528SMauro Carvalho Chehab struct i2c_adapter* i2c) 526*9a0bf528SMauro Carvalho Chehab { 527*9a0bf528SMauro Carvalho Chehab struct or51211_state* state = NULL; 528*9a0bf528SMauro Carvalho Chehab 529*9a0bf528SMauro Carvalho Chehab /* Allocate memory for the internal state */ 530*9a0bf528SMauro Carvalho Chehab state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL); 531*9a0bf528SMauro Carvalho Chehab if (state == NULL) 532*9a0bf528SMauro Carvalho Chehab return NULL; 533*9a0bf528SMauro Carvalho Chehab 534*9a0bf528SMauro Carvalho Chehab /* Setup the state */ 535*9a0bf528SMauro Carvalho Chehab state->config = config; 536*9a0bf528SMauro Carvalho Chehab state->i2c = i2c; 537*9a0bf528SMauro Carvalho Chehab state->initialized = 0; 538*9a0bf528SMauro Carvalho Chehab state->current_frequency = 0; 539*9a0bf528SMauro Carvalho Chehab 540*9a0bf528SMauro Carvalho Chehab /* Create dvb_frontend */ 541*9a0bf528SMauro Carvalho Chehab memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops)); 542*9a0bf528SMauro Carvalho Chehab state->frontend.demodulator_priv = state; 543*9a0bf528SMauro Carvalho Chehab return &state->frontend; 544*9a0bf528SMauro Carvalho Chehab } 545*9a0bf528SMauro Carvalho Chehab 546*9a0bf528SMauro Carvalho Chehab static struct dvb_frontend_ops or51211_ops = { 547*9a0bf528SMauro Carvalho Chehab .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, 548*9a0bf528SMauro Carvalho Chehab .info = { 549*9a0bf528SMauro Carvalho Chehab .name = "Oren OR51211 VSB Frontend", 550*9a0bf528SMauro Carvalho Chehab .frequency_min = 44000000, 551*9a0bf528SMauro Carvalho Chehab .frequency_max = 958000000, 552*9a0bf528SMauro Carvalho Chehab .frequency_stepsize = 166666, 553*9a0bf528SMauro Carvalho Chehab .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 554*9a0bf528SMauro Carvalho Chehab FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 555*9a0bf528SMauro Carvalho Chehab FE_CAN_8VSB 556*9a0bf528SMauro Carvalho Chehab }, 557*9a0bf528SMauro Carvalho Chehab 558*9a0bf528SMauro Carvalho Chehab .release = or51211_release, 559*9a0bf528SMauro Carvalho Chehab 560*9a0bf528SMauro Carvalho Chehab .init = or51211_init, 561*9a0bf528SMauro Carvalho Chehab .sleep = or51211_sleep, 562*9a0bf528SMauro Carvalho Chehab 563*9a0bf528SMauro Carvalho Chehab .set_frontend = or51211_set_parameters, 564*9a0bf528SMauro Carvalho Chehab .get_tune_settings = or51211_get_tune_settings, 565*9a0bf528SMauro Carvalho Chehab 566*9a0bf528SMauro Carvalho Chehab .read_status = or51211_read_status, 567*9a0bf528SMauro Carvalho Chehab .read_ber = or51211_read_ber, 568*9a0bf528SMauro Carvalho Chehab .read_signal_strength = or51211_read_signal_strength, 569*9a0bf528SMauro Carvalho Chehab .read_snr = or51211_read_snr, 570*9a0bf528SMauro Carvalho Chehab .read_ucblocks = or51211_read_ucblocks, 571*9a0bf528SMauro Carvalho Chehab }; 572*9a0bf528SMauro Carvalho Chehab 573*9a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644); 574*9a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 575*9a0bf528SMauro Carvalho Chehab 576*9a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver"); 577*9a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Kirk Lapray"); 578*9a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 579*9a0bf528SMauro Carvalho Chehab 580*9a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(or51211_attach); 581*9a0bf528SMauro Carvalho Chehab 582