cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cxd2820r_t2.c (9360B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Sony CXD2820R demodulator driver
      4 *
      5 * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
      6 */
      7
      8
      9#include "cxd2820r_priv.h"
     10
     11int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
     12{
     13	struct cxd2820r_priv *priv = fe->demodulator_priv;
     14	struct i2c_client *client = priv->client[0];
     15	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
     16	int ret, bw_i;
     17	unsigned int utmp;
     18	u32 if_frequency;
     19	u8 buf[3], bw_param;
     20	u8 bw_params1[][5] = {
     21		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
     22		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
     23		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
     24		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
     25	};
     26	struct reg_val_mask tab[] = {
     27		{ 0x00080, 0x02, 0xff },
     28		{ 0x00081, 0x20, 0xff },
     29		{ 0x00085, 0x07, 0xff },
     30		{ 0x00088, 0x01, 0xff },
     31		{ 0x02069, 0x01, 0xff },
     32
     33		{ 0x0207f, 0x2a, 0xff },
     34		{ 0x02082, 0x0a, 0xff },
     35		{ 0x02083, 0x0a, 0xff },
     36		{ 0x020cb, priv->if_agc_polarity << 6, 0x40 },
     37		{ 0x02070, priv->ts_mode, 0xff },
     38		{ 0x02071, !priv->ts_clk_inv << 6, 0x40 },
     39		{ 0x020b5, priv->spec_inv << 4, 0x10 },
     40		{ 0x02567, 0x07, 0x0f },
     41		{ 0x02569, 0x03, 0x03 },
     42		{ 0x02595, 0x1a, 0xff },
     43		{ 0x02596, 0x50, 0xff },
     44		{ 0x02a8c, 0x00, 0xff },
     45		{ 0x02a8d, 0x34, 0xff },
     46		{ 0x02a45, 0x06, 0x07 },
     47		{ 0x03f10, 0x0d, 0xff },
     48		{ 0x03f11, 0x02, 0xff },
     49		{ 0x03f12, 0x01, 0xff },
     50		{ 0x03f23, 0x2c, 0xff },
     51		{ 0x03f51, 0x13, 0xff },
     52		{ 0x03f52, 0x01, 0xff },
     53		{ 0x03f53, 0x00, 0xff },
     54		{ 0x027e6, 0x14, 0xff },
     55		{ 0x02786, 0x02, 0x07 },
     56		{ 0x02787, 0x40, 0xe0 },
     57		{ 0x027ef, 0x10, 0x18 },
     58	};
     59
     60	dev_dbg(&client->dev,
     61		"delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d stream_id=%u\n",
     62		c->delivery_system, c->modulation, c->frequency,
     63		c->bandwidth_hz, c->inversion, c->stream_id);
     64
     65	switch (c->bandwidth_hz) {
     66	case 5000000:
     67		bw_i = 0;
     68		bw_param = 3;
     69		break;
     70	case 6000000:
     71		bw_i = 1;
     72		bw_param = 2;
     73		break;
     74	case 7000000:
     75		bw_i = 2;
     76		bw_param = 1;
     77		break;
     78	case 8000000:
     79		bw_i = 3;
     80		bw_param = 0;
     81		break;
     82	default:
     83		return -EINVAL;
     84	}
     85
     86	/* program tuner */
     87	if (fe->ops.tuner_ops.set_params)
     88		fe->ops.tuner_ops.set_params(fe);
     89
     90	if (priv->delivery_system != SYS_DVBT2) {
     91		ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
     92		if (ret)
     93			goto error;
     94	}
     95
     96	priv->delivery_system = SYS_DVBT2;
     97
     98	/* program IF frequency */
     99	if (fe->ops.tuner_ops.get_if_frequency) {
    100		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
    101		if (ret)
    102			goto error;
    103		dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
    104	} else {
    105		ret = -EINVAL;
    106		goto error;
    107	}
    108
    109	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
    110	buf[0] = (utmp >> 16) & 0xff;
    111	buf[1] = (utmp >>  8) & 0xff;
    112	buf[2] = (utmp >>  0) & 0xff;
    113	ret = regmap_bulk_write(priv->regmap[0], 0x20b6, buf, 3);
    114	if (ret)
    115		goto error;
    116
    117	/* PLP filtering */
    118	if (c->stream_id > 255) {
    119		dev_dbg(&client->dev, "disable PLP filtering\n");
    120		ret = regmap_write(priv->regmap[0], 0x23ad, 0x00);
    121		if (ret)
    122			goto error;
    123	} else {
    124		dev_dbg(&client->dev, "enable PLP filtering\n");
    125		ret = regmap_write(priv->regmap[0], 0x23af, c->stream_id & 0xff);
    126		if (ret)
    127			goto error;
    128		ret = regmap_write(priv->regmap[0], 0x23ad, 0x01);
    129		if (ret)
    130			goto error;
    131	}
    132
    133	ret = regmap_bulk_write(priv->regmap[0], 0x209f, bw_params1[bw_i], 5);
    134	if (ret)
    135		goto error;
    136
    137	ret = regmap_update_bits(priv->regmap[0], 0x20d7, 0xc0, bw_param << 6);
    138	if (ret)
    139		goto error;
    140
    141	ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
    142	if (ret)
    143		goto error;
    144
    145	ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
    146	if (ret)
    147		goto error;
    148
    149	return ret;
    150error:
    151	dev_dbg(&client->dev, "failed=%d\n", ret);
    152	return ret;
    153
    154}
    155
    156int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
    157			     struct dtv_frontend_properties *c)
    158{
    159	struct cxd2820r_priv *priv = fe->demodulator_priv;
    160	struct i2c_client *client = priv->client[0];
    161	int ret;
    162	unsigned int utmp;
    163	u8 buf[2];
    164
    165	dev_dbg(&client->dev, "\n");
    166
    167	ret = regmap_bulk_read(priv->regmap[0], 0x205c, buf, 2);
    168	if (ret)
    169		goto error;
    170
    171	switch ((buf[0] >> 0) & 0x07) {
    172	case 0:
    173		c->transmission_mode = TRANSMISSION_MODE_2K;
    174		break;
    175	case 1:
    176		c->transmission_mode = TRANSMISSION_MODE_8K;
    177		break;
    178	case 2:
    179		c->transmission_mode = TRANSMISSION_MODE_4K;
    180		break;
    181	case 3:
    182		c->transmission_mode = TRANSMISSION_MODE_1K;
    183		break;
    184	case 4:
    185		c->transmission_mode = TRANSMISSION_MODE_16K;
    186		break;
    187	case 5:
    188		c->transmission_mode = TRANSMISSION_MODE_32K;
    189		break;
    190	}
    191
    192	switch ((buf[1] >> 4) & 0x07) {
    193	case 0:
    194		c->guard_interval = GUARD_INTERVAL_1_32;
    195		break;
    196	case 1:
    197		c->guard_interval = GUARD_INTERVAL_1_16;
    198		break;
    199	case 2:
    200		c->guard_interval = GUARD_INTERVAL_1_8;
    201		break;
    202	case 3:
    203		c->guard_interval = GUARD_INTERVAL_1_4;
    204		break;
    205	case 4:
    206		c->guard_interval = GUARD_INTERVAL_1_128;
    207		break;
    208	case 5:
    209		c->guard_interval = GUARD_INTERVAL_19_128;
    210		break;
    211	case 6:
    212		c->guard_interval = GUARD_INTERVAL_19_256;
    213		break;
    214	}
    215
    216	ret = regmap_bulk_read(priv->regmap[0], 0x225b, buf, 2);
    217	if (ret)
    218		goto error;
    219
    220	switch ((buf[0] >> 0) & 0x07) {
    221	case 0:
    222		c->fec_inner = FEC_1_2;
    223		break;
    224	case 1:
    225		c->fec_inner = FEC_3_5;
    226		break;
    227	case 2:
    228		c->fec_inner = FEC_2_3;
    229		break;
    230	case 3:
    231		c->fec_inner = FEC_3_4;
    232		break;
    233	case 4:
    234		c->fec_inner = FEC_4_5;
    235		break;
    236	case 5:
    237		c->fec_inner = FEC_5_6;
    238		break;
    239	}
    240
    241	switch ((buf[1] >> 0) & 0x07) {
    242	case 0:
    243		c->modulation = QPSK;
    244		break;
    245	case 1:
    246		c->modulation = QAM_16;
    247		break;
    248	case 2:
    249		c->modulation = QAM_64;
    250		break;
    251	case 3:
    252		c->modulation = QAM_256;
    253		break;
    254	}
    255
    256	ret = regmap_read(priv->regmap[0], 0x20b5, &utmp);
    257	if (ret)
    258		goto error;
    259
    260	switch ((utmp >> 4) & 0x01) {
    261	case 0:
    262		c->inversion = INVERSION_OFF;
    263		break;
    264	case 1:
    265		c->inversion = INVERSION_ON;
    266		break;
    267	}
    268
    269	return ret;
    270error:
    271	dev_dbg(&client->dev, "failed=%d\n", ret);
    272	return ret;
    273}
    274
    275int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
    276{
    277	struct cxd2820r_priv *priv = fe->demodulator_priv;
    278	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
    279	struct i2c_client *client = priv->client[0];
    280	int ret;
    281	unsigned int utmp, utmp1, utmp2;
    282	u8 buf[4];
    283
    284	/* Lock detection */
    285	ret = regmap_bulk_read(priv->regmap[0], 0x2010, &buf[0], 1);
    286	if (ret)
    287		goto error;
    288
    289	utmp1 = (buf[0] >> 0) & 0x07;
    290	utmp2 = (buf[0] >> 5) & 0x01;
    291
    292	if (utmp1 == 6 && utmp2 == 1) {
    293		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
    294			  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
    295	} else if (utmp1 == 6 || utmp2 == 1) {
    296		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
    297			  FE_HAS_VITERBI | FE_HAS_SYNC;
    298	} else {
    299		*status = 0;
    300	}
    301
    302	dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
    303		*status, 1, buf, utmp1, utmp2);
    304
    305	/* Signal strength */
    306	if (*status & FE_HAS_SIGNAL) {
    307		unsigned int strength;
    308
    309		ret = regmap_bulk_read(priv->regmap[0], 0x2026, buf, 2);
    310		if (ret)
    311			goto error;
    312
    313		utmp = buf[0] << 8 | buf[1] << 0;
    314		utmp = ~utmp & 0x0fff;
    315		/* Scale value to 0x0000-0xffff */
    316		strength = utmp << 4 | utmp >> 8;
    317
    318		c->strength.len = 1;
    319		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
    320		c->strength.stat[0].uvalue = strength;
    321	} else {
    322		c->strength.len = 1;
    323		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    324	}
    325
    326	/* CNR */
    327	if (*status & FE_HAS_VITERBI) {
    328		unsigned int cnr;
    329
    330		ret = regmap_bulk_read(priv->regmap[0], 0x2028, buf, 2);
    331		if (ret)
    332			goto error;
    333
    334		utmp = buf[0] << 8 | buf[1] << 0;
    335		utmp = utmp & 0x0fff;
    336		#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
    337		if (utmp)
    338			cnr = div_u64((u64)(intlog10(utmp)
    339				      - CXD2820R_LOG10_8_24) * 10000,
    340				      (1 << 24));
    341		else
    342			cnr = 0;
    343
    344		c->cnr.len = 1;
    345		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
    346		c->cnr.stat[0].svalue = cnr;
    347	} else {
    348		c->cnr.len = 1;
    349		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    350	}
    351
    352	/* BER */
    353	if (*status & FE_HAS_SYNC) {
    354		unsigned int post_bit_error;
    355
    356		ret = regmap_bulk_read(priv->regmap[0], 0x2039, buf, 4);
    357		if (ret)
    358			goto error;
    359
    360		if ((buf[0] >> 4) & 0x01) {
    361			post_bit_error = buf[0] << 24 | buf[1] << 16 |
    362					 buf[2] << 8 | buf[3] << 0;
    363			post_bit_error &= 0x0fffffff;
    364		} else {
    365			post_bit_error = 0;
    366		}
    367
    368		priv->post_bit_error += post_bit_error;
    369
    370		c->post_bit_error.len = 1;
    371		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
    372		c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
    373	} else {
    374		c->post_bit_error.len = 1;
    375		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    376	}
    377
    378	return ret;
    379error:
    380	dev_dbg(&client->dev, "failed=%d\n", ret);
    381	return ret;
    382}
    383
    384int cxd2820r_sleep_t2(struct dvb_frontend *fe)
    385{
    386	struct cxd2820r_priv *priv = fe->demodulator_priv;
    387	struct i2c_client *client = priv->client[0];
    388	int ret;
    389	static const struct reg_val_mask tab[] = {
    390		{ 0x000ff, 0x1f, 0xff },
    391		{ 0x00085, 0x00, 0xff },
    392		{ 0x00088, 0x01, 0xff },
    393		{ 0x02069, 0x00, 0xff },
    394		{ 0x00081, 0x00, 0xff },
    395		{ 0x00080, 0x00, 0xff },
    396	};
    397
    398	dev_dbg(&client->dev, "\n");
    399
    400	ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
    401	if (ret)
    402		goto error;
    403
    404	priv->delivery_system = SYS_UNDEFINED;
    405
    406	return ret;
    407error:
    408	dev_dbg(&client->dev, "failed=%d\n", ret);
    409	return ret;
    410}
    411
    412int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
    413	struct dvb_frontend_tune_settings *s)
    414{
    415	s->min_delay_ms = 1500;
    416	s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
    417	s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
    418
    419	return 0;
    420}