1*1802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2cba862dcSMauro Carvalho Chehab /* 368b3289fSMatthias Schwarzott * Driver for Zarlink zl10036 DVB-S silicon tuner 468b3289fSMatthias Schwarzott * 568b3289fSMatthias Schwarzott * Copyright (C) 2006 Tino Reichardt 668b3289fSMatthias Schwarzott * Copyright (C) 2007-2009 Matthias Schwarzott <zzam@gentoo.de> 768b3289fSMatthias Schwarzott * 868b3289fSMatthias Schwarzott ** 968b3289fSMatthias Schwarzott * The data sheet for this tuner can be found at: 1068b3289fSMatthias Schwarzott * http://www.mcmilk.de/projects/dvb-card/datasheets/ZL10036.pdf 1168b3289fSMatthias Schwarzott * 1268b3289fSMatthias Schwarzott * This one is working: (at my Avermedia DVB-S Pro) 1368b3289fSMatthias Schwarzott * - zl10036 (40pin, FTA) 1468b3289fSMatthias Schwarzott * 1568b3289fSMatthias Schwarzott * A driver for zl10038 should be very similar. 1668b3289fSMatthias Schwarzott */ 1768b3289fSMatthias Schwarzott 1868b3289fSMatthias Schwarzott #include <linux/module.h> 1968b3289fSMatthias Schwarzott #include <linux/dvb/frontend.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 210389b34eSMatthias Schwarzott #include <linux/types.h> 2268b3289fSMatthias Schwarzott 2368b3289fSMatthias Schwarzott #include "zl10036.h" 2468b3289fSMatthias Schwarzott 2568b3289fSMatthias Schwarzott static int zl10036_debug; 2668b3289fSMatthias Schwarzott #define dprintk(level, args...) \ 2768b3289fSMatthias Schwarzott do { if (zl10036_debug & level) printk(KERN_DEBUG "zl10036: " args); \ 2868b3289fSMatthias Schwarzott } while (0) 2968b3289fSMatthias Schwarzott 3068b3289fSMatthias Schwarzott #define deb_info(args...) dprintk(0x01, args) 3168b3289fSMatthias Schwarzott #define deb_i2c(args...) dprintk(0x02, args) 3268b3289fSMatthias Schwarzott 3368b3289fSMatthias Schwarzott struct zl10036_state { 3468b3289fSMatthias Schwarzott struct i2c_adapter *i2c; 3568b3289fSMatthias Schwarzott const struct zl10036_config *config; 3668b3289fSMatthias Schwarzott u32 frequency; 3768b3289fSMatthias Schwarzott u8 br, bf; 3868b3289fSMatthias Schwarzott }; 3968b3289fSMatthias Schwarzott 4068b3289fSMatthias Schwarzott 4168b3289fSMatthias Schwarzott /* This driver assumes the tuner is driven by a 10.111MHz Cristal */ 4268b3289fSMatthias Schwarzott #define _XTAL 10111 4368b3289fSMatthias Schwarzott 4468b3289fSMatthias Schwarzott /* Some of the possible dividers: 4568b3289fSMatthias Schwarzott * 64, (write 0x05 to reg), freq step size 158kHz 4668b3289fSMatthias Schwarzott * 10, (write 0x0a to reg), freq step size 1.011kHz (used here) 4768b3289fSMatthias Schwarzott * 5, (write 0x09 to reg), freq step size 2.022kHz 4868b3289fSMatthias Schwarzott */ 4968b3289fSMatthias Schwarzott 5068b3289fSMatthias Schwarzott #define _RDIV 10 5168b3289fSMatthias Schwarzott #define _RDIV_REG 0x0a 5268b3289fSMatthias Schwarzott #define _FR (_XTAL/_RDIV) 5368b3289fSMatthias Schwarzott 5468b3289fSMatthias Schwarzott #define STATUS_POR 0x80 /* Power on Reset */ 5568b3289fSMatthias Schwarzott #define STATUS_FL 0x40 /* Frequency & Phase Lock */ 5668b3289fSMatthias Schwarzott 5768b3289fSMatthias Schwarzott /* read/write for zl10036 and zl10038 */ 5868b3289fSMatthias Schwarzott 5968b3289fSMatthias Schwarzott static int zl10036_read_status_reg(struct zl10036_state *state) 6068b3289fSMatthias Schwarzott { 6168b3289fSMatthias Schwarzott u8 status; 6268b3289fSMatthias Schwarzott struct i2c_msg msg[1] = { 6368b3289fSMatthias Schwarzott { .addr = state->config->tuner_address, .flags = I2C_M_RD, 6468b3289fSMatthias Schwarzott .buf = &status, .len = sizeof(status) }, 6568b3289fSMatthias Schwarzott }; 6668b3289fSMatthias Schwarzott 6768b3289fSMatthias Schwarzott if (i2c_transfer(state->i2c, msg, 1) != 1) { 6868b3289fSMatthias Schwarzott printk(KERN_ERR "%s: i2c read failed at addr=%02x\n", 6968b3289fSMatthias Schwarzott __func__, state->config->tuner_address); 7068b3289fSMatthias Schwarzott return -EIO; 7168b3289fSMatthias Schwarzott } 7268b3289fSMatthias Schwarzott 7368b3289fSMatthias Schwarzott deb_i2c("R(status): %02x [FL=%d]\n", status, 7468b3289fSMatthias Schwarzott (status & STATUS_FL) ? 1 : 0); 7568b3289fSMatthias Schwarzott if (status & STATUS_POR) 764bd69e7bSMauro Carvalho Chehab deb_info("%s: Power-On-Reset bit enabled - need to initialize the tuner\n", 774bd69e7bSMauro Carvalho Chehab __func__); 7868b3289fSMatthias Schwarzott 7968b3289fSMatthias Schwarzott return status; 8068b3289fSMatthias Schwarzott } 8168b3289fSMatthias Schwarzott 8268b3289fSMatthias Schwarzott static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count) 8368b3289fSMatthias Schwarzott { 8468b3289fSMatthias Schwarzott struct i2c_msg msg[1] = { 8568b3289fSMatthias Schwarzott { .addr = state->config->tuner_address, .flags = 0, 8668b3289fSMatthias Schwarzott .buf = buf, .len = count }, 8768b3289fSMatthias Schwarzott }; 8868b3289fSMatthias Schwarzott u8 reg = 0; 8968b3289fSMatthias Schwarzott int ret; 9068b3289fSMatthias Schwarzott 9168b3289fSMatthias Schwarzott if (zl10036_debug & 0x02) { 9268b3289fSMatthias Schwarzott /* every 8bit-value satisifes this! 9368b3289fSMatthias Schwarzott * so only check for debug log */ 9468b3289fSMatthias Schwarzott if ((buf[0] & 0x80) == 0x00) 9568b3289fSMatthias Schwarzott reg = 2; 9668b3289fSMatthias Schwarzott else if ((buf[0] & 0xc0) == 0x80) 9768b3289fSMatthias Schwarzott reg = 4; 9868b3289fSMatthias Schwarzott else if ((buf[0] & 0xf0) == 0xc0) 9968b3289fSMatthias Schwarzott reg = 6; 10068b3289fSMatthias Schwarzott else if ((buf[0] & 0xf0) == 0xd0) 10168b3289fSMatthias Schwarzott reg = 8; 10268b3289fSMatthias Schwarzott else if ((buf[0] & 0xf0) == 0xe0) 10368b3289fSMatthias Schwarzott reg = 10; 10468b3289fSMatthias Schwarzott else if ((buf[0] & 0xf0) == 0xf0) 10568b3289fSMatthias Schwarzott reg = 12; 10668b3289fSMatthias Schwarzott 10768b3289fSMatthias Schwarzott deb_i2c("W(%d):", reg); 10868b3289fSMatthias Schwarzott { 10968b3289fSMatthias Schwarzott int i; 11068b3289fSMatthias Schwarzott for (i = 0; i < count; i++) 11168b3289fSMatthias Schwarzott printk(KERN_CONT " %02x", buf[i]); 11268b3289fSMatthias Schwarzott printk(KERN_CONT "\n"); 11368b3289fSMatthias Schwarzott } 11468b3289fSMatthias Schwarzott } 11568b3289fSMatthias Schwarzott 11668b3289fSMatthias Schwarzott ret = i2c_transfer(state->i2c, msg, 1); 11768b3289fSMatthias Schwarzott if (ret != 1) { 11868b3289fSMatthias Schwarzott printk(KERN_ERR "%s: i2c error, ret=%d\n", __func__, ret); 11968b3289fSMatthias Schwarzott return -EIO; 12068b3289fSMatthias Schwarzott } 12168b3289fSMatthias Schwarzott 12268b3289fSMatthias Schwarzott return 0; 12368b3289fSMatthias Schwarzott } 12468b3289fSMatthias Schwarzott 125f2709c20SMauro Carvalho Chehab static void zl10036_release(struct dvb_frontend *fe) 126f2709c20SMauro Carvalho Chehab { 127f2709c20SMauro Carvalho Chehab struct zl10036_state *state = fe->tuner_priv; 128f2709c20SMauro Carvalho Chehab 129f2709c20SMauro Carvalho Chehab fe->tuner_priv = NULL; 130f2709c20SMauro Carvalho Chehab kfree(state); 131f2709c20SMauro Carvalho Chehab } 132f2709c20SMauro Carvalho Chehab 13368b3289fSMatthias Schwarzott static int zl10036_sleep(struct dvb_frontend *fe) 13468b3289fSMatthias Schwarzott { 13568b3289fSMatthias Schwarzott struct zl10036_state *state = fe->tuner_priv; 13668b3289fSMatthias Schwarzott u8 buf[] = { 0xf0, 0x80 }; /* regs 12/13 */ 13768b3289fSMatthias Schwarzott int ret; 13868b3289fSMatthias Schwarzott 13968b3289fSMatthias Schwarzott deb_info("%s\n", __func__); 14068b3289fSMatthias Schwarzott 14168b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 14268b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ 14368b3289fSMatthias Schwarzott 14468b3289fSMatthias Schwarzott ret = zl10036_write(state, buf, sizeof(buf)); 14568b3289fSMatthias Schwarzott 14668b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 14768b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ 14868b3289fSMatthias Schwarzott 14968b3289fSMatthias Schwarzott return ret; 15068b3289fSMatthias Schwarzott } 15168b3289fSMatthias Schwarzott 152cba862dcSMauro Carvalho Chehab /* 15368b3289fSMatthias Schwarzott * register map of the ZL10036/ZL10038 15468b3289fSMatthias Schwarzott * 15568b3289fSMatthias Schwarzott * reg[default] content 15668b3289fSMatthias Schwarzott * 2[0x00]: 0 | N14 | N13 | N12 | N11 | N10 | N9 | N8 15768b3289fSMatthias Schwarzott * 3[0x00]: N7 | N6 | N5 | N4 | N3 | N2 | N1 | N0 15868b3289fSMatthias Schwarzott * 4[0x80]: 1 | 0 | RFG | BA1 | BA0 | BG1 | BG0 | LEN 15968b3289fSMatthias Schwarzott * 5[0x00]: P0 | C1 | C0 | R4 | R3 | R2 | R1 | R0 16068b3289fSMatthias Schwarzott * 6[0xc0]: 1 | 1 | 0 | 0 | RSD | 0 | 0 | 0 16168b3289fSMatthias Schwarzott * 7[0x20]: P1 | BF6 | BF5 | BF4 | BF3 | BF2 | BF1 | 0 16268b3289fSMatthias Schwarzott * 8[0xdb]: 1 | 1 | 0 | 1 | 0 | CC | 1 | 1 16368b3289fSMatthias Schwarzott * 9[0x30]: VSD | V2 | V1 | V0 | S3 | S2 | S1 | S0 16468b3289fSMatthias Schwarzott * 10[0xe1]: 1 | 1 | 1 | 0 | 0 | LS2 | LS1 | LS0 16568b3289fSMatthias Schwarzott * 11[0xf5]: WS | WH2 | WH1 | WH0 | WL2 | WL1 | WL0 | WRE 16668b3289fSMatthias Schwarzott * 12[0xf0]: 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 16768b3289fSMatthias Schwarzott * 13[0x28]: PD | BR4 | BR3 | BR2 | BR1 | BR0 | CLR | TL 16868b3289fSMatthias Schwarzott */ 16968b3289fSMatthias Schwarzott 17068b3289fSMatthias Schwarzott static int zl10036_set_frequency(struct zl10036_state *state, u32 frequency) 17168b3289fSMatthias Schwarzott { 17268b3289fSMatthias Schwarzott u8 buf[2]; 17368b3289fSMatthias Schwarzott u32 div, foffset; 17468b3289fSMatthias Schwarzott 17568b3289fSMatthias Schwarzott div = (frequency + _FR/2) / _FR; 17668b3289fSMatthias Schwarzott state->frequency = div * _FR; 17768b3289fSMatthias Schwarzott 17868b3289fSMatthias Schwarzott foffset = frequency - state->frequency; 17968b3289fSMatthias Schwarzott 18068b3289fSMatthias Schwarzott buf[0] = (div >> 8) & 0x7f; 18168b3289fSMatthias Schwarzott buf[1] = (div >> 0) & 0xff; 18268b3289fSMatthias Schwarzott 18368b3289fSMatthias Schwarzott deb_info("%s: ftodo=%u fpriv=%u ferr=%d div=%u\n", __func__, 18468b3289fSMatthias Schwarzott frequency, state->frequency, foffset, div); 18568b3289fSMatthias Schwarzott 18668b3289fSMatthias Schwarzott return zl10036_write(state, buf, sizeof(buf)); 18768b3289fSMatthias Schwarzott } 18868b3289fSMatthias Schwarzott 18968b3289fSMatthias Schwarzott static int zl10036_set_bandwidth(struct zl10036_state *state, u32 fbw) 19068b3289fSMatthias Schwarzott { 19168b3289fSMatthias Schwarzott /* fbw is measured in kHz */ 19268b3289fSMatthias Schwarzott u8 br, bf; 19368b3289fSMatthias Schwarzott int ret; 19468b3289fSMatthias Schwarzott u8 buf_bf[] = { 19568b3289fSMatthias Schwarzott 0xc0, 0x00, /* 6/7: rsd=0 bf=0 */ 19668b3289fSMatthias Schwarzott }; 19768b3289fSMatthias Schwarzott u8 buf_br[] = { 19868b3289fSMatthias Schwarzott 0xf0, 0x00, /* 12/13: br=0xa clr=0 tl=0*/ 19968b3289fSMatthias Schwarzott }; 20068b3289fSMatthias Schwarzott u8 zl10036_rsd_off[] = { 0xc8 }; /* set RSD=1 */ 20168b3289fSMatthias Schwarzott 20268b3289fSMatthias Schwarzott /* ensure correct values */ 20368b3289fSMatthias Schwarzott if (fbw > 35000) 20468b3289fSMatthias Schwarzott fbw = 35000; 20568b3289fSMatthias Schwarzott if (fbw < 8000) 20668b3289fSMatthias Schwarzott fbw = 8000; 20768b3289fSMatthias Schwarzott 20868b3289fSMatthias Schwarzott #define _BR_MAXIMUM (_XTAL/575) /* _XTAL / 575kHz = 17 */ 20968b3289fSMatthias Schwarzott 21068b3289fSMatthias Schwarzott /* <= 28,82 MHz */ 21168b3289fSMatthias Schwarzott if (fbw <= 28820) { 21268b3289fSMatthias Schwarzott br = _BR_MAXIMUM; 21368b3289fSMatthias Schwarzott } else { 214cba862dcSMauro Carvalho Chehab /* 21568b3289fSMatthias Schwarzott * f(bw)=34,6MHz f(xtal)=10.111MHz 21668b3289fSMatthias Schwarzott * br = (10111/34600) * 63 * 1/K = 14; 21768b3289fSMatthias Schwarzott */ 21868b3289fSMatthias Schwarzott br = ((_XTAL * 21 * 1000) / (fbw * 419)); 21968b3289fSMatthias Schwarzott } 22068b3289fSMatthias Schwarzott 22168b3289fSMatthias Schwarzott /* ensure correct values */ 22268b3289fSMatthias Schwarzott if (br < 4) 22368b3289fSMatthias Schwarzott br = 4; 22468b3289fSMatthias Schwarzott if (br > _BR_MAXIMUM) 22568b3289fSMatthias Schwarzott br = _BR_MAXIMUM; 22668b3289fSMatthias Schwarzott 22768b3289fSMatthias Schwarzott /* 22868b3289fSMatthias Schwarzott * k = 1.257 22968b3289fSMatthias Schwarzott * bf = fbw/_XTAL * br * k - 1 */ 23068b3289fSMatthias Schwarzott 23168b3289fSMatthias Schwarzott bf = (fbw * br * 1257) / (_XTAL * 1000) - 1; 23268b3289fSMatthias Schwarzott 23368b3289fSMatthias Schwarzott /* ensure correct values */ 23468b3289fSMatthias Schwarzott if (bf > 62) 23568b3289fSMatthias Schwarzott bf = 62; 23668b3289fSMatthias Schwarzott 23768b3289fSMatthias Schwarzott buf_bf[1] = (bf << 1) & 0x7e; 23868b3289fSMatthias Schwarzott buf_br[1] = (br << 2) & 0x7c; 23968b3289fSMatthias Schwarzott deb_info("%s: BW=%d br=%u bf=%u\n", __func__, fbw, br, bf); 24068b3289fSMatthias Schwarzott 24168b3289fSMatthias Schwarzott if (br != state->br) { 24268b3289fSMatthias Schwarzott ret = zl10036_write(state, buf_br, sizeof(buf_br)); 24368b3289fSMatthias Schwarzott if (ret < 0) 24468b3289fSMatthias Schwarzott return ret; 24568b3289fSMatthias Schwarzott } 24668b3289fSMatthias Schwarzott 24768b3289fSMatthias Schwarzott if (bf != state->bf) { 24868b3289fSMatthias Schwarzott ret = zl10036_write(state, buf_bf, sizeof(buf_bf)); 24968b3289fSMatthias Schwarzott if (ret < 0) 25068b3289fSMatthias Schwarzott return ret; 25168b3289fSMatthias Schwarzott 25268b3289fSMatthias Schwarzott /* time = br/(32* fxtal) */ 25368b3289fSMatthias Schwarzott /* minimal sleep time to be calculated 25468b3289fSMatthias Schwarzott * maximum br is 63 -> max time = 2 /10 MHz = 2e-7 */ 25568b3289fSMatthias Schwarzott msleep(1); 25668b3289fSMatthias Schwarzott 25768b3289fSMatthias Schwarzott ret = zl10036_write(state, zl10036_rsd_off, 25868b3289fSMatthias Schwarzott sizeof(zl10036_rsd_off)); 25968b3289fSMatthias Schwarzott if (ret < 0) 26068b3289fSMatthias Schwarzott return ret; 26168b3289fSMatthias Schwarzott } 26268b3289fSMatthias Schwarzott 26368b3289fSMatthias Schwarzott state->br = br; 26468b3289fSMatthias Schwarzott state->bf = bf; 26568b3289fSMatthias Schwarzott 26668b3289fSMatthias Schwarzott return 0; 26768b3289fSMatthias Schwarzott } 26868b3289fSMatthias Schwarzott 26968b3289fSMatthias Schwarzott static int zl10036_set_gain_params(struct zl10036_state *state, 27068b3289fSMatthias Schwarzott int c) 27168b3289fSMatthias Schwarzott { 27268b3289fSMatthias Schwarzott u8 buf[2]; 27368b3289fSMatthias Schwarzott u8 rfg, ba, bg; 27468b3289fSMatthias Schwarzott 27568b3289fSMatthias Schwarzott /* default values */ 27668b3289fSMatthias Schwarzott rfg = 0; /* enable when using an lna */ 27768b3289fSMatthias Schwarzott ba = 1; 27868b3289fSMatthias Schwarzott bg = 1; 27968b3289fSMatthias Schwarzott 28068b3289fSMatthias Schwarzott /* reg 4 */ 28168b3289fSMatthias Schwarzott buf[0] = 0x80 | ((rfg << 5) & 0x20) 28268b3289fSMatthias Schwarzott | ((ba << 3) & 0x18) | ((bg << 1) & 0x06); 28368b3289fSMatthias Schwarzott 28468b3289fSMatthias Schwarzott if (!state->config->rf_loop_enable) 28568b3289fSMatthias Schwarzott buf[0] |= 0x01; 28668b3289fSMatthias Schwarzott 28768b3289fSMatthias Schwarzott /* P0=0 */ 28868b3289fSMatthias Schwarzott buf[1] = _RDIV_REG | ((c << 5) & 0x60); 28968b3289fSMatthias Schwarzott 29068b3289fSMatthias Schwarzott deb_info("%s: c=%u rfg=%u ba=%u bg=%u\n", __func__, c, rfg, ba, bg); 29168b3289fSMatthias Schwarzott return zl10036_write(state, buf, sizeof(buf)); 29268b3289fSMatthias Schwarzott } 29368b3289fSMatthias Schwarzott 29414d24d14SMauro Carvalho Chehab static int zl10036_set_params(struct dvb_frontend *fe) 29568b3289fSMatthias Schwarzott { 296f40d0f01SMauro Carvalho Chehab struct dtv_frontend_properties *p = &fe->dtv_property_cache; 29768b3289fSMatthias Schwarzott struct zl10036_state *state = fe->tuner_priv; 29868b3289fSMatthias Schwarzott int ret = 0; 299f40d0f01SMauro Carvalho Chehab u32 frequency = p->frequency; 30068b3289fSMatthias Schwarzott u32 fbw; 30168b3289fSMatthias Schwarzott int i; 30268b3289fSMatthias Schwarzott u8 c; 30368b3289fSMatthias Schwarzott 30468b3289fSMatthias Schwarzott /* ensure correct values 30568b3289fSMatthias Schwarzott * maybe redundant as core already checks this */ 306f1b1eabfSMauro Carvalho Chehab if ((frequency < fe->ops.info.frequency_min_hz / kHz) 307f1b1eabfSMauro Carvalho Chehab || (frequency > fe->ops.info.frequency_max_hz / kHz)) 30868b3289fSMatthias Schwarzott return -EINVAL; 30968b3289fSMatthias Schwarzott 310cba862dcSMauro Carvalho Chehab /* 31168b3289fSMatthias Schwarzott * alpha = 1.35 for dvb-s 31268b3289fSMatthias Schwarzott * fBW = (alpha*symbolrate)/(2*0.8) 31368b3289fSMatthias Schwarzott * 1.35 / (2*0.8) = 27 / 32 31468b3289fSMatthias Schwarzott */ 315f40d0f01SMauro Carvalho Chehab fbw = (27 * p->symbol_rate) / 32; 31668b3289fSMatthias Schwarzott 31768b3289fSMatthias Schwarzott /* scale to kHz */ 31868b3289fSMatthias Schwarzott fbw /= 1000; 31968b3289fSMatthias Schwarzott 32068b3289fSMatthias Schwarzott /* Add safe margin of 3MHz */ 32168b3289fSMatthias Schwarzott fbw += 3000; 32268b3289fSMatthias Schwarzott 32368b3289fSMatthias Schwarzott /* setting the charge pump - guessed values */ 32468b3289fSMatthias Schwarzott if (frequency < 950000) 32568b3289fSMatthias Schwarzott return -EINVAL; 32668b3289fSMatthias Schwarzott else if (frequency < 1250000) 32768b3289fSMatthias Schwarzott c = 0; 32868b3289fSMatthias Schwarzott else if (frequency < 1750000) 32968b3289fSMatthias Schwarzott c = 1; 33068b3289fSMatthias Schwarzott else if (frequency < 2175000) 33168b3289fSMatthias Schwarzott c = 2; 33268b3289fSMatthias Schwarzott else 33368b3289fSMatthias Schwarzott return -EINVAL; 33468b3289fSMatthias Schwarzott 33568b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 33668b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ 33768b3289fSMatthias Schwarzott 33868b3289fSMatthias Schwarzott ret = zl10036_set_gain_params(state, c); 33968b3289fSMatthias Schwarzott if (ret < 0) 34068b3289fSMatthias Schwarzott goto error; 34168b3289fSMatthias Schwarzott 342f40d0f01SMauro Carvalho Chehab ret = zl10036_set_frequency(state, p->frequency); 34368b3289fSMatthias Schwarzott if (ret < 0) 34468b3289fSMatthias Schwarzott goto error; 34568b3289fSMatthias Schwarzott 34668b3289fSMatthias Schwarzott ret = zl10036_set_bandwidth(state, fbw); 34768b3289fSMatthias Schwarzott if (ret < 0) 34868b3289fSMatthias Schwarzott goto error; 34968b3289fSMatthias Schwarzott 35068b3289fSMatthias Schwarzott /* wait for tuner lock - no idea if this is really needed */ 35168b3289fSMatthias Schwarzott for (i = 0; i < 20; i++) { 35268b3289fSMatthias Schwarzott ret = zl10036_read_status_reg(state); 35368b3289fSMatthias Schwarzott if (ret < 0) 35468b3289fSMatthias Schwarzott goto error; 35568b3289fSMatthias Schwarzott 35668b3289fSMatthias Schwarzott /* check Frequency & Phase Lock Bit */ 35768b3289fSMatthias Schwarzott if (ret & STATUS_FL) 35868b3289fSMatthias Schwarzott break; 35968b3289fSMatthias Schwarzott 36068b3289fSMatthias Schwarzott msleep(10); 36168b3289fSMatthias Schwarzott } 36268b3289fSMatthias Schwarzott 36368b3289fSMatthias Schwarzott error: 36468b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 36568b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ 36668b3289fSMatthias Schwarzott 36768b3289fSMatthias Schwarzott return ret; 36868b3289fSMatthias Schwarzott } 36968b3289fSMatthias Schwarzott 37068b3289fSMatthias Schwarzott static int zl10036_get_frequency(struct dvb_frontend *fe, u32 *frequency) 37168b3289fSMatthias Schwarzott { 37268b3289fSMatthias Schwarzott struct zl10036_state *state = fe->tuner_priv; 37368b3289fSMatthias Schwarzott 37468b3289fSMatthias Schwarzott *frequency = state->frequency; 37568b3289fSMatthias Schwarzott 37668b3289fSMatthias Schwarzott return 0; 37768b3289fSMatthias Schwarzott } 37868b3289fSMatthias Schwarzott 37968b3289fSMatthias Schwarzott static int zl10036_init_regs(struct zl10036_state *state) 38068b3289fSMatthias Schwarzott { 38168b3289fSMatthias Schwarzott int ret; 38268b3289fSMatthias Schwarzott int i; 38368b3289fSMatthias Schwarzott 38468b3289fSMatthias Schwarzott /* could also be one block from reg 2 to 13 and additional 10/11 */ 38568b3289fSMatthias Schwarzott u8 zl10036_init_tab[][2] = { 38668b3289fSMatthias Schwarzott { 0x04, 0x00 }, /* 2/3: div=0x400 - arbitrary value */ 38768b3289fSMatthias Schwarzott { 0x8b, _RDIV_REG }, /* 4/5: rfg=0 ba=1 bg=1 len=? */ 38868b3289fSMatthias Schwarzott /* p0=0 c=0 r=_RDIV_REG */ 38968b3289fSMatthias Schwarzott { 0xc0, 0x20 }, /* 6/7: rsd=0 bf=0x10 */ 39068b3289fSMatthias Schwarzott { 0xd3, 0x40 }, /* 8/9: from datasheet */ 39168b3289fSMatthias Schwarzott { 0xe3, 0x5b }, /* 10/11: lock window level */ 39268b3289fSMatthias Schwarzott { 0xf0, 0x28 }, /* 12/13: br=0xa clr=0 tl=0*/ 39368b3289fSMatthias Schwarzott { 0xe3, 0xf9 }, /* 10/11: unlock window level */ 39468b3289fSMatthias Schwarzott }; 39568b3289fSMatthias Schwarzott 39668b3289fSMatthias Schwarzott /* invalid values to trigger writing */ 39768b3289fSMatthias Schwarzott state->br = 0xff; 39868b3289fSMatthias Schwarzott state->bf = 0xff; 39968b3289fSMatthias Schwarzott 40068b3289fSMatthias Schwarzott if (!state->config->rf_loop_enable) 40121163565SDan Carpenter zl10036_init_tab[1][0] |= 0x01; 40268b3289fSMatthias Schwarzott 40368b3289fSMatthias Schwarzott deb_info("%s\n", __func__); 40468b3289fSMatthias Schwarzott 40568b3289fSMatthias Schwarzott for (i = 0; i < ARRAY_SIZE(zl10036_init_tab); i++) { 40668b3289fSMatthias Schwarzott ret = zl10036_write(state, zl10036_init_tab[i], 2); 40768b3289fSMatthias Schwarzott if (ret < 0) 40868b3289fSMatthias Schwarzott return ret; 40968b3289fSMatthias Schwarzott } 41068b3289fSMatthias Schwarzott 41168b3289fSMatthias Schwarzott return 0; 41268b3289fSMatthias Schwarzott } 41368b3289fSMatthias Schwarzott 41468b3289fSMatthias Schwarzott static int zl10036_init(struct dvb_frontend *fe) 41568b3289fSMatthias Schwarzott { 41668b3289fSMatthias Schwarzott struct zl10036_state *state = fe->tuner_priv; 41768b3289fSMatthias Schwarzott int ret = 0; 41868b3289fSMatthias Schwarzott 41968b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 42068b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ 42168b3289fSMatthias Schwarzott 42268b3289fSMatthias Schwarzott ret = zl10036_read_status_reg(state); 42368b3289fSMatthias Schwarzott if (ret < 0) 42468b3289fSMatthias Schwarzott return ret; 42568b3289fSMatthias Schwarzott 42668b3289fSMatthias Schwarzott /* Only init if Power-on-Reset bit is set? */ 42768b3289fSMatthias Schwarzott ret = zl10036_init_regs(state); 42868b3289fSMatthias Schwarzott 42968b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 43068b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ 43168b3289fSMatthias Schwarzott 43268b3289fSMatthias Schwarzott return ret; 43368b3289fSMatthias Schwarzott } 43468b3289fSMatthias Schwarzott 43514c4bf3cSJulia Lawall static const struct dvb_tuner_ops zl10036_tuner_ops = { 43668b3289fSMatthias Schwarzott .info = { 43768b3289fSMatthias Schwarzott .name = "Zarlink ZL10036", 438a3f90c75SMauro Carvalho Chehab .frequency_min_hz = 950 * MHz, 439a3f90c75SMauro Carvalho Chehab .frequency_max_hz = 2175 * MHz 44068b3289fSMatthias Schwarzott }, 44168b3289fSMatthias Schwarzott .init = zl10036_init, 442f2709c20SMauro Carvalho Chehab .release = zl10036_release, 44368b3289fSMatthias Schwarzott .sleep = zl10036_sleep, 44468b3289fSMatthias Schwarzott .set_params = zl10036_set_params, 44568b3289fSMatthias Schwarzott .get_frequency = zl10036_get_frequency, 44668b3289fSMatthias Schwarzott }; 44768b3289fSMatthias Schwarzott 44868b3289fSMatthias Schwarzott struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe, 44968b3289fSMatthias Schwarzott const struct zl10036_config *config, 45068b3289fSMatthias Schwarzott struct i2c_adapter *i2c) 45168b3289fSMatthias Schwarzott { 4527e270941SJesper Juhl struct zl10036_state *state; 45368b3289fSMatthias Schwarzott int ret; 45468b3289fSMatthias Schwarzott 4557e270941SJesper Juhl if (!config) { 45668b3289fSMatthias Schwarzott printk(KERN_ERR "%s: no config specified", __func__); 4577e270941SJesper Juhl return NULL; 45868b3289fSMatthias Schwarzott } 45968b3289fSMatthias Schwarzott 46068b3289fSMatthias Schwarzott state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL); 4617e270941SJesper Juhl if (!state) 46268b3289fSMatthias Schwarzott return NULL; 46368b3289fSMatthias Schwarzott 46468b3289fSMatthias Schwarzott state->config = config; 46568b3289fSMatthias Schwarzott state->i2c = i2c; 46668b3289fSMatthias Schwarzott 46768b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 46868b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ 46968b3289fSMatthias Schwarzott 47068b3289fSMatthias Schwarzott ret = zl10036_read_status_reg(state); 47168b3289fSMatthias Schwarzott if (ret < 0) { 47268b3289fSMatthias Schwarzott printk(KERN_ERR "%s: No zl10036 found\n", __func__); 47368b3289fSMatthias Schwarzott goto error; 47468b3289fSMatthias Schwarzott } 47568b3289fSMatthias Schwarzott 47668b3289fSMatthias Schwarzott ret = zl10036_init_regs(state); 47768b3289fSMatthias Schwarzott if (ret < 0) { 47868b3289fSMatthias Schwarzott printk(KERN_ERR "%s: tuner initialization failed\n", 47968b3289fSMatthias Schwarzott __func__); 48068b3289fSMatthias Schwarzott goto error; 48168b3289fSMatthias Schwarzott } 48268b3289fSMatthias Schwarzott 48368b3289fSMatthias Schwarzott if (fe->ops.i2c_gate_ctrl) 48468b3289fSMatthias Schwarzott fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ 48568b3289fSMatthias Schwarzott 48668b3289fSMatthias Schwarzott fe->tuner_priv = state; 48768b3289fSMatthias Schwarzott 48868b3289fSMatthias Schwarzott memcpy(&fe->ops.tuner_ops, &zl10036_tuner_ops, 48968b3289fSMatthias Schwarzott sizeof(struct dvb_tuner_ops)); 49068b3289fSMatthias Schwarzott printk(KERN_INFO "%s: tuner initialization (%s addr=0x%02x) ok\n", 49168b3289fSMatthias Schwarzott __func__, fe->ops.tuner_ops.info.name, config->tuner_address); 49268b3289fSMatthias Schwarzott 49368b3289fSMatthias Schwarzott return fe; 49468b3289fSMatthias Schwarzott 49568b3289fSMatthias Schwarzott error: 4967e270941SJesper Juhl kfree(state); 49768b3289fSMatthias Schwarzott return NULL; 49868b3289fSMatthias Schwarzott } 49968b3289fSMatthias Schwarzott EXPORT_SYMBOL(zl10036_attach); 50068b3289fSMatthias Schwarzott 50168b3289fSMatthias Schwarzott module_param_named(debug, zl10036_debug, int, 0644); 50268b3289fSMatthias Schwarzott MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 50368b3289fSMatthias Schwarzott MODULE_DESCRIPTION("DVB ZL10036 driver"); 50468b3289fSMatthias Schwarzott MODULE_AUTHOR("Tino Reichardt"); 50568b3289fSMatthias Schwarzott MODULE_AUTHOR("Matthias Schwarzott"); 50668b3289fSMatthias Schwarzott MODULE_LICENSE("GPL"); 507