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