brintos

brintos / linux-shallow public Read only

0
0
Text · 9.9 KiB · 4d5b1c8 Raw
456 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ITE IT913X silicon tuner driver4 *5 *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)6 *  IT9137 Copyright (C) ITE Tech Inc.7 */8 9#include "it913x.h"10#include <linux/platform_device.h>11#include <linux/regmap.h>12 13struct it913x_dev {14	struct platform_device *pdev;15	struct regmap *regmap;16	struct dvb_frontend *fe;17	u8 chip_ver:2;18	u8 role:2;19	u16 xtal;20	u8 fdiv;21	u8 clk_mode;22	u32 fn_min;23	bool active;24};25 26static int it913x_init(struct dvb_frontend *fe)27{28	struct it913x_dev *dev = fe->tuner_priv;29	struct platform_device *pdev = dev->pdev;30	int ret;31	unsigned int utmp;32	u8 iqik_m_cal, nv_val, buf[2];33	static const u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};34	unsigned long timeout;35 36	dev_dbg(&pdev->dev, "role %u\n", dev->role);37 38	ret = regmap_write(dev->regmap, 0x80ec4c, 0x68);39	if (ret)40		goto err;41 42	usleep_range(10000, 100000);43 44	ret = regmap_read(dev->regmap, 0x80ec86, &utmp);45	if (ret)46		goto err;47 48	switch (utmp) {49	case 0:50		/* 12.000 MHz */51		dev->clk_mode = utmp;52		dev->xtal = 2000;53		dev->fdiv = 3;54		iqik_m_cal = 16;55		break;56	case 1:57		/* 20.480 MHz */58		dev->clk_mode = utmp;59		dev->xtal = 640;60		dev->fdiv = 1;61		iqik_m_cal = 6;62		break;63	default:64		dev_err(&pdev->dev, "unknown clock identifier %d\n", utmp);65		ret = -EINVAL;66		goto err;67	}68 69	ret = regmap_read(dev->regmap, 0x80ed03,  &utmp);70	if (ret)71		goto err;72 73	else if (utmp < ARRAY_SIZE(nv))74		nv_val = nv[utmp];75	else76		nv_val = 2;77 78	#define TIMEOUT 5079	timeout = jiffies + msecs_to_jiffies(TIMEOUT);80	while (!time_after(jiffies, timeout)) {81		ret = regmap_bulk_read(dev->regmap, 0x80ed23, buf, 2);82		if (ret)83			goto err;84 85		utmp = (buf[1] << 8) | (buf[0] << 0);86		if (utmp)87			break;88	}89 90	dev_dbg(&pdev->dev, "r_fbc_m_bdry took %u ms, val %u\n",91			jiffies_to_msecs(jiffies) -92			(jiffies_to_msecs(timeout) - TIMEOUT), utmp);93 94	dev->fn_min = dev->xtal * utmp;95	dev->fn_min /= (dev->fdiv * nv_val);96	dev->fn_min *= 1000;97	dev_dbg(&pdev->dev, "fn_min %u\n", dev->fn_min);98 99	/*100	 * Chip version BX never sets that flag so we just wait 50ms in that101	 * case. It is possible poll BX similarly than AX and then timeout in102	 * order to get 50ms delay, but that causes about 120 extra I2C103	 * messages. As for now, we just wait and reduce IO.104	 */105	if (dev->chip_ver == 1) {106		#define TIMEOUT 50107		timeout = jiffies + msecs_to_jiffies(TIMEOUT);108		while (!time_after(jiffies, timeout)) {109			ret = regmap_read(dev->regmap, 0x80ec82, &utmp);110			if (ret)111				goto err;112 113			if (utmp)114				break;115		}116 117		dev_dbg(&pdev->dev, "p_tsm_init_mode took %u ms, val %u\n",118				jiffies_to_msecs(jiffies) -119				(jiffies_to_msecs(timeout) - TIMEOUT), utmp);120	} else {121		msleep(50);122	}123 124	ret = regmap_write(dev->regmap, 0x80ed81, iqik_m_cal);125	if (ret)126		goto err;127 128	ret = regmap_write(dev->regmap, 0x80ec57, 0x00);129	if (ret)130		goto err;131 132	ret = regmap_write(dev->regmap, 0x80ec58, 0x00);133	if (ret)134		goto err;135 136	ret = regmap_write(dev->regmap, 0x80ec40, 0x01);137	if (ret)138		goto err;139 140	dev->active = true;141 142	return 0;143err:144	dev_dbg(&pdev->dev, "failed %d\n", ret);145	return ret;146}147 148static int it913x_sleep(struct dvb_frontend *fe)149{150	struct it913x_dev *dev = fe->tuner_priv;151	struct platform_device *pdev = dev->pdev;152	int ret, len;153 154	dev_dbg(&pdev->dev, "role %u\n", dev->role);155 156	dev->active = false;157 158	ret  = regmap_bulk_write(dev->regmap, 0x80ec40, "\x00", 1);159	if (ret)160		goto err;161 162	/*163	 * Writing '0x00' to master tuner register '0x80ec08' causes slave tuner164	 * communication lost. Due to that, we cannot put master full sleep.165	 */166	if (dev->role == IT913X_ROLE_DUAL_MASTER)167		len = 4;168	else169		len = 15;170 171	dev_dbg(&pdev->dev, "role %u, len %d\n", dev->role, len);172 173	ret = regmap_bulk_write(dev->regmap, 0x80ec02,174			"\x3f\x1f\x3f\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",175			len);176	if (ret)177		goto err;178 179	ret = regmap_bulk_write(dev->regmap, 0x80ec12, "\x00\x00\x00\x00", 4);180	if (ret)181		goto err;182 183	ret = regmap_bulk_write(dev->regmap, 0x80ec17,184			"\x00\x00\x00\x00\x00\x00\x00\x00\x00", 9);185	if (ret)186		goto err;187 188	ret = regmap_bulk_write(dev->regmap, 0x80ec22,189			"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10);190	if (ret)191		goto err;192 193	ret = regmap_bulk_write(dev->regmap, 0x80ec20, "\x00", 1);194	if (ret)195		goto err;196 197	ret = regmap_bulk_write(dev->regmap, 0x80ec3f, "\x01", 1);198	if (ret)199		goto err;200 201	return 0;202err:203	dev_dbg(&pdev->dev, "failed %d\n", ret);204	return ret;205}206 207static int it913x_set_params(struct dvb_frontend *fe)208{209	struct it913x_dev *dev = fe->tuner_priv;210	struct platform_device *pdev = dev->pdev;211	struct dtv_frontend_properties *c = &fe->dtv_property_cache;212	int ret;213	unsigned int utmp;214	u32 pre_lo_freq, t_cal_freq;215	u16 iqik_m_cal, n_div;216	u8 u8tmp, n, l_band, lna_band;217 218	dev_dbg(&pdev->dev, "role=%u, frequency %u, bandwidth_hz %u\n",219			dev->role, c->frequency, c->bandwidth_hz);220 221	if (!dev->active) {222		ret = -EINVAL;223		goto err;224	}225 226	if (c->frequency <=         74000000) {227		n_div = 48;228		n = 0;229	} else if (c->frequency <= 111000000) {230		n_div = 32;231		n = 1;232	} else if (c->frequency <= 148000000) {233		n_div = 24;234		n = 2;235	} else if (c->frequency <= 222000000) {236		n_div = 16;237		n = 3;238	} else if (c->frequency <= 296000000) {239		n_div = 12;240		n = 4;241	} else if (c->frequency <= 445000000) {242		n_div = 8;243		n = 5;244	} else if (c->frequency <= dev->fn_min) {245		n_div = 6;246		n = 6;247	} else if (c->frequency <= 950000000) {248		n_div = 4;249		n = 7;250	} else {251		n_div = 2;252		n = 0;253	}254 255	ret = regmap_read(dev->regmap, 0x80ed81, &utmp);256	if (ret)257		goto err;258 259	iqik_m_cal = utmp * n_div;260 261	if (utmp < 0x20) {262		if (dev->clk_mode == 0)263			iqik_m_cal = (iqik_m_cal * 9) >> 5;264		else265			iqik_m_cal >>= 1;266	} else {267		iqik_m_cal = 0x40 - iqik_m_cal;268		if (dev->clk_mode == 0)269			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);270		else271			iqik_m_cal = ~(iqik_m_cal >> 1);272	}273 274	t_cal_freq = (c->frequency / 1000) * n_div * dev->fdiv;275	pre_lo_freq = t_cal_freq / dev->xtal;276	utmp = pre_lo_freq * dev->xtal;277 278	if ((t_cal_freq - utmp) >= (dev->xtal >> 1))279		pre_lo_freq++;280 281	pre_lo_freq += (u32) n << 13;282	/* Frequency OMEGA_IQIK_M_CAL_MID*/283	t_cal_freq = pre_lo_freq + (u32)iqik_m_cal;284	dev_dbg(&pdev->dev, "t_cal_freq %u, pre_lo_freq %u\n",285			t_cal_freq, pre_lo_freq);286 287	if (c->frequency <=         440000000) {288		l_band = 0;289		lna_band = 0;290	} else if (c->frequency <=  484000000) {291		l_band = 1;292		lna_band = 1;293	} else if (c->frequency <=  533000000) {294		l_band = 1;295		lna_band = 2;296	} else if (c->frequency <=  587000000) {297		l_band = 1;298		lna_band = 3;299	} else if (c->frequency <=  645000000) {300		l_band = 1;301		lna_band = 4;302	} else if (c->frequency <=  710000000) {303		l_band = 1;304		lna_band = 5;305	} else if (c->frequency <=  782000000) {306		l_band = 1;307		lna_band = 6;308	} else if (c->frequency <=  860000000) {309		l_band = 1;310		lna_band = 7;311	} else if (c->frequency <= 1492000000) {312		l_band = 1;313		lna_band = 0;314	} else if (c->frequency <= 1685000000) {315		l_band = 1;316		lna_band = 1;317	} else {318		ret = -EINVAL;319		goto err;320	}321 322	/* XXX: latest windows driver does not set that at all */323	ret = regmap_write(dev->regmap, 0x80ee06, lna_band);324	if (ret)325		goto err;326 327	if (c->bandwidth_hz <=      5000000)328		u8tmp = 0;329	else if (c->bandwidth_hz <= 6000000)330		u8tmp = 2;331	else if (c->bandwidth_hz <= 7000000)332		u8tmp = 4;333	else334		u8tmp = 6;       /* 8000000 */335 336	ret = regmap_write(dev->regmap, 0x80ec56, u8tmp);337	if (ret)338		goto err;339 340	/* XXX: latest windows driver sets different value (a8 != 68) */341	ret = regmap_write(dev->regmap, 0x80ec4c, 0xa0 | (l_band << 3));342	if (ret)343		goto err;344 345	ret = regmap_write(dev->regmap, 0x80ec4d, (t_cal_freq >> 0) & 0xff);346	if (ret)347		goto err;348 349	ret = regmap_write(dev->regmap, 0x80ec4e, (t_cal_freq >> 8) & 0xff);350	if (ret)351		goto err;352 353	ret = regmap_write(dev->regmap, 0x80011e, (pre_lo_freq >> 0) & 0xff);354	if (ret)355		goto err;356 357	ret = regmap_write(dev->regmap, 0x80011f, (pre_lo_freq >> 8) & 0xff);358	if (ret)359		goto err;360 361	return 0;362err:363	dev_dbg(&pdev->dev, "failed %d\n", ret);364	return ret;365}366 367static const struct dvb_tuner_ops it913x_tuner_ops = {368	.info = {369		.name             = "ITE IT913X",370		.frequency_min_hz = 174 * MHz,371		.frequency_max_hz = 862 * MHz,372	},373 374	.init = it913x_init,375	.sleep = it913x_sleep,376	.set_params = it913x_set_params,377};378 379static int it913x_probe(struct platform_device *pdev)380{381	struct it913x_platform_data *pdata = pdev->dev.platform_data;382	struct dvb_frontend *fe = pdata->fe;383	struct it913x_dev *dev;384	const struct platform_device_id *id = platform_get_device_id(pdev);385	int ret;386	char *chip_ver_str;387 388	dev = kzalloc(sizeof(struct it913x_dev), GFP_KERNEL);389	if (dev == NULL) {390		ret = -ENOMEM;391		dev_err(&pdev->dev, "kzalloc() failed\n");392		goto err;393	}394 395	dev->pdev = pdev;396	dev->regmap = pdata->regmap;397	dev->fe = pdata->fe;398	dev->chip_ver = id->driver_data;399	dev->role = pdata->role;400 401	fe->tuner_priv = dev;402	memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,403			sizeof(struct dvb_tuner_ops));404	platform_set_drvdata(pdev, dev);405 406	if (dev->chip_ver == 1)407		chip_ver_str = "AX";408	else if (dev->chip_ver == 2)409		chip_ver_str = "BX";410	else411		chip_ver_str = "??";412 413	dev_info(&pdev->dev, "ITE IT913X %s successfully attached\n",414		 chip_ver_str);415	dev_dbg(&pdev->dev, "chip_ver %u, role %u\n", dev->chip_ver, dev->role);416	return 0;417err:418	dev_dbg(&pdev->dev, "failed %d\n", ret);419	return ret;420}421 422static void it913x_remove(struct platform_device *pdev)423{424	struct it913x_dev *dev = platform_get_drvdata(pdev);425	struct dvb_frontend *fe = dev->fe;426 427	dev_dbg(&pdev->dev, "\n");428 429	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));430	fe->tuner_priv = NULL;431	kfree(dev);432}433 434static const struct platform_device_id it913x_id_table[] = {435	{"it9133ax-tuner", 1},436	{"it9133bx-tuner", 2},437	{},438};439MODULE_DEVICE_TABLE(platform, it913x_id_table);440 441static struct platform_driver it913x_driver = {442	.driver = {443		.name	= "it913x",444		.suppress_bind_attrs	= true,445	},446	.probe		= it913x_probe,447	.remove_new	= it913x_remove,448	.id_table	= it913x_id_table,449};450 451module_platform_driver(it913x_driver);452 453MODULE_DESCRIPTION("ITE IT913X silicon tuner driver");454MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");455MODULE_LICENSE("GPL");456