18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Afatech AF9033 demodulator driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
68c2ecf20Sopenharmony_ci * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "af9033_priv.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistruct af9033_dev {
128c2ecf20Sopenharmony_ci	struct i2c_client *client;
138c2ecf20Sopenharmony_ci	struct regmap *regmap;
148c2ecf20Sopenharmony_ci	struct dvb_frontend fe;
158c2ecf20Sopenharmony_ci	struct af9033_config cfg;
168c2ecf20Sopenharmony_ci	bool is_af9035;
178c2ecf20Sopenharmony_ci	bool is_it9135;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	u32 bandwidth_hz;
208c2ecf20Sopenharmony_ci	bool ts_mode_parallel;
218c2ecf20Sopenharmony_ci	bool ts_mode_serial;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	enum fe_status fe_status;
248c2ecf20Sopenharmony_ci	u64 post_bit_error_prev; /* for old read_ber we return (curr - prev) */
258c2ecf20Sopenharmony_ci	u64 post_bit_error;
268c2ecf20Sopenharmony_ci	u64 post_bit_count;
278c2ecf20Sopenharmony_ci	u64 error_block_count;
288c2ecf20Sopenharmony_ci	u64 total_block_count;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Write reg val table using reg addr auto increment */
328c2ecf20Sopenharmony_cistatic int af9033_wr_reg_val_tab(struct af9033_dev *dev,
338c2ecf20Sopenharmony_ci				 const struct reg_val *tab, int tab_len)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
368c2ecf20Sopenharmony_ci#define MAX_TAB_LEN 212
378c2ecf20Sopenharmony_ci	int ret, i, j;
388c2ecf20Sopenharmony_ci	u8 buf[1 + MAX_TAB_LEN];
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "tab_len=%d\n", tab_len);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (tab_len > sizeof(buf)) {
438c2ecf20Sopenharmony_ci		dev_warn(&client->dev, "tab len %d is too big\n", tab_len);
448c2ecf20Sopenharmony_ci		return -EINVAL;
458c2ecf20Sopenharmony_ci	}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i < tab_len; i++) {
488c2ecf20Sopenharmony_ci		buf[j] = tab[i].val;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci		if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) {
518c2ecf20Sopenharmony_ci			ret = regmap_bulk_write(dev->regmap, tab[i].reg - j,
528c2ecf20Sopenharmony_ci						buf, j + 1);
538c2ecf20Sopenharmony_ci			if (ret)
548c2ecf20Sopenharmony_ci				goto err;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci			j = 0;
578c2ecf20Sopenharmony_ci		} else {
588c2ecf20Sopenharmony_ci			j++;
598c2ecf20Sopenharmony_ci		}
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	return 0;
638c2ecf20Sopenharmony_cierr:
648c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
658c2ecf20Sopenharmony_ci	return ret;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic int af9033_init(struct dvb_frontend *fe)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
718c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
728c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
738c2ecf20Sopenharmony_ci	int ret, i, len;
748c2ecf20Sopenharmony_ci	unsigned int utmp;
758c2ecf20Sopenharmony_ci	const struct reg_val *init;
768c2ecf20Sopenharmony_ci	u8 buf[4];
778c2ecf20Sopenharmony_ci	struct reg_val_mask tab[] = {
788c2ecf20Sopenharmony_ci		{ 0x80fb24, 0x00, 0x08 },
798c2ecf20Sopenharmony_ci		{ 0x80004c, 0x00, 0xff },
808c2ecf20Sopenharmony_ci		{ 0x00f641, dev->cfg.tuner, 0xff },
818c2ecf20Sopenharmony_ci		{ 0x80f5ca, 0x01, 0x01 },
828c2ecf20Sopenharmony_ci		{ 0x80f715, 0x01, 0x01 },
838c2ecf20Sopenharmony_ci		{ 0x00f41f, 0x04, 0x04 },
848c2ecf20Sopenharmony_ci		{ 0x00f41a, 0x01, 0x01 },
858c2ecf20Sopenharmony_ci		{ 0x80f731, 0x00, 0x01 },
868c2ecf20Sopenharmony_ci		{ 0x00d91e, 0x00, 0x01 },
878c2ecf20Sopenharmony_ci		{ 0x00d919, 0x00, 0x01 },
888c2ecf20Sopenharmony_ci		{ 0x80f732, 0x00, 0x01 },
898c2ecf20Sopenharmony_ci		{ 0x00d91f, 0x00, 0x01 },
908c2ecf20Sopenharmony_ci		{ 0x00d91a, 0x00, 0x01 },
918c2ecf20Sopenharmony_ci		{ 0x80f730, 0x00, 0x01 },
928c2ecf20Sopenharmony_ci		{ 0x80f778, 0x00, 0xff },
938c2ecf20Sopenharmony_ci		{ 0x80f73c, 0x01, 0x01 },
948c2ecf20Sopenharmony_ci		{ 0x80f776, 0x00, 0x01 },
958c2ecf20Sopenharmony_ci		{ 0x00d8fd, 0x01, 0xff },
968c2ecf20Sopenharmony_ci		{ 0x00d830, 0x01, 0xff },
978c2ecf20Sopenharmony_ci		{ 0x00d831, 0x00, 0xff },
988c2ecf20Sopenharmony_ci		{ 0x00d832, 0x00, 0xff },
998c2ecf20Sopenharmony_ci		{ 0x80f985, dev->ts_mode_serial, 0x01 },
1008c2ecf20Sopenharmony_ci		{ 0x80f986, dev->ts_mode_parallel, 0x01 },
1018c2ecf20Sopenharmony_ci		{ 0x00d827, 0x00, 0xff },
1028c2ecf20Sopenharmony_ci		{ 0x00d829, 0x00, 0xff },
1038c2ecf20Sopenharmony_ci		{ 0x800045, dev->cfg.adc_multiplier, 0xff },
1048c2ecf20Sopenharmony_ci	};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	/* Main clk control */
1098c2ecf20Sopenharmony_ci	utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000);
1108c2ecf20Sopenharmony_ci	buf[0] = (utmp >>  0) & 0xff;
1118c2ecf20Sopenharmony_ci	buf[1] = (utmp >>  8) & 0xff;
1128c2ecf20Sopenharmony_ci	buf[2] = (utmp >> 16) & 0xff;
1138c2ecf20Sopenharmony_ci	buf[3] = (utmp >> 24) & 0xff;
1148c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4);
1158c2ecf20Sopenharmony_ci	if (ret)
1168c2ecf20Sopenharmony_ci		goto err;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "clk=%u clk_cw=%08x\n", dev->cfg.clock, utmp);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/* ADC clk control */
1218c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
1228c2ecf20Sopenharmony_ci		if (clock_adc_lut[i].clock == dev->cfg.clock)
1238c2ecf20Sopenharmony_ci			break;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci	if (i == ARRAY_SIZE(clock_adc_lut)) {
1268c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Couldn't find ADC config for clock %d\n",
1278c2ecf20Sopenharmony_ci			dev->cfg.clock);
1288c2ecf20Sopenharmony_ci		goto err;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000);
1328c2ecf20Sopenharmony_ci	buf[0] = (utmp >>  0) & 0xff;
1338c2ecf20Sopenharmony_ci	buf[1] = (utmp >>  8) & 0xff;
1348c2ecf20Sopenharmony_ci	buf[2] = (utmp >> 16) & 0xff;
1358c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3);
1368c2ecf20Sopenharmony_ci	if (ret)
1378c2ecf20Sopenharmony_ci		goto err;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "adc=%u adc_cw=%06x\n",
1408c2ecf20Sopenharmony_ci		clock_adc_lut[i].adc, utmp);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* Config register table */
1438c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tab); i++) {
1448c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask,
1458c2ecf20Sopenharmony_ci					 tab[i].val);
1468c2ecf20Sopenharmony_ci		if (ret)
1478c2ecf20Sopenharmony_ci			goto err;
1488c2ecf20Sopenharmony_ci	}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/* Demod clk output */
1518c2ecf20Sopenharmony_ci	if (dev->cfg.dyn0_clk) {
1528c2ecf20Sopenharmony_ci		ret = regmap_write(dev->regmap, 0x80fba8, 0x00);
1538c2ecf20Sopenharmony_ci		if (ret)
1548c2ecf20Sopenharmony_ci			goto err;
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* TS interface */
1588c2ecf20Sopenharmony_ci	if (dev->cfg.ts_mode == AF9033_TS_MODE_USB) {
1598c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x80f9a5, 0x01, 0x00);
1608c2ecf20Sopenharmony_ci		if (ret)
1618c2ecf20Sopenharmony_ci			goto err;
1628c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x01);
1638c2ecf20Sopenharmony_ci		if (ret)
1648c2ecf20Sopenharmony_ci			goto err;
1658c2ecf20Sopenharmony_ci	} else {
1668c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x80f990, 0x01, 0x00);
1678c2ecf20Sopenharmony_ci		if (ret)
1688c2ecf20Sopenharmony_ci			goto err;
1698c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x80f9b5, 0x01, 0x00);
1708c2ecf20Sopenharmony_ci		if (ret)
1718c2ecf20Sopenharmony_ci			goto err;
1728c2ecf20Sopenharmony_ci	}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	/* Demod core settings */
1758c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "load ofsm settings\n");
1768c2ecf20Sopenharmony_ci	switch (dev->cfg.tuner) {
1778c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_38:
1788c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_51:
1798c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_52:
1808c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(ofsm_init_it9135_v1);
1818c2ecf20Sopenharmony_ci		init = ofsm_init_it9135_v1;
1828c2ecf20Sopenharmony_ci		break;
1838c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
1848c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
1858c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
1868c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(ofsm_init_it9135_v2);
1878c2ecf20Sopenharmony_ci		init = ofsm_init_it9135_v2;
1888c2ecf20Sopenharmony_ci		break;
1898c2ecf20Sopenharmony_ci	default:
1908c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(ofsm_init);
1918c2ecf20Sopenharmony_ci		init = ofsm_init;
1928c2ecf20Sopenharmony_ci		break;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	ret = af9033_wr_reg_val_tab(dev, init, len);
1968c2ecf20Sopenharmony_ci	if (ret)
1978c2ecf20Sopenharmony_ci		goto err;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* Demod tuner specific settings */
2008c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "load tuner specific settings\n");
2018c2ecf20Sopenharmony_ci	switch (dev->cfg.tuner) {
2028c2ecf20Sopenharmony_ci	case AF9033_TUNER_TUA9001:
2038c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_tua9001);
2048c2ecf20Sopenharmony_ci		init = tuner_init_tua9001;
2058c2ecf20Sopenharmony_ci		break;
2068c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC0011:
2078c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_fc0011);
2088c2ecf20Sopenharmony_ci		init = tuner_init_fc0011;
2098c2ecf20Sopenharmony_ci		break;
2108c2ecf20Sopenharmony_ci	case AF9033_TUNER_MXL5007T:
2118c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_mxl5007t);
2128c2ecf20Sopenharmony_ci		init = tuner_init_mxl5007t;
2138c2ecf20Sopenharmony_ci		break;
2148c2ecf20Sopenharmony_ci	case AF9033_TUNER_TDA18218:
2158c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_tda18218);
2168c2ecf20Sopenharmony_ci		init = tuner_init_tda18218;
2178c2ecf20Sopenharmony_ci		break;
2188c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC2580:
2198c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_fc2580);
2208c2ecf20Sopenharmony_ci		init = tuner_init_fc2580;
2218c2ecf20Sopenharmony_ci		break;
2228c2ecf20Sopenharmony_ci	case AF9033_TUNER_FC0012:
2238c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_fc0012);
2248c2ecf20Sopenharmony_ci		init = tuner_init_fc0012;
2258c2ecf20Sopenharmony_ci		break;
2268c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_38:
2278c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_38);
2288c2ecf20Sopenharmony_ci		init = tuner_init_it9135_38;
2298c2ecf20Sopenharmony_ci		break;
2308c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_51:
2318c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_51);
2328c2ecf20Sopenharmony_ci		init = tuner_init_it9135_51;
2338c2ecf20Sopenharmony_ci		break;
2348c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_52:
2358c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_52);
2368c2ecf20Sopenharmony_ci		init = tuner_init_it9135_52;
2378c2ecf20Sopenharmony_ci		break;
2388c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
2398c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_60);
2408c2ecf20Sopenharmony_ci		init = tuner_init_it9135_60;
2418c2ecf20Sopenharmony_ci		break;
2428c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
2438c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_61);
2448c2ecf20Sopenharmony_ci		init = tuner_init_it9135_61;
2458c2ecf20Sopenharmony_ci		break;
2468c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
2478c2ecf20Sopenharmony_ci		len = ARRAY_SIZE(tuner_init_it9135_62);
2488c2ecf20Sopenharmony_ci		init = tuner_init_it9135_62;
2498c2ecf20Sopenharmony_ci		break;
2508c2ecf20Sopenharmony_ci	default:
2518c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "unsupported tuner ID=%d\n",
2528c2ecf20Sopenharmony_ci			dev->cfg.tuner);
2538c2ecf20Sopenharmony_ci		ret = -ENODEV;
2548c2ecf20Sopenharmony_ci		goto err;
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	ret = af9033_wr_reg_val_tab(dev, init, len);
2588c2ecf20Sopenharmony_ci	if (ret)
2598c2ecf20Sopenharmony_ci		goto err;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
2628c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x00d91c, 0x01, 0x01);
2638c2ecf20Sopenharmony_ci		if (ret)
2648c2ecf20Sopenharmony_ci			goto err;
2658c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00);
2668c2ecf20Sopenharmony_ci		if (ret)
2678c2ecf20Sopenharmony_ci			goto err;
2688c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x00);
2698c2ecf20Sopenharmony_ci		if (ret)
2708c2ecf20Sopenharmony_ci			goto err;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	switch (dev->cfg.tuner) {
2748c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
2758c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
2768c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
2778c2ecf20Sopenharmony_ci		ret = regmap_write(dev->regmap, 0x800000, 0x01);
2788c2ecf20Sopenharmony_ci		if (ret)
2798c2ecf20Sopenharmony_ci			goto err;
2808c2ecf20Sopenharmony_ci	}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	dev->bandwidth_hz = 0; /* Force to program all parameters */
2838c2ecf20Sopenharmony_ci	/* Init stats here in order signal app which stats are supported */
2848c2ecf20Sopenharmony_ci	c->strength.len = 1;
2858c2ecf20Sopenharmony_ci	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2868c2ecf20Sopenharmony_ci	c->cnr.len = 1;
2878c2ecf20Sopenharmony_ci	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2888c2ecf20Sopenharmony_ci	c->block_count.len = 1;
2898c2ecf20Sopenharmony_ci	c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2908c2ecf20Sopenharmony_ci	c->block_error.len = 1;
2918c2ecf20Sopenharmony_ci	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2928c2ecf20Sopenharmony_ci	c->post_bit_count.len = 1;
2938c2ecf20Sopenharmony_ci	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2948c2ecf20Sopenharmony_ci	c->post_bit_error.len = 1;
2958c2ecf20Sopenharmony_ci	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return 0;
2988c2ecf20Sopenharmony_cierr:
2998c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
3008c2ecf20Sopenharmony_ci	return ret;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic int af9033_sleep(struct dvb_frontend *fe)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
3068c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
3078c2ecf20Sopenharmony_ci	int ret;
3088c2ecf20Sopenharmony_ci	unsigned int utmp;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x80004c, 0x01);
3138c2ecf20Sopenharmony_ci	if (ret)
3148c2ecf20Sopenharmony_ci		goto err;
3158c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x800000, 0x00);
3168c2ecf20Sopenharmony_ci	if (ret)
3178c2ecf20Sopenharmony_ci		goto err;
3188c2ecf20Sopenharmony_ci	ret = regmap_read_poll_timeout(dev->regmap, 0x80004c, utmp, utmp == 0,
3198c2ecf20Sopenharmony_ci				       5000, 1000000);
3208c2ecf20Sopenharmony_ci	if (ret)
3218c2ecf20Sopenharmony_ci		goto err;
3228c2ecf20Sopenharmony_ci	ret = regmap_update_bits(dev->regmap, 0x80fb24, 0x08, 0x08);
3238c2ecf20Sopenharmony_ci	if (ret)
3248c2ecf20Sopenharmony_ci		goto err;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* Prevent current leak by setting TS interface to parallel mode */
3278c2ecf20Sopenharmony_ci	if (dev->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
3288c2ecf20Sopenharmony_ci		/* Enable parallel TS */
3298c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x00d917, 0x01, 0x00);
3308c2ecf20Sopenharmony_ci		if (ret)
3318c2ecf20Sopenharmony_ci			goto err;
3328c2ecf20Sopenharmony_ci		ret = regmap_update_bits(dev->regmap, 0x00d916, 0x01, 0x01);
3338c2ecf20Sopenharmony_ci		if (ret)
3348c2ecf20Sopenharmony_ci			goto err;
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	return 0;
3388c2ecf20Sopenharmony_cierr:
3398c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
3408c2ecf20Sopenharmony_ci	return ret;
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic int af9033_get_tune_settings(struct dvb_frontend *fe,
3448c2ecf20Sopenharmony_ci				    struct dvb_frontend_tune_settings *fesettings)
3458c2ecf20Sopenharmony_ci{
3468c2ecf20Sopenharmony_ci	/* 800 => 2000 because IT9135 v2 is slow to gain lock */
3478c2ecf20Sopenharmony_ci	fesettings->min_delay_ms = 2000;
3488c2ecf20Sopenharmony_ci	fesettings->step_size = 0;
3498c2ecf20Sopenharmony_ci	fesettings->max_drift = 0;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic int af9033_set_frontend(struct dvb_frontend *fe)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
3578c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
3588c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
3598c2ecf20Sopenharmony_ci	int ret, i;
3608c2ecf20Sopenharmony_ci	unsigned int utmp, adc_freq;
3618c2ecf20Sopenharmony_ci	u8 tmp, buf[3], bandwidth_reg_val;
3628c2ecf20Sopenharmony_ci	u32 if_frequency;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u\n",
3658c2ecf20Sopenharmony_ci		c->frequency, c->bandwidth_hz);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	/* Check bandwidth */
3688c2ecf20Sopenharmony_ci	switch (c->bandwidth_hz) {
3698c2ecf20Sopenharmony_ci	case 6000000:
3708c2ecf20Sopenharmony_ci		bandwidth_reg_val = 0x00;
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	case 7000000:
3738c2ecf20Sopenharmony_ci		bandwidth_reg_val = 0x01;
3748c2ecf20Sopenharmony_ci		break;
3758c2ecf20Sopenharmony_ci	case 8000000:
3768c2ecf20Sopenharmony_ci		bandwidth_reg_val = 0x02;
3778c2ecf20Sopenharmony_ci		break;
3788c2ecf20Sopenharmony_ci	default:
3798c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "invalid bandwidth_hz\n");
3808c2ecf20Sopenharmony_ci		ret = -EINVAL;
3818c2ecf20Sopenharmony_ci		goto err;
3828c2ecf20Sopenharmony_ci	}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	/* Program tuner */
3858c2ecf20Sopenharmony_ci	if (fe->ops.tuner_ops.set_params)
3868c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.set_params(fe);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/* Coefficients */
3898c2ecf20Sopenharmony_ci	if (c->bandwidth_hz != dev->bandwidth_hz) {
3908c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
3918c2ecf20Sopenharmony_ci			if (coeff_lut[i].clock == dev->cfg.clock &&
3928c2ecf20Sopenharmony_ci			    coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
3938c2ecf20Sopenharmony_ci				break;
3948c2ecf20Sopenharmony_ci			}
3958c2ecf20Sopenharmony_ci		}
3968c2ecf20Sopenharmony_ci		if (i == ARRAY_SIZE(coeff_lut)) {
3978c2ecf20Sopenharmony_ci			dev_err(&client->dev,
3988c2ecf20Sopenharmony_ci				"Couldn't find config for clock %u\n",
3998c2ecf20Sopenharmony_ci				dev->cfg.clock);
4008c2ecf20Sopenharmony_ci			ret = -EINVAL;
4018c2ecf20Sopenharmony_ci			goto err;
4028c2ecf20Sopenharmony_ci		}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		ret = regmap_bulk_write(dev->regmap, 0x800001, coeff_lut[i].val,
4058c2ecf20Sopenharmony_ci					sizeof(coeff_lut[i].val));
4068c2ecf20Sopenharmony_ci		if (ret)
4078c2ecf20Sopenharmony_ci			goto err;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* IF frequency control */
4118c2ecf20Sopenharmony_ci	if (c->bandwidth_hz != dev->bandwidth_hz) {
4128c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
4138c2ecf20Sopenharmony_ci			if (clock_adc_lut[i].clock == dev->cfg.clock)
4148c2ecf20Sopenharmony_ci				break;
4158c2ecf20Sopenharmony_ci		}
4168c2ecf20Sopenharmony_ci		if (i == ARRAY_SIZE(clock_adc_lut)) {
4178c2ecf20Sopenharmony_ci			dev_err(&client->dev,
4188c2ecf20Sopenharmony_ci				"Couldn't find ADC clock for clock %u\n",
4198c2ecf20Sopenharmony_ci				dev->cfg.clock);
4208c2ecf20Sopenharmony_ci			ret = -EINVAL;
4218c2ecf20Sopenharmony_ci			goto err;
4228c2ecf20Sopenharmony_ci		}
4238c2ecf20Sopenharmony_ci		adc_freq = clock_adc_lut[i].adc;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci		if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
4268c2ecf20Sopenharmony_ci			adc_freq = 2 * adc_freq;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci		/* Get used IF frequency */
4298c2ecf20Sopenharmony_ci		if (fe->ops.tuner_ops.get_if_frequency)
4308c2ecf20Sopenharmony_ci			fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
4318c2ecf20Sopenharmony_ci		else
4328c2ecf20Sopenharmony_ci			if_frequency = 0;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci		utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000,
4358c2ecf20Sopenharmony_ci					     adc_freq);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		if (!dev->cfg.spec_inv && if_frequency)
4388c2ecf20Sopenharmony_ci			utmp = 0x800000 - utmp;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci		buf[0] = (utmp >>  0) & 0xff;
4418c2ecf20Sopenharmony_ci		buf[1] = (utmp >>  8) & 0xff;
4428c2ecf20Sopenharmony_ci		buf[2] = (utmp >> 16) & 0xff;
4438c2ecf20Sopenharmony_ci		ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3);
4448c2ecf20Sopenharmony_ci		if (ret)
4458c2ecf20Sopenharmony_ci			goto err;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "if_frequency_cw=%06x\n", utmp);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci		dev->bandwidth_hz = c->bandwidth_hz;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	ret = regmap_update_bits(dev->regmap, 0x80f904, 0x03,
4538c2ecf20Sopenharmony_ci				 bandwidth_reg_val);
4548c2ecf20Sopenharmony_ci	if (ret)
4558c2ecf20Sopenharmony_ci		goto err;
4568c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x800040, 0x00);
4578c2ecf20Sopenharmony_ci	if (ret)
4588c2ecf20Sopenharmony_ci		goto err;
4598c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x800047, 0x00);
4608c2ecf20Sopenharmony_ci	if (ret)
4618c2ecf20Sopenharmony_ci		goto err;
4628c2ecf20Sopenharmony_ci	ret = regmap_update_bits(dev->regmap, 0x80f999, 0x01, 0x00);
4638c2ecf20Sopenharmony_ci	if (ret)
4648c2ecf20Sopenharmony_ci		goto err;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (c->frequency <= 230000000)
4678c2ecf20Sopenharmony_ci		tmp = 0x00; /* VHF */
4688c2ecf20Sopenharmony_ci	else
4698c2ecf20Sopenharmony_ci		tmp = 0x01; /* UHF */
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x80004b, tmp);
4728c2ecf20Sopenharmony_ci	if (ret)
4738c2ecf20Sopenharmony_ci		goto err;
4748c2ecf20Sopenharmony_ci	/* Reset FSM */
4758c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x800000, 0x00);
4768c2ecf20Sopenharmony_ci	if (ret)
4778c2ecf20Sopenharmony_ci		goto err;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	return 0;
4808c2ecf20Sopenharmony_cierr:
4818c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
4828c2ecf20Sopenharmony_ci	return ret;
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic int af9033_get_frontend(struct dvb_frontend *fe,
4868c2ecf20Sopenharmony_ci			       struct dtv_frontend_properties *c)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
4898c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
4908c2ecf20Sopenharmony_ci	int ret;
4918c2ecf20Sopenharmony_ci	u8 buf[8];
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/* Read all needed TPS registers */
4968c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 8);
4978c2ecf20Sopenharmony_ci	if (ret)
4988c2ecf20Sopenharmony_ci		goto err;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	switch ((buf[0] >> 0) & 3) {
5018c2ecf20Sopenharmony_ci	case 0:
5028c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_2K;
5038c2ecf20Sopenharmony_ci		break;
5048c2ecf20Sopenharmony_ci	case 1:
5058c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_8K;
5068c2ecf20Sopenharmony_ci		break;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	switch ((buf[1] >> 0) & 3) {
5108c2ecf20Sopenharmony_ci	case 0:
5118c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_32;
5128c2ecf20Sopenharmony_ci		break;
5138c2ecf20Sopenharmony_ci	case 1:
5148c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_16;
5158c2ecf20Sopenharmony_ci		break;
5168c2ecf20Sopenharmony_ci	case 2:
5178c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_8;
5188c2ecf20Sopenharmony_ci		break;
5198c2ecf20Sopenharmony_ci	case 3:
5208c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_4;
5218c2ecf20Sopenharmony_ci		break;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	switch ((buf[2] >> 0) & 7) {
5258c2ecf20Sopenharmony_ci	case 0:
5268c2ecf20Sopenharmony_ci		c->hierarchy = HIERARCHY_NONE;
5278c2ecf20Sopenharmony_ci		break;
5288c2ecf20Sopenharmony_ci	case 1:
5298c2ecf20Sopenharmony_ci		c->hierarchy = HIERARCHY_1;
5308c2ecf20Sopenharmony_ci		break;
5318c2ecf20Sopenharmony_ci	case 2:
5328c2ecf20Sopenharmony_ci		c->hierarchy = HIERARCHY_2;
5338c2ecf20Sopenharmony_ci		break;
5348c2ecf20Sopenharmony_ci	case 3:
5358c2ecf20Sopenharmony_ci		c->hierarchy = HIERARCHY_4;
5368c2ecf20Sopenharmony_ci		break;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	switch ((buf[3] >> 0) & 3) {
5408c2ecf20Sopenharmony_ci	case 0:
5418c2ecf20Sopenharmony_ci		c->modulation = QPSK;
5428c2ecf20Sopenharmony_ci		break;
5438c2ecf20Sopenharmony_ci	case 1:
5448c2ecf20Sopenharmony_ci		c->modulation = QAM_16;
5458c2ecf20Sopenharmony_ci		break;
5468c2ecf20Sopenharmony_ci	case 2:
5478c2ecf20Sopenharmony_ci		c->modulation = QAM_64;
5488c2ecf20Sopenharmony_ci		break;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	switch ((buf[4] >> 0) & 3) {
5528c2ecf20Sopenharmony_ci	case 0:
5538c2ecf20Sopenharmony_ci		c->bandwidth_hz = 6000000;
5548c2ecf20Sopenharmony_ci		break;
5558c2ecf20Sopenharmony_ci	case 1:
5568c2ecf20Sopenharmony_ci		c->bandwidth_hz = 7000000;
5578c2ecf20Sopenharmony_ci		break;
5588c2ecf20Sopenharmony_ci	case 2:
5598c2ecf20Sopenharmony_ci		c->bandwidth_hz = 8000000;
5608c2ecf20Sopenharmony_ci		break;
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	switch ((buf[6] >> 0) & 7) {
5648c2ecf20Sopenharmony_ci	case 0:
5658c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_1_2;
5668c2ecf20Sopenharmony_ci		break;
5678c2ecf20Sopenharmony_ci	case 1:
5688c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_2_3;
5698c2ecf20Sopenharmony_ci		break;
5708c2ecf20Sopenharmony_ci	case 2:
5718c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_3_4;
5728c2ecf20Sopenharmony_ci		break;
5738c2ecf20Sopenharmony_ci	case 3:
5748c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_5_6;
5758c2ecf20Sopenharmony_ci		break;
5768c2ecf20Sopenharmony_ci	case 4:
5778c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_7_8;
5788c2ecf20Sopenharmony_ci		break;
5798c2ecf20Sopenharmony_ci	case 5:
5808c2ecf20Sopenharmony_ci		c->code_rate_HP = FEC_NONE;
5818c2ecf20Sopenharmony_ci		break;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	switch ((buf[7] >> 0) & 7) {
5858c2ecf20Sopenharmony_ci	case 0:
5868c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_1_2;
5878c2ecf20Sopenharmony_ci		break;
5888c2ecf20Sopenharmony_ci	case 1:
5898c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_2_3;
5908c2ecf20Sopenharmony_ci		break;
5918c2ecf20Sopenharmony_ci	case 2:
5928c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_3_4;
5938c2ecf20Sopenharmony_ci		break;
5948c2ecf20Sopenharmony_ci	case 3:
5958c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_5_6;
5968c2ecf20Sopenharmony_ci		break;
5978c2ecf20Sopenharmony_ci	case 4:
5988c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_7_8;
5998c2ecf20Sopenharmony_ci		break;
6008c2ecf20Sopenharmony_ci	case 5:
6018c2ecf20Sopenharmony_ci		c->code_rate_LP = FEC_NONE;
6028c2ecf20Sopenharmony_ci		break;
6038c2ecf20Sopenharmony_ci	}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	return 0;
6068c2ecf20Sopenharmony_cierr:
6078c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
6088c2ecf20Sopenharmony_ci	return ret;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic int af9033_read_status(struct dvb_frontend *fe, enum fe_status *status)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
6148c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
6158c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6168c2ecf20Sopenharmony_ci	int ret, tmp = 0;
6178c2ecf20Sopenharmony_ci	u8 buf[7];
6188c2ecf20Sopenharmony_ci	unsigned int utmp, utmp1;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	*status = 0;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	/* Radio channel status: 0=no result, 1=has signal, 2=no signal */
6258c2ecf20Sopenharmony_ci	ret = regmap_read(dev->regmap, 0x800047, &utmp);
6268c2ecf20Sopenharmony_ci	if (ret)
6278c2ecf20Sopenharmony_ci		goto err;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	/* Has signal */
6308c2ecf20Sopenharmony_ci	if (utmp == 0x01)
6318c2ecf20Sopenharmony_ci		*status |= FE_HAS_SIGNAL;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (utmp != 0x02) {
6348c2ecf20Sopenharmony_ci		/* TPS lock */
6358c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x80f5a9, &utmp);
6368c2ecf20Sopenharmony_ci		if (ret)
6378c2ecf20Sopenharmony_ci			goto err;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci		if ((utmp >> 0) & 0x01)
6408c2ecf20Sopenharmony_ci			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
6418c2ecf20Sopenharmony_ci					FE_HAS_VITERBI;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci		/* Full lock */
6448c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x80f999, &utmp);
6458c2ecf20Sopenharmony_ci		if (ret)
6468c2ecf20Sopenharmony_ci			goto err;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci		if ((utmp >> 0) & 0x01)
6498c2ecf20Sopenharmony_ci			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
6508c2ecf20Sopenharmony_ci					FE_HAS_VITERBI | FE_HAS_SYNC |
6518c2ecf20Sopenharmony_ci					FE_HAS_LOCK;
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	dev->fe_status = *status;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	/* Signal strength */
6578c2ecf20Sopenharmony_ci	if (dev->fe_status & FE_HAS_SIGNAL) {
6588c2ecf20Sopenharmony_ci		if (dev->is_af9035) {
6598c2ecf20Sopenharmony_ci			ret = regmap_read(dev->regmap, 0x80004a, &utmp);
6608c2ecf20Sopenharmony_ci			if (ret)
6618c2ecf20Sopenharmony_ci				goto err;
6628c2ecf20Sopenharmony_ci			tmp = -utmp * 1000;
6638c2ecf20Sopenharmony_ci		} else {
6648c2ecf20Sopenharmony_ci			ret = regmap_read(dev->regmap, 0x8000f7, &utmp);
6658c2ecf20Sopenharmony_ci			if (ret)
6668c2ecf20Sopenharmony_ci				goto err;
6678c2ecf20Sopenharmony_ci			tmp = (utmp - 100) * 1000;
6688c2ecf20Sopenharmony_ci		}
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci		c->strength.len = 1;
6718c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_DECIBEL;
6728c2ecf20Sopenharmony_ci		c->strength.stat[0].svalue = tmp;
6738c2ecf20Sopenharmony_ci	} else {
6748c2ecf20Sopenharmony_ci		c->strength.len = 1;
6758c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6768c2ecf20Sopenharmony_ci	}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	/* CNR */
6798c2ecf20Sopenharmony_ci	if (dev->fe_status & FE_HAS_VITERBI) {
6808c2ecf20Sopenharmony_ci		/* Read raw SNR value */
6818c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(dev->regmap, 0x80002c, buf, 3);
6828c2ecf20Sopenharmony_ci		if (ret)
6838c2ecf20Sopenharmony_ci			goto err;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci		utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci		/* Read superframe number */
6888c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x80f78b, &utmp);
6898c2ecf20Sopenharmony_ci		if (ret)
6908c2ecf20Sopenharmony_ci			goto err;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci		if (utmp)
6938c2ecf20Sopenharmony_ci			utmp1 /= utmp;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci		/* Read current transmission mode */
6968c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x80f900, &utmp);
6978c2ecf20Sopenharmony_ci		if (ret)
6988c2ecf20Sopenharmony_ci			goto err;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci		switch ((utmp >> 0) & 3) {
7018c2ecf20Sopenharmony_ci		case 0:
7028c2ecf20Sopenharmony_ci			/* 2k */
7038c2ecf20Sopenharmony_ci			utmp1 *= 4;
7048c2ecf20Sopenharmony_ci			break;
7058c2ecf20Sopenharmony_ci		case 1:
7068c2ecf20Sopenharmony_ci			/* 8k */
7078c2ecf20Sopenharmony_ci			utmp1 *= 1;
7088c2ecf20Sopenharmony_ci			break;
7098c2ecf20Sopenharmony_ci		case 2:
7108c2ecf20Sopenharmony_ci			/* 4k */
7118c2ecf20Sopenharmony_ci			utmp1 *= 2;
7128c2ecf20Sopenharmony_ci			break;
7138c2ecf20Sopenharmony_ci		default:
7148c2ecf20Sopenharmony_ci			utmp1 *= 0;
7158c2ecf20Sopenharmony_ci			break;
7168c2ecf20Sopenharmony_ci		}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci		/* Read current modulation */
7198c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x80f903, &utmp);
7208c2ecf20Sopenharmony_ci		if (ret)
7218c2ecf20Sopenharmony_ci			goto err;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci		switch ((utmp >> 0) & 3) {
7248c2ecf20Sopenharmony_ci		case 0:
7258c2ecf20Sopenharmony_ci			/*
7268c2ecf20Sopenharmony_ci			 * QPSK
7278c2ecf20Sopenharmony_ci			 * CNR[dB] 13 * -log10((1690000 - value) / value) + 2.6
7288c2ecf20Sopenharmony_ci			 * value [653799, 1689999], 2.6 / 13 = 3355443
7298c2ecf20Sopenharmony_ci			 */
7308c2ecf20Sopenharmony_ci			utmp1 = clamp(utmp1, 653799U, 1689999U);
7318c2ecf20Sopenharmony_ci			utmp1 = ((u64)(intlog10(utmp1)
7328c2ecf20Sopenharmony_ci				 - intlog10(1690000 - utmp1)
7338c2ecf20Sopenharmony_ci				 + 3355443) * 13 * 1000) >> 24;
7348c2ecf20Sopenharmony_ci			break;
7358c2ecf20Sopenharmony_ci		case 1:
7368c2ecf20Sopenharmony_ci			/*
7378c2ecf20Sopenharmony_ci			 * QAM-16
7388c2ecf20Sopenharmony_ci			 * CNR[dB] 6 * log10((value - 370000) / (828000 - value)) + 15.7
7398c2ecf20Sopenharmony_ci			 * value [371105, 827999], 15.7 / 6 = 43900382
7408c2ecf20Sopenharmony_ci			 */
7418c2ecf20Sopenharmony_ci			utmp1 = clamp(utmp1, 371105U, 827999U);
7428c2ecf20Sopenharmony_ci			utmp1 = ((u64)(intlog10(utmp1 - 370000)
7438c2ecf20Sopenharmony_ci				 - intlog10(828000 - utmp1)
7448c2ecf20Sopenharmony_ci				 + 43900382) * 6 * 1000) >> 24;
7458c2ecf20Sopenharmony_ci			break;
7468c2ecf20Sopenharmony_ci		case 2:
7478c2ecf20Sopenharmony_ci			/*
7488c2ecf20Sopenharmony_ci			 * QAM-64
7498c2ecf20Sopenharmony_ci			 * CNR[dB] 8 * log10((value - 193000) / (425000 - value)) + 23.8
7508c2ecf20Sopenharmony_ci			 * value [193246, 424999], 23.8 / 8 = 49912218
7518c2ecf20Sopenharmony_ci			 */
7528c2ecf20Sopenharmony_ci			utmp1 = clamp(utmp1, 193246U, 424999U);
7538c2ecf20Sopenharmony_ci			utmp1 = ((u64)(intlog10(utmp1 - 193000)
7548c2ecf20Sopenharmony_ci				 - intlog10(425000 - utmp1)
7558c2ecf20Sopenharmony_ci				 + 49912218) * 8 * 1000) >> 24;
7568c2ecf20Sopenharmony_ci			break;
7578c2ecf20Sopenharmony_ci		default:
7588c2ecf20Sopenharmony_ci			utmp1 = 0;
7598c2ecf20Sopenharmony_ci			break;
7608c2ecf20Sopenharmony_ci		}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "cnr=%u\n", utmp1);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
7658c2ecf20Sopenharmony_ci		c->cnr.stat[0].svalue = utmp1;
7668c2ecf20Sopenharmony_ci	} else {
7678c2ecf20Sopenharmony_ci		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	/* UCB/PER/BER */
7718c2ecf20Sopenharmony_ci	if (dev->fe_status & FE_HAS_LOCK) {
7728c2ecf20Sopenharmony_ci		/* Outer FEC, 204 byte packets */
7738c2ecf20Sopenharmony_ci		u16 abort_packet_count, rsd_packet_count;
7748c2ecf20Sopenharmony_ci		/* Inner FEC, bits */
7758c2ecf20Sopenharmony_ci		u32 rsd_bit_err_count;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci		/*
7788c2ecf20Sopenharmony_ci		 * Packet count used for measurement is 10000
7798c2ecf20Sopenharmony_ci		 * (rsd_packet_count). Maybe it should be increased?
7808c2ecf20Sopenharmony_ci		 */
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(dev->regmap, 0x800032, buf, 7);
7838c2ecf20Sopenharmony_ci		if (ret)
7848c2ecf20Sopenharmony_ci			goto err;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci		abort_packet_count = (buf[1] << 8) | (buf[0] << 0);
7878c2ecf20Sopenharmony_ci		rsd_bit_err_count = (buf[4] << 16) | (buf[3] << 8) | buf[2];
7888c2ecf20Sopenharmony_ci		rsd_packet_count = (buf[6] << 8) | (buf[5] << 0);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci		dev->error_block_count += abort_packet_count;
7918c2ecf20Sopenharmony_ci		dev->total_block_count += rsd_packet_count;
7928c2ecf20Sopenharmony_ci		dev->post_bit_error += rsd_bit_err_count;
7938c2ecf20Sopenharmony_ci		dev->post_bit_count += rsd_packet_count * 204 * 8;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		c->block_count.len = 1;
7968c2ecf20Sopenharmony_ci		c->block_count.stat[0].scale = FE_SCALE_COUNTER;
7978c2ecf20Sopenharmony_ci		c->block_count.stat[0].uvalue = dev->total_block_count;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci		c->block_error.len = 1;
8008c2ecf20Sopenharmony_ci		c->block_error.stat[0].scale = FE_SCALE_COUNTER;
8018c2ecf20Sopenharmony_ci		c->block_error.stat[0].uvalue = dev->error_block_count;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci		c->post_bit_count.len = 1;
8048c2ecf20Sopenharmony_ci		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
8058c2ecf20Sopenharmony_ci		c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci		c->post_bit_error.len = 1;
8088c2ecf20Sopenharmony_ci		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
8098c2ecf20Sopenharmony_ci		c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
8108c2ecf20Sopenharmony_ci	}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	return 0;
8138c2ecf20Sopenharmony_cierr:
8148c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
8158c2ecf20Sopenharmony_ci	return ret;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_cistatic int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
8218c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
8228c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
8238c2ecf20Sopenharmony_ci	int ret;
8248c2ecf20Sopenharmony_ci	unsigned int utmp;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	/* Use DVBv5 CNR */
8298c2ecf20Sopenharmony_ci	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) {
8308c2ecf20Sopenharmony_ci		/* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */
8318c2ecf20Sopenharmony_ci		if (dev->is_af9035) {
8328c2ecf20Sopenharmony_ci			/* 1000x => 10x (0.1 dB) */
8338c2ecf20Sopenharmony_ci			*snr = div_s64(c->cnr.stat[0].svalue, 100);
8348c2ecf20Sopenharmony_ci		} else {
8358c2ecf20Sopenharmony_ci			/* 1000x => 1x (1 dB) */
8368c2ecf20Sopenharmony_ci			*snr = div_s64(c->cnr.stat[0].svalue, 1000);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci			/* Read current modulation */
8398c2ecf20Sopenharmony_ci			ret = regmap_read(dev->regmap, 0x80f903, &utmp);
8408c2ecf20Sopenharmony_ci			if (ret)
8418c2ecf20Sopenharmony_ci				goto err;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci			/* scale value to 0x0000-0xffff */
8448c2ecf20Sopenharmony_ci			switch ((utmp >> 0) & 3) {
8458c2ecf20Sopenharmony_ci			case 0:
8468c2ecf20Sopenharmony_ci				*snr = *snr * 0xffff / 23;
8478c2ecf20Sopenharmony_ci				break;
8488c2ecf20Sopenharmony_ci			case 1:
8498c2ecf20Sopenharmony_ci				*snr = *snr * 0xffff / 26;
8508c2ecf20Sopenharmony_ci				break;
8518c2ecf20Sopenharmony_ci			case 2:
8528c2ecf20Sopenharmony_ci				*snr = *snr * 0xffff / 32;
8538c2ecf20Sopenharmony_ci				break;
8548c2ecf20Sopenharmony_ci			default:
8558c2ecf20Sopenharmony_ci				goto err;
8568c2ecf20Sopenharmony_ci			}
8578c2ecf20Sopenharmony_ci		}
8588c2ecf20Sopenharmony_ci	} else {
8598c2ecf20Sopenharmony_ci		*snr = 0;
8608c2ecf20Sopenharmony_ci	}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	return 0;
8638c2ecf20Sopenharmony_cierr:
8648c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
8658c2ecf20Sopenharmony_ci	return ret;
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_cistatic int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
8718c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
8728c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
8738c2ecf20Sopenharmony_ci	int ret, tmp, power_real;
8748c2ecf20Sopenharmony_ci	unsigned int utmp;
8758c2ecf20Sopenharmony_ci	u8 gain_offset, buf[7];
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	if (dev->is_af9035) {
8808c2ecf20Sopenharmony_ci		/* Read signal strength of 0-100 scale */
8818c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x800048, &utmp);
8828c2ecf20Sopenharmony_ci		if (ret)
8838c2ecf20Sopenharmony_ci			goto err;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		/* Scale value to 0x0000-0xffff */
8868c2ecf20Sopenharmony_ci		*strength = utmp * 0xffff / 100;
8878c2ecf20Sopenharmony_ci	} else {
8888c2ecf20Sopenharmony_ci		ret = regmap_read(dev->regmap, 0x8000f7, &utmp);
8898c2ecf20Sopenharmony_ci		if (ret)
8908c2ecf20Sopenharmony_ci			goto err;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(dev->regmap, 0x80f900, buf, 7);
8938c2ecf20Sopenharmony_ci		if (ret)
8948c2ecf20Sopenharmony_ci			goto err;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci		if (c->frequency <= 300000000)
8978c2ecf20Sopenharmony_ci			gain_offset = 7; /* VHF */
8988c2ecf20Sopenharmony_ci		else
8998c2ecf20Sopenharmony_ci			gain_offset = 4; /* UHF */
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci		power_real = (utmp - 100 - gain_offset) -
9028c2ecf20Sopenharmony_ci			power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)];
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci		if (power_real < -15)
9058c2ecf20Sopenharmony_ci			tmp = 0;
9068c2ecf20Sopenharmony_ci		else if ((power_real >= -15) && (power_real < 0))
9078c2ecf20Sopenharmony_ci			tmp = (2 * (power_real + 15)) / 3;
9088c2ecf20Sopenharmony_ci		else if ((power_real >= 0) && (power_real < 20))
9098c2ecf20Sopenharmony_ci			tmp = 4 * power_real + 10;
9108c2ecf20Sopenharmony_ci		else if ((power_real >= 20) && (power_real < 35))
9118c2ecf20Sopenharmony_ci			tmp = (2 * (power_real - 20)) / 3 + 90;
9128c2ecf20Sopenharmony_ci		else
9138c2ecf20Sopenharmony_ci			tmp = 100;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci		/* Scale value to 0x0000-0xffff */
9168c2ecf20Sopenharmony_ci		*strength = tmp * 0xffff / 100;
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	return 0;
9208c2ecf20Sopenharmony_cierr:
9218c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
9228c2ecf20Sopenharmony_ci	return ret;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic int af9033_read_ber(struct dvb_frontend *fe, u32 *ber)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	*ber = (dev->post_bit_error - dev->post_bit_error_prev);
9308c2ecf20Sopenharmony_ci	dev->post_bit_error_prev = dev->post_bit_error;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	return 0;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	*ucblocks = dev->error_block_count;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	return 0;
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_cistatic int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
9478c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
9488c2ecf20Sopenharmony_ci	int ret;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "enable=%d\n", enable);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	ret = regmap_update_bits(dev->regmap, 0x00fa04, 0x01, enable);
9538c2ecf20Sopenharmony_ci	if (ret)
9548c2ecf20Sopenharmony_ci		goto err;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	return 0;
9578c2ecf20Sopenharmony_cierr:
9588c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
9598c2ecf20Sopenharmony_ci	return ret;
9608c2ecf20Sopenharmony_ci}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_cistatic int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
9658c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
9668c2ecf20Sopenharmony_ci	int ret;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "onoff=%d\n", onoff);
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	ret = regmap_update_bits(dev->regmap, 0x80f993, 0x01, onoff);
9718c2ecf20Sopenharmony_ci	if (ret)
9728c2ecf20Sopenharmony_ci		goto err;
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	return 0;
9758c2ecf20Sopenharmony_cierr:
9768c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
9778c2ecf20Sopenharmony_ci	return ret;
9788c2ecf20Sopenharmony_ci}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_cistatic int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid,
9818c2ecf20Sopenharmony_ci			     int onoff)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	struct af9033_dev *dev = fe->demodulator_priv;
9848c2ecf20Sopenharmony_ci	struct i2c_client *client = dev->client;
9858c2ecf20Sopenharmony_ci	int ret;
9868c2ecf20Sopenharmony_ci	u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff};
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n",
9898c2ecf20Sopenharmony_ci		index, pid, onoff);
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	if (pid > 0x1fff)
9928c2ecf20Sopenharmony_ci		return 0;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(dev->regmap, 0x80f996, wbuf, 2);
9958c2ecf20Sopenharmony_ci	if (ret)
9968c2ecf20Sopenharmony_ci		goto err;
9978c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x80f994, onoff);
9988c2ecf20Sopenharmony_ci	if (ret)
9998c2ecf20Sopenharmony_ci		goto err;
10008c2ecf20Sopenharmony_ci	ret = regmap_write(dev->regmap, 0x80f995, index);
10018c2ecf20Sopenharmony_ci	if (ret)
10028c2ecf20Sopenharmony_ci		goto err;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	return 0;
10058c2ecf20Sopenharmony_cierr:
10068c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
10078c2ecf20Sopenharmony_ci	return ret;
10088c2ecf20Sopenharmony_ci}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops af9033_ops = {
10118c2ecf20Sopenharmony_ci	.delsys = {SYS_DVBT},
10128c2ecf20Sopenharmony_ci	.info = {
10138c2ecf20Sopenharmony_ci		.name = "Afatech AF9033 (DVB-T)",
10148c2ecf20Sopenharmony_ci		.frequency_min_hz = 174 * MHz,
10158c2ecf20Sopenharmony_ci		.frequency_max_hz = 862 * MHz,
10168c2ecf20Sopenharmony_ci		.frequency_stepsize_hz = 250 * kHz,
10178c2ecf20Sopenharmony_ci		.caps =	FE_CAN_FEC_1_2 |
10188c2ecf20Sopenharmony_ci			FE_CAN_FEC_2_3 |
10198c2ecf20Sopenharmony_ci			FE_CAN_FEC_3_4 |
10208c2ecf20Sopenharmony_ci			FE_CAN_FEC_5_6 |
10218c2ecf20Sopenharmony_ci			FE_CAN_FEC_7_8 |
10228c2ecf20Sopenharmony_ci			FE_CAN_FEC_AUTO |
10238c2ecf20Sopenharmony_ci			FE_CAN_QPSK |
10248c2ecf20Sopenharmony_ci			FE_CAN_QAM_16 |
10258c2ecf20Sopenharmony_ci			FE_CAN_QAM_64 |
10268c2ecf20Sopenharmony_ci			FE_CAN_QAM_AUTO |
10278c2ecf20Sopenharmony_ci			FE_CAN_TRANSMISSION_MODE_AUTO |
10288c2ecf20Sopenharmony_ci			FE_CAN_GUARD_INTERVAL_AUTO |
10298c2ecf20Sopenharmony_ci			FE_CAN_HIERARCHY_AUTO |
10308c2ecf20Sopenharmony_ci			FE_CAN_RECOVER |
10318c2ecf20Sopenharmony_ci			FE_CAN_MUTE_TS
10328c2ecf20Sopenharmony_ci	},
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	.init = af9033_init,
10358c2ecf20Sopenharmony_ci	.sleep = af9033_sleep,
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	.get_tune_settings = af9033_get_tune_settings,
10388c2ecf20Sopenharmony_ci	.set_frontend = af9033_set_frontend,
10398c2ecf20Sopenharmony_ci	.get_frontend = af9033_get_frontend,
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	.read_status = af9033_read_status,
10428c2ecf20Sopenharmony_ci	.read_snr = af9033_read_snr,
10438c2ecf20Sopenharmony_ci	.read_signal_strength = af9033_read_signal_strength,
10448c2ecf20Sopenharmony_ci	.read_ber = af9033_read_ber,
10458c2ecf20Sopenharmony_ci	.read_ucblocks = af9033_read_ucblocks,
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	.i2c_gate_ctrl = af9033_i2c_gate_ctrl,
10488c2ecf20Sopenharmony_ci};
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_cistatic int af9033_probe(struct i2c_client *client,
10518c2ecf20Sopenharmony_ci			const struct i2c_device_id *id)
10528c2ecf20Sopenharmony_ci{
10538c2ecf20Sopenharmony_ci	struct af9033_config *cfg = client->dev.platform_data;
10548c2ecf20Sopenharmony_ci	struct af9033_dev *dev;
10558c2ecf20Sopenharmony_ci	int ret;
10568c2ecf20Sopenharmony_ci	u8 buf[8];
10578c2ecf20Sopenharmony_ci	u32 reg;
10588c2ecf20Sopenharmony_ci	static const struct regmap_config regmap_config = {
10598c2ecf20Sopenharmony_ci		.reg_bits    =  24,
10608c2ecf20Sopenharmony_ci		.val_bits    =  8,
10618c2ecf20Sopenharmony_ci	};
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	/* Allocate memory for the internal state */
10648c2ecf20Sopenharmony_ci	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
10658c2ecf20Sopenharmony_ci	if (!dev) {
10668c2ecf20Sopenharmony_ci		ret = -ENOMEM;
10678c2ecf20Sopenharmony_ci		goto err;
10688c2ecf20Sopenharmony_ci	}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	/* Setup the state */
10718c2ecf20Sopenharmony_ci	dev->client = client;
10728c2ecf20Sopenharmony_ci	memcpy(&dev->cfg, cfg, sizeof(dev->cfg));
10738c2ecf20Sopenharmony_ci	switch (dev->cfg.ts_mode) {
10748c2ecf20Sopenharmony_ci	case AF9033_TS_MODE_PARALLEL:
10758c2ecf20Sopenharmony_ci		dev->ts_mode_parallel = true;
10768c2ecf20Sopenharmony_ci		break;
10778c2ecf20Sopenharmony_ci	case AF9033_TS_MODE_SERIAL:
10788c2ecf20Sopenharmony_ci		dev->ts_mode_serial = true;
10798c2ecf20Sopenharmony_ci		break;
10808c2ecf20Sopenharmony_ci	case AF9033_TS_MODE_USB:
10818c2ecf20Sopenharmony_ci		/* USB mode for AF9035 */
10828c2ecf20Sopenharmony_ci	default:
10838c2ecf20Sopenharmony_ci		break;
10848c2ecf20Sopenharmony_ci	}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	if (dev->cfg.clock != 12000000) {
10878c2ecf20Sopenharmony_ci		ret = -ENODEV;
10888c2ecf20Sopenharmony_ci		dev_err(&client->dev,
10898c2ecf20Sopenharmony_ci			"Unsupported clock %u Hz. Only 12000000 Hz is supported currently\n",
10908c2ecf20Sopenharmony_ci			dev->cfg.clock);
10918c2ecf20Sopenharmony_ci		goto err_kfree;
10928c2ecf20Sopenharmony_ci	}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	/* Create regmap */
10958c2ecf20Sopenharmony_ci	dev->regmap = regmap_init_i2c(client, &regmap_config);
10968c2ecf20Sopenharmony_ci	if (IS_ERR(dev->regmap)) {
10978c2ecf20Sopenharmony_ci		ret = PTR_ERR(dev->regmap);
10988c2ecf20Sopenharmony_ci		goto err_kfree;
10998c2ecf20Sopenharmony_ci	}
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	/* Firmware version */
11028c2ecf20Sopenharmony_ci	switch (dev->cfg.tuner) {
11038c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_38:
11048c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_51:
11058c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_52:
11068c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_60:
11078c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_61:
11088c2ecf20Sopenharmony_ci	case AF9033_TUNER_IT9135_62:
11098c2ecf20Sopenharmony_ci		dev->is_it9135 = true;
11108c2ecf20Sopenharmony_ci		reg = 0x004bfc;
11118c2ecf20Sopenharmony_ci		break;
11128c2ecf20Sopenharmony_ci	default:
11138c2ecf20Sopenharmony_ci		dev->is_af9035 = true;
11148c2ecf20Sopenharmony_ci		reg = 0x0083e9;
11158c2ecf20Sopenharmony_ci		break;
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(dev->regmap, reg, &buf[0], 4);
11198c2ecf20Sopenharmony_ci	if (ret)
11208c2ecf20Sopenharmony_ci		goto err_regmap_exit;
11218c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(dev->regmap, 0x804191, &buf[4], 4);
11228c2ecf20Sopenharmony_ci	if (ret)
11238c2ecf20Sopenharmony_ci		goto err_regmap_exit;
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	dev_info(&client->dev,
11268c2ecf20Sopenharmony_ci		 "firmware version: LINK %d.%d.%d.%d - OFDM %d.%d.%d.%d\n",
11278c2ecf20Sopenharmony_ci		 buf[0], buf[1], buf[2], buf[3],
11288c2ecf20Sopenharmony_ci		 buf[4], buf[5], buf[6], buf[7]);
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	/* Sleep as chip seems to be partly active by default */
11318c2ecf20Sopenharmony_ci	/* IT9135 did not like to sleep at that early */
11328c2ecf20Sopenharmony_ci	if (dev->is_af9035) {
11338c2ecf20Sopenharmony_ci		ret = regmap_write(dev->regmap, 0x80004c, 0x01);
11348c2ecf20Sopenharmony_ci		if (ret)
11358c2ecf20Sopenharmony_ci			goto err_regmap_exit;
11368c2ecf20Sopenharmony_ci		ret = regmap_write(dev->regmap, 0x800000, 0x00);
11378c2ecf20Sopenharmony_ci		if (ret)
11388c2ecf20Sopenharmony_ci			goto err_regmap_exit;
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	/* Create dvb frontend */
11428c2ecf20Sopenharmony_ci	memcpy(&dev->fe.ops, &af9033_ops, sizeof(dev->fe.ops));
11438c2ecf20Sopenharmony_ci	dev->fe.demodulator_priv = dev;
11448c2ecf20Sopenharmony_ci	*cfg->fe = &dev->fe;
11458c2ecf20Sopenharmony_ci	if (cfg->ops) {
11468c2ecf20Sopenharmony_ci		cfg->ops->pid_filter = af9033_pid_filter;
11478c2ecf20Sopenharmony_ci		cfg->ops->pid_filter_ctrl = af9033_pid_filter_ctrl;
11488c2ecf20Sopenharmony_ci	}
11498c2ecf20Sopenharmony_ci	cfg->regmap = dev->regmap;
11508c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, dev);
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci	dev_info(&client->dev, "Afatech AF9033 successfully attached\n");
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	return 0;
11558c2ecf20Sopenharmony_cierr_regmap_exit:
11568c2ecf20Sopenharmony_ci	regmap_exit(dev->regmap);
11578c2ecf20Sopenharmony_cierr_kfree:
11588c2ecf20Sopenharmony_ci	kfree(dev);
11598c2ecf20Sopenharmony_cierr:
11608c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
11618c2ecf20Sopenharmony_ci	return ret;
11628c2ecf20Sopenharmony_ci}
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_cistatic int af9033_remove(struct i2c_client *client)
11658c2ecf20Sopenharmony_ci{
11668c2ecf20Sopenharmony_ci	struct af9033_dev *dev = i2c_get_clientdata(client);
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	regmap_exit(dev->regmap);
11718c2ecf20Sopenharmony_ci	kfree(dev);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	return 0;
11748c2ecf20Sopenharmony_ci}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic const struct i2c_device_id af9033_id_table[] = {
11778c2ecf20Sopenharmony_ci	{"af9033", 0},
11788c2ecf20Sopenharmony_ci	{}
11798c2ecf20Sopenharmony_ci};
11808c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, af9033_id_table);
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_cistatic struct i2c_driver af9033_driver = {
11838c2ecf20Sopenharmony_ci	.driver = {
11848c2ecf20Sopenharmony_ci		.name	= "af9033",
11858c2ecf20Sopenharmony_ci		.suppress_bind_attrs	= true,
11868c2ecf20Sopenharmony_ci	},
11878c2ecf20Sopenharmony_ci	.probe		= af9033_probe,
11888c2ecf20Sopenharmony_ci	.remove		= af9033_remove,
11898c2ecf20Sopenharmony_ci	.id_table	= af9033_id_table,
11908c2ecf20Sopenharmony_ci};
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_cimodule_i2c_driver(af9033_driver);
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ciMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
11958c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver");
11968c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1197