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