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