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

tda8083.c (11448B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3    Driver for Philips TDA8083 based QPSK Demodulator
      4
      5    Copyright (C) 2001 Convergence Integrated Media GmbH
      6
      7    written by Ralph Metzler <ralph@convergence.de>
      8
      9    adoption to the new DVB frontend API and diagnostic ioctl's
     10    by Holger Waechtler <holger@convergence.de>
     11
     12
     13*/
     14
     15#include <linux/init.h>
     16#include <linux/kernel.h>
     17#include <linux/module.h>
     18#include <linux/string.h>
     19#include <linux/slab.h>
     20#include <linux/jiffies.h>
     21#include <media/dvb_frontend.h>
     22#include "tda8083.h"
     23
     24
     25struct tda8083_state {
     26	struct i2c_adapter* i2c;
     27	/* configuration settings */
     28	const struct tda8083_config* config;
     29	struct dvb_frontend frontend;
     30};
     31
     32static int debug;
     33#define dprintk(args...) \
     34	do { \
     35		if (debug) printk(KERN_DEBUG "tda8083: " args); \
     36	} while (0)
     37
     38
     39static u8 tda8083_init_tab [] = {
     40	0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
     41	0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
     42	0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
     43	0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
     44	0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
     45	0x00, 0x00, 0x00, 0x00
     46};
     47
     48
     49static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
     50{
     51	int ret;
     52	u8 buf [] = { reg, data };
     53	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
     54
     55	ret = i2c_transfer(state->i2c, &msg, 1);
     56
     57	if (ret != 1)
     58		dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
     59			__func__, reg, ret);
     60
     61	return (ret != 1) ? -1 : 0;
     62}
     63
     64static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
     65{
     66	int ret;
     67	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
     68			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
     69
     70	ret = i2c_transfer(state->i2c, msg, 2);
     71
     72	if (ret != 2)
     73		dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
     74			__func__, reg1, ret);
     75
     76	return ret == 2 ? 0 : -1;
     77}
     78
     79static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
     80{
     81	u8 val;
     82
     83	tda8083_readregs (state, reg, &val, 1);
     84
     85	return val;
     86}
     87
     88static int tda8083_set_inversion(struct tda8083_state *state,
     89				 enum fe_spectral_inversion inversion)
     90{
     91	/*  XXX FIXME: implement other modes than FEC_AUTO */
     92	if (inversion == INVERSION_AUTO)
     93		return 0;
     94
     95	return -EINVAL;
     96}
     97
     98static int tda8083_set_fec(struct tda8083_state *state, enum fe_code_rate fec)
     99{
    100	if (fec == FEC_AUTO)
    101		return tda8083_writereg (state, 0x07, 0xff);
    102
    103	if (fec >= FEC_1_2 && fec <= FEC_8_9)
    104		return tda8083_writereg (state, 0x07, 1 << (FEC_8_9 - fec));
    105
    106	return -EINVAL;
    107}
    108
    109static enum fe_code_rate tda8083_get_fec(struct tda8083_state *state)
    110{
    111	u8 index;
    112	static enum fe_code_rate fec_tab[] = {
    113		FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
    114		FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8
    115	};
    116
    117	index = tda8083_readreg(state, 0x0e) & 0x07;
    118
    119	return fec_tab [index];
    120}
    121
    122static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
    123{
    124	u32 ratio;
    125	u32 tmp;
    126	u8 filter;
    127
    128	if (srate > 32000000)
    129		srate = 32000000;
    130	if (srate < 500000)
    131		srate = 500000;
    132
    133	filter = 0;
    134	if (srate < 24000000)
    135		filter = 2;
    136	if (srate < 16000000)
    137		filter = 3;
    138
    139	tmp = 31250 << 16;
    140	ratio = tmp / srate;
    141
    142	tmp = (tmp % srate) << 8;
    143	ratio = (ratio << 8) + tmp / srate;
    144
    145	tmp = (tmp % srate) << 8;
    146	ratio = (ratio << 8) + tmp / srate;
    147
    148	dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio);
    149
    150	tda8083_writereg (state, 0x05, filter);
    151	tda8083_writereg (state, 0x02, (ratio >> 16) & 0xff);
    152	tda8083_writereg (state, 0x03, (ratio >>  8) & 0xff);
    153	tda8083_writereg (state, 0x04, (ratio      ) & 0xff);
    154
    155	tda8083_writereg (state, 0x00, 0x3c);
    156	tda8083_writereg (state, 0x00, 0x04);
    157
    158	return 1;
    159}
    160
    161static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
    162{
    163	unsigned long start = jiffies;
    164
    165	while (time_is_after_jiffies(start + timeout) &&
    166	       !(tda8083_readreg(state, 0x02) & 0x80))
    167	{
    168		msleep(50);
    169	}
    170}
    171
    172static int tda8083_set_tone(struct tda8083_state *state,
    173			    enum fe_sec_tone_mode tone)
    174{
    175	tda8083_writereg (state, 0x26, 0xf1);
    176
    177	switch (tone) {
    178	case SEC_TONE_OFF:
    179		return tda8083_writereg (state, 0x29, 0x00);
    180	case SEC_TONE_ON:
    181		return tda8083_writereg (state, 0x29, 0x80);
    182	default:
    183		return -EINVAL;
    184	}
    185}
    186
    187static int tda8083_set_voltage(struct tda8083_state *state,
    188			       enum fe_sec_voltage voltage)
    189{
    190	switch (voltage) {
    191	case SEC_VOLTAGE_13:
    192		return tda8083_writereg (state, 0x20, 0x00);
    193	case SEC_VOLTAGE_18:
    194		return tda8083_writereg (state, 0x20, 0x11);
    195	default:
    196		return -EINVAL;
    197	}
    198}
    199
    200static int tda8083_send_diseqc_burst(struct tda8083_state *state,
    201				     enum fe_sec_mini_cmd burst)
    202{
    203	switch (burst) {
    204	case SEC_MINI_A:
    205		tda8083_writereg (state, 0x29, (5 << 2));  /* send burst A */
    206		break;
    207	case SEC_MINI_B:
    208		tda8083_writereg (state, 0x29, (7 << 2));  /* send B */
    209		break;
    210	default:
    211		return -EINVAL;
    212	}
    213
    214	tda8083_wait_diseqc_fifo (state, 100);
    215
    216	return 0;
    217}
    218
    219static int tda8083_send_diseqc_msg(struct dvb_frontend *fe,
    220				   struct dvb_diseqc_master_cmd *m)
    221{
    222	struct tda8083_state* state = fe->demodulator_priv;
    223	int i;
    224
    225	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
    226
    227	for (i=0; i<m->msg_len; i++)
    228		tda8083_writereg (state, 0x23 + i, m->msg[i]);
    229
    230	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (3 << 2)); /* send!! */
    231
    232	tda8083_wait_diseqc_fifo (state, 100);
    233
    234	return 0;
    235}
    236
    237static int tda8083_read_status(struct dvb_frontend *fe,
    238			       enum fe_status *status)
    239{
    240	struct tda8083_state* state = fe->demodulator_priv;
    241
    242	u8 signal = ~tda8083_readreg (state, 0x01);
    243	u8 sync = tda8083_readreg (state, 0x02);
    244
    245	*status = 0;
    246
    247	if (signal > 10)
    248		*status |= FE_HAS_SIGNAL;
    249
    250	if (sync & 0x01)
    251		*status |= FE_HAS_CARRIER;
    252
    253	if (sync & 0x02)
    254		*status |= FE_HAS_VITERBI;
    255
    256	if (sync & 0x10)
    257		*status |= FE_HAS_SYNC;
    258
    259	if (sync & 0x20) /* frontend can not lock */
    260		*status |= FE_TIMEDOUT;
    261
    262	if ((sync & 0x1f) == 0x1f)
    263		*status |= FE_HAS_LOCK;
    264
    265	return 0;
    266}
    267
    268static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
    269{
    270	struct tda8083_state* state = fe->demodulator_priv;
    271	int ret;
    272	u8 buf[3];
    273
    274	if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
    275		return ret;
    276
    277	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
    278
    279	return 0;
    280}
    281
    282static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
    283{
    284	struct tda8083_state* state = fe->demodulator_priv;
    285
    286	u8 signal = ~tda8083_readreg (state, 0x01);
    287	*strength = (signal << 8) | signal;
    288
    289	return 0;
    290}
    291
    292static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
    293{
    294	struct tda8083_state* state = fe->demodulator_priv;
    295
    296	u8 _snr = tda8083_readreg (state, 0x08);
    297	*snr = (_snr << 8) | _snr;
    298
    299	return 0;
    300}
    301
    302static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
    303{
    304	struct tda8083_state* state = fe->demodulator_priv;
    305
    306	*ucblocks = tda8083_readreg(state, 0x0f);
    307	if (*ucblocks == 0xff)
    308		*ucblocks = 0xffffffff;
    309
    310	return 0;
    311}
    312
    313static int tda8083_set_frontend(struct dvb_frontend *fe)
    314{
    315	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
    316	struct tda8083_state* state = fe->demodulator_priv;
    317
    318	if (fe->ops.tuner_ops.set_params) {
    319		fe->ops.tuner_ops.set_params(fe);
    320		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
    321	}
    322
    323	tda8083_set_inversion (state, p->inversion);
    324	tda8083_set_fec(state, p->fec_inner);
    325	tda8083_set_symbolrate(state, p->symbol_rate);
    326
    327	tda8083_writereg (state, 0x00, 0x3c);
    328	tda8083_writereg (state, 0x00, 0x04);
    329
    330	return 0;
    331}
    332
    333static int tda8083_get_frontend(struct dvb_frontend *fe,
    334				struct dtv_frontend_properties *p)
    335{
    336	struct tda8083_state* state = fe->demodulator_priv;
    337
    338	/*  FIXME: get symbolrate & frequency offset...*/
    339	/*p->frequency = ???;*/
    340	p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
    341			INVERSION_ON : INVERSION_OFF;
    342	p->fec_inner = tda8083_get_fec(state);
    343	/*p->symbol_rate = tda8083_get_symbolrate (state);*/
    344
    345	return 0;
    346}
    347
    348static int tda8083_sleep(struct dvb_frontend* fe)
    349{
    350	struct tda8083_state* state = fe->demodulator_priv;
    351
    352	tda8083_writereg (state, 0x00, 0x02);
    353	return 0;
    354}
    355
    356static int tda8083_init(struct dvb_frontend* fe)
    357{
    358	struct tda8083_state* state = fe->demodulator_priv;
    359	int i;
    360
    361	for (i=0; i<44; i++)
    362		tda8083_writereg (state, i, tda8083_init_tab[i]);
    363
    364	tda8083_writereg (state, 0x00, 0x3c);
    365	tda8083_writereg (state, 0x00, 0x04);
    366
    367	return 0;
    368}
    369
    370static int tda8083_diseqc_send_burst(struct dvb_frontend *fe,
    371				     enum fe_sec_mini_cmd burst)
    372{
    373	struct tda8083_state* state = fe->demodulator_priv;
    374
    375	tda8083_send_diseqc_burst (state, burst);
    376	tda8083_writereg (state, 0x00, 0x3c);
    377	tda8083_writereg (state, 0x00, 0x04);
    378
    379	return 0;
    380}
    381
    382static int tda8083_diseqc_set_tone(struct dvb_frontend *fe,
    383				   enum fe_sec_tone_mode tone)
    384{
    385	struct tda8083_state* state = fe->demodulator_priv;
    386
    387	tda8083_set_tone (state, tone);
    388	tda8083_writereg (state, 0x00, 0x3c);
    389	tda8083_writereg (state, 0x00, 0x04);
    390
    391	return 0;
    392}
    393
    394static int tda8083_diseqc_set_voltage(struct dvb_frontend *fe,
    395				      enum fe_sec_voltage voltage)
    396{
    397	struct tda8083_state* state = fe->demodulator_priv;
    398
    399	tda8083_set_voltage (state, voltage);
    400	tda8083_writereg (state, 0x00, 0x3c);
    401	tda8083_writereg (state, 0x00, 0x04);
    402
    403	return 0;
    404}
    405
    406static void tda8083_release(struct dvb_frontend* fe)
    407{
    408	struct tda8083_state* state = fe->demodulator_priv;
    409	kfree(state);
    410}
    411
    412static const struct dvb_frontend_ops tda8083_ops;
    413
    414struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
    415				    struct i2c_adapter* i2c)
    416{
    417	struct tda8083_state* state = NULL;
    418
    419	/* allocate memory for the internal state */
    420	state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
    421	if (state == NULL) goto error;
    422
    423	/* setup the state */
    424	state->config = config;
    425	state->i2c = i2c;
    426
    427	/* check if the demod is there */
    428	if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
    429
    430	/* create dvb_frontend */
    431	memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
    432	state->frontend.demodulator_priv = state;
    433	return &state->frontend;
    434
    435error:
    436	kfree(state);
    437	return NULL;
    438}
    439
    440static const struct dvb_frontend_ops tda8083_ops = {
    441	.delsys = { SYS_DVBS },
    442	.info = {
    443		.name			= "Philips TDA8083 DVB-S",
    444		.frequency_min_hz	=  920 * MHz,     /* TDA8060 */
    445		.frequency_max_hz	= 2200 * MHz,    /* TDA8060 */
    446		.frequency_stepsize_hz	=  125 * kHz,
    447		.symbol_rate_min	= 12000000,
    448		.symbol_rate_max	= 30000000,
    449	/*      .symbol_rate_tolerance	= ???,*/
    450		.caps = FE_CAN_INVERSION_AUTO |
    451			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
    452			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
    453			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
    454			FE_CAN_QPSK | FE_CAN_MUTE_TS
    455	},
    456
    457	.release = tda8083_release,
    458
    459	.init = tda8083_init,
    460	.sleep = tda8083_sleep,
    461
    462	.set_frontend = tda8083_set_frontend,
    463	.get_frontend = tda8083_get_frontend,
    464
    465	.read_status = tda8083_read_status,
    466	.read_signal_strength = tda8083_read_signal_strength,
    467	.read_snr = tda8083_read_snr,
    468	.read_ber = tda8083_read_ber,
    469	.read_ucblocks = tda8083_read_ucblocks,
    470
    471	.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
    472	.diseqc_send_burst = tda8083_diseqc_send_burst,
    473	.set_tone = tda8083_diseqc_set_tone,
    474	.set_voltage = tda8083_diseqc_set_voltage,
    475};
    476
    477module_param(debug, int, 0644);
    478MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
    479
    480MODULE_DESCRIPTION("Philips TDA8083 DVB-S Demodulator");
    481MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
    482MODULE_LICENSE("GPL");
    483
    484EXPORT_SYMBOL(tda8083_attach);