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