mt20xx.c (15425B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * i2c tv tuner chip device driver 4 * controls microtune tuners, mt2032 + mt2050 at the moment. 5 * 6 * This "mt20xx" module was split apart from the original "tuner" module. 7 */ 8#include <linux/delay.h> 9#include <linux/i2c.h> 10#include <linux/slab.h> 11#include <linux/videodev2.h> 12#include "tuner-i2c.h" 13#include "mt20xx.h" 14 15static int debug; 16module_param(debug, int, 0644); 17MODULE_PARM_DESC(debug, "enable verbose debug messages"); 18 19/* ---------------------------------------------------------------------- */ 20 21static unsigned int optimize_vco = 1; 22module_param(optimize_vco, int, 0644); 23 24static unsigned int tv_antenna = 1; 25module_param(tv_antenna, int, 0644); 26 27static unsigned int radio_antenna; 28module_param(radio_antenna, int, 0644); 29 30/* ---------------------------------------------------------------------- */ 31 32#define MT2032 0x04 33#define MT2030 0x06 34#define MT2040 0x07 35#define MT2050 0x42 36 37static char *microtune_part[] = { 38 [ MT2030 ] = "MT2030", 39 [ MT2032 ] = "MT2032", 40 [ MT2040 ] = "MT2040", 41 [ MT2050 ] = "MT2050", 42}; 43 44struct microtune_priv { 45 struct tuner_i2c_props i2c_props; 46 47 unsigned int xogc; 48 //unsigned int radio_if2; 49 50 u32 frequency; 51}; 52 53static void microtune_release(struct dvb_frontend *fe) 54{ 55 kfree(fe->tuner_priv); 56 fe->tuner_priv = NULL; 57} 58 59static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency) 60{ 61 struct microtune_priv *priv = fe->tuner_priv; 62 *frequency = priv->frequency; 63 return 0; 64} 65 66// IsSpurInBand()? 67static int mt2032_spurcheck(struct dvb_frontend *fe, 68 int f1, int f2, int spectrum_from,int spectrum_to) 69{ 70 struct microtune_priv *priv = fe->tuner_priv; 71 int n1=1,n2,f; 72 73 f1=f1/1000; //scale to kHz to avoid 32bit overflows 74 f2=f2/1000; 75 spectrum_from/=1000; 76 spectrum_to/=1000; 77 78 tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n", 79 f1,f2,spectrum_from,spectrum_to); 80 81 do { 82 n2=-n1; 83 f=n1*(f1-f2); 84 do { 85 n2--; 86 f=f-f2; 87 tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f); 88 89 if( (f>spectrum_from) && (f<spectrum_to)) 90 tuner_dbg("mt2032 spurcheck triggered: %d\n",n1); 91 } while ( (f>(f2-spectrum_to)) || (n2>-5)); 92 n1++; 93 } while (n1<5); 94 95 return 1; 96} 97 98static int mt2032_compute_freq(struct dvb_frontend *fe, 99 unsigned int rfin, 100 unsigned int if1, unsigned int if2, 101 unsigned int spectrum_from, 102 unsigned int spectrum_to, 103 unsigned char *buf, 104 int *ret_sel, 105 unsigned int xogc) //all in Hz 106{ 107 struct microtune_priv *priv = fe->tuner_priv; 108 unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, 109 desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; 110 111 fref= 5250 *1000; //5.25MHz 112 desired_lo1=rfin+if1; 113 114 lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); 115 lo1n=lo1/8; 116 lo1a=lo1-(lo1n*8); 117 118 s=rfin/1000/1000+1090; 119 120 if(optimize_vco) { 121 if(s>1890) sel=0; 122 else if(s>1720) sel=1; 123 else if(s>1530) sel=2; 124 else if(s>1370) sel=3; 125 else sel=4; // >1090 126 } 127 else { 128 if(s>1790) sel=0; // <1958 129 else if(s>1617) sel=1; 130 else if(s>1449) sel=2; 131 else if(s>1291) sel=3; 132 else sel=4; // >1090 133 } 134 *ret_sel=sel; 135 136 lo1freq=(lo1a+8*lo1n)*fref; 137 138 tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", 139 rfin,lo1,lo1n,lo1a,sel,lo1freq); 140 141 desired_lo2=lo1freq-rfin-if2; 142 lo2=(desired_lo2)/fref; 143 lo2n=lo2/8; 144 lo2a=lo2-(lo2n*8); 145 lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith 146 lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; 147 148 tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", 149 rfin,lo2,lo2n,lo2a,lo2num,lo2freq); 150 151 if (lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a > 7 || lo2n < 17 || 152 lo2n > 30) { 153 tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", 154 lo1a, lo1n, lo2a,lo2n); 155 return(-1); 156 } 157 158 mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to); 159 // should recalculate lo1 (one step up/down) 160 161 // set up MT2032 register map for transfer over i2c 162 buf[0]=lo1n-1; 163 buf[1]=lo1a | (sel<<4); 164 buf[2]=0x86; // LOGC 165 buf[3]=0x0f; //reserved 166 buf[4]=0x1f; 167 buf[5]=(lo2n-1) | (lo2a<<5); 168 if(rfin >400*1000*1000) 169 buf[6]=0xe4; 170 else 171 buf[6]=0xf4; // set PKEN per rev 1.2 172 buf[7]=8+xogc; 173 buf[8]=0xc3; //reserved 174 buf[9]=0x4e; //reserved 175 buf[10]=0xec; //reserved 176 buf[11]=(lo2num&0xff); 177 buf[12]=(lo2num>>8) |0x80; // Lo2RST 178 179 return 0; 180} 181 182static int mt2032_check_lo_lock(struct dvb_frontend *fe) 183{ 184 struct microtune_priv *priv = fe->tuner_priv; 185 int try,lock=0; 186 unsigned char buf[2]; 187 188 for(try=0;try<10;try++) { 189 buf[0]=0x0e; 190 tuner_i2c_xfer_send(&priv->i2c_props,buf,1); 191 tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); 192 tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); 193 lock=buf[0] &0x06; 194 195 if (lock==6) 196 break; 197 198 tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); 199 udelay(1000); 200 } 201 return lock; 202} 203 204static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock) 205{ 206 struct microtune_priv *priv = fe->tuner_priv; 207 unsigned char buf[2]; 208 int tad1; 209 210 buf[0]=0x0f; 211 tuner_i2c_xfer_send(&priv->i2c_props,buf,1); 212 tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); 213 tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); 214 tad1=buf[0]&0x07; 215 216 if(tad1 ==0) return lock; 217 if(tad1 ==1) return lock; 218 219 if(tad1==2) { 220 if(sel==0) 221 return lock; 222 else sel--; 223 } 224 else { 225 if(sel<4) 226 sel++; 227 else 228 return lock; 229 } 230 231 tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel); 232 233 buf[0]=0x0f; 234 buf[1]=sel; 235 tuner_i2c_xfer_send(&priv->i2c_props,buf,2); 236 lock=mt2032_check_lo_lock(fe); 237 return lock; 238} 239 240 241static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin, 242 unsigned int if1, unsigned int if2, 243 unsigned int from, unsigned int to) 244{ 245 unsigned char buf[21]; 246 int lint_try,ret,sel,lock=0; 247 struct microtune_priv *priv = fe->tuner_priv; 248 249 tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", 250 rfin,if1,if2,from,to); 251 252 buf[0]=0; 253 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); 254 tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); 255 256 buf[0]=0; 257 ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); 258 if (ret<0) 259 return; 260 261 // send only the relevant registers per Rev. 1.2 262 buf[0]=0; 263 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4); 264 buf[5]=5; 265 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4); 266 buf[11]=11; 267 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3); 268 if(ret!=3) 269 tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); 270 271 // wait for PLLs to lock (per manual), retry LINT if not. 272 for(lint_try=0; lint_try<2; lint_try++) { 273 lock=mt2032_check_lo_lock(fe); 274 275 if(optimize_vco) 276 lock=mt2032_optimize_vco(fe,sel,lock); 277 if(lock==6) break; 278 279 tuner_dbg("mt2032: re-init PLLs by LINT\n"); 280 buf[0]=7; 281 buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs 282 tuner_i2c_xfer_send(&priv->i2c_props,buf,2); 283 mdelay(10); 284 buf[1]=8+priv->xogc; 285 tuner_i2c_xfer_send(&priv->i2c_props,buf,2); 286 } 287 288 if (lock!=6) 289 tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); 290 291 buf[0]=2; 292 buf[1]=0x20; // LOGC for optimal phase noise 293 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); 294 if (ret!=2) 295 tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); 296} 297 298 299static int mt2032_set_tv_freq(struct dvb_frontend *fe, 300 struct analog_parameters *params) 301{ 302 int if2,from,to; 303 304 // signal bandwidth and picture carrier 305 if (params->std & V4L2_STD_525_60) { 306 // NTSC 307 from = 40750*1000; 308 to = 46750*1000; 309 if2 = 45750*1000; 310 } else { 311 // PAL 312 from = 32900*1000; 313 to = 39900*1000; 314 if2 = 38900*1000; 315 } 316 317 mt2032_set_if_freq(fe, params->frequency*62500, 318 1090*1000*1000, if2, from, to); 319 320 return 0; 321} 322 323static int mt2032_set_radio_freq(struct dvb_frontend *fe, 324 struct analog_parameters *params) 325{ 326 struct microtune_priv *priv = fe->tuner_priv; 327 int if2; 328 329 if (params->std & V4L2_STD_525_60) { 330 tuner_dbg("pinnacle ntsc\n"); 331 if2 = 41300 * 1000; 332 } else { 333 tuner_dbg("pinnacle pal\n"); 334 if2 = 33300 * 1000; 335 } 336 337 // per Manual for FM tuning: first if center freq. 1085 MHz 338 mt2032_set_if_freq(fe, params->frequency * 125 / 2, 339 1085*1000*1000,if2,if2,if2); 340 341 return 0; 342} 343 344static int mt2032_set_params(struct dvb_frontend *fe, 345 struct analog_parameters *params) 346{ 347 struct microtune_priv *priv = fe->tuner_priv; 348 int ret = -EINVAL; 349 350 switch (params->mode) { 351 case V4L2_TUNER_RADIO: 352 ret = mt2032_set_radio_freq(fe, params); 353 priv->frequency = params->frequency * 125 / 2; 354 break; 355 case V4L2_TUNER_ANALOG_TV: 356 case V4L2_TUNER_DIGITAL_TV: 357 ret = mt2032_set_tv_freq(fe, params); 358 priv->frequency = params->frequency * 62500; 359 break; 360 } 361 362 return ret; 363} 364 365static const struct dvb_tuner_ops mt2032_tuner_ops = { 366 .set_analog_params = mt2032_set_params, 367 .release = microtune_release, 368 .get_frequency = microtune_get_frequency, 369}; 370 371// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 372static int mt2032_init(struct dvb_frontend *fe) 373{ 374 struct microtune_priv *priv = fe->tuner_priv; 375 unsigned char buf[21]; 376 int ret,xogc,xok=0; 377 378 // Initialize Registers per spec. 379 buf[1]=2; // Index to register 2 380 buf[2]=0xff; 381 buf[3]=0x0f; 382 buf[4]=0x1f; 383 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4); 384 385 buf[5]=6; // Index register 6 386 buf[6]=0xe4; 387 buf[7]=0x8f; 388 buf[8]=0xc3; 389 buf[9]=0x4e; 390 buf[10]=0xec; 391 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6); 392 393 buf[12]=13; // Index register 13 394 buf[13]=0x32; 395 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2); 396 397 // Adjust XOGC (register 7), wait for XOK 398 xogc=7; 399 do { 400 tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); 401 mdelay(10); 402 buf[0]=0x0e; 403 tuner_i2c_xfer_send(&priv->i2c_props,buf,1); 404 tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); 405 xok=buf[0]&0x01; 406 tuner_dbg("mt2032: xok = 0x%02x\n",xok); 407 if (xok == 1) break; 408 409 xogc--; 410 tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); 411 if (xogc == 3) { 412 xogc=4; // min. 4 per spec 413 break; 414 } 415 buf[0]=0x07; 416 buf[1]=0x88 + xogc; 417 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); 418 if (ret!=2) 419 tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); 420 } while (xok != 1 ); 421 priv->xogc=xogc; 422 423 memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops)); 424 425 return(1); 426} 427 428static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna) 429{ 430 struct microtune_priv *priv = fe->tuner_priv; 431 unsigned char buf[2]; 432 433 buf[0] = 6; 434 buf[1] = antenna ? 0x11 : 0x10; 435 tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); 436 tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); 437} 438 439static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2) 440{ 441 struct microtune_priv *priv = fe->tuner_priv; 442 unsigned int if1=1218*1000*1000; 443 unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; 444 int ret; 445 unsigned char buf[6]; 446 447 tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n", 448 freq,if1,if2); 449 450 f_lo1=freq+if1; 451 f_lo1=(f_lo1/1000000)*1000000; 452 453 f_lo2=f_lo1-freq-if2; 454 f_lo2=(f_lo2/50000)*50000; 455 456 lo1=f_lo1/4000000; 457 lo2=f_lo2/4000000; 458 459 f_lo1_modulo= f_lo1-(lo1*4000000); 460 f_lo2_modulo= f_lo2-(lo2*4000000); 461 462 num1=4*f_lo1_modulo/4000000; 463 num2=4096*(f_lo2_modulo/1000)/4000; 464 465 // todo spurchecks 466 467 div1a=(lo1/12)-1; 468 div1b=lo1-(div1a+1)*12; 469 470 div2a=(lo2/8)-1; 471 div2b=lo2-(div2a+1)*8; 472 473 if (debug > 1) { 474 tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); 475 tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", 476 num1,num2,div1a,div1b,div2a,div2b); 477 } 478 479 buf[0]=1; 480 buf[1]= 4*div1b + num1; 481 if(freq<275*1000*1000) buf[1] = buf[1]|0x80; 482 483 buf[2]=div1a; 484 buf[3]=32*div2b + num2/256; 485 buf[4]=num2-(num2/256)*256; 486 buf[5]=div2a; 487 if(num2!=0) buf[5]=buf[5]|0x40; 488 489 if (debug > 1) 490 tuner_dbg("bufs is: %*ph\n", 6, buf); 491 492 ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6); 493 if (ret!=6) 494 tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); 495} 496 497static int mt2050_set_tv_freq(struct dvb_frontend *fe, 498 struct analog_parameters *params) 499{ 500 unsigned int if2; 501 502 if (params->std & V4L2_STD_525_60) { 503 // NTSC 504 if2 = 45750*1000; 505 } else { 506 // PAL 507 if2 = 38900*1000; 508 } 509 if (V4L2_TUNER_DIGITAL_TV == params->mode) { 510 // DVB (pinnacle 300i) 511 if2 = 36150*1000; 512 } 513 mt2050_set_if_freq(fe, params->frequency*62500, if2); 514 mt2050_set_antenna(fe, tv_antenna); 515 516 return 0; 517} 518 519static int mt2050_set_radio_freq(struct dvb_frontend *fe, 520 struct analog_parameters *params) 521{ 522 struct microtune_priv *priv = fe->tuner_priv; 523 int if2; 524 525 if (params->std & V4L2_STD_525_60) { 526 tuner_dbg("pinnacle ntsc\n"); 527 if2 = 41300 * 1000; 528 } else { 529 tuner_dbg("pinnacle pal\n"); 530 if2 = 33300 * 1000; 531 } 532 533 mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2); 534 mt2050_set_antenna(fe, radio_antenna); 535 536 return 0; 537} 538 539static int mt2050_set_params(struct dvb_frontend *fe, 540 struct analog_parameters *params) 541{ 542 struct microtune_priv *priv = fe->tuner_priv; 543 int ret = -EINVAL; 544 545 switch (params->mode) { 546 case V4L2_TUNER_RADIO: 547 ret = mt2050_set_radio_freq(fe, params); 548 priv->frequency = params->frequency * 125 / 2; 549 break; 550 case V4L2_TUNER_ANALOG_TV: 551 case V4L2_TUNER_DIGITAL_TV: 552 ret = mt2050_set_tv_freq(fe, params); 553 priv->frequency = params->frequency * 62500; 554 break; 555 } 556 557 return ret; 558} 559 560static const struct dvb_tuner_ops mt2050_tuner_ops = { 561 .set_analog_params = mt2050_set_params, 562 .release = microtune_release, 563 .get_frequency = microtune_get_frequency, 564}; 565 566static int mt2050_init(struct dvb_frontend *fe) 567{ 568 struct microtune_priv *priv = fe->tuner_priv; 569 unsigned char buf[2]; 570 571 buf[0] = 6; 572 buf[1] = 0x10; 573 tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */ 574 575 buf[0] = 0x0f; 576 buf[1] = 0x0f; 577 tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */ 578 579 buf[0] = 0x0d; 580 tuner_i2c_xfer_send(&priv->i2c_props, buf, 1); 581 tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1); 582 583 tuner_dbg("mt2050: sro is %x\n", buf[0]); 584 585 memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops)); 586 587 return 0; 588} 589 590struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, 591 struct i2c_adapter* i2c_adap, 592 u8 i2c_addr) 593{ 594 struct microtune_priv *priv = NULL; 595 char *name; 596 unsigned char buf[21]; 597 int company_code; 598 599 priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); 600 if (priv == NULL) 601 return NULL; 602 fe->tuner_priv = priv; 603 604 priv->i2c_props.addr = i2c_addr; 605 priv->i2c_props.adap = i2c_adap; 606 priv->i2c_props.name = "mt20xx"; 607 608 //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ 609 610 memset(buf,0,sizeof(buf)); 611 612 name = "unknown"; 613 614 tuner_i2c_xfer_send(&priv->i2c_props,buf,1); 615 tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); 616 if (debug) 617 tuner_dbg("MT20xx hexdump: %*ph\n", 21, buf); 618 619 company_code = buf[0x11] << 8 | buf[0x12]; 620 tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", 621 company_code,buf[0x13],buf[0x14]); 622 623 624 if (buf[0x13] < ARRAY_SIZE(microtune_part) && 625 NULL != microtune_part[buf[0x13]]) 626 name = microtune_part[buf[0x13]]; 627 switch (buf[0x13]) { 628 case MT2032: 629 mt2032_init(fe); 630 break; 631 case MT2050: 632 mt2050_init(fe); 633 break; 634 default: 635 tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", 636 name); 637 return NULL; 638 } 639 640 strscpy(fe->ops.tuner_ops.info.name, name, 641 sizeof(fe->ops.tuner_ops.info.name)); 642 tuner_info("microtune %s found, OK\n",name); 643 return fe; 644} 645 646EXPORT_SYMBOL_GPL(microtune_attach); 647 648MODULE_DESCRIPTION("Microtune tuner driver"); 649MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); 650MODULE_LICENSE("GPL");