18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Sony CXD2820R demodulator driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "cxd2820r_priv.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciint cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct cxd2820r_priv *priv = fe->demodulator_priv;
148c2ecf20Sopenharmony_ci	struct i2c_client *client = priv->client[0];
158c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
168c2ecf20Sopenharmony_ci	int ret, bw_i;
178c2ecf20Sopenharmony_ci	unsigned int utmp;
188c2ecf20Sopenharmony_ci	u32 if_frequency;
198c2ecf20Sopenharmony_ci	u8 buf[3], bw_param;
208c2ecf20Sopenharmony_ci	u8 bw_params1[][5] = {
218c2ecf20Sopenharmony_ci		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
228c2ecf20Sopenharmony_ci		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
238c2ecf20Sopenharmony_ci		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
248c2ecf20Sopenharmony_ci		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
258c2ecf20Sopenharmony_ci	};
268c2ecf20Sopenharmony_ci	struct reg_val_mask tab[] = {
278c2ecf20Sopenharmony_ci		{ 0x00080, 0x02, 0xff },
288c2ecf20Sopenharmony_ci		{ 0x00081, 0x20, 0xff },
298c2ecf20Sopenharmony_ci		{ 0x00085, 0x07, 0xff },
308c2ecf20Sopenharmony_ci		{ 0x00088, 0x01, 0xff },
318c2ecf20Sopenharmony_ci		{ 0x02069, 0x01, 0xff },
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci		{ 0x0207f, 0x2a, 0xff },
348c2ecf20Sopenharmony_ci		{ 0x02082, 0x0a, 0xff },
358c2ecf20Sopenharmony_ci		{ 0x02083, 0x0a, 0xff },
368c2ecf20Sopenharmony_ci		{ 0x020cb, priv->if_agc_polarity << 6, 0x40 },
378c2ecf20Sopenharmony_ci		{ 0x02070, priv->ts_mode, 0xff },
388c2ecf20Sopenharmony_ci		{ 0x02071, !priv->ts_clk_inv << 6, 0x40 },
398c2ecf20Sopenharmony_ci		{ 0x020b5, priv->spec_inv << 4, 0x10 },
408c2ecf20Sopenharmony_ci		{ 0x02567, 0x07, 0x0f },
418c2ecf20Sopenharmony_ci		{ 0x02569, 0x03, 0x03 },
428c2ecf20Sopenharmony_ci		{ 0x02595, 0x1a, 0xff },
438c2ecf20Sopenharmony_ci		{ 0x02596, 0x50, 0xff },
448c2ecf20Sopenharmony_ci		{ 0x02a8c, 0x00, 0xff },
458c2ecf20Sopenharmony_ci		{ 0x02a8d, 0x34, 0xff },
468c2ecf20Sopenharmony_ci		{ 0x02a45, 0x06, 0x07 },
478c2ecf20Sopenharmony_ci		{ 0x03f10, 0x0d, 0xff },
488c2ecf20Sopenharmony_ci		{ 0x03f11, 0x02, 0xff },
498c2ecf20Sopenharmony_ci		{ 0x03f12, 0x01, 0xff },
508c2ecf20Sopenharmony_ci		{ 0x03f23, 0x2c, 0xff },
518c2ecf20Sopenharmony_ci		{ 0x03f51, 0x13, 0xff },
528c2ecf20Sopenharmony_ci		{ 0x03f52, 0x01, 0xff },
538c2ecf20Sopenharmony_ci		{ 0x03f53, 0x00, 0xff },
548c2ecf20Sopenharmony_ci		{ 0x027e6, 0x14, 0xff },
558c2ecf20Sopenharmony_ci		{ 0x02786, 0x02, 0x07 },
568c2ecf20Sopenharmony_ci		{ 0x02787, 0x40, 0xe0 },
578c2ecf20Sopenharmony_ci		{ 0x027ef, 0x10, 0x18 },
588c2ecf20Sopenharmony_ci	};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	dev_dbg(&client->dev,
618c2ecf20Sopenharmony_ci		"delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d stream_id=%u\n",
628c2ecf20Sopenharmony_ci		c->delivery_system, c->modulation, c->frequency,
638c2ecf20Sopenharmony_ci		c->bandwidth_hz, c->inversion, c->stream_id);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	switch (c->bandwidth_hz) {
668c2ecf20Sopenharmony_ci	case 5000000:
678c2ecf20Sopenharmony_ci		bw_i = 0;
688c2ecf20Sopenharmony_ci		bw_param = 3;
698c2ecf20Sopenharmony_ci		break;
708c2ecf20Sopenharmony_ci	case 6000000:
718c2ecf20Sopenharmony_ci		bw_i = 1;
728c2ecf20Sopenharmony_ci		bw_param = 2;
738c2ecf20Sopenharmony_ci		break;
748c2ecf20Sopenharmony_ci	case 7000000:
758c2ecf20Sopenharmony_ci		bw_i = 2;
768c2ecf20Sopenharmony_ci		bw_param = 1;
778c2ecf20Sopenharmony_ci		break;
788c2ecf20Sopenharmony_ci	case 8000000:
798c2ecf20Sopenharmony_ci		bw_i = 3;
808c2ecf20Sopenharmony_ci		bw_param = 0;
818c2ecf20Sopenharmony_ci		break;
828c2ecf20Sopenharmony_ci	default:
838c2ecf20Sopenharmony_ci		return -EINVAL;
848c2ecf20Sopenharmony_ci	}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* program tuner */
878c2ecf20Sopenharmony_ci	if (fe->ops.tuner_ops.set_params)
888c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.set_params(fe);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (priv->delivery_system != SYS_DVBT2) {
918c2ecf20Sopenharmony_ci		ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
928c2ecf20Sopenharmony_ci		if (ret)
938c2ecf20Sopenharmony_ci			goto error;
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	priv->delivery_system = SYS_DVBT2;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/* program IF frequency */
998c2ecf20Sopenharmony_ci	if (fe->ops.tuner_ops.get_if_frequency) {
1008c2ecf20Sopenharmony_ci		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
1018c2ecf20Sopenharmony_ci		if (ret)
1028c2ecf20Sopenharmony_ci			goto error;
1038c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
1048c2ecf20Sopenharmony_ci	} else {
1058c2ecf20Sopenharmony_ci		ret = -EINVAL;
1068c2ecf20Sopenharmony_ci		goto error;
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
1108c2ecf20Sopenharmony_ci	buf[0] = (utmp >> 16) & 0xff;
1118c2ecf20Sopenharmony_ci	buf[1] = (utmp >>  8) & 0xff;
1128c2ecf20Sopenharmony_ci	buf[2] = (utmp >>  0) & 0xff;
1138c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(priv->regmap[0], 0x20b6, buf, 3);
1148c2ecf20Sopenharmony_ci	if (ret)
1158c2ecf20Sopenharmony_ci		goto error;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/* PLP filtering */
1188c2ecf20Sopenharmony_ci	if (c->stream_id > 255) {
1198c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "disable PLP filtering\n");
1208c2ecf20Sopenharmony_ci		ret = regmap_write(priv->regmap[0], 0x23ad, 0x00);
1218c2ecf20Sopenharmony_ci		if (ret)
1228c2ecf20Sopenharmony_ci			goto error;
1238c2ecf20Sopenharmony_ci	} else {
1248c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "enable PLP filtering\n");
1258c2ecf20Sopenharmony_ci		ret = regmap_write(priv->regmap[0], 0x23af, c->stream_id & 0xff);
1268c2ecf20Sopenharmony_ci		if (ret)
1278c2ecf20Sopenharmony_ci			goto error;
1288c2ecf20Sopenharmony_ci		ret = regmap_write(priv->regmap[0], 0x23ad, 0x01);
1298c2ecf20Sopenharmony_ci		if (ret)
1308c2ecf20Sopenharmony_ci			goto error;
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(priv->regmap[0], 0x209f, bw_params1[bw_i], 5);
1348c2ecf20Sopenharmony_ci	if (ret)
1358c2ecf20Sopenharmony_ci		goto error;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	ret = regmap_update_bits(priv->regmap[0], 0x20d7, 0xc0, bw_param << 6);
1388c2ecf20Sopenharmony_ci	if (ret)
1398c2ecf20Sopenharmony_ci		goto error;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
1428c2ecf20Sopenharmony_ci	if (ret)
1438c2ecf20Sopenharmony_ci		goto error;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
1468c2ecf20Sopenharmony_ci	if (ret)
1478c2ecf20Sopenharmony_ci		goto error;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return ret;
1508c2ecf20Sopenharmony_cierror:
1518c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
1528c2ecf20Sopenharmony_ci	return ret;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciint cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
1578c2ecf20Sopenharmony_ci			     struct dtv_frontend_properties *c)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct cxd2820r_priv *priv = fe->demodulator_priv;
1608c2ecf20Sopenharmony_ci	struct i2c_client *client = priv->client[0];
1618c2ecf20Sopenharmony_ci	int ret;
1628c2ecf20Sopenharmony_ci	unsigned int utmp;
1638c2ecf20Sopenharmony_ci	u8 buf[2];
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(priv->regmap[0], 0x205c, buf, 2);
1688c2ecf20Sopenharmony_ci	if (ret)
1698c2ecf20Sopenharmony_ci		goto error;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	switch ((buf[0] >> 0) & 0x07) {
1728c2ecf20Sopenharmony_ci	case 0:
1738c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_2K;
1748c2ecf20Sopenharmony_ci		break;
1758c2ecf20Sopenharmony_ci	case 1:
1768c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_8K;
1778c2ecf20Sopenharmony_ci		break;
1788c2ecf20Sopenharmony_ci	case 2:
1798c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_4K;
1808c2ecf20Sopenharmony_ci		break;
1818c2ecf20Sopenharmony_ci	case 3:
1828c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_1K;
1838c2ecf20Sopenharmony_ci		break;
1848c2ecf20Sopenharmony_ci	case 4:
1858c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_16K;
1868c2ecf20Sopenharmony_ci		break;
1878c2ecf20Sopenharmony_ci	case 5:
1888c2ecf20Sopenharmony_ci		c->transmission_mode = TRANSMISSION_MODE_32K;
1898c2ecf20Sopenharmony_ci		break;
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	switch ((buf[1] >> 4) & 0x07) {
1938c2ecf20Sopenharmony_ci	case 0:
1948c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_32;
1958c2ecf20Sopenharmony_ci		break;
1968c2ecf20Sopenharmony_ci	case 1:
1978c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_16;
1988c2ecf20Sopenharmony_ci		break;
1998c2ecf20Sopenharmony_ci	case 2:
2008c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_8;
2018c2ecf20Sopenharmony_ci		break;
2028c2ecf20Sopenharmony_ci	case 3:
2038c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_4;
2048c2ecf20Sopenharmony_ci		break;
2058c2ecf20Sopenharmony_ci	case 4:
2068c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_1_128;
2078c2ecf20Sopenharmony_ci		break;
2088c2ecf20Sopenharmony_ci	case 5:
2098c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_19_128;
2108c2ecf20Sopenharmony_ci		break;
2118c2ecf20Sopenharmony_ci	case 6:
2128c2ecf20Sopenharmony_ci		c->guard_interval = GUARD_INTERVAL_19_256;
2138c2ecf20Sopenharmony_ci		break;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(priv->regmap[0], 0x225b, buf, 2);
2178c2ecf20Sopenharmony_ci	if (ret)
2188c2ecf20Sopenharmony_ci		goto error;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	switch ((buf[0] >> 0) & 0x07) {
2218c2ecf20Sopenharmony_ci	case 0:
2228c2ecf20Sopenharmony_ci		c->fec_inner = FEC_1_2;
2238c2ecf20Sopenharmony_ci		break;
2248c2ecf20Sopenharmony_ci	case 1:
2258c2ecf20Sopenharmony_ci		c->fec_inner = FEC_3_5;
2268c2ecf20Sopenharmony_ci		break;
2278c2ecf20Sopenharmony_ci	case 2:
2288c2ecf20Sopenharmony_ci		c->fec_inner = FEC_2_3;
2298c2ecf20Sopenharmony_ci		break;
2308c2ecf20Sopenharmony_ci	case 3:
2318c2ecf20Sopenharmony_ci		c->fec_inner = FEC_3_4;
2328c2ecf20Sopenharmony_ci		break;
2338c2ecf20Sopenharmony_ci	case 4:
2348c2ecf20Sopenharmony_ci		c->fec_inner = FEC_4_5;
2358c2ecf20Sopenharmony_ci		break;
2368c2ecf20Sopenharmony_ci	case 5:
2378c2ecf20Sopenharmony_ci		c->fec_inner = FEC_5_6;
2388c2ecf20Sopenharmony_ci		break;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	switch ((buf[1] >> 0) & 0x07) {
2428c2ecf20Sopenharmony_ci	case 0:
2438c2ecf20Sopenharmony_ci		c->modulation = QPSK;
2448c2ecf20Sopenharmony_ci		break;
2458c2ecf20Sopenharmony_ci	case 1:
2468c2ecf20Sopenharmony_ci		c->modulation = QAM_16;
2478c2ecf20Sopenharmony_ci		break;
2488c2ecf20Sopenharmony_ci	case 2:
2498c2ecf20Sopenharmony_ci		c->modulation = QAM_64;
2508c2ecf20Sopenharmony_ci		break;
2518c2ecf20Sopenharmony_ci	case 3:
2528c2ecf20Sopenharmony_ci		c->modulation = QAM_256;
2538c2ecf20Sopenharmony_ci		break;
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	ret = regmap_read(priv->regmap[0], 0x20b5, &utmp);
2578c2ecf20Sopenharmony_ci	if (ret)
2588c2ecf20Sopenharmony_ci		goto error;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	switch ((utmp >> 4) & 0x01) {
2618c2ecf20Sopenharmony_ci	case 0:
2628c2ecf20Sopenharmony_ci		c->inversion = INVERSION_OFF;
2638c2ecf20Sopenharmony_ci		break;
2648c2ecf20Sopenharmony_ci	case 1:
2658c2ecf20Sopenharmony_ci		c->inversion = INVERSION_ON;
2668c2ecf20Sopenharmony_ci		break;
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return ret;
2708c2ecf20Sopenharmony_cierror:
2718c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
2728c2ecf20Sopenharmony_ci	return ret;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciint cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	struct cxd2820r_priv *priv = fe->demodulator_priv;
2788c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
2798c2ecf20Sopenharmony_ci	struct i2c_client *client = priv->client[0];
2808c2ecf20Sopenharmony_ci	int ret;
2818c2ecf20Sopenharmony_ci	unsigned int utmp, utmp1, utmp2;
2828c2ecf20Sopenharmony_ci	u8 buf[4];
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Lock detection */
2858c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(priv->regmap[0], 0x2010, &buf[0], 1);
2868c2ecf20Sopenharmony_ci	if (ret)
2878c2ecf20Sopenharmony_ci		goto error;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	utmp1 = (buf[0] >> 0) & 0x07;
2908c2ecf20Sopenharmony_ci	utmp2 = (buf[0] >> 5) & 0x01;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (utmp1 == 6 && utmp2 == 1) {
2938c2ecf20Sopenharmony_ci		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
2948c2ecf20Sopenharmony_ci			  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
2958c2ecf20Sopenharmony_ci	} else if (utmp1 == 6 || utmp2 == 1) {
2968c2ecf20Sopenharmony_ci		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
2978c2ecf20Sopenharmony_ci			  FE_HAS_VITERBI | FE_HAS_SYNC;
2988c2ecf20Sopenharmony_ci	} else {
2998c2ecf20Sopenharmony_ci		*status = 0;
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
3038c2ecf20Sopenharmony_ci		*status, 1, buf, utmp1, utmp2);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	/* Signal strength */
3068c2ecf20Sopenharmony_ci	if (*status & FE_HAS_SIGNAL) {
3078c2ecf20Sopenharmony_ci		unsigned int strength;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(priv->regmap[0], 0x2026, buf, 2);
3108c2ecf20Sopenharmony_ci		if (ret)
3118c2ecf20Sopenharmony_ci			goto error;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		utmp = buf[0] << 8 | buf[1] << 0;
3148c2ecf20Sopenharmony_ci		utmp = ~utmp & 0x0fff;
3158c2ecf20Sopenharmony_ci		/* Scale value to 0x0000-0xffff */
3168c2ecf20Sopenharmony_ci		strength = utmp << 4 | utmp >> 8;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		c->strength.len = 1;
3198c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
3208c2ecf20Sopenharmony_ci		c->strength.stat[0].uvalue = strength;
3218c2ecf20Sopenharmony_ci	} else {
3228c2ecf20Sopenharmony_ci		c->strength.len = 1;
3238c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* CNR */
3278c2ecf20Sopenharmony_ci	if (*status & FE_HAS_VITERBI) {
3288c2ecf20Sopenharmony_ci		unsigned int cnr;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(priv->regmap[0], 0x2028, buf, 2);
3318c2ecf20Sopenharmony_ci		if (ret)
3328c2ecf20Sopenharmony_ci			goto error;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		utmp = buf[0] << 8 | buf[1] << 0;
3358c2ecf20Sopenharmony_ci		utmp = utmp & 0x0fff;
3368c2ecf20Sopenharmony_ci		#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
3378c2ecf20Sopenharmony_ci		if (utmp)
3388c2ecf20Sopenharmony_ci			cnr = div_u64((u64)(intlog10(utmp)
3398c2ecf20Sopenharmony_ci				      - CXD2820R_LOG10_8_24) * 10000,
3408c2ecf20Sopenharmony_ci				      (1 << 24));
3418c2ecf20Sopenharmony_ci		else
3428c2ecf20Sopenharmony_ci			cnr = 0;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci		c->cnr.len = 1;
3458c2ecf20Sopenharmony_ci		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
3468c2ecf20Sopenharmony_ci		c->cnr.stat[0].svalue = cnr;
3478c2ecf20Sopenharmony_ci	} else {
3488c2ecf20Sopenharmony_ci		c->cnr.len = 1;
3498c2ecf20Sopenharmony_ci		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	/* BER */
3538c2ecf20Sopenharmony_ci	if (*status & FE_HAS_SYNC) {
3548c2ecf20Sopenharmony_ci		unsigned int post_bit_error;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci		ret = regmap_bulk_read(priv->regmap[0], 0x2039, buf, 4);
3578c2ecf20Sopenharmony_ci		if (ret)
3588c2ecf20Sopenharmony_ci			goto error;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci		if ((buf[0] >> 4) & 0x01) {
3618c2ecf20Sopenharmony_ci			post_bit_error = buf[0] << 24 | buf[1] << 16 |
3628c2ecf20Sopenharmony_ci					 buf[2] << 8 | buf[3] << 0;
3638c2ecf20Sopenharmony_ci			post_bit_error &= 0x0fffffff;
3648c2ecf20Sopenharmony_ci		} else {
3658c2ecf20Sopenharmony_ci			post_bit_error = 0;
3668c2ecf20Sopenharmony_ci		}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci		priv->post_bit_error += post_bit_error;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci		c->post_bit_error.len = 1;
3718c2ecf20Sopenharmony_ci		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
3728c2ecf20Sopenharmony_ci		c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
3738c2ecf20Sopenharmony_ci	} else {
3748c2ecf20Sopenharmony_ci		c->post_bit_error.len = 1;
3758c2ecf20Sopenharmony_ci		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	return ret;
3798c2ecf20Sopenharmony_cierror:
3808c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
3818c2ecf20Sopenharmony_ci	return ret;
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ciint cxd2820r_sleep_t2(struct dvb_frontend *fe)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	struct cxd2820r_priv *priv = fe->demodulator_priv;
3878c2ecf20Sopenharmony_ci	struct i2c_client *client = priv->client[0];
3888c2ecf20Sopenharmony_ci	int ret;
3898c2ecf20Sopenharmony_ci	static const struct reg_val_mask tab[] = {
3908c2ecf20Sopenharmony_ci		{ 0x000ff, 0x1f, 0xff },
3918c2ecf20Sopenharmony_ci		{ 0x00085, 0x00, 0xff },
3928c2ecf20Sopenharmony_ci		{ 0x00088, 0x01, 0xff },
3938c2ecf20Sopenharmony_ci		{ 0x02069, 0x00, 0xff },
3948c2ecf20Sopenharmony_ci		{ 0x00081, 0x00, 0xff },
3958c2ecf20Sopenharmony_ci		{ 0x00080, 0x00, 0xff },
3968c2ecf20Sopenharmony_ci	};
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
4018c2ecf20Sopenharmony_ci	if (ret)
4028c2ecf20Sopenharmony_ci		goto error;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	priv->delivery_system = SYS_UNDEFINED;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	return ret;
4078c2ecf20Sopenharmony_cierror:
4088c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "failed=%d\n", ret);
4098c2ecf20Sopenharmony_ci	return ret;
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ciint cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
4138c2ecf20Sopenharmony_ci	struct dvb_frontend_tune_settings *s)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	s->min_delay_ms = 1500;
4168c2ecf20Sopenharmony_ci	s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
4178c2ecf20Sopenharmony_ci	s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	return 0;
4208c2ecf20Sopenharmony_ci}
421