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

m88rs6000t.c (16059B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for the internal tuner of Montage M88RS6000
      4 *
      5 * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
      6 */
      7
      8#include "m88rs6000t.h"
      9#include <linux/regmap.h>
     10
     11struct m88rs6000t_dev {
     12	struct m88rs6000t_config cfg;
     13	struct i2c_client *client;
     14	struct regmap *regmap;
     15	u32 frequency_khz;
     16};
     17
     18struct m88rs6000t_reg_val {
     19	u8 reg;
     20	u8 val;
     21};
     22
     23/* set demod main mclk and ts mclk */
     24static int m88rs6000t_set_demod_mclk(struct dvb_frontend *fe)
     25{
     26	struct m88rs6000t_dev *dev = fe->tuner_priv;
     27	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
     28	u8 reg11, reg15, reg16, reg1D, reg1E, reg1F;
     29	u8 N, f0 = 0, f1 = 0, f2 = 0, f3 = 0;
     30	u16 pll_div_fb;
     31	u32 div, ts_mclk;
     32	unsigned int utmp;
     33	int ret;
     34
     35	/* select demod main mclk */
     36	ret = regmap_read(dev->regmap, 0x15, &utmp);
     37	if (ret)
     38		goto err;
     39	reg15 = utmp;
     40	if (c->symbol_rate > 45010000) {
     41		reg11 = 0x0E;
     42		reg15 |= 0x02;
     43		reg16 = 115; /* mclk = 110.25MHz */
     44	} else {
     45		reg11 = 0x0A;
     46		reg15 &= ~0x02;
     47		reg16 = 96; /* mclk = 96MHz */
     48	}
     49
     50	/* set ts mclk */
     51	if (c->delivery_system == SYS_DVBS)
     52		ts_mclk = 96000;
     53	else
     54		ts_mclk = 144000;
     55
     56	pll_div_fb = (reg15 & 0x01) << 8;
     57	pll_div_fb += reg16;
     58	pll_div_fb += 32;
     59
     60	div = 36000 * pll_div_fb;
     61	div /= ts_mclk;
     62
     63	if (div <= 32) {
     64		N = 2;
     65		f0 = 0;
     66		f1 = div / 2;
     67		f2 = div - f1;
     68		f3 = 0;
     69	} else if (div <= 48) {
     70		N = 3;
     71		f0 = div / 3;
     72		f1 = (div - f0) / 2;
     73		f2 = div - f0 - f1;
     74		f3 = 0;
     75	} else if (div <= 64) {
     76		N = 4;
     77		f0 = div / 4;
     78		f1 = (div - f0) / 3;
     79		f2 = (div - f0 - f1) / 2;
     80		f3 = div - f0 - f1 - f2;
     81	} else {
     82		N = 4;
     83		f0 = 16;
     84		f1 = 16;
     85		f2 = 16;
     86		f3 = 16;
     87	}
     88
     89	if (f0 == 16)
     90		f0 = 0;
     91	if (f1 == 16)
     92		f1 = 0;
     93	if (f2 == 16)
     94		f2 = 0;
     95	if (f3 == 16)
     96		f3 = 0;
     97
     98	ret = regmap_read(dev->regmap, 0x1D, &utmp);
     99	if (ret)
    100		goto err;
    101	reg1D = utmp;
    102	reg1D &= ~0x03;
    103	reg1D |= N - 1;
    104	reg1E = ((f3 << 4) + f2) & 0xFF;
    105	reg1F = ((f1 << 4) + f0) & 0xFF;
    106
    107	/* program and recalibrate demod PLL */
    108	ret = regmap_write(dev->regmap, 0x05, 0x40);
    109	if (ret)
    110		goto err;
    111	ret = regmap_write(dev->regmap, 0x11, 0x08);
    112	if (ret)
    113		goto err;
    114	ret = regmap_write(dev->regmap, 0x15, reg15);
    115	if (ret)
    116		goto err;
    117	ret = regmap_write(dev->regmap, 0x16, reg16);
    118	if (ret)
    119		goto err;
    120	ret = regmap_write(dev->regmap, 0x1D, reg1D);
    121	if (ret)
    122		goto err;
    123	ret = regmap_write(dev->regmap, 0x1E, reg1E);
    124	if (ret)
    125		goto err;
    126	ret = regmap_write(dev->regmap, 0x1F, reg1F);
    127	if (ret)
    128		goto err;
    129	ret = regmap_write(dev->regmap, 0x17, 0xc1);
    130	if (ret)
    131		goto err;
    132	ret = regmap_write(dev->regmap, 0x17, 0x81);
    133	if (ret)
    134		goto err;
    135	usleep_range(5000, 50000);
    136	ret = regmap_write(dev->regmap, 0x05, 0x00);
    137	if (ret)
    138		goto err;
    139	ret = regmap_write(dev->regmap, 0x11, reg11);
    140	if (ret)
    141		goto err;
    142	usleep_range(5000, 50000);
    143err:
    144	if (ret)
    145		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    146	return ret;
    147}
    148
    149static int m88rs6000t_set_pll_freq(struct m88rs6000t_dev *dev,
    150			u32 tuner_freq_MHz)
    151{
    152	u32 fcry_KHz, ulNDiv1, ulNDiv2, ulNDiv;
    153	u8 refDiv, ucLoDiv1, ucLomod1, ucLoDiv2, ucLomod2, ucLoDiv, ucLomod;
    154	u8 reg27, reg29, reg42, reg42buf;
    155	unsigned int utmp;
    156	int ret;
    157
    158	fcry_KHz = 27000; /* in kHz */
    159	refDiv = 27;
    160
    161	ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
    162	if (ret)
    163		goto err;
    164	ret = regmap_write(dev->regmap, 0x31, 0x00);
    165	if (ret)
    166		goto err;
    167	ret = regmap_write(dev->regmap, 0x2c, 0x02);
    168	if (ret)
    169		goto err;
    170
    171	if (tuner_freq_MHz >= 1550) {
    172		ucLoDiv1 = 2;
    173		ucLomod1 = 0;
    174		ucLoDiv2 = 2;
    175		ucLomod2 = 0;
    176	} else if (tuner_freq_MHz >= 1380) {
    177		ucLoDiv1 = 3;
    178		ucLomod1 = 16;
    179		ucLoDiv2 = 2;
    180		ucLomod2 = 0;
    181	} else if (tuner_freq_MHz >= 1070) {
    182		ucLoDiv1 = 3;
    183		ucLomod1 = 16;
    184		ucLoDiv2 = 3;
    185		ucLomod2 = 16;
    186	} else if (tuner_freq_MHz >= 1000) {
    187		ucLoDiv1 = 3;
    188		ucLomod1 = 16;
    189		ucLoDiv2 = 4;
    190		ucLomod2 = 64;
    191	} else if (tuner_freq_MHz >= 775) {
    192		ucLoDiv1 = 4;
    193		ucLomod1 = 64;
    194		ucLoDiv2 = 4;
    195		ucLomod2 = 64;
    196	} else if (tuner_freq_MHz >= 700) {
    197		ucLoDiv1 = 6;
    198		ucLomod1 = 48;
    199		ucLoDiv2 = 4;
    200		ucLomod2 = 64;
    201	} else if (tuner_freq_MHz >= 520) {
    202		ucLoDiv1 = 6;
    203		ucLomod1 = 48;
    204		ucLoDiv2 = 6;
    205		ucLomod2 = 48;
    206	} else {
    207		ucLoDiv1 = 8;
    208		ucLomod1 = 96;
    209		ucLoDiv2 = 8;
    210		ucLomod2 = 96;
    211	}
    212
    213	ulNDiv1 = ((tuner_freq_MHz * ucLoDiv1 * 1000) * refDiv
    214			/ fcry_KHz - 1024) / 2;
    215	ulNDiv2 = ((tuner_freq_MHz * ucLoDiv2 * 1000) * refDiv
    216			/ fcry_KHz - 1024) / 2;
    217
    218	reg27 = (((ulNDiv1 >> 8) & 0x0F) + ucLomod1) & 0x7F;
    219	ret = regmap_write(dev->regmap, 0x27, reg27);
    220	if (ret)
    221		goto err;
    222	ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv1 & 0xFF));
    223	if (ret)
    224		goto err;
    225	reg29 = (((ulNDiv2 >> 8) & 0x0F) + ucLomod2) & 0x7f;
    226	ret = regmap_write(dev->regmap, 0x29, reg29);
    227	if (ret)
    228		goto err;
    229	ret = regmap_write(dev->regmap, 0x2a, (u8)(ulNDiv2 & 0xFF));
    230	if (ret)
    231		goto err;
    232	ret = regmap_write(dev->regmap, 0x2F, 0xf5);
    233	if (ret)
    234		goto err;
    235	ret = regmap_write(dev->regmap, 0x30, 0x05);
    236	if (ret)
    237		goto err;
    238	ret = regmap_write(dev->regmap, 0x08, 0x1f);
    239	if (ret)
    240		goto err;
    241	ret = regmap_write(dev->regmap, 0x08, 0x3f);
    242	if (ret)
    243		goto err;
    244	ret = regmap_write(dev->regmap, 0x09, 0x20);
    245	if (ret)
    246		goto err;
    247	ret = regmap_write(dev->regmap, 0x09, 0x00);
    248	if (ret)
    249		goto err;
    250	ret = regmap_write(dev->regmap, 0x3e, 0x11);
    251	if (ret)
    252		goto err;
    253	ret = regmap_write(dev->regmap, 0x08, 0x2f);
    254	if (ret)
    255		goto err;
    256	ret = regmap_write(dev->regmap, 0x08, 0x3f);
    257	if (ret)
    258		goto err;
    259	ret = regmap_write(dev->regmap, 0x09, 0x10);
    260	if (ret)
    261		goto err;
    262	ret = regmap_write(dev->regmap, 0x09, 0x00);
    263	if (ret)
    264		goto err;
    265	usleep_range(2000, 50000);
    266
    267	ret = regmap_read(dev->regmap, 0x42, &utmp);
    268	if (ret)
    269		goto err;
    270	reg42 = utmp;
    271
    272	ret = regmap_write(dev->regmap, 0x3e, 0x10);
    273	if (ret)
    274		goto err;
    275	ret = regmap_write(dev->regmap, 0x08, 0x2f);
    276	if (ret)
    277		goto err;
    278	ret = regmap_write(dev->regmap, 0x08, 0x3f);
    279	if (ret)
    280		goto err;
    281	ret = regmap_write(dev->regmap, 0x09, 0x10);
    282	if (ret)
    283		goto err;
    284	ret = regmap_write(dev->regmap, 0x09, 0x00);
    285	if (ret)
    286		goto err;
    287	usleep_range(2000, 50000);
    288
    289	ret = regmap_read(dev->regmap, 0x42, &utmp);
    290	if (ret)
    291		goto err;
    292	reg42buf = utmp;
    293	if (reg42buf < reg42) {
    294		ret = regmap_write(dev->regmap, 0x3e, 0x11);
    295		if (ret)
    296			goto err;
    297	}
    298	usleep_range(5000, 50000);
    299
    300	ret = regmap_read(dev->regmap, 0x2d, &utmp);
    301	if (ret)
    302		goto err;
    303	ret = regmap_write(dev->regmap, 0x2d, utmp);
    304	if (ret)
    305		goto err;
    306	ret = regmap_read(dev->regmap, 0x2e, &utmp);
    307	if (ret)
    308		goto err;
    309	ret = regmap_write(dev->regmap, 0x2e, utmp);
    310	if (ret)
    311		goto err;
    312
    313	ret = regmap_read(dev->regmap, 0x27, &utmp);
    314	if (ret)
    315		goto err;
    316	reg27 = utmp & 0x70;
    317	ret = regmap_read(dev->regmap, 0x83, &utmp);
    318	if (ret)
    319		goto err;
    320	if (reg27 == (utmp & 0x70)) {
    321		ucLoDiv	= ucLoDiv1;
    322		ulNDiv = ulNDiv1;
    323		ucLomod = ucLomod1 / 16;
    324	} else {
    325		ucLoDiv	= ucLoDiv2;
    326		ulNDiv = ulNDiv2;
    327		ucLomod = ucLomod2 / 16;
    328	}
    329
    330	if ((ucLoDiv == 3) || (ucLoDiv == 6)) {
    331		refDiv = 18;
    332		ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
    333		if (ret)
    334			goto err;
    335		ulNDiv = ((tuner_freq_MHz * ucLoDiv * 1000) * refDiv
    336				/ fcry_KHz - 1024) / 2;
    337	}
    338
    339	reg27 = (0x80 + ((ucLomod << 4) & 0x70)
    340			+ ((ulNDiv >> 8) & 0x0F)) & 0xFF;
    341	ret = regmap_write(dev->regmap, 0x27, reg27);
    342	if (ret)
    343		goto err;
    344	ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv & 0xFF));
    345	if (ret)
    346		goto err;
    347	ret = regmap_write(dev->regmap, 0x29, 0x80);
    348	if (ret)
    349		goto err;
    350	ret = regmap_write(dev->regmap, 0x31, 0x03);
    351	if (ret)
    352		goto err;
    353
    354	if (ucLoDiv == 3)
    355		utmp = 0xCE;
    356	else
    357		utmp = 0x8A;
    358	ret = regmap_write(dev->regmap, 0x3b, utmp);
    359	if (ret)
    360		goto err;
    361
    362	dev->frequency_khz = fcry_KHz * (ulNDiv * 2 + 1024) / refDiv / ucLoDiv;
    363
    364	dev_dbg(&dev->client->dev,
    365		"actual tune frequency=%d\n", dev->frequency_khz);
    366err:
    367	if (ret)
    368		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    369	return ret;
    370}
    371
    372static int m88rs6000t_set_bb(struct m88rs6000t_dev *dev,
    373		u32 symbol_rate_KSs, s32 lpf_offset_KHz)
    374{
    375	u32 f3dB;
    376	u8  reg40;
    377
    378	f3dB = symbol_rate_KSs * 9 / 14 + 2000;
    379	f3dB += lpf_offset_KHz;
    380	f3dB = clamp_val(f3dB, 6000U, 43000U);
    381	reg40 = f3dB / 1000;
    382	return regmap_write(dev->regmap, 0x40, reg40);
    383}
    384
    385static int m88rs6000t_set_params(struct dvb_frontend *fe)
    386{
    387	struct m88rs6000t_dev *dev = fe->tuner_priv;
    388	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
    389	int ret;
    390	s32 lpf_offset_KHz;
    391	u32 realFreq, freq_MHz;
    392
    393	dev_dbg(&dev->client->dev,
    394			"frequency=%d symbol_rate=%d\n",
    395			c->frequency, c->symbol_rate);
    396
    397	if (c->symbol_rate < 5000000)
    398		lpf_offset_KHz = 3000;
    399	else
    400		lpf_offset_KHz = 0;
    401
    402	realFreq = c->frequency + lpf_offset_KHz;
    403	/* set tuner pll.*/
    404	freq_MHz = (realFreq + 500) / 1000;
    405	ret = m88rs6000t_set_pll_freq(dev, freq_MHz);
    406	if (ret)
    407		goto err;
    408	ret = m88rs6000t_set_bb(dev, c->symbol_rate / 1000, lpf_offset_KHz);
    409	if (ret)
    410		goto err;
    411	ret = regmap_write(dev->regmap, 0x00, 0x01);
    412	if (ret)
    413		goto err;
    414	ret = regmap_write(dev->regmap, 0x00, 0x00);
    415	if (ret)
    416		goto err;
    417	/* set demod mlck */
    418	ret = m88rs6000t_set_demod_mclk(fe);
    419err:
    420	if (ret)
    421		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    422	return ret;
    423}
    424
    425static int m88rs6000t_init(struct dvb_frontend *fe)
    426{
    427	struct m88rs6000t_dev *dev = fe->tuner_priv;
    428	int ret;
    429
    430	dev_dbg(&dev->client->dev, "%s:\n", __func__);
    431
    432	ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
    433	if (ret)
    434		goto err;
    435	usleep_range(5000, 50000);
    436	ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
    437	if (ret)
    438		goto err;
    439	usleep_range(10000, 50000);
    440	ret = regmap_write(dev->regmap, 0x07, 0x7d);
    441err:
    442	if (ret)
    443		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    444	return ret;
    445}
    446
    447static int m88rs6000t_sleep(struct dvb_frontend *fe)
    448{
    449	struct m88rs6000t_dev *dev = fe->tuner_priv;
    450	int ret;
    451
    452	dev_dbg(&dev->client->dev, "%s:\n", __func__);
    453
    454	ret = regmap_write(dev->regmap, 0x07, 0x6d);
    455	if (ret) {
    456		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    457		return ret;
    458	}
    459	usleep_range(5000, 10000);
    460	return 0;
    461}
    462
    463static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
    464{
    465	struct m88rs6000t_dev *dev = fe->tuner_priv;
    466
    467	dev_dbg(&dev->client->dev, "\n");
    468
    469	*frequency = dev->frequency_khz;
    470	return 0;
    471}
    472
    473static int m88rs6000t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
    474{
    475	struct m88rs6000t_dev *dev = fe->tuner_priv;
    476
    477	dev_dbg(&dev->client->dev, "\n");
    478
    479	*frequency = 0; /* Zero-IF */
    480	return 0;
    481}
    482
    483
    484static int m88rs6000t_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
    485{
    486	struct m88rs6000t_dev *dev = fe->tuner_priv;
    487	unsigned int val, i;
    488	int ret;
    489	u16 gain;
    490	u32 PGA2_cri_GS = 46, PGA2_crf_GS = 290, TIA_GS = 290;
    491	u32 RF_GC = 1200, IF_GC = 1100, BB_GC = 300;
    492	u32 PGA2_GC = 300, TIA_GC = 300, PGA2_cri = 0, PGA2_crf = 0;
    493	u32 RFG = 0, IFG = 0, BBG = 0, PGA2G = 0, TIAG = 0;
    494	u32 RFGS[13] = {0, 245, 266, 268, 270, 285,
    495			298, 295, 283, 285, 285, 300, 300};
    496	u32 IFGS[12] = {0, 300, 230, 270, 270, 285,
    497			295, 285, 290, 295, 295, 310};
    498	u32 BBGS[14] = {0, 286, 275, 290, 294, 300, 290,
    499			290, 285, 283, 260, 295, 290, 260};
    500
    501	ret = regmap_read(dev->regmap, 0x5A, &val);
    502	if (ret)
    503		goto err;
    504	RF_GC = val & 0x0f;
    505
    506	ret = regmap_read(dev->regmap, 0x5F, &val);
    507	if (ret)
    508		goto err;
    509	IF_GC = val & 0x0f;
    510
    511	ret = regmap_read(dev->regmap, 0x3F, &val);
    512	if (ret)
    513		goto err;
    514	TIA_GC = (val >> 4) & 0x07;
    515
    516	ret = regmap_read(dev->regmap, 0x77, &val);
    517	if (ret)
    518		goto err;
    519	BB_GC = (val >> 4) & 0x0f;
    520
    521	ret = regmap_read(dev->regmap, 0x76, &val);
    522	if (ret)
    523		goto err;
    524	PGA2_GC = val & 0x3f;
    525	PGA2_cri = PGA2_GC >> 2;
    526	PGA2_crf = PGA2_GC & 0x03;
    527
    528	for (i = 0; i <= RF_GC && i < ARRAY_SIZE(RFGS); i++)
    529		RFG += RFGS[i];
    530
    531	if (RF_GC == 0)
    532		RFG += 400;
    533	if (RF_GC == 1)
    534		RFG += 300;
    535	if (RF_GC == 2)
    536		RFG += 200;
    537	if (RF_GC == 3)
    538		RFG += 100;
    539
    540	for (i = 0; i <= IF_GC && i < ARRAY_SIZE(IFGS); i++)
    541		IFG += IFGS[i];
    542
    543	TIAG = TIA_GC * TIA_GS;
    544
    545	for (i = 0; i <= BB_GC && i < ARRAY_SIZE(BBGS); i++)
    546		BBG += BBGS[i];
    547
    548	PGA2G = PGA2_cri * PGA2_cri_GS + PGA2_crf * PGA2_crf_GS;
    549
    550	gain = RFG + IFG - TIAG + BBG + PGA2G;
    551
    552	/* scale value to 0x0000-0xffff */
    553	gain = clamp_val(gain, 1000U, 10500U);
    554	*strength = (10500 - gain) * 0xffff / (10500 - 1000);
    555err:
    556	if (ret)
    557		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
    558	return ret;
    559}
    560
    561static const struct dvb_tuner_ops m88rs6000t_tuner_ops = {
    562	.info = {
    563		.name             = "Montage M88RS6000 Internal Tuner",
    564		.frequency_min_hz =  950 * MHz,
    565		.frequency_max_hz = 2150 * MHz,
    566	},
    567
    568	.init = m88rs6000t_init,
    569	.sleep = m88rs6000t_sleep,
    570	.set_params = m88rs6000t_set_params,
    571	.get_frequency = m88rs6000t_get_frequency,
    572	.get_if_frequency = m88rs6000t_get_if_frequency,
    573	.get_rf_strength = m88rs6000t_get_rf_strength,
    574};
    575
    576static int m88rs6000t_probe(struct i2c_client *client,
    577		const struct i2c_device_id *id)
    578{
    579	struct m88rs6000t_config *cfg = client->dev.platform_data;
    580	struct dvb_frontend *fe = cfg->fe;
    581	struct m88rs6000t_dev *dev;
    582	int ret, i;
    583	unsigned int utmp;
    584	static const struct regmap_config regmap_config = {
    585		.reg_bits = 8,
    586		.val_bits = 8,
    587	};
    588	static const struct m88rs6000t_reg_val reg_vals[] = {
    589		{0x10, 0xfb},
    590		{0x24, 0x38},
    591		{0x11, 0x0a},
    592		{0x12, 0x00},
    593		{0x2b, 0x1c},
    594		{0x44, 0x48},
    595		{0x54, 0x24},
    596		{0x55, 0x06},
    597		{0x59, 0x00},
    598		{0x5b, 0x4c},
    599		{0x60, 0x8b},
    600		{0x61, 0xf4},
    601		{0x65, 0x07},
    602		{0x6d, 0x6f},
    603		{0x6e, 0x31},
    604		{0x3c, 0xf3},
    605		{0x37, 0x0f},
    606		{0x48, 0x28},
    607		{0x49, 0xd8},
    608		{0x70, 0x66},
    609		{0x71, 0xCF},
    610		{0x72, 0x81},
    611		{0x73, 0xA7},
    612		{0x74, 0x4F},
    613		{0x75, 0xFC},
    614	};
    615
    616	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    617	if (!dev) {
    618		ret = -ENOMEM;
    619		dev_err(&client->dev, "kzalloc() failed\n");
    620		goto err;
    621	}
    622
    623	memcpy(&dev->cfg, cfg, sizeof(struct m88rs6000t_config));
    624	dev->client = client;
    625	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
    626	if (IS_ERR(dev->regmap)) {
    627		ret = PTR_ERR(dev->regmap);
    628		goto err;
    629	}
    630
    631	ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
    632	if (ret)
    633		goto err;
    634	usleep_range(5000, 50000);
    635	ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
    636	if (ret)
    637		goto err;
    638	usleep_range(10000, 50000);
    639	ret = regmap_write(dev->regmap, 0x07, 0x7d);
    640	if (ret)
    641		goto err;
    642	ret = regmap_write(dev->regmap, 0x04, 0x01);
    643	if (ret)
    644		goto err;
    645
    646	/* check tuner chip id */
    647	ret = regmap_read(dev->regmap, 0x01, &utmp);
    648	if (ret)
    649		goto err;
    650	dev_info(&dev->client->dev, "chip_id=%02x\n", utmp);
    651	if (utmp != 0x64) {
    652		ret = -ENODEV;
    653		goto err;
    654	}
    655
    656	/* tuner init. */
    657	ret = regmap_write(dev->regmap, 0x05, 0x40);
    658	if (ret)
    659		goto err;
    660	ret = regmap_write(dev->regmap, 0x11, 0x08);
    661	if (ret)
    662		goto err;
    663	ret = regmap_write(dev->regmap, 0x15, 0x6c);
    664	if (ret)
    665		goto err;
    666	ret = regmap_write(dev->regmap, 0x17, 0xc1);
    667	if (ret)
    668		goto err;
    669	ret = regmap_write(dev->regmap, 0x17, 0x81);
    670	if (ret)
    671		goto err;
    672	usleep_range(10000, 50000);
    673	ret = regmap_write(dev->regmap, 0x05, 0x00);
    674	if (ret)
    675		goto err;
    676	ret = regmap_write(dev->regmap, 0x11, 0x0a);
    677	if (ret)
    678		goto err;
    679
    680	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
    681		ret = regmap_write(dev->regmap,
    682				reg_vals[i].reg, reg_vals[i].val);
    683		if (ret)
    684			goto err;
    685	}
    686
    687	dev_info(&dev->client->dev, "Montage M88RS6000 internal tuner successfully identified\n");
    688
    689	fe->tuner_priv = dev;
    690	memcpy(&fe->ops.tuner_ops, &m88rs6000t_tuner_ops,
    691			sizeof(struct dvb_tuner_ops));
    692	i2c_set_clientdata(client, dev);
    693	return 0;
    694err:
    695	dev_dbg(&client->dev, "failed=%d\n", ret);
    696	kfree(dev);
    697	return ret;
    698}
    699
    700static int m88rs6000t_remove(struct i2c_client *client)
    701{
    702	struct m88rs6000t_dev *dev = i2c_get_clientdata(client);
    703	struct dvb_frontend *fe = dev->cfg.fe;
    704
    705	dev_dbg(&client->dev, "\n");
    706
    707	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
    708	fe->tuner_priv = NULL;
    709	kfree(dev);
    710
    711	return 0;
    712}
    713
    714static const struct i2c_device_id m88rs6000t_id[] = {
    715	{"m88rs6000t", 0},
    716	{}
    717};
    718MODULE_DEVICE_TABLE(i2c, m88rs6000t_id);
    719
    720static struct i2c_driver m88rs6000t_driver = {
    721	.driver = {
    722		.name	= "m88rs6000t",
    723	},
    724	.probe		= m88rs6000t_probe,
    725	.remove		= m88rs6000t_remove,
    726	.id_table	= m88rs6000t_id,
    727};
    728
    729module_i2c_driver(m88rs6000t_driver);
    730
    731MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
    732MODULE_DESCRIPTION("Montage M88RS6000 internal tuner driver");
    733MODULE_LICENSE("GPL");