cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stv6111.c (14023B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for the ST STV6111 tuner
      4 *
      5 * Copyright (C) 2014 Digital Devices GmbH
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/moduleparam.h>
     11#include <linux/init.h>
     12#include <linux/delay.h>
     13#include <linux/firmware.h>
     14#include <linux/i2c.h>
     15#include <asm/div64.h>
     16
     17#include "stv6111.h"
     18
     19#include <media/dvb_frontend.h>
     20
     21struct stv {
     22	struct i2c_adapter *i2c;
     23	u8 adr;
     24
     25	u8 reg[11];
     26	u32 ref_freq;
     27	u32 frequency;
     28};
     29
     30struct slookup {
     31	s16 value;
     32	u16 reg_value;
     33};
     34
     35static const struct slookup lnagain_nf_lookup[] = {
     36	/* Gain *100dB // Reg */
     37	{ 2572,	0 },
     38	{ 2575, 1 },
     39	{ 2580, 2 },
     40	{ 2588, 3 },
     41	{ 2596, 4 },
     42	{ 2611, 5 },
     43	{ 2633, 6 },
     44	{ 2664, 7 },
     45	{ 2701, 8 },
     46	{ 2753, 9 },
     47	{ 2816, 10 },
     48	{ 2902, 11 },
     49	{ 2995, 12 },
     50	{ 3104, 13 },
     51	{ 3215, 14 },
     52	{ 3337, 15 },
     53	{ 3492, 16 },
     54	{ 3614, 17 },
     55	{ 3731, 18 },
     56	{ 3861, 19 },
     57	{ 3988, 20 },
     58	{ 4124, 21 },
     59	{ 4253, 22 },
     60	{ 4386,	23 },
     61	{ 4505,	24 },
     62	{ 4623,	25 },
     63	{ 4726,	26 },
     64	{ 4821,	27 },
     65	{ 4903,	28 },
     66	{ 4979,	29 },
     67	{ 5045,	30 },
     68	{ 5102,	31 }
     69};
     70
     71static const struct slookup lnagain_iip3_lookup[] = {
     72	/* Gain *100dB // reg */
     73	{ 1548,	0 },
     74	{ 1552,	1 },
     75	{ 1569,	2 },
     76	{ 1565,	3 },
     77	{ 1577,	4 },
     78	{ 1594,	5 },
     79	{ 1627,	6 },
     80	{ 1656,	7 },
     81	{ 1700,	8 },
     82	{ 1748,	9 },
     83	{ 1805,	10 },
     84	{ 1896,	11 },
     85	{ 1995,	12 },
     86	{ 2113,	13 },
     87	{ 2233,	14 },
     88	{ 2366,	15 },
     89	{ 2543,	16 },
     90	{ 2687,	17 },
     91	{ 2842,	18 },
     92	{ 2999,	19 },
     93	{ 3167,	20 },
     94	{ 3342,	21 },
     95	{ 3507,	22 },
     96	{ 3679,	23 },
     97	{ 3827,	24 },
     98	{ 3970,	25 },
     99	{ 4094,	26 },
    100	{ 4210,	27 },
    101	{ 4308,	28 },
    102	{ 4396,	29 },
    103	{ 4468,	30 },
    104	{ 4535,	31 }
    105};
    106
    107static const struct slookup gain_rfagc_lookup[] = {
    108	/* Gain *100dB // reg */
    109	{ 4870,	0x3000 },
    110	{ 4850,	0x3C00 },
    111	{ 4800,	0x4500 },
    112	{ 4750,	0x4800 },
    113	{ 4700,	0x4B00 },
    114	{ 4650,	0x4D00 },
    115	{ 4600,	0x4F00 },
    116	{ 4550,	0x5100 },
    117	{ 4500,	0x5200 },
    118	{ 4420,	0x5500 },
    119	{ 4316,	0x5800 },
    120	{ 4200,	0x5B00 },
    121	{ 4119,	0x5D00 },
    122	{ 3999,	0x6000 },
    123	{ 3950,	0x6100 },
    124	{ 3876,	0x6300 },
    125	{ 3755,	0x6600 },
    126	{ 3641,	0x6900 },
    127	{ 3567,	0x6B00 },
    128	{ 3425,	0x6F00 },
    129	{ 3350,	0x7100 },
    130	{ 3236,	0x7400 },
    131	{ 3118,	0x7700 },
    132	{ 3004,	0x7A00 },
    133	{ 2917,	0x7C00 },
    134	{ 2776,	0x7F00 },
    135	{ 2635,	0x8200 },
    136	{ 2516,	0x8500 },
    137	{ 2406,	0x8800 },
    138	{ 2290,	0x8B00 },
    139	{ 2170,	0x8E00 },
    140	{ 2073,	0x9100 },
    141	{ 1949,	0x9400 },
    142	{ 1836,	0x9700 },
    143	{ 1712,	0x9A00 },
    144	{ 1631,	0x9C00 },
    145	{ 1515,	0x9F00 },
    146	{ 1400,	0xA200 },
    147	{ 1323,	0xA400 },
    148	{ 1203,	0xA700 },
    149	{ 1091,	0xAA00 },
    150	{ 1011,	0xAC00 },
    151	{ 904,	0xAF00 },
    152	{ 787,	0xB200 },
    153	{ 685,	0xB500 },
    154	{ 571,	0xB800 },
    155	{ 464,	0xBB00 },
    156	{ 374,	0xBE00 },
    157	{ 275,	0xC200 },
    158	{ 181,	0xC600 },
    159	{ 102,	0xCC00 },
    160	{ 49,	0xD900 }
    161};
    162
    163/*
    164 * This table is 6 dB too low comapred to the others (probably created with
    165 * a different BB_MAG setting)
    166 */
    167static const struct slookup gain_channel_agc_nf_lookup[] = {
    168	/* Gain *100dB // reg */
    169	{ 7082,	0x3000 },
    170	{ 7052,	0x4000 },
    171	{ 7007,	0x4600 },
    172	{ 6954,	0x4A00 },
    173	{ 6909,	0x4D00 },
    174	{ 6833,	0x5100 },
    175	{ 6753,	0x5400 },
    176	{ 6659,	0x5700 },
    177	{ 6561,	0x5A00 },
    178	{ 6472,	0x5C00 },
    179	{ 6366,	0x5F00 },
    180	{ 6259,	0x6100 },
    181	{ 6151,	0x6400 },
    182	{ 6026,	0x6700 },
    183	{ 5920,	0x6900 },
    184	{ 5835,	0x6B00 },
    185	{ 5770,	0x6C00 },
    186	{ 5681,	0x6E00 },
    187	{ 5596,	0x7000 },
    188	{ 5503,	0x7200 },
    189	{ 5429,	0x7300 },
    190	{ 5319,	0x7500 },
    191	{ 5220,	0x7700 },
    192	{ 5111,	0x7900 },
    193	{ 4983,	0x7B00 },
    194	{ 4876,	0x7D00 },
    195	{ 4755,	0x7F00 },
    196	{ 4635,	0x8100 },
    197	{ 4499,	0x8300 },
    198	{ 4405,	0x8500 },
    199	{ 4323,	0x8600 },
    200	{ 4233,	0x8800 },
    201	{ 4156,	0x8A00 },
    202	{ 4038,	0x8C00 },
    203	{ 3935,	0x8E00 },
    204	{ 3823,	0x9000 },
    205	{ 3712,	0x9200 },
    206	{ 3601,	0x9500 },
    207	{ 3511,	0x9700 },
    208	{ 3413,	0x9900 },
    209	{ 3309,	0x9B00 },
    210	{ 3213,	0x9D00 },
    211	{ 3088,	0x9F00 },
    212	{ 2992,	0xA100 },
    213	{ 2878,	0xA400 },
    214	{ 2769,	0xA700 },
    215	{ 2645,	0xAA00 },
    216	{ 2538,	0xAD00 },
    217	{ 2441,	0xB000 },
    218	{ 2350,	0xB600 },
    219	{ 2237,	0xBA00 },
    220	{ 2137,	0xBF00 },
    221	{ 2039,	0xC500 },
    222	{ 1938,	0xDF00 },
    223	{ 1927,	0xFF00 }
    224};
    225
    226static const struct slookup gain_channel_agc_iip3_lookup[] = {
    227	/* Gain *100dB // reg */
    228	{ 7070,	0x3000 },
    229	{ 7028,	0x4000 },
    230	{ 7019,	0x4600 },
    231	{ 6900,	0x4A00 },
    232	{ 6811,	0x4D00 },
    233	{ 6763,	0x5100 },
    234	{ 6690,	0x5400 },
    235	{ 6644,	0x5700 },
    236	{ 6617,	0x5A00 },
    237	{ 6598,	0x5C00 },
    238	{ 6462,	0x5F00 },
    239	{ 6348,	0x6100 },
    240	{ 6197,	0x6400 },
    241	{ 6154,	0x6700 },
    242	{ 6098,	0x6900 },
    243	{ 5893,	0x6B00 },
    244	{ 5812,	0x6C00 },
    245	{ 5773,	0x6E00 },
    246	{ 5723,	0x7000 },
    247	{ 5661,	0x7200 },
    248	{ 5579,	0x7300 },
    249	{ 5460,	0x7500 },
    250	{ 5308,	0x7700 },
    251	{ 5099,	0x7900 },
    252	{ 4910,	0x7B00 },
    253	{ 4800,	0x7D00 },
    254	{ 4785,	0x7F00 },
    255	{ 4635,	0x8100 },
    256	{ 4466,	0x8300 },
    257	{ 4314,	0x8500 },
    258	{ 4295,	0x8600 },
    259	{ 4144,	0x8800 },
    260	{ 3920,	0x8A00 },
    261	{ 3889,	0x8C00 },
    262	{ 3771,	0x8E00 },
    263	{ 3655,	0x9000 },
    264	{ 3446,	0x9200 },
    265	{ 3298,	0x9500 },
    266	{ 3083,	0x9700 },
    267	{ 3015,	0x9900 },
    268	{ 2833,	0x9B00 },
    269	{ 2746,	0x9D00 },
    270	{ 2632,	0x9F00 },
    271	{ 2598,	0xA100 },
    272	{ 2480,	0xA400 },
    273	{ 2236,	0xA700 },
    274	{ 2171,	0xAA00 },
    275	{ 2060,	0xAD00 },
    276	{ 1999,	0xB000 },
    277	{ 1974,	0xB600 },
    278	{ 1820,	0xBA00 },
    279	{ 1741,	0xBF00 },
    280	{ 1655,	0xC500 },
    281	{ 1444,	0xDF00 },
    282	{ 1325,	0xFF00 },
    283};
    284
    285static inline u32 muldiv32(u32 a, u32 b, u32 c)
    286{
    287	u64 tmp64;
    288
    289	tmp64 = (u64)a * (u64)b;
    290	do_div(tmp64, c);
    291
    292	return (u32)tmp64;
    293}
    294
    295static int i2c_read(struct i2c_adapter *adap,
    296		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
    297{
    298	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
    299				     .buf = msg, .len = len},
    300				   { .addr = adr, .flags = I2C_M_RD,
    301				     .buf = answ, .len = alen } };
    302	if (i2c_transfer(adap, msgs, 2) != 2) {
    303		dev_err(&adap->dev, "i2c read error\n");
    304		return -EIO;
    305	}
    306	return 0;
    307}
    308
    309static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
    310{
    311	struct i2c_msg msg = {.addr = adr, .flags = 0,
    312			      .buf = data, .len = len};
    313
    314	if (i2c_transfer(adap, &msg, 1) != 1) {
    315		dev_err(&adap->dev, "i2c write error\n");
    316		return -EIO;
    317	}
    318	return 0;
    319}
    320
    321static int write_regs(struct stv *state, int reg, int len)
    322{
    323	u8 d[12];
    324
    325	memcpy(&d[1], &state->reg[reg], len);
    326	d[0] = reg;
    327	return i2c_write(state->i2c, state->adr, d, len + 1);
    328}
    329
    330static int write_reg(struct stv *state, u8 reg, u8 val)
    331{
    332	u8 d[2] = {reg, val};
    333
    334	return i2c_write(state->i2c, state->adr, d, 2);
    335}
    336
    337static int read_reg(struct stv *state, u8 reg, u8 *val)
    338{
    339	return i2c_read(state->i2c, state->adr, &reg, 1, val, 1);
    340}
    341
    342static int wait_for_call_done(struct stv *state, u8 mask)
    343{
    344	int status = 0;
    345	u32 lock_retry_count = 10;
    346
    347	while (lock_retry_count > 0) {
    348		u8 regval;
    349
    350		status = read_reg(state, 9, &regval);
    351		if (status < 0)
    352			return status;
    353
    354		if ((regval & mask) == 0)
    355			break;
    356		usleep_range(4000, 6000);
    357		lock_retry_count -= 1;
    358
    359		status = -EIO;
    360	}
    361	return status;
    362}
    363
    364static void init_state(struct stv *state)
    365{
    366	u32 clkdiv = 0;
    367	u32 agcmode = 0;
    368	u32 agcref = 2;
    369	u32 agcset = 0xffffffff;
    370	u32 bbmode = 0xffffffff;
    371
    372	state->reg[0] = 0x08;
    373	state->reg[1] = 0x41;
    374	state->reg[2] = 0x8f;
    375	state->reg[3] = 0x00;
    376	state->reg[4] = 0xce;
    377	state->reg[5] = 0x54;
    378	state->reg[6] = 0x55;
    379	state->reg[7] = 0x45;
    380	state->reg[8] = 0x46;
    381	state->reg[9] = 0xbd;
    382	state->reg[10] = 0x11;
    383
    384	state->ref_freq = 16000;
    385
    386	if (clkdiv <= 3)
    387		state->reg[0x00] |= (clkdiv & 0x03);
    388	if (agcmode <= 3) {
    389		state->reg[0x03] |= (agcmode << 5);
    390		if (agcmode == 0x01)
    391			state->reg[0x01] |= 0x30;
    392	}
    393	if (bbmode <= 3)
    394		state->reg[0x01] = (state->reg[0x01] & ~0x30) | (bbmode << 4);
    395	if (agcref <= 7)
    396		state->reg[0x03] |= agcref;
    397	if (agcset <= 31)
    398		state->reg[0x02] = (state->reg[0x02] & ~0x1F) | agcset | 0x40;
    399}
    400
    401static int attach_init(struct stv *state)
    402{
    403	if (write_regs(state, 0, 11))
    404		return -ENODEV;
    405	return 0;
    406}
    407
    408static void release(struct dvb_frontend *fe)
    409{
    410	kfree(fe->tuner_priv);
    411	fe->tuner_priv = NULL;
    412}
    413
    414static int set_bandwidth(struct dvb_frontend *fe, u32 cutoff_frequency)
    415{
    416	struct stv *state = fe->tuner_priv;
    417	u32 index = (cutoff_frequency + 999999) / 1000000;
    418	int stat = 0;
    419
    420	if (index < 6)
    421		index = 6;
    422	if (index > 50)
    423		index = 50;
    424	if ((state->reg[0x08] & ~0xFC) == ((index - 6) << 2))
    425		return 0;
    426
    427	state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2);
    428	state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x08;
    429	if (fe->ops.i2c_gate_ctrl)
    430		stat = fe->ops.i2c_gate_ctrl(fe, 1);
    431	if (!stat) {
    432		write_regs(state, 0x08, 2);
    433		wait_for_call_done(state, 0x08);
    434	}
    435	if (fe->ops.i2c_gate_ctrl && !stat)
    436		fe->ops.i2c_gate_ctrl(fe, 0);
    437	return stat;
    438}
    439
    440static int set_lof(struct stv *state, u32 local_frequency, u32 cutoff_frequency)
    441{
    442	u32 index = (cutoff_frequency + 999999) / 1000000;
    443	u32 frequency = (local_frequency + 500) / 1000;
    444	u32 p = 1, psel = 0, fvco, div, frac;
    445	u8 icp, tmp;
    446
    447	if (index < 6)
    448		index = 6;
    449	if (index > 50)
    450		index = 50;
    451
    452	if (frequency <= 1300000) {
    453		p =  4;
    454		psel = 1;
    455	} else {
    456		p =  2;
    457		psel = 0;
    458	}
    459	fvco = frequency * p;
    460	div = fvco / state->ref_freq;
    461	frac = fvco % state->ref_freq;
    462	frac = muldiv32(frac, 0x40000, state->ref_freq);
    463
    464	icp = 0;
    465	if (fvco < 2700000)
    466		icp = 0;
    467	else if (fvco < 2950000)
    468		icp = 1;
    469	else if (fvco < 3300000)
    470		icp = 2;
    471	else if (fvco < 3700000)
    472		icp = 3;
    473	else if (fvco < 4200000)
    474		icp = 5;
    475	else if (fvco < 4800000)
    476		icp = 6;
    477	else
    478		icp = 7;
    479
    480	state->reg[0x02] |= 0x80; /* LNA IIP3 Mode */
    481
    482	state->reg[0x03] = (state->reg[0x03] & ~0x80) | (psel << 7);
    483	state->reg[0x04] = (div & 0xFF);
    484	state->reg[0x05] = (((div >> 8) & 0x01) | ((frac & 0x7F) << 1)) & 0xff;
    485	state->reg[0x06] = ((frac >> 7) & 0xFF);
    486	state->reg[0x07] = (state->reg[0x07] & ~0x07) | ((frac >> 15) & 0x07);
    487	state->reg[0x07] = (state->reg[0x07] & ~0xE0) | (icp << 5);
    488
    489	state->reg[0x08] = (state->reg[0x08] & ~0xFC) | ((index - 6) << 2);
    490	/* Start cal vco,CF */
    491	state->reg[0x09] = (state->reg[0x09] & ~0x0C) | 0x0C;
    492	write_regs(state, 2, 8);
    493
    494	wait_for_call_done(state, 0x0C);
    495
    496	usleep_range(10000, 12000);
    497
    498	read_reg(state, 0x03, &tmp);
    499	if (tmp & 0x10)	{
    500		state->reg[0x02] &= ~0x80; /* LNA NF Mode */
    501		write_regs(state, 2, 1);
    502	}
    503	read_reg(state, 0x08, &tmp);
    504
    505	state->frequency = frequency;
    506
    507	return 0;
    508}
    509
    510static int set_params(struct dvb_frontend *fe)
    511{
    512	struct stv *state = fe->tuner_priv;
    513	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
    514	u32 freq, cutoff;
    515	int stat = 0;
    516
    517	if (p->delivery_system != SYS_DVBS && p->delivery_system != SYS_DVBS2)
    518		return -EINVAL;
    519
    520	freq = p->frequency * 1000;
    521	cutoff = 5000000 + muldiv32(p->symbol_rate, 135, 200);
    522
    523	if (fe->ops.i2c_gate_ctrl)
    524		stat = fe->ops.i2c_gate_ctrl(fe, 1);
    525	if (!stat)
    526		set_lof(state, freq, cutoff);
    527	if (fe->ops.i2c_gate_ctrl && !stat)
    528		fe->ops.i2c_gate_ctrl(fe, 0);
    529	return 0;
    530}
    531
    532static s32 table_lookup(const struct slookup *table,
    533			int table_size, u16 reg_value)
    534{
    535	s32 gain;
    536	s32 reg_diff;
    537	int imin = 0;
    538	int imax = table_size - 1;
    539	int i;
    540
    541	/* Assumes Table[0].RegValue < Table[imax].RegValue */
    542	if (reg_value <= table[0].reg_value) {
    543		gain = table[0].value;
    544	} else if (reg_value >= table[imax].reg_value) {
    545		gain = table[imax].value;
    546	} else {
    547		while ((imax - imin) > 1) {
    548			i = (imax + imin) / 2;
    549			if ((table[imin].reg_value <= reg_value) &&
    550			    (reg_value <= table[i].reg_value))
    551				imax = i;
    552			else
    553				imin = i;
    554		}
    555		reg_diff = table[imax].reg_value - table[imin].reg_value;
    556		gain = table[imin].value;
    557		if (reg_diff != 0)
    558			gain += ((s32)(reg_value - table[imin].reg_value) *
    559				(s32)(table[imax].value
    560				- table[imin].value)) / reg_diff;
    561	}
    562	return gain;
    563}
    564
    565static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
    566{
    567	struct stv *state = fe->tuner_priv;
    568	u16 rfagc = *st;
    569	s32 gain;
    570
    571	if ((state->reg[0x03] & 0x60) == 0) {
    572		/* RF Mode, Read AGC ADC */
    573		u8 reg = 0;
    574		int stat = 0;
    575
    576		if (fe->ops.i2c_gate_ctrl)
    577			stat = fe->ops.i2c_gate_ctrl(fe, 1);
    578		if (!stat) {
    579			write_reg(state, 0x02, state->reg[0x02] | 0x20);
    580			read_reg(state, 2, &reg);
    581			if (reg & 0x20)
    582				read_reg(state, 2, &reg);
    583		}
    584		if (fe->ops.i2c_gate_ctrl && !stat)
    585			fe->ops.i2c_gate_ctrl(fe, 0);
    586
    587		if ((state->reg[0x02] & 0x80) == 0)
    588			/* NF */
    589			gain = table_lookup(lnagain_nf_lookup,
    590					    ARRAY_SIZE(lnagain_nf_lookup),
    591					    reg & 0x1F);
    592		else
    593			/* IIP3 */
    594			gain = table_lookup(lnagain_iip3_lookup,
    595					    ARRAY_SIZE(lnagain_iip3_lookup),
    596					    reg & 0x1F);
    597
    598		gain += table_lookup(gain_rfagc_lookup,
    599				     ARRAY_SIZE(gain_rfagc_lookup), rfagc);
    600
    601		gain -= 2400;
    602	} else {
    603		/* Channel Mode */
    604		if ((state->reg[0x02] & 0x80) == 0) {
    605			/* NF */
    606			gain = table_lookup(
    607				gain_channel_agc_nf_lookup,
    608				ARRAY_SIZE(gain_channel_agc_nf_lookup), rfagc);
    609
    610			gain += 600;
    611		} else {
    612			/* IIP3 */
    613			gain = table_lookup(
    614				gain_channel_agc_iip3_lookup,
    615				ARRAY_SIZE(gain_channel_agc_iip3_lookup),
    616				rfagc);
    617		}
    618	}
    619
    620	if (state->frequency > 0)
    621		/* Tilt correction ( 0.00016 dB/MHz ) */
    622		gain -= ((((s32)(state->frequency / 1000) - 1550) * 2) / 12);
    623
    624	/* + (BBGain * 10); */
    625	gain +=  (s32)((state->reg[0x01] & 0xC0) >> 6) * 600 - 1300;
    626
    627	if (gain < 0)
    628		gain = 0;
    629	else if (gain > 10000)
    630		gain = 10000;
    631
    632	*st = 10000 - gain;
    633
    634	return 0;
    635}
    636
    637static const struct dvb_tuner_ops tuner_ops = {
    638	.info = {
    639		.name		= "ST STV6111",
    640		.frequency_min_hz =  950 * MHz,
    641		.frequency_max_hz = 2150 * MHz,
    642	},
    643	.set_params		= set_params,
    644	.release		= release,
    645	.get_rf_strength	= get_rf_strength,
    646	.set_bandwidth		= set_bandwidth,
    647};
    648
    649struct dvb_frontend *stv6111_attach(struct dvb_frontend *fe,
    650				    struct i2c_adapter *i2c, u8 adr)
    651{
    652	struct stv *state;
    653	int stat = -ENODEV;
    654	int gatestat = 0;
    655
    656	state = kzalloc(sizeof(*state), GFP_KERNEL);
    657	if (!state)
    658		return NULL;
    659	state->adr = adr;
    660	state->i2c = i2c;
    661	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
    662	init_state(state);
    663
    664	if (fe->ops.i2c_gate_ctrl)
    665		gatestat = fe->ops.i2c_gate_ctrl(fe, 1);
    666	if (!gatestat)
    667		stat = attach_init(state);
    668	if (fe->ops.i2c_gate_ctrl && !gatestat)
    669		fe->ops.i2c_gate_ctrl(fe, 0);
    670	if (stat < 0) {
    671		kfree(state);
    672		return NULL;
    673	}
    674	fe->tuner_priv = state;
    675	return fe;
    676}
    677EXPORT_SYMBOL_GPL(stv6111_attach);
    678
    679MODULE_DESCRIPTION("ST STV6111 satellite tuner driver");
    680MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
    681MODULE_LICENSE("GPL v2");