Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");