1/* 2 STV6110(A) Silicon tuner driver 3 4 Copyright (C) Manu Abraham <abraham.manu@gmail.com> 5 6 Copyright (C) ST Microelectronics 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23#include <linux/init.h> 24#include <linux/kernel.h> 25#include <linux/module.h> 26#include <linux/slab.h> 27#include <linux/string.h> 28 29#include "dvb_frontend.h" 30 31#include "stv6110x_reg.h" 32#include "stv6110x.h" 33#include "stv6110x_priv.h" 34 35/* Max transfer size done by I2C transfer functions */ 36#define MAX_XFER_SIZE 64 37 38static unsigned int verbose; 39module_param(verbose, int, 0644); 40MODULE_PARM_DESC(verbose, "Set Verbosity level"); 41 42static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) 43{ 44 int ret; 45 const struct stv6110x_config *config = stv6110x->config; 46 u8 b0[] = { reg }; 47 u8 b1[] = { 0 }; 48 struct i2c_msg msg[] = { 49 { .addr = config->addr, .flags = 0, .buf = b0, .len = 1 }, 50 { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } 51 }; 52 53 ret = i2c_transfer(stv6110x->i2c, msg, 2); 54 if (ret != 2) { 55 dprintk(FE_ERROR, 1, "I/O Error"); 56 return -EREMOTEIO; 57 } 58 *data = b1[0]; 59 60 return 0; 61} 62 63static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len) 64{ 65 int ret; 66 const struct stv6110x_config *config = stv6110x->config; 67 u8 buf[MAX_XFER_SIZE]; 68 69 struct i2c_msg msg = { 70 .addr = config->addr, 71 .flags = 0, 72 .buf = buf, 73 .len = len + 1 74 }; 75 76 if (1 + len > sizeof(buf)) { 77 printk(KERN_WARNING 78 "%s: i2c wr: len=%d is too big!\n", 79 KBUILD_MODNAME, len); 80 return -EINVAL; 81 } 82 83 if (start + len > 8) 84 return -EINVAL; 85 86 buf[0] = start; 87 memcpy(&buf[1], data, len); 88 89 ret = i2c_transfer(stv6110x->i2c, &msg, 1); 90 if (ret != 1) { 91 dprintk(FE_ERROR, 1, "I/O Error"); 92 return -EREMOTEIO; 93 } 94 95 return 0; 96} 97 98static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) 99{ 100 return stv6110x_write_regs(stv6110x, reg, &data, 1); 101} 102 103static int stv6110x_init(struct dvb_frontend *fe) 104{ 105 struct stv6110x_state *stv6110x = fe->tuner_priv; 106 int ret; 107 108 ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, 109 ARRAY_SIZE(stv6110x->regs)); 110 if (ret < 0) { 111 dprintk(FE_ERROR, 1, "Initialization failed"); 112 return -1; 113 } 114 115 return 0; 116} 117 118static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) 119{ 120 struct stv6110x_state *stv6110x = fe->tuner_priv; 121 u32 rDiv, divider; 122 s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000; 123 u8 i; 124 125 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); 126 127 if (frequency <= 1023000) { 128 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); 129 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); 130 pVal = 40; 131 } else if (frequency <= 1300000) { 132 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); 133 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); 134 pVal = 40; 135 } else if (frequency <= 2046000) { 136 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); 137 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); 138 pVal = 20; 139 } else { 140 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); 141 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); 142 pVal = 20; 143 } 144 145 for (rDiv = 0; rDiv <= 3; rDiv++) { 146 pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv); 147 148 if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal)))) 149 rDivOpt = rDiv; 150 151 pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt); 152 } 153 154 divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; 155 divider = (divider + 5) / 10; 156 157 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); 158 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); 159 STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); 160 161 /* VCO Auto calibration */ 162 STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); 163 164 stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); 165 stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]); 166 stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]); 167 stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); 168 169 for (i = 0; i < TRIALS; i++) { 170 stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); 171 if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1])) 172 break; 173 msleep(1); 174 } 175 176 return 0; 177} 178 179static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency) 180{ 181 struct stv6110x_state *stv6110x = fe->tuner_priv; 182 183 stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]); 184 stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]); 185 186 *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]), 187 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz; 188 189 *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) + 190 STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1]))); 191 192 *frequency >>= 2; 193 194 return 0; 195} 196 197static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) 198{ 199 struct stv6110x_state *stv6110x = fe->tuner_priv; 200 u32 halfbw; 201 u8 i; 202 203 halfbw = bandwidth >> 1; 204 205 if (halfbw > 36000000) 206 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ 207 else if (halfbw < 5000000) 208 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ 209 else 210 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ 211 212 213 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ 214 STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ 215 216 stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); 217 stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); 218 219 for (i = 0; i < TRIALS; i++) { 220 stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); 221 if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1])) 222 break; 223 msleep(1); 224 } 225 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ 226 stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); 227 228 return 0; 229} 230 231static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 232{ 233 struct stv6110x_state *stv6110x = fe->tuner_priv; 234 235 stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]); 236 *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000; 237 238 return 0; 239} 240 241static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock) 242{ 243 struct stv6110x_state *stv6110x = fe->tuner_priv; 244 245 /* setup divider */ 246 switch (refclock) { 247 default: 248 case 1: 249 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); 250 break; 251 case 2: 252 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); 253 break; 254 case 4: 255 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); 256 break; 257 case 8: 258 case 0: 259 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); 260 break; 261 } 262 stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); 263 264 return 0; 265} 266 267static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain) 268{ 269 struct stv6110x_state *stv6110x = fe->tuner_priv; 270 271 stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]); 272 *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]); 273 274 return 0; 275} 276 277static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain) 278{ 279 struct stv6110x_state *stv6110x = fe->tuner_priv; 280 281 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); 282 stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); 283 284 return 0; 285} 286 287static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) 288{ 289 struct stv6110x_state *stv6110x = fe->tuner_priv; 290 int ret; 291 292 switch (mode) { 293 case TUNER_SLEEP: 294 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0); 295 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0); 296 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0); 297 break; 298 299 case TUNER_WAKE: 300 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1); 301 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1); 302 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1); 303 break; 304 } 305 306 ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); 307 if (ret < 0) { 308 dprintk(FE_ERROR, 1, "I/O Error"); 309 return -EIO; 310 } 311 312 return 0; 313} 314 315static int stv6110x_sleep(struct dvb_frontend *fe) 316{ 317 if (fe->tuner_priv) 318 return stv6110x_set_mode(fe, TUNER_SLEEP); 319 320 return 0; 321} 322 323static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) 324{ 325 struct stv6110x_state *stv6110x = fe->tuner_priv; 326 327 stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); 328 329 if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1])) 330 *status = TUNER_PHASELOCKED; 331 else 332 *status = 0; 333 334 return 0; 335} 336 337 338static int stv6110x_release(struct dvb_frontend *fe) 339{ 340 struct stv6110x_state *stv6110x = fe->tuner_priv; 341 342 fe->tuner_priv = NULL; 343 kfree(stv6110x); 344 345 return 0; 346} 347 348static struct dvb_tuner_ops stv6110x_ops = { 349 .info = { 350 .name = "STV6110(A) Silicon Tuner", 351 .frequency_min = 950000, 352 .frequency_max = 2150000, 353 .frequency_step = 0, 354 }, 355 .release = stv6110x_release 356}; 357 358static struct stv6110x_devctl stv6110x_ctl = { 359 .tuner_init = stv6110x_init, 360 .tuner_sleep = stv6110x_sleep, 361 .tuner_set_mode = stv6110x_set_mode, 362 .tuner_set_frequency = stv6110x_set_frequency, 363 .tuner_get_frequency = stv6110x_get_frequency, 364 .tuner_set_bandwidth = stv6110x_set_bandwidth, 365 .tuner_get_bandwidth = stv6110x_get_bandwidth, 366 .tuner_set_bbgain = stv6110x_set_bbgain, 367 .tuner_get_bbgain = stv6110x_get_bbgain, 368 .tuner_set_refclk = stv6110x_set_refclock, 369 .tuner_get_status = stv6110x_get_status, 370}; 371 372struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, 373 const struct stv6110x_config *config, 374 struct i2c_adapter *i2c) 375{ 376 struct stv6110x_state *stv6110x; 377 u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; 378 379 stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); 380 if (!stv6110x) 381 return NULL; 382 383 stv6110x->i2c = i2c; 384 stv6110x->config = config; 385 stv6110x->devctl = &stv6110x_ctl; 386 memcpy(stv6110x->regs, default_regs, 8); 387 388 /* setup divider */ 389 switch (stv6110x->config->clk_div) { 390 default: 391 case 1: 392 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); 393 break; 394 case 2: 395 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); 396 break; 397 case 4: 398 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); 399 break; 400 case 8: 401 case 0: 402 STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); 403 break; 404 } 405 406 fe->tuner_priv = stv6110x; 407 fe->ops.tuner_ops = stv6110x_ops; 408 409 printk(KERN_INFO "%s: Attaching STV6110x\n", __func__); 410 return stv6110x->devctl; 411} 412EXPORT_SYMBOL(stv6110x_attach); 413 414MODULE_AUTHOR("Manu Abraham"); 415MODULE_DESCRIPTION("STV6110x Silicon tuner"); 416MODULE_LICENSE("GPL"); 417