brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · 2ad0a3c Raw
332 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * E3C EC100 demodulator driver4 *5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>6 */7 8#include <media/dvb_frontend.h>9#include "ec100.h"10 11struct ec100_state {12	struct i2c_adapter *i2c;13	struct dvb_frontend frontend;14	struct ec100_config config;15 16	u16 ber;17};18 19/* write single register */20static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)21{22	int ret;23	u8 buf[2] = {reg, val};24	struct i2c_msg msg[1] = {25		{26			.addr = state->config.demod_address,27			.flags = 0,28			.len = sizeof(buf),29			.buf = buf,30		}31	};32 33	ret = i2c_transfer(state->i2c, msg, 1);34	if (ret == 1) {35		ret = 0;36	} else {37		dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",38				KBUILD_MODNAME, ret, reg);39		ret = -EREMOTEIO;40	}41 42	return ret;43}44 45/* read single register */46static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)47{48	int ret;49	struct i2c_msg msg[2] = {50		{51			.addr = state->config.demod_address,52			.flags = 0,53			.len = 1,54			.buf = &reg55		}, {56			.addr = state->config.demod_address,57			.flags = I2C_M_RD,58			.len = 1,59			.buf = val60		}61	};62 63	ret = i2c_transfer(state->i2c, msg, 2);64	if (ret == 2) {65		ret = 0;66	} else {67		dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n",68				KBUILD_MODNAME, ret, reg);69		ret = -EREMOTEIO;70	}71 72	return ret;73}74 75static int ec100_set_frontend(struct dvb_frontend *fe)76{77	struct dtv_frontend_properties *c = &fe->dtv_property_cache;78	struct ec100_state *state = fe->demodulator_priv;79	int ret;80	u8 tmp, tmp2;81 82	dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",83			__func__, c->frequency, c->bandwidth_hz);84 85	/* program tuner */86	if (fe->ops.tuner_ops.set_params)87		fe->ops.tuner_ops.set_params(fe);88 89	ret = ec100_write_reg(state, 0x04, 0x06);90	if (ret)91		goto error;92	ret = ec100_write_reg(state, 0x67, 0x58);93	if (ret)94		goto error;95	ret = ec100_write_reg(state, 0x05, 0x18);96	if (ret)97		goto error;98 99	/* reg/bw |   6  |   7  |   8100	   -------+------+------+------101	   A 0x1b | 0xa1 | 0xe7 | 0x2c102	   A 0x1c | 0x55 | 0x63 | 0x72103	   -------+------+------+------104	   B 0x1b | 0xb7 | 0x00 | 0x49105	   B 0x1c | 0x55 | 0x64 | 0x72 */106 107	switch (c->bandwidth_hz) {108	case 6000000:109		tmp = 0xb7;110		tmp2 = 0x55;111		break;112	case 7000000:113		tmp = 0x00;114		tmp2 = 0x64;115		break;116	case 8000000:117	default:118		tmp = 0x49;119		tmp2 = 0x72;120	}121 122	ret = ec100_write_reg(state, 0x1b, tmp);123	if (ret)124		goto error;125	ret = ec100_write_reg(state, 0x1c, tmp2);126	if (ret)127		goto error;128 129	ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */130	if (ret)131		goto error;132	ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */133	if (ret)134		goto error;135 136	ret = ec100_write_reg(state, 0x08, 0x24);137	if (ret)138		goto error;139 140	ret = ec100_write_reg(state, 0x00, 0x00); /* go */141	if (ret)142		goto error;143	ret = ec100_write_reg(state, 0x00, 0x20); /* go */144	if (ret)145		goto error;146 147	return ret;148error:149	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);150	return ret;151}152 153static int ec100_get_tune_settings(struct dvb_frontend *fe,154	struct dvb_frontend_tune_settings *fesettings)155{156	fesettings->min_delay_ms = 300;157	fesettings->step_size = 0;158	fesettings->max_drift = 0;159 160	return 0;161}162 163static int ec100_read_status(struct dvb_frontend *fe, enum fe_status *status)164{165	struct ec100_state *state = fe->demodulator_priv;166	int ret;167	u8 tmp;168	*status = 0;169 170	ret = ec100_read_reg(state, 0x42, &tmp);171	if (ret)172		goto error;173 174	if (tmp & 0x80) {175		/* bit7 set - have lock */176		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |177			FE_HAS_SYNC | FE_HAS_LOCK;178	} else {179		ret = ec100_read_reg(state, 0x01, &tmp);180		if (ret)181			goto error;182 183		if (tmp & 0x10) {184			/* bit4 set - have signal */185			*status |= FE_HAS_SIGNAL;186			if (!(tmp & 0x01)) {187				/* bit0 clear - have ~valid signal */188				*status |= FE_HAS_CARRIER |  FE_HAS_VITERBI;189			}190		}191	}192 193	return ret;194error:195	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);196	return ret;197}198 199static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)200{201	struct ec100_state *state = fe->demodulator_priv;202	int ret;203	u8 tmp, tmp2;204	u16 ber2;205 206	*ber = 0;207 208	ret = ec100_read_reg(state, 0x65, &tmp);209	if (ret)210		goto error;211	ret = ec100_read_reg(state, 0x66, &tmp2);212	if (ret)213		goto error;214 215	ber2 = (tmp2 << 8) | tmp;216 217	/* if counter overflow or clear */218	if (ber2 < state->ber)219		*ber = ber2;220	else221		*ber = ber2 - state->ber;222 223	state->ber = ber2;224 225	return ret;226error:227	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);228	return ret;229}230 231static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)232{233	struct ec100_state *state = fe->demodulator_priv;234	int ret;235	u8 tmp;236 237	ret = ec100_read_reg(state, 0x24, &tmp);238	if (ret) {239		*strength = 0;240		goto error;241	}242 243	*strength = ((tmp << 8) | tmp);244 245	return ret;246error:247	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);248	return ret;249}250 251static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)252{253	*snr = 0;254	return 0;255}256 257static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)258{259	*ucblocks = 0;260	return 0;261}262 263static void ec100_release(struct dvb_frontend *fe)264{265	struct ec100_state *state = fe->demodulator_priv;266	kfree(state);267}268 269static const struct dvb_frontend_ops ec100_ops;270 271struct dvb_frontend *ec100_attach(const struct ec100_config *config,272	struct i2c_adapter *i2c)273{274	int ret;275	struct ec100_state *state = NULL;276	u8 tmp;277 278	/* allocate memory for the internal state */279	state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);280	if (state == NULL)281		goto error;282 283	/* setup the state */284	state->i2c = i2c;285	memcpy(&state->config, config, sizeof(struct ec100_config));286 287	/* check if the demod is there */288	ret = ec100_read_reg(state, 0x33, &tmp);289	if (ret || tmp != 0x0b)290		goto error;291 292	/* create dvb_frontend */293	memcpy(&state->frontend.ops, &ec100_ops,294		sizeof(struct dvb_frontend_ops));295	state->frontend.demodulator_priv = state;296 297	return &state->frontend;298error:299	kfree(state);300	return NULL;301}302EXPORT_SYMBOL_GPL(ec100_attach);303 304static const struct dvb_frontend_ops ec100_ops = {305	.delsys = { SYS_DVBT },306	.info = {307		.name = "E3C EC100 DVB-T",308		.caps =309			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |310			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |311			FE_CAN_QPSK | FE_CAN_QAM_16 |312			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |313			FE_CAN_TRANSMISSION_MODE_AUTO |314			FE_CAN_GUARD_INTERVAL_AUTO |315			FE_CAN_HIERARCHY_AUTO |316			FE_CAN_MUTE_TS317	},318 319	.release = ec100_release,320	.set_frontend = ec100_set_frontend,321	.get_tune_settings = ec100_get_tune_settings,322	.read_status = ec100_read_status,323	.read_ber = ec100_read_ber,324	.read_signal_strength = ec100_read_signal_strength,325	.read_snr = ec100_read_snr,326	.read_ucblocks = ec100_read_ucblocks,327};328 329MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");330MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");331MODULE_LICENSE("GPL");332