116216333SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29a0bf528SMauro Carvalho Chehab /*
39a0bf528SMauro Carvalho Chehab  * Sony CXD2820R demodulator driver
49a0bf528SMauro Carvalho Chehab  *
59a0bf528SMauro Carvalho Chehab  * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
69a0bf528SMauro Carvalho Chehab  */
79a0bf528SMauro Carvalho Chehab 
89a0bf528SMauro Carvalho Chehab 
99a0bf528SMauro Carvalho Chehab #include "cxd2820r_priv.h"
109a0bf528SMauro Carvalho Chehab 
cxd2820r_set_frontend_t2(struct dvb_frontend * fe)119a0bf528SMauro Carvalho Chehab int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
129a0bf528SMauro Carvalho Chehab {
137e3e68bcSMauro Carvalho Chehab 	struct cxd2820r_priv *priv = fe->demodulator_priv;
14c98975f9SAntti Palosaari 	struct i2c_client *client = priv->client[0];
15c98975f9SAntti Palosaari 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1643e2ea63SAntti Palosaari 	int ret, bw_i;
17fcd09f65SAntti Palosaari 	unsigned int utmp;
18fcd09f65SAntti Palosaari 	u32 if_frequency;
199a0bf528SMauro Carvalho Chehab 	u8 buf[3], bw_param;
209a0bf528SMauro Carvalho Chehab 	u8 bw_params1[][5] = {
219a0bf528SMauro Carvalho Chehab 		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
229a0bf528SMauro Carvalho Chehab 		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
239a0bf528SMauro Carvalho Chehab 		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
249a0bf528SMauro Carvalho Chehab 		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
259a0bf528SMauro Carvalho Chehab 	};
269a0bf528SMauro Carvalho Chehab 	struct reg_val_mask tab[] = {
279a0bf528SMauro Carvalho Chehab 		{ 0x00080, 0x02, 0xff },
289a0bf528SMauro Carvalho Chehab 		{ 0x00081, 0x20, 0xff },
299a0bf528SMauro Carvalho Chehab 		{ 0x00085, 0x07, 0xff },
309a0bf528SMauro Carvalho Chehab 		{ 0x00088, 0x01, 0xff },
319a0bf528SMauro Carvalho Chehab 		{ 0x02069, 0x01, 0xff },
329a0bf528SMauro Carvalho Chehab 
339a0bf528SMauro Carvalho Chehab 		{ 0x0207f, 0x2a, 0xff },
349a0bf528SMauro Carvalho Chehab 		{ 0x02082, 0x0a, 0xff },
359a0bf528SMauro Carvalho Chehab 		{ 0x02083, 0x0a, 0xff },
3607fdf7d9SAntti Palosaari 		{ 0x020cb, priv->if_agc_polarity << 6, 0x40 },
3707fdf7d9SAntti Palosaari 		{ 0x02070, priv->ts_mode, 0xff },
3807fdf7d9SAntti Palosaari 		{ 0x02071, !priv->ts_clk_inv << 6, 0x40 },
3907fdf7d9SAntti Palosaari 		{ 0x020b5, priv->spec_inv << 4, 0x10 },
409a0bf528SMauro Carvalho Chehab 		{ 0x02567, 0x07, 0x0f },
419a0bf528SMauro Carvalho Chehab 		{ 0x02569, 0x03, 0x03 },
429a0bf528SMauro Carvalho Chehab 		{ 0x02595, 0x1a, 0xff },
439a0bf528SMauro Carvalho Chehab 		{ 0x02596, 0x50, 0xff },
449a0bf528SMauro Carvalho Chehab 		{ 0x02a8c, 0x00, 0xff },
459a0bf528SMauro Carvalho Chehab 		{ 0x02a8d, 0x34, 0xff },
469a0bf528SMauro Carvalho Chehab 		{ 0x02a45, 0x06, 0x07 },
479a0bf528SMauro Carvalho Chehab 		{ 0x03f10, 0x0d, 0xff },
489a0bf528SMauro Carvalho Chehab 		{ 0x03f11, 0x02, 0xff },
499a0bf528SMauro Carvalho Chehab 		{ 0x03f12, 0x01, 0xff },
509a0bf528SMauro Carvalho Chehab 		{ 0x03f23, 0x2c, 0xff },
519a0bf528SMauro Carvalho Chehab 		{ 0x03f51, 0x13, 0xff },
529a0bf528SMauro Carvalho Chehab 		{ 0x03f52, 0x01, 0xff },
539a0bf528SMauro Carvalho Chehab 		{ 0x03f53, 0x00, 0xff },
549a0bf528SMauro Carvalho Chehab 		{ 0x027e6, 0x14, 0xff },
559a0bf528SMauro Carvalho Chehab 		{ 0x02786, 0x02, 0x07 },
569a0bf528SMauro Carvalho Chehab 		{ 0x02787, 0x40, 0xe0 },
579a0bf528SMauro Carvalho Chehab 		{ 0x027ef, 0x10, 0x18 },
589a0bf528SMauro Carvalho Chehab 	};
599a0bf528SMauro Carvalho Chehab 
60c98975f9SAntti Palosaari 	dev_dbg(&client->dev,
61c98975f9SAntti Palosaari 		"delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d stream_id=%u\n",
62c98975f9SAntti Palosaari 		c->delivery_system, c->modulation, c->frequency,
63c98975f9SAntti Palosaari 		c->bandwidth_hz, c->inversion, c->stream_id);
649a0bf528SMauro Carvalho Chehab 
659a0bf528SMauro Carvalho Chehab 	switch (c->bandwidth_hz) {
669a0bf528SMauro Carvalho Chehab 	case 5000000:
679a0bf528SMauro Carvalho Chehab 		bw_i = 0;
689a0bf528SMauro Carvalho Chehab 		bw_param = 3;
699a0bf528SMauro Carvalho Chehab 		break;
709a0bf528SMauro Carvalho Chehab 	case 6000000:
719a0bf528SMauro Carvalho Chehab 		bw_i = 1;
729a0bf528SMauro Carvalho Chehab 		bw_param = 2;
739a0bf528SMauro Carvalho Chehab 		break;
749a0bf528SMauro Carvalho Chehab 	case 7000000:
759a0bf528SMauro Carvalho Chehab 		bw_i = 2;
769a0bf528SMauro Carvalho Chehab 		bw_param = 1;
779a0bf528SMauro Carvalho Chehab 		break;
789a0bf528SMauro Carvalho Chehab 	case 8000000:
799a0bf528SMauro Carvalho Chehab 		bw_i = 3;
809a0bf528SMauro Carvalho Chehab 		bw_param = 0;
819a0bf528SMauro Carvalho Chehab 		break;
829a0bf528SMauro Carvalho Chehab 	default:
839a0bf528SMauro Carvalho Chehab 		return -EINVAL;
849a0bf528SMauro Carvalho Chehab 	}
859a0bf528SMauro Carvalho Chehab 
869a0bf528SMauro Carvalho Chehab 	/* program tuner */
879a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.set_params)
889a0bf528SMauro Carvalho Chehab 		fe->ops.tuner_ops.set_params(fe);
899a0bf528SMauro Carvalho Chehab 
909a0bf528SMauro Carvalho Chehab 	if (priv->delivery_system != SYS_DVBT2) {
9143e2ea63SAntti Palosaari 		ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
929a0bf528SMauro Carvalho Chehab 		if (ret)
939a0bf528SMauro Carvalho Chehab 			goto error;
949a0bf528SMauro Carvalho Chehab 	}
959a0bf528SMauro Carvalho Chehab 
969a0bf528SMauro Carvalho Chehab 	priv->delivery_system = SYS_DVBT2;
979a0bf528SMauro Carvalho Chehab 
989a0bf528SMauro Carvalho Chehab 	/* program IF frequency */
999a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.get_if_frequency) {
100fcd09f65SAntti Palosaari 		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
1019a0bf528SMauro Carvalho Chehab 		if (ret)
1029a0bf528SMauro Carvalho Chehab 			goto error;
103c98975f9SAntti Palosaari 		dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
104fcd09f65SAntti Palosaari 	} else {
105fcd09f65SAntti Palosaari 		ret = -EINVAL;
106fcd09f65SAntti Palosaari 		goto error;
107fcd09f65SAntti Palosaari 	}
1089a0bf528SMauro Carvalho Chehab 
109fcd09f65SAntti Palosaari 	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
110fcd09f65SAntti Palosaari 	buf[0] = (utmp >> 16) & 0xff;
111fcd09f65SAntti Palosaari 	buf[1] = (utmp >>  8) & 0xff;
112fcd09f65SAntti Palosaari 	buf[2] = (utmp >>  0) & 0xff;
11343e2ea63SAntti Palosaari 	ret = regmap_bulk_write(priv->regmap[0], 0x20b6, buf, 3);
114fcd09f65SAntti Palosaari 	if (ret)
115fcd09f65SAntti Palosaari 		goto error;
1169a0bf528SMauro Carvalho Chehab 
1174a74772eSEvgeny Plehov 	/* PLP filtering */
118a9af5392SMauro Carvalho Chehab 	if (c->stream_id > 255) {
119c98975f9SAntti Palosaari 		dev_dbg(&client->dev, "disable PLP filtering\n");
12043e2ea63SAntti Palosaari 		ret = regmap_write(priv->regmap[0], 0x23ad, 0x00);
1214a74772eSEvgeny Plehov 		if (ret)
1224a74772eSEvgeny Plehov 			goto error;
1234a74772eSEvgeny Plehov 	} else {
124c98975f9SAntti Palosaari 		dev_dbg(&client->dev, "enable PLP filtering\n");
12543e2ea63SAntti Palosaari 		ret = regmap_write(priv->regmap[0], 0x23af, c->stream_id & 0xff);
1264a74772eSEvgeny Plehov 		if (ret)
1274a74772eSEvgeny Plehov 			goto error;
12843e2ea63SAntti Palosaari 		ret = regmap_write(priv->regmap[0], 0x23ad, 0x01);
1294a74772eSEvgeny Plehov 		if (ret)
1304a74772eSEvgeny Plehov 			goto error;
1314a74772eSEvgeny Plehov 	}
1324a74772eSEvgeny Plehov 
13343e2ea63SAntti Palosaari 	ret = regmap_bulk_write(priv->regmap[0], 0x209f, bw_params1[bw_i], 5);
1349a0bf528SMauro Carvalho Chehab 	if (ret)
1359a0bf528SMauro Carvalho Chehab 		goto error;
1369a0bf528SMauro Carvalho Chehab 
13743e2ea63SAntti Palosaari 	ret = regmap_update_bits(priv->regmap[0], 0x20d7, 0xc0, bw_param << 6);
1389a0bf528SMauro Carvalho Chehab 	if (ret)
1399a0bf528SMauro Carvalho Chehab 		goto error;
1409a0bf528SMauro Carvalho Chehab 
14143e2ea63SAntti Palosaari 	ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
1429a0bf528SMauro Carvalho Chehab 	if (ret)
1439a0bf528SMauro Carvalho Chehab 		goto error;
1449a0bf528SMauro Carvalho Chehab 
14543e2ea63SAntti Palosaari 	ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
1469a0bf528SMauro Carvalho Chehab 	if (ret)
1479a0bf528SMauro Carvalho Chehab 		goto error;
1489a0bf528SMauro Carvalho Chehab 
1499a0bf528SMauro Carvalho Chehab 	return ret;
1509a0bf528SMauro Carvalho Chehab error:
151c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
1529a0bf528SMauro Carvalho Chehab 	return ret;
1539a0bf528SMauro Carvalho Chehab 
1549a0bf528SMauro Carvalho Chehab }
1559a0bf528SMauro Carvalho Chehab 
cxd2820r_get_frontend_t2(struct dvb_frontend * fe,struct dtv_frontend_properties * c)1567e3e68bcSMauro Carvalho Chehab int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
1577e3e68bcSMauro Carvalho Chehab 			     struct dtv_frontend_properties *c)
1589a0bf528SMauro Carvalho Chehab {
1599a0bf528SMauro Carvalho Chehab 	struct cxd2820r_priv *priv = fe->demodulator_priv;
160c98975f9SAntti Palosaari 	struct i2c_client *client = priv->client[0];
1619a0bf528SMauro Carvalho Chehab 	int ret;
16243e2ea63SAntti Palosaari 	unsigned int utmp;
1639a0bf528SMauro Carvalho Chehab 	u8 buf[2];
1649a0bf528SMauro Carvalho Chehab 
165c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "\n");
166c98975f9SAntti Palosaari 
16743e2ea63SAntti Palosaari 	ret = regmap_bulk_read(priv->regmap[0], 0x205c, buf, 2);
1689a0bf528SMauro Carvalho Chehab 	if (ret)
1699a0bf528SMauro Carvalho Chehab 		goto error;
1709a0bf528SMauro Carvalho Chehab 
1719a0bf528SMauro Carvalho Chehab 	switch ((buf[0] >> 0) & 0x07) {
1729a0bf528SMauro Carvalho Chehab 	case 0:
1739a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_2K;
1749a0bf528SMauro Carvalho Chehab 		break;
1759a0bf528SMauro Carvalho Chehab 	case 1:
1769a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_8K;
1779a0bf528SMauro Carvalho Chehab 		break;
1789a0bf528SMauro Carvalho Chehab 	case 2:
1799a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_4K;
1809a0bf528SMauro Carvalho Chehab 		break;
1819a0bf528SMauro Carvalho Chehab 	case 3:
1829a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_1K;
1839a0bf528SMauro Carvalho Chehab 		break;
1849a0bf528SMauro Carvalho Chehab 	case 4:
1859a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_16K;
1869a0bf528SMauro Carvalho Chehab 		break;
1879a0bf528SMauro Carvalho Chehab 	case 5:
1889a0bf528SMauro Carvalho Chehab 		c->transmission_mode = TRANSMISSION_MODE_32K;
1899a0bf528SMauro Carvalho Chehab 		break;
1909a0bf528SMauro Carvalho Chehab 	}
1919a0bf528SMauro Carvalho Chehab 
1929a0bf528SMauro Carvalho Chehab 	switch ((buf[1] >> 4) & 0x07) {
1939a0bf528SMauro Carvalho Chehab 	case 0:
1949a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_1_32;
1959a0bf528SMauro Carvalho Chehab 		break;
1969a0bf528SMauro Carvalho Chehab 	case 1:
1979a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_1_16;
1989a0bf528SMauro Carvalho Chehab 		break;
1999a0bf528SMauro Carvalho Chehab 	case 2:
2009a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_1_8;
2019a0bf528SMauro Carvalho Chehab 		break;
2029a0bf528SMauro Carvalho Chehab 	case 3:
2039a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_1_4;
2049a0bf528SMauro Carvalho Chehab 		break;
2059a0bf528SMauro Carvalho Chehab 	case 4:
2069a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_1_128;
2079a0bf528SMauro Carvalho Chehab 		break;
2089a0bf528SMauro Carvalho Chehab 	case 5:
2099a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_19_128;
2109a0bf528SMauro Carvalho Chehab 		break;
2119a0bf528SMauro Carvalho Chehab 	case 6:
2129a0bf528SMauro Carvalho Chehab 		c->guard_interval = GUARD_INTERVAL_19_256;
2139a0bf528SMauro Carvalho Chehab 		break;
2149a0bf528SMauro Carvalho Chehab 	}
2159a0bf528SMauro Carvalho Chehab 
21643e2ea63SAntti Palosaari 	ret = regmap_bulk_read(priv->regmap[0], 0x225b, buf, 2);
2179a0bf528SMauro Carvalho Chehab 	if (ret)
2189a0bf528SMauro Carvalho Chehab 		goto error;
2199a0bf528SMauro Carvalho Chehab 
2209a0bf528SMauro Carvalho Chehab 	switch ((buf[0] >> 0) & 0x07) {
2219a0bf528SMauro Carvalho Chehab 	case 0:
2229a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_1_2;
2239a0bf528SMauro Carvalho Chehab 		break;
2249a0bf528SMauro Carvalho Chehab 	case 1:
2259a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_3_5;
2269a0bf528SMauro Carvalho Chehab 		break;
2279a0bf528SMauro Carvalho Chehab 	case 2:
2289a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_2_3;
2299a0bf528SMauro Carvalho Chehab 		break;
2309a0bf528SMauro Carvalho Chehab 	case 3:
2319a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_3_4;
2329a0bf528SMauro Carvalho Chehab 		break;
2339a0bf528SMauro Carvalho Chehab 	case 4:
2349a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_4_5;
2359a0bf528SMauro Carvalho Chehab 		break;
2369a0bf528SMauro Carvalho Chehab 	case 5:
2379a0bf528SMauro Carvalho Chehab 		c->fec_inner = FEC_5_6;
2389a0bf528SMauro Carvalho Chehab 		break;
2399a0bf528SMauro Carvalho Chehab 	}
2409a0bf528SMauro Carvalho Chehab 
2419a0bf528SMauro Carvalho Chehab 	switch ((buf[1] >> 0) & 0x07) {
2429a0bf528SMauro Carvalho Chehab 	case 0:
2439a0bf528SMauro Carvalho Chehab 		c->modulation = QPSK;
2449a0bf528SMauro Carvalho Chehab 		break;
2459a0bf528SMauro Carvalho Chehab 	case 1:
2469a0bf528SMauro Carvalho Chehab 		c->modulation = QAM_16;
2479a0bf528SMauro Carvalho Chehab 		break;
2489a0bf528SMauro Carvalho Chehab 	case 2:
2499a0bf528SMauro Carvalho Chehab 		c->modulation = QAM_64;
2509a0bf528SMauro Carvalho Chehab 		break;
2519a0bf528SMauro Carvalho Chehab 	case 3:
2529a0bf528SMauro Carvalho Chehab 		c->modulation = QAM_256;
2539a0bf528SMauro Carvalho Chehab 		break;
2549a0bf528SMauro Carvalho Chehab 	}
2559a0bf528SMauro Carvalho Chehab 
25643e2ea63SAntti Palosaari 	ret = regmap_read(priv->regmap[0], 0x20b5, &utmp);
2579a0bf528SMauro Carvalho Chehab 	if (ret)
2589a0bf528SMauro Carvalho Chehab 		goto error;
2599a0bf528SMauro Carvalho Chehab 
26043e2ea63SAntti Palosaari 	switch ((utmp >> 4) & 0x01) {
2619a0bf528SMauro Carvalho Chehab 	case 0:
2629a0bf528SMauro Carvalho Chehab 		c->inversion = INVERSION_OFF;
2639a0bf528SMauro Carvalho Chehab 		break;
2649a0bf528SMauro Carvalho Chehab 	case 1:
2659a0bf528SMauro Carvalho Chehab 		c->inversion = INVERSION_ON;
2669a0bf528SMauro Carvalho Chehab 		break;
2679a0bf528SMauro Carvalho Chehab 	}
2689a0bf528SMauro Carvalho Chehab 
2699a0bf528SMauro Carvalho Chehab 	return ret;
2709a0bf528SMauro Carvalho Chehab error:
271c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
2729a0bf528SMauro Carvalho Chehab 	return ret;
2739a0bf528SMauro Carvalho Chehab }
2749a0bf528SMauro Carvalho Chehab 
cxd2820r_read_status_t2(struct dvb_frontend * fe,enum fe_status * status)2750df289a2SMauro Carvalho Chehab int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
2769a0bf528SMauro Carvalho Chehab {
2779a0bf528SMauro Carvalho Chehab 	struct cxd2820r_priv *priv = fe->demodulator_priv;
27891171fb6SAntti Palosaari 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
279c98975f9SAntti Palosaari 	struct i2c_client *client = priv->client[0];
2809a0bf528SMauro Carvalho Chehab 	int ret;
281d51dc917SAntti Palosaari 	unsigned int utmp, utmp1, utmp2;
28291171fb6SAntti Palosaari 	u8 buf[4];
2839a0bf528SMauro Carvalho Chehab 
284d51dc917SAntti Palosaari 	/* Lock detection */
28543e2ea63SAntti Palosaari 	ret = regmap_bulk_read(priv->regmap[0], 0x2010, &buf[0], 1);
2869a0bf528SMauro Carvalho Chehab 	if (ret)
2879a0bf528SMauro Carvalho Chehab 		goto error;
2889a0bf528SMauro Carvalho Chehab 
289d51dc917SAntti Palosaari 	utmp1 = (buf[0] >> 0) & 0x07;
290d51dc917SAntti Palosaari 	utmp2 = (buf[0] >> 5) & 0x01;
291d51dc917SAntti Palosaari 
292d51dc917SAntti Palosaari 	if (utmp1 == 6 && utmp2 == 1) {
293d51dc917SAntti Palosaari 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
2949a0bf528SMauro Carvalho Chehab 			  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
295d51dc917SAntti Palosaari 	} else if (utmp1 == 6 || utmp2 == 1) {
296d51dc917SAntti Palosaari 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
2979a0bf528SMauro Carvalho Chehab 			  FE_HAS_VITERBI | FE_HAS_SYNC;
298d51dc917SAntti Palosaari 	} else {
299d51dc917SAntti Palosaari 		*status = 0;
3009a0bf528SMauro Carvalho Chehab 	}
3019a0bf528SMauro Carvalho Chehab 
302d51dc917SAntti Palosaari 	dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
303d51dc917SAntti Palosaari 		*status, 1, buf, utmp1, utmp2);
3049a0bf528SMauro Carvalho Chehab 
30591171fb6SAntti Palosaari 	/* Signal strength */
30691171fb6SAntti Palosaari 	if (*status & FE_HAS_SIGNAL) {
30791171fb6SAntti Palosaari 		unsigned int strength;
30891171fb6SAntti Palosaari 
30943e2ea63SAntti Palosaari 		ret = regmap_bulk_read(priv->regmap[0], 0x2026, buf, 2);
31091171fb6SAntti Palosaari 		if (ret)
31191171fb6SAntti Palosaari 			goto error;
31291171fb6SAntti Palosaari 
31391171fb6SAntti Palosaari 		utmp = buf[0] << 8 | buf[1] << 0;
31491171fb6SAntti Palosaari 		utmp = ~utmp & 0x0fff;
31591171fb6SAntti Palosaari 		/* Scale value to 0x0000-0xffff */
31691171fb6SAntti Palosaari 		strength = utmp << 4 | utmp >> 8;
31791171fb6SAntti Palosaari 
31891171fb6SAntti Palosaari 		c->strength.len = 1;
31991171fb6SAntti Palosaari 		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
32091171fb6SAntti Palosaari 		c->strength.stat[0].uvalue = strength;
32191171fb6SAntti Palosaari 	} else {
32291171fb6SAntti Palosaari 		c->strength.len = 1;
32391171fb6SAntti Palosaari 		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
32491171fb6SAntti Palosaari 	}
32591171fb6SAntti Palosaari 
32691171fb6SAntti Palosaari 	/* CNR */
32791171fb6SAntti Palosaari 	if (*status & FE_HAS_VITERBI) {
32891171fb6SAntti Palosaari 		unsigned int cnr;
32991171fb6SAntti Palosaari 
33043e2ea63SAntti Palosaari 		ret = regmap_bulk_read(priv->regmap[0], 0x2028, buf, 2);
33191171fb6SAntti Palosaari 		if (ret)
33291171fb6SAntti Palosaari 			goto error;
33391171fb6SAntti Palosaari 
33491171fb6SAntti Palosaari 		utmp = buf[0] << 8 | buf[1] << 0;
33591171fb6SAntti Palosaari 		utmp = utmp & 0x0fff;
33691171fb6SAntti Palosaari 		#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
33791171fb6SAntti Palosaari 		if (utmp)
33891171fb6SAntti Palosaari 			cnr = div_u64((u64)(intlog10(utmp)
33991171fb6SAntti Palosaari 				      - CXD2820R_LOG10_8_24) * 10000,
34091171fb6SAntti Palosaari 				      (1 << 24));
34191171fb6SAntti Palosaari 		else
34291171fb6SAntti Palosaari 			cnr = 0;
34391171fb6SAntti Palosaari 
34491171fb6SAntti Palosaari 		c->cnr.len = 1;
34591171fb6SAntti Palosaari 		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
34691171fb6SAntti Palosaari 		c->cnr.stat[0].svalue = cnr;
34791171fb6SAntti Palosaari 	} else {
34891171fb6SAntti Palosaari 		c->cnr.len = 1;
34991171fb6SAntti Palosaari 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
35091171fb6SAntti Palosaari 	}
35191171fb6SAntti Palosaari 
35291171fb6SAntti Palosaari 	/* BER */
35391171fb6SAntti Palosaari 	if (*status & FE_HAS_SYNC) {
35491171fb6SAntti Palosaari 		unsigned int post_bit_error;
35591171fb6SAntti Palosaari 
35643e2ea63SAntti Palosaari 		ret = regmap_bulk_read(priv->regmap[0], 0x2039, buf, 4);
35791171fb6SAntti Palosaari 		if (ret)
35891171fb6SAntti Palosaari 			goto error;
35991171fb6SAntti Palosaari 
36091171fb6SAntti Palosaari 		if ((buf[0] >> 4) & 0x01) {
36191171fb6SAntti Palosaari 			post_bit_error = buf[0] << 24 | buf[1] << 16 |
36291171fb6SAntti Palosaari 					 buf[2] << 8 | buf[3] << 0;
36391171fb6SAntti Palosaari 			post_bit_error &= 0x0fffffff;
36491171fb6SAntti Palosaari 		} else {
36591171fb6SAntti Palosaari 			post_bit_error = 0;
36691171fb6SAntti Palosaari 		}
36791171fb6SAntti Palosaari 
36891171fb6SAntti Palosaari 		priv->post_bit_error += post_bit_error;
36991171fb6SAntti Palosaari 
37091171fb6SAntti Palosaari 		c->post_bit_error.len = 1;
37191171fb6SAntti Palosaari 		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
37291171fb6SAntti Palosaari 		c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
37391171fb6SAntti Palosaari 	} else {
37491171fb6SAntti Palosaari 		c->post_bit_error.len = 1;
37591171fb6SAntti Palosaari 		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
37691171fb6SAntti Palosaari 	}
37791171fb6SAntti Palosaari 
3789a0bf528SMauro Carvalho Chehab 	return ret;
3799a0bf528SMauro Carvalho Chehab error:
380c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
3819a0bf528SMauro Carvalho Chehab 	return ret;
3829a0bf528SMauro Carvalho Chehab }
3839a0bf528SMauro Carvalho Chehab 
cxd2820r_sleep_t2(struct dvb_frontend * fe)3849a0bf528SMauro Carvalho Chehab int cxd2820r_sleep_t2(struct dvb_frontend *fe)
3859a0bf528SMauro Carvalho Chehab {
3869a0bf528SMauro Carvalho Chehab 	struct cxd2820r_priv *priv = fe->demodulator_priv;
387c98975f9SAntti Palosaari 	struct i2c_client *client = priv->client[0];
38843e2ea63SAntti Palosaari 	int ret;
389*ed4e1569SColin Ian King 	static const struct reg_val_mask tab[] = {
3909a0bf528SMauro Carvalho Chehab 		{ 0x000ff, 0x1f, 0xff },
3919a0bf528SMauro Carvalho Chehab 		{ 0x00085, 0x00, 0xff },
3929a0bf528SMauro Carvalho Chehab 		{ 0x00088, 0x01, 0xff },
3939a0bf528SMauro Carvalho Chehab 		{ 0x02069, 0x00, 0xff },
3949a0bf528SMauro Carvalho Chehab 		{ 0x00081, 0x00, 0xff },
3959a0bf528SMauro Carvalho Chehab 		{ 0x00080, 0x00, 0xff },
3969a0bf528SMauro Carvalho Chehab 	};
3979a0bf528SMauro Carvalho Chehab 
398c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "\n");
3999a0bf528SMauro Carvalho Chehab 
40043e2ea63SAntti Palosaari 	ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
4019a0bf528SMauro Carvalho Chehab 	if (ret)
4029a0bf528SMauro Carvalho Chehab 		goto error;
4039a0bf528SMauro Carvalho Chehab 
4049a0bf528SMauro Carvalho Chehab 	priv->delivery_system = SYS_UNDEFINED;
4059a0bf528SMauro Carvalho Chehab 
4069a0bf528SMauro Carvalho Chehab 	return ret;
4079a0bf528SMauro Carvalho Chehab error:
408c98975f9SAntti Palosaari 	dev_dbg(&client->dev, "failed=%d\n", ret);
4099a0bf528SMauro Carvalho Chehab 	return ret;
4109a0bf528SMauro Carvalho Chehab }
4119a0bf528SMauro Carvalho Chehab 
cxd2820r_get_tune_settings_t2(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * s)4129a0bf528SMauro Carvalho Chehab int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
4139a0bf528SMauro Carvalho Chehab 	struct dvb_frontend_tune_settings *s)
4149a0bf528SMauro Carvalho Chehab {
4159a0bf528SMauro Carvalho Chehab 	s->min_delay_ms = 1500;
416f1b1eabfSMauro Carvalho Chehab 	s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
417f1b1eabfSMauro Carvalho Chehab 	s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
4189a0bf528SMauro Carvalho Chehab 
4199a0bf528SMauro Carvalho Chehab 	return 0;
4209a0bf528SMauro Carvalho Chehab }
421