brintos

brintos / linux-shallow public Read only

0
0
Text · 19.2 KiB · d6b6b8b Raw
815 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Silicon Labs Si2168 DVB-T/T2/C demodulator driver4 *5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>6 */7 8#include <linux/delay.h>9 10#include "si2168_priv.h"11 12static const struct dvb_frontend_ops si2168_ops;13 14static void cmd_init(struct si2168_cmd *cmd, const u8 *buf, int wlen, int rlen)15{16	memcpy(cmd->args, buf, wlen);17	cmd->wlen = wlen;18	cmd->rlen = rlen;19}20 21/* execute firmware command */22static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)23{24	struct si2168_dev *dev = i2c_get_clientdata(client);25	int ret;26	unsigned long timeout;27 28	mutex_lock(&dev->i2c_mutex);29 30	if (cmd->wlen) {31		/* write cmd and args for firmware */32		ret = i2c_master_send(client, cmd->args, cmd->wlen);33		if (ret < 0) {34			goto err_mutex_unlock;35		} else if (ret != cmd->wlen) {36			ret = -EREMOTEIO;37			goto err_mutex_unlock;38		}39	}40 41	if (cmd->rlen) {42		/* wait cmd execution terminate */43		#define TIMEOUT 7044		timeout = jiffies + msecs_to_jiffies(TIMEOUT);45		while (!time_after(jiffies, timeout)) {46			ret = i2c_master_recv(client, cmd->args, cmd->rlen);47			if (ret < 0) {48				goto err_mutex_unlock;49			} else if (ret != cmd->rlen) {50				ret = -EREMOTEIO;51				goto err_mutex_unlock;52			}53 54			/* firmware ready? */55			if ((cmd->args[0] >> 7) & 0x01)56				break;57		}58 59		dev_dbg(&client->dev, "cmd execution took %d ms\n",60				jiffies_to_msecs(jiffies) -61				(jiffies_to_msecs(timeout) - TIMEOUT));62 63		/* error bit set? */64		if ((cmd->args[0] >> 6) & 0x01) {65			ret = -EREMOTEIO;66			goto err_mutex_unlock;67		}68 69		if (!((cmd->args[0] >> 7) & 0x01)) {70			ret = -ETIMEDOUT;71			goto err_mutex_unlock;72		}73	}74 75	mutex_unlock(&dev->i2c_mutex);76	return 0;77err_mutex_unlock:78	mutex_unlock(&dev->i2c_mutex);79	dev_dbg(&client->dev, "failed=%d\n", ret);80	return ret;81}82 83static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)84{85	struct i2c_client *client = fe->demodulator_priv;86	struct si2168_dev *dev = i2c_get_clientdata(client);87	struct si2168_cmd cmd;88	int ret = 0;89 90	dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire);91 92	/* set manual value */93	if (dev->ts_mode & SI2168_TS_CLK_MANUAL) {94		cmd_init(&cmd, "\x14\x00\x0d\x10\xe8\x03", 6, 4);95		ret = si2168_cmd_execute(client, &cmd);96		if (ret)97			return ret;98	}99	/* set TS_MODE property */100	cmd_init(&cmd, "\x14\x00\x01\x10\x10\x00", 6, 4);101	if (dev->ts_mode & SI2168_TS_CLK_MANUAL)102		cmd.args[4] = SI2168_TS_CLK_MANUAL;103	if (acquire)104		cmd.args[4] |= dev->ts_mode;105	else106		cmd.args[4] |= SI2168_TS_TRISTATE;107	if (dev->ts_clock_gapped)108		cmd.args[4] |= 0x40;109	ret = si2168_cmd_execute(client, &cmd);110 111	return ret;112}113 114static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status)115{116	struct i2c_client *client = fe->demodulator_priv;117	struct si2168_dev *dev = i2c_get_clientdata(client);118	struct dtv_frontend_properties *c = &fe->dtv_property_cache;119	int ret, i;120	unsigned int utmp, utmp1, utmp2;121	struct si2168_cmd cmd;122 123	*status = 0;124 125	if (!dev->active) {126		ret = -EAGAIN;127		goto err;128	}129 130	switch (c->delivery_system) {131	case SYS_DVBT:132		cmd_init(&cmd, "\xa0\x01", 2, 13);133		break;134	case SYS_DVBC_ANNEX_A:135		cmd_init(&cmd, "\x90\x01", 2, 9);136		break;137	case SYS_DVBT2:138		cmd_init(&cmd, "\x50\x01", 2, 14);139		break;140	default:141		ret = -EINVAL;142		goto err;143	}144 145	ret = si2168_cmd_execute(client, &cmd);146	if (ret)147		goto err;148 149	switch ((cmd.args[2] >> 1) & 0x03) {150	case 0x01:151		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;152		break;153	case 0x03:154		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |155				FE_HAS_SYNC | FE_HAS_LOCK;156		break;157	}158 159	dev->fe_status = *status;160 161	if (*status & FE_HAS_LOCK) {162		c->cnr.len = 1;163		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;164		c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;165	} else {166		c->cnr.len = 1;167		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;168	}169 170	dev_dbg(&client->dev, "status=%02x args=%*ph\n",171			*status, cmd.rlen, cmd.args);172 173	/* BER */174	if (*status & FE_HAS_VITERBI) {175		cmd_init(&cmd, "\x82\x00", 2, 3);176		ret = si2168_cmd_execute(client, &cmd);177		if (ret)178			goto err;179 180		/*181		 * Firmware returns [0, 255] mantissa and [0, 8] exponent.182		 * Convert to DVB API: mantissa * 10^(8 - exponent) / 10^8183		 */184		utmp = clamp(8 - cmd.args[1], 0, 8);185		for (i = 0, utmp1 = 1; i < utmp; i++)186			utmp1 = utmp1 * 10;187 188		utmp1 = cmd.args[2] * utmp1;189		utmp2 = 100000000; /* 10^8 */190 191		dev_dbg(&client->dev,192			"post_bit_error=%u post_bit_count=%u ber=%u*10^-%u\n",193			utmp1, utmp2, cmd.args[2], cmd.args[1]);194 195		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;196		c->post_bit_error.stat[0].uvalue += utmp1;197		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;198		c->post_bit_count.stat[0].uvalue += utmp2;199	} else {200		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;201		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;202	}203 204	/* UCB */205	if (*status & FE_HAS_SYNC) {206		cmd_init(&cmd, "\x84\x01", 2, 3);207		ret = si2168_cmd_execute(client, &cmd);208		if (ret)209			goto err;210 211		utmp1 = cmd.args[2] << 8 | cmd.args[1] << 0;212		dev_dbg(&client->dev, "block_error=%u\n", utmp1);213 214		/* Sometimes firmware returns bogus value */215		if (utmp1 == 0xffff)216			utmp1 = 0;217 218		c->block_error.stat[0].scale = FE_SCALE_COUNTER;219		c->block_error.stat[0].uvalue += utmp1;220	} else {221		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;222	}223 224	return 0;225err:226	dev_dbg(&client->dev, "failed=%d\n", ret);227	return ret;228}229 230static int si2168_set_frontend(struct dvb_frontend *fe)231{232	struct i2c_client *client = fe->demodulator_priv;233	struct si2168_dev *dev = i2c_get_clientdata(client);234	struct dtv_frontend_properties *c = &fe->dtv_property_cache;235	int ret;236	struct si2168_cmd cmd;237	u8 bandwidth, delivery_system;238 239	dev_dbg(&client->dev,240			"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%u\n",241			c->delivery_system, c->modulation, c->frequency,242			c->bandwidth_hz, c->symbol_rate, c->inversion,243			c->stream_id);244 245	if (!dev->active) {246		ret = -EAGAIN;247		goto err;248	}249 250	switch (c->delivery_system) {251	case SYS_DVBT:252		delivery_system = 0x20;253		break;254	case SYS_DVBC_ANNEX_A:255		delivery_system = 0x30;256		break;257	case SYS_DVBT2:258		delivery_system = 0x70;259		break;260	default:261		ret = -EINVAL;262		goto err;263	}264 265	if (c->bandwidth_hz == 0) {266		ret = -EINVAL;267		goto err;268	} else if (c->bandwidth_hz <= 2000000)269		bandwidth = 0x02;270	else if (c->bandwidth_hz <= 5000000)271		bandwidth = 0x05;272	else if (c->bandwidth_hz <= 6000000)273		bandwidth = 0x06;274	else if (c->bandwidth_hz <= 7000000)275		bandwidth = 0x07;276	else if (c->bandwidth_hz <= 8000000)277		bandwidth = 0x08;278	else if (c->bandwidth_hz <= 9000000)279		bandwidth = 0x09;280	else if (c->bandwidth_hz <= 10000000)281		bandwidth = 0x0a;282	else283		bandwidth = 0x0f;284 285	/* program tuner */286	if (fe->ops.tuner_ops.set_params) {287		ret = fe->ops.tuner_ops.set_params(fe);288		if (ret)289			goto err;290	}291 292	cmd_init(&cmd, "\x88\x02\x02\x02\x02", 5, 5);293	ret = si2168_cmd_execute(client, &cmd);294	if (ret)295		goto err;296 297	/* that has no big effect */298	if (c->delivery_system == SYS_DVBT)299		cmd_init(&cmd, "\x89\x21\x06\x11\xff\x98", 6, 3);300	else if (c->delivery_system == SYS_DVBC_ANNEX_A)301		cmd_init(&cmd, "\x89\x21\x06\x11\x89\xf0", 6, 3);302	else if (c->delivery_system == SYS_DVBT2)303		cmd_init(&cmd, "\x89\x21\x06\x11\x89\x20", 6, 3);304	ret = si2168_cmd_execute(client, &cmd);305	if (ret)306		goto err;307 308	if (c->delivery_system == SYS_DVBT2) {309		/* select PLP */310		cmd.args[0] = 0x52;311		cmd.args[1] = c->stream_id & 0xff;312		cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;313		cmd.wlen = 3;314		cmd.rlen = 1;315		ret = si2168_cmd_execute(client, &cmd);316		if (ret)317			goto err;318	}319 320	cmd_init(&cmd, "\x51\x03", 2, 12);321	ret = si2168_cmd_execute(client, &cmd);322	if (ret)323		goto err;324 325	cmd_init(&cmd, "\x12\x08\x04", 3, 3);326	ret = si2168_cmd_execute(client, &cmd);327	if (ret)328		goto err;329 330	cmd_init(&cmd, "\x14\x00\x0c\x10\x12\x00", 6, 4);331	ret = si2168_cmd_execute(client, &cmd);332	if (ret)333		goto err;334 335	cmd_init(&cmd, "\x14\x00\x06\x10\x24\x00", 6, 4);336	ret = si2168_cmd_execute(client, &cmd);337	if (ret)338		goto err;339 340	cmd_init(&cmd, "\x14\x00\x07\x10\x00\x24", 6, 4);341	ret = si2168_cmd_execute(client, &cmd);342	if (ret)343		goto err;344 345	cmd_init(&cmd, "\x14\x00\x0a\x10\x00\x00", 6, 4);346	cmd.args[4] = delivery_system | bandwidth;347	if (dev->spectral_inversion)348		cmd.args[5] |= 1;349	ret = si2168_cmd_execute(client, &cmd);350	if (ret)351		goto err;352 353	/* set DVB-C symbol rate */354	if (c->delivery_system == SYS_DVBC_ANNEX_A) {355		cmd_init(&cmd, "\x14\x00\x02\x11\x00\x00", 6, 4);356		cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff;357		cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;358		ret = si2168_cmd_execute(client, &cmd);359		if (ret)360			goto err;361	}362 363	cmd_init(&cmd, "\x14\x00\x0f\x10\x10\x00", 6, 4);364	ret = si2168_cmd_execute(client, &cmd);365	if (ret)366		goto err;367 368	cmd_init(&cmd, "\x14\x00\x09\x10\xe3\x08", 6, 4);369	cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;370	ret = si2168_cmd_execute(client, &cmd);371	if (ret)372		goto err;373 374	cmd_init(&cmd, "\x14\x00\x08\x10\xd7\x05", 6, 4);375	cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;376	ret = si2168_cmd_execute(client, &cmd);377	if (ret)378		goto err;379 380	cmd_init(&cmd, "\x14\x00\x01\x12\x00\x00", 6, 4);381	ret = si2168_cmd_execute(client, &cmd);382	if (ret)383		goto err;384 385	cmd_init(&cmd, "\x14\x00\x01\x03\x0c\x00", 6, 4);386	ret = si2168_cmd_execute(client, &cmd);387	if (ret)388		goto err;389 390	cmd_init(&cmd, "\x85", 1, 1);391	ret = si2168_cmd_execute(client, &cmd);392	if (ret)393		goto err;394 395	dev->delivery_system = c->delivery_system;396 397	/* enable ts bus */398	ret = si2168_ts_bus_ctrl(fe, 1);399	if (ret)400		goto err;401 402	return 0;403err:404	dev_dbg(&client->dev, "failed=%d\n", ret);405	return ret;406}407 408static int si2168_init(struct dvb_frontend *fe)409{410	struct i2c_client *client = fe->demodulator_priv;411	struct si2168_dev *dev = i2c_get_clientdata(client);412	struct dtv_frontend_properties *c = &fe->dtv_property_cache;413	int ret, len, remaining;414	const struct firmware *fw;415	struct si2168_cmd cmd;416 417	dev_dbg(&client->dev, "\n");418 419	/* initialize */420	cmd_init(&cmd, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00",421		 13, 0);422	ret = si2168_cmd_execute(client, &cmd);423	if (ret)424		goto err;425 426	if (dev->warm) {427		/* resume */428		cmd_init(&cmd, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8, 1);429		ret = si2168_cmd_execute(client, &cmd);430		if (ret)431			goto err;432 433		udelay(100);434		cmd_init(&cmd, "\x85", 1, 1);435		ret = si2168_cmd_execute(client, &cmd);436		if (ret)437			goto err;438 439		goto warm;440	}441 442	/* power up */443	cmd_init(&cmd, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8, 1);444	ret = si2168_cmd_execute(client, &cmd);445	if (ret)446		goto err;447 448	/* request the firmware, this will block and timeout */449	ret = request_firmware(&fw, dev->firmware_name, &client->dev);450	if (ret) {451		dev_err(&client->dev,452			"firmware file '%s' not found\n",453			dev->firmware_name);454		goto err_release_firmware;455	}456 457	dev_info(&client->dev, "downloading firmware from file '%s'\n",458			dev->firmware_name);459 460	if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {461		/* firmware is in the new format */462		for (remaining = fw->size; remaining > 0; remaining -= 17) {463			len = fw->data[fw->size - remaining];464			if (len > SI2168_ARGLEN) {465				ret = -EINVAL;466				break;467			}468			cmd_init(&cmd, &fw->data[(fw->size - remaining) + 1],469				 len, 1);470			ret = si2168_cmd_execute(client, &cmd);471			if (ret)472				break;473		}474	} else if (fw->size % 8 == 0) {475		/* firmware is in the old format */476		for (remaining = fw->size; remaining > 0; remaining -= 8) {477			cmd_init(&cmd, &fw->data[fw->size - remaining], 8, 1);478			ret = si2168_cmd_execute(client, &cmd);479			if (ret)480				break;481		}482	} else {483		/* bad or unknown firmware format */484		ret = -EINVAL;485	}486 487	if (ret) {488		dev_err(&client->dev, "firmware download failed %d\n", ret);489		goto err_release_firmware;490	}491 492	release_firmware(fw);493 494	cmd_init(&cmd, "\x01\x01", 2, 1);495	ret = si2168_cmd_execute(client, &cmd);496	if (ret)497		goto err;498 499	/* query firmware version */500	cmd_init(&cmd, "\x11", 1, 10);501	ret = si2168_cmd_execute(client, &cmd);502	if (ret)503		goto err;504 505	dev->version = (cmd.args[9] + '@') << 24 | (cmd.args[6] - '0') << 16 |506		       (cmd.args[7] - '0') << 8 | (cmd.args[8]) << 0;507	dev_info(&client->dev, "firmware version: %c %d.%d.%d\n",508		 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff,509		 dev->version >> 8 & 0xff, dev->version >> 0 & 0xff);510 511	/* set ts mode */512	ret = si2168_ts_bus_ctrl(fe, 1);513	if (ret)514		goto err;515 516	dev->warm = true;517	dev->initialized = true;518warm:519	/* Init stats here to indicate which stats are supported */520	c->cnr.len = 1;521	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;522	c->post_bit_error.len = 1;523	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;524	c->post_bit_count.len = 1;525	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;526	c->block_error.len = 1;527	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;528 529	dev->active = true;530 531	return 0;532err_release_firmware:533	release_firmware(fw);534err:535	dev_dbg(&client->dev, "failed=%d\n", ret);536	return ret;537}538 539static int si2168_resume(struct dvb_frontend *fe)540{541	struct i2c_client *client = fe->demodulator_priv;542	struct si2168_dev *dev = i2c_get_clientdata(client);543 544	/*545	 * check whether si2168_init() has been called successfully546	 * outside of a resume cycle. Only call it (and load firmware)547	 * in this case. si2168_init() is only called during resume548	 * once the device has actually been used. Otherwise, leave the549	 * device untouched.550	 */551	if (dev->initialized) {552		dev_dbg(&client->dev, "previously initialized, call si2168_init()\n");553		return si2168_init(fe);554	}555	dev_dbg(&client->dev, "not initialized yet, skipping init on resume\n");556	return 0;557}558 559static int si2168_sleep(struct dvb_frontend *fe)560{561	struct i2c_client *client = fe->demodulator_priv;562	struct si2168_dev *dev = i2c_get_clientdata(client);563	int ret;564	struct si2168_cmd cmd;565 566	dev_dbg(&client->dev, "\n");567 568	dev->active = false;569 570	/* tri-state data bus */571	ret = si2168_ts_bus_ctrl(fe, 0);572	if (ret)573		goto err;574 575	/* Firmware later than B 4.0-11 loses warm state during sleep */576	if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0))577		dev->warm = false;578 579	cmd_init(&cmd, "\x13", 1, 0);580	ret = si2168_cmd_execute(client, &cmd);581	if (ret)582		goto err;583 584	return 0;585err:586	dev_dbg(&client->dev, "failed=%d\n", ret);587	return ret;588}589 590static int si2168_get_tune_settings(struct dvb_frontend *fe,591	struct dvb_frontend_tune_settings *s)592{593	s->min_delay_ms = 900;594 595	return 0;596}597 598static int si2168_select(struct i2c_mux_core *muxc, u32 chan)599{600	struct i2c_client *client = i2c_mux_priv(muxc);601	int ret;602	struct si2168_cmd cmd;603 604	/* open I2C gate */605	cmd_init(&cmd, "\xc0\x0d\x01", 3, 0);606	ret = si2168_cmd_execute(client, &cmd);607	if (ret)608		goto err;609 610	return 0;611err:612	dev_dbg(&client->dev, "failed=%d\n", ret);613	return ret;614}615 616static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan)617{618	struct i2c_client *client = i2c_mux_priv(muxc);619	int ret;620	struct si2168_cmd cmd;621 622	/* close I2C gate */623	cmd_init(&cmd, "\xc0\x0d\x00", 3, 0);624	ret = si2168_cmd_execute(client, &cmd);625	if (ret)626		goto err;627 628	return 0;629err:630	dev_dbg(&client->dev, "failed=%d\n", ret);631	return ret;632}633 634static const struct dvb_frontend_ops si2168_ops = {635	.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},636	.info = {637		.name = "Silicon Labs Si2168",638		.frequency_min_hz      =  48 * MHz,639		.frequency_max_hz      = 870 * MHz,640		.frequency_stepsize_hz = 62500,641		.symbol_rate_min       = 1000000,642		.symbol_rate_max       = 7200000,643		.caps =	FE_CAN_FEC_1_2 |644			FE_CAN_FEC_2_3 |645			FE_CAN_FEC_3_4 |646			FE_CAN_FEC_5_6 |647			FE_CAN_FEC_7_8 |648			FE_CAN_FEC_AUTO |649			FE_CAN_QPSK |650			FE_CAN_QAM_16 |651			FE_CAN_QAM_32 |652			FE_CAN_QAM_64 |653			FE_CAN_QAM_128 |654			FE_CAN_QAM_256 |655			FE_CAN_QAM_AUTO |656			FE_CAN_TRANSMISSION_MODE_AUTO |657			FE_CAN_GUARD_INTERVAL_AUTO |658			FE_CAN_HIERARCHY_AUTO |659			FE_CAN_MUTE_TS |660			FE_CAN_2G_MODULATION |661			FE_CAN_MULTISTREAM662	},663 664	.get_tune_settings = si2168_get_tune_settings,665 666	.init = si2168_init,667	.sleep = si2168_sleep,668	.resume = si2168_resume,669 670	.set_frontend = si2168_set_frontend,671 672	.read_status = si2168_read_status,673};674 675static int si2168_probe(struct i2c_client *client)676{677	struct si2168_config *config = client->dev.platform_data;678	struct si2168_dev *dev;679	int ret;680	struct si2168_cmd cmd;681 682	dev_dbg(&client->dev, "\n");683 684	dev = kzalloc(sizeof(*dev), GFP_KERNEL);685	if (!dev) {686		ret = -ENOMEM;687		goto err;688	}689 690	i2c_set_clientdata(client, dev);691	mutex_init(&dev->i2c_mutex);692 693	/* Initialize */694	cmd_init(&cmd, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00",695		 13, 0);696	ret = si2168_cmd_execute(client, &cmd);697	if (ret)698		goto err_kfree;699 700	/* Power up */701	cmd_init(&cmd, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8, 1);702	ret = si2168_cmd_execute(client, &cmd);703	if (ret)704		goto err_kfree;705 706	/* Query chip revision */707	cmd_init(&cmd, "\x02", 1, 13);708	ret = si2168_cmd_execute(client, &cmd);709	if (ret)710		goto err_kfree;711 712	dev->chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 |713		       cmd.args[3] << 8 | cmd.args[4] << 0;714 715	switch (dev->chip_id) {716	case SI2168_CHIP_ID_A20:717		dev->firmware_name = SI2168_A20_FIRMWARE;718		break;719	case SI2168_CHIP_ID_A30:720		dev->firmware_name = SI2168_A30_FIRMWARE;721		break;722	case SI2168_CHIP_ID_B40:723		dev->firmware_name = SI2168_B40_FIRMWARE;724		break;725	case SI2168_CHIP_ID_D60:726		dev->firmware_name = SI2168_D60_FIRMWARE;727		break;728	default:729		dev_dbg(&client->dev, "unknown chip version Si21%d-%c%c%c\n",730			cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);731		ret = -ENODEV;732		goto err_kfree;733	}734 735	dev->version = (cmd.args[1]) << 24 | (cmd.args[3] - '0') << 16 |736		       (cmd.args[4] - '0') << 8 | (cmd.args[5]) << 0;737 738	/* create mux i2c adapter for tuner */739	dev->muxc = i2c_mux_alloc(client->adapter, &client->dev,740				  1, 0, I2C_MUX_LOCKED,741				  si2168_select, si2168_deselect);742	if (!dev->muxc) {743		ret = -ENOMEM;744		goto err_kfree;745	}746	dev->muxc->priv = client;747	ret = i2c_mux_add_adapter(dev->muxc, 0, 0);748	if (ret)749		goto err_kfree;750 751	/* create dvb_frontend */752	memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));753	dev->fe.demodulator_priv = client;754	*config->i2c_adapter = dev->muxc->adapter[0];755	*config->fe = &dev->fe;756	dev->ts_mode = config->ts_mode;757	dev->ts_clock_inv = config->ts_clock_inv;758	dev->ts_clock_gapped = config->ts_clock_gapped;759	dev->spectral_inversion = config->spectral_inversion;760 761	dev_info(&client->dev, "Silicon Labs Si2168-%c%d%d successfully identified\n",762		 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff,763		 dev->version >> 8 & 0xff);764	dev_info(&client->dev, "firmware version: %c %d.%d.%d\n",765		 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff,766		 dev->version >> 8 & 0xff, dev->version >> 0 & 0xff);767 768	return 0;769err_kfree:770	kfree(dev);771err:772	dev_warn(&client->dev, "probe failed = %d\n", ret);773	return ret;774}775 776static void si2168_remove(struct i2c_client *client)777{778	struct si2168_dev *dev = i2c_get_clientdata(client);779 780	dev_dbg(&client->dev, "\n");781 782	i2c_mux_del_adapters(dev->muxc);783 784	dev->fe.ops.release = NULL;785	dev->fe.demodulator_priv = NULL;786 787	kfree(dev);788}789 790static const struct i2c_device_id si2168_id_table[] = {791	{ "si2168" },792	{}793};794MODULE_DEVICE_TABLE(i2c, si2168_id_table);795 796static struct i2c_driver si2168_driver = {797	.driver = {798		.name                = "si2168",799		.suppress_bind_attrs = true,800	},801	.probe		= si2168_probe,802	.remove		= si2168_remove,803	.id_table	= si2168_id_table,804};805 806module_i2c_driver(si2168_driver);807 808MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");809MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");810MODULE_LICENSE("GPL");811MODULE_FIRMWARE(SI2168_A20_FIRMWARE);812MODULE_FIRMWARE(SI2168_A30_FIRMWARE);813MODULE_FIRMWARE(SI2168_B40_FIRMWARE);814MODULE_FIRMWARE(SI2168_D60_FIRMWARE);815