1 /* 2 * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner 3 * 4 * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include "mxl111sf-tuner.h" 22 #include "mxl111sf-phy.h" 23 #include "mxl111sf-reg.h" 24 25 /* debug */ 26 static int mxl111sf_tuner_debug; 27 module_param_named(debug, mxl111sf_tuner_debug, int, 0644); 28 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); 29 30 #define mxl_dbg(fmt, arg...) \ 31 if (mxl111sf_tuner_debug) \ 32 mxl_printk(KERN_DEBUG, fmt, ##arg) 33 34 /* ------------------------------------------------------------------------ */ 35 36 struct mxl111sf_tuner_state { 37 struct mxl111sf_state *mxl_state; 38 39 struct mxl111sf_tuner_config *cfg; 40 41 enum mxl_if_freq if_freq; 42 43 u32 frequency; 44 u32 bandwidth; 45 }; 46 47 static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state, 48 u8 addr, u8 *data) 49 { 50 return (state->cfg->read_reg) ? 51 state->cfg->read_reg(state->mxl_state, addr, data) : 52 -EINVAL; 53 } 54 55 static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state, 56 u8 addr, u8 data) 57 { 58 return (state->cfg->write_reg) ? 59 state->cfg->write_reg(state->mxl_state, addr, data) : 60 -EINVAL; 61 } 62 63 static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state, 64 struct mxl111sf_reg_ctrl_info *ctrl_reg_info) 65 { 66 return (state->cfg->program_regs) ? 67 state->cfg->program_regs(state->mxl_state, ctrl_reg_info) : 68 -EINVAL; 69 } 70 71 static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state, 72 int onoff) 73 { 74 return (state->cfg->top_master_ctrl) ? 75 state->cfg->top_master_ctrl(state->mxl_state, onoff) : 76 -EINVAL; 77 } 78 79 /* ------------------------------------------------------------------------ */ 80 81 static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = { 82 {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3, 83 DIG_MODEINDEX, _A, _CSF, */ 84 {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */ 85 {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */ 86 {0, 0, 0} 87 }; 88 89 /* ------------------------------------------------------------------------ */ 90 91 static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq, 92 u8 bw) 93 { 94 u8 filt_bw; 95 96 /* set channel bandwidth */ 97 switch (bw) { 98 case 0: /* ATSC */ 99 filt_bw = 25; 100 break; 101 case 1: /* QAM */ 102 filt_bw = 69; 103 break; 104 case 6: 105 filt_bw = 21; 106 break; 107 case 7: 108 filt_bw = 42; 109 break; 110 case 8: 111 filt_bw = 63; 112 break; 113 default: 114 pr_err("%s: invalid bandwidth setting!", __func__); 115 return NULL; 116 } 117 118 /* calculate RF channel */ 119 freq /= 1000000; 120 121 freq *= 64; 122 #if 0 123 /* do round */ 124 freq += 0.5; 125 #endif 126 /* set bandwidth */ 127 mxl_phy_tune_rf[0].data = filt_bw; 128 129 /* set RF */ 130 mxl_phy_tune_rf[1].data = (freq & 0xff); 131 mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff; 132 133 /* start tune */ 134 return mxl_phy_tune_rf; 135 } 136 137 static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state) 138 { 139 int ret; 140 u8 ctrl; 141 #if 0 142 u16 iffcw; 143 u32 if_freq; 144 #endif 145 mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)", 146 state->cfg->invert_spectrum, state->cfg->if_freq); 147 148 /* set IF polarity */ 149 ctrl = state->cfg->invert_spectrum; 150 151 ctrl |= state->cfg->if_freq; 152 153 ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl); 154 if (mxl_fail(ret)) 155 goto fail; 156 157 #if 0 158 if_freq /= 1000000; 159 160 /* do round */ 161 if_freq += 0.5; 162 163 if (MXL_IF_LO == state->cfg->if_freq) { 164 ctrl = 0x08; 165 iffcw = (u16)(if_freq / (108 * 4096)); 166 } else if (MXL_IF_HI == state->cfg->if_freq) { 167 ctrl = 0x08; 168 iffcw = (u16)(if_freq / (216 * 4096)); 169 } else { 170 ctrl = 0; 171 iffcw = 0; 172 } 173 174 ctrl |= (iffcw >> 8); 175 #endif 176 ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl); 177 if (mxl_fail(ret)) 178 goto fail; 179 180 ctrl &= 0xf0; 181 ctrl |= 0x90; 182 183 ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl); 184 if (mxl_fail(ret)) 185 goto fail; 186 187 #if 0 188 ctrl = iffcw & 0x00ff; 189 #endif 190 ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl); 191 if (mxl_fail(ret)) 192 goto fail; 193 194 state->if_freq = state->cfg->if_freq; 195 fail: 196 return ret; 197 } 198 199 static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw) 200 { 201 struct mxl111sf_tuner_state *state = fe->tuner_priv; 202 static struct mxl111sf_reg_ctrl_info *reg_ctrl_array; 203 int ret; 204 u8 mxl_mode; 205 206 mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw); 207 208 /* stop tune */ 209 ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0); 210 if (mxl_fail(ret)) 211 goto fail; 212 213 /* check device mode */ 214 ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode); 215 if (mxl_fail(ret)) 216 goto fail; 217 218 /* Fill out registers for channel tune */ 219 reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw); 220 if (!reg_ctrl_array) 221 return -EINVAL; 222 223 ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array); 224 if (mxl_fail(ret)) 225 goto fail; 226 227 if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) { 228 /* IF tuner mode only */ 229 mxl1x1sf_tuner_top_master_ctrl(state, 0); 230 mxl1x1sf_tuner_top_master_ctrl(state, 1); 231 mxl1x1sf_tuner_set_if_output_freq(state); 232 } 233 234 ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1); 235 if (mxl_fail(ret)) 236 goto fail; 237 238 if (state->cfg->ant_hunt) 239 state->cfg->ant_hunt(fe); 240 fail: 241 return ret; 242 } 243 244 static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state, 245 int *rf_synth_lock, 246 int *ref_synth_lock) 247 { 248 int ret; 249 u8 data; 250 251 *rf_synth_lock = 0; 252 *ref_synth_lock = 0; 253 254 ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data); 255 if (mxl_fail(ret)) 256 goto fail; 257 258 *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0; 259 *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0; 260 fail: 261 return ret; 262 } 263 264 #if 0 265 static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state, 266 int onoff) 267 { 268 return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG, 269 onoff ? 1 : 0); 270 } 271 #endif 272 273 /* ------------------------------------------------------------------------ */ 274 275 static int mxl111sf_tuner_set_params(struct dvb_frontend *fe) 276 { 277 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 278 u32 delsys = c->delivery_system; 279 struct mxl111sf_tuner_state *state = fe->tuner_priv; 280 int ret; 281 u8 bw; 282 283 mxl_dbg("()"); 284 285 switch (delsys) { 286 case SYS_ATSC: 287 case SYS_ATSCMH: 288 bw = 0; /* ATSC */ 289 break; 290 case SYS_DVBC_ANNEX_B: 291 bw = 1; /* US CABLE */ 292 break; 293 case SYS_DVBT: 294 switch (c->bandwidth_hz) { 295 case 6000000: 296 bw = 6; 297 break; 298 case 7000000: 299 bw = 7; 300 break; 301 case 8000000: 302 bw = 8; 303 break; 304 default: 305 pr_err("%s: bandwidth not set!", __func__); 306 return -EINVAL; 307 } 308 break; 309 default: 310 pr_err("%s: modulation type not supported!", __func__); 311 return -EINVAL; 312 } 313 ret = mxl1x1sf_tune_rf(fe, c->frequency, bw); 314 if (mxl_fail(ret)) 315 goto fail; 316 317 state->frequency = c->frequency; 318 state->bandwidth = c->bandwidth_hz; 319 fail: 320 return ret; 321 } 322 323 /* ------------------------------------------------------------------------ */ 324 325 #if 0 326 static int mxl111sf_tuner_init(struct dvb_frontend *fe) 327 { 328 struct mxl111sf_tuner_state *state = fe->tuner_priv; 329 int ret; 330 331 /* wake from standby handled by usb driver */ 332 333 return ret; 334 } 335 336 static int mxl111sf_tuner_sleep(struct dvb_frontend *fe) 337 { 338 struct mxl111sf_tuner_state *state = fe->tuner_priv; 339 int ret; 340 341 /* enter standby mode handled by usb driver */ 342 343 return ret; 344 } 345 #endif 346 347 /* ------------------------------------------------------------------------ */ 348 349 static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status) 350 { 351 struct mxl111sf_tuner_state *state = fe->tuner_priv; 352 int rf_locked, ref_locked, ret; 353 354 *status = 0; 355 356 ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked); 357 if (mxl_fail(ret)) 358 goto fail; 359 mxl_info("%s%s", rf_locked ? "rf locked " : "", 360 ref_locked ? "ref locked" : ""); 361 362 if ((rf_locked) || (ref_locked)) 363 *status |= TUNER_STATUS_LOCKED; 364 fail: 365 return ret; 366 } 367 368 static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength) 369 { 370 struct mxl111sf_tuner_state *state = fe->tuner_priv; 371 u8 val1, val2; 372 int ret; 373 374 *strength = 0; 375 376 ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02); 377 if (mxl_fail(ret)) 378 goto fail; 379 ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1); 380 if (mxl_fail(ret)) 381 goto fail; 382 ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2); 383 if (mxl_fail(ret)) 384 goto fail; 385 386 *strength = val1 | ((val2 & 0x07) << 8); 387 fail: 388 ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00); 389 mxl_fail(ret); 390 391 return ret; 392 } 393 394 /* ------------------------------------------------------------------------ */ 395 396 static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency) 397 { 398 struct mxl111sf_tuner_state *state = fe->tuner_priv; 399 *frequency = state->frequency; 400 return 0; 401 } 402 403 static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 404 { 405 struct mxl111sf_tuner_state *state = fe->tuner_priv; 406 *bandwidth = state->bandwidth; 407 return 0; 408 } 409 410 static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe, 411 u32 *frequency) 412 { 413 struct mxl111sf_tuner_state *state = fe->tuner_priv; 414 415 *frequency = 0; 416 417 switch (state->if_freq) { 418 case MXL_IF_4_0: /* 4.0 MHz */ 419 *frequency = 4000000; 420 break; 421 case MXL_IF_4_5: /* 4.5 MHz */ 422 *frequency = 4500000; 423 break; 424 case MXL_IF_4_57: /* 4.57 MHz */ 425 *frequency = 4570000; 426 break; 427 case MXL_IF_5_0: /* 5.0 MHz */ 428 *frequency = 5000000; 429 break; 430 case MXL_IF_5_38: /* 5.38 MHz */ 431 *frequency = 5380000; 432 break; 433 case MXL_IF_6_0: /* 6.0 MHz */ 434 *frequency = 6000000; 435 break; 436 case MXL_IF_6_28: /* 6.28 MHz */ 437 *frequency = 6280000; 438 break; 439 case MXL_IF_7_2: /* 7.2 MHz */ 440 *frequency = 7200000; 441 break; 442 case MXL_IF_35_25: /* 35.25 MHz */ 443 *frequency = 35250000; 444 break; 445 case MXL_IF_36: /* 36 MHz */ 446 *frequency = 36000000; 447 break; 448 case MXL_IF_36_15: /* 36.15 MHz */ 449 *frequency = 36150000; 450 break; 451 case MXL_IF_44: /* 44 MHz */ 452 *frequency = 44000000; 453 break; 454 } 455 return 0; 456 } 457 458 static int mxl111sf_tuner_release(struct dvb_frontend *fe) 459 { 460 struct mxl111sf_tuner_state *state = fe->tuner_priv; 461 mxl_dbg("()"); 462 kfree(state); 463 fe->tuner_priv = NULL; 464 return 0; 465 } 466 467 /* ------------------------------------------------------------------------- */ 468 469 static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { 470 .info = { 471 .name = "MaxLinear MxL111SF", 472 #if 0 473 .frequency_min = , 474 .frequency_max = , 475 .frequency_step = , 476 #endif 477 }, 478 #if 0 479 .init = mxl111sf_tuner_init, 480 .sleep = mxl111sf_tuner_sleep, 481 #endif 482 .set_params = mxl111sf_tuner_set_params, 483 .get_status = mxl111sf_tuner_get_status, 484 .get_rf_strength = mxl111sf_get_rf_strength, 485 .get_frequency = mxl111sf_tuner_get_frequency, 486 .get_bandwidth = mxl111sf_tuner_get_bandwidth, 487 .get_if_frequency = mxl111sf_tuner_get_if_frequency, 488 .release = mxl111sf_tuner_release, 489 }; 490 491 struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, 492 struct mxl111sf_state *mxl_state, 493 struct mxl111sf_tuner_config *cfg) 494 { 495 struct mxl111sf_tuner_state *state = NULL; 496 497 mxl_dbg("()"); 498 499 state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL); 500 if (state == NULL) 501 return NULL; 502 503 state->mxl_state = mxl_state; 504 state->cfg = cfg; 505 506 memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops, 507 sizeof(struct dvb_tuner_ops)); 508 509 fe->tuner_priv = state; 510 return fe; 511 } 512 EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach); 513 514 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver"); 515 MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); 516 MODULE_LICENSE("GPL"); 517 MODULE_VERSION("0.1"); 518 519 /* 520 * Overrides for Emacs so that we follow Linus's tabbing style. 521 * --------------------------------------------------------------------------- 522 * Local variables: 523 * c-basic-offset: 8 524 * End: 525 */ 526