brintos

brintos / linux-shallow public Read only

0
0
Text · 29.1 KiB · 0037b4b Raw
1176 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 DVB device driver for cx231xx4 5 Copyright (C) 2008 <srinivasa.deevi at conexant dot com>6		Based on em28xx driver7 8 */9 10#include "cx231xx.h"11#include <linux/kernel.h>12#include <linux/slab.h>13 14#include <media/dvbdev.h>15#include <media/dmxdev.h>16#include <media/dvb_demux.h>17#include <media/dvb_net.h>18#include <media/dvb_frontend.h>19#include <media/v4l2-common.h>20#include <media/tuner.h>21 22#include "xc5000.h"23#include "s5h1432.h"24#include "tda18271.h"25#include "s5h1411.h"26#include "lgdt3305.h"27#include "si2165.h"28#include "si2168.h"29#include "mb86a20s.h"30#include "si2157.h"31#include "lgdt3306a.h"32#include "r820t.h"33#include "mn88473.h"34 35MODULE_DESCRIPTION("driver for cx231xx based DVB cards");36MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");37MODULE_LICENSE("GPL");38 39static unsigned int debug;40module_param(debug, int, 0644);41MODULE_PARM_DESC(debug, "enable debug messages [dvb]");42 43DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);44 45#define CX231XX_DVB_NUM_BUFS 546#define CX231XX_DVB_MAX_PACKETSIZE 56447#define CX231XX_DVB_MAX_PACKETS 6448#define CX231XX_DVB_MAX_FRONTENDS 249 50struct cx231xx_dvb {51	struct dvb_frontend *frontend[CX231XX_DVB_MAX_FRONTENDS];52 53	/* feed count management */54	struct mutex lock;55	int nfeeds;56 57	/* general boilerplate stuff */58	struct dvb_adapter adapter;59	struct dvb_demux demux;60	struct dmxdev dmxdev;61	struct dmx_frontend fe_hw;62	struct dmx_frontend fe_mem;63	struct dvb_net net;64	struct i2c_client *i2c_client_demod[2];65	struct i2c_client *i2c_client_tuner;66};67 68static struct s5h1432_config dvico_s5h1432_config = {69	.output_mode   = S5H1432_SERIAL_OUTPUT,70	.gpio          = S5H1432_GPIO_ON,71	.qam_if        = S5H1432_IF_4000,72	.vsb_if        = S5H1432_IF_4000,73	.inversion     = S5H1432_INVERSION_OFF,74	.status_mode   = S5H1432_DEMODLOCKING,75	.mpeg_timing   = S5H1432_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,76};77 78static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {79	.dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,80		      .if_lvl = 1, .rfagc_top = 0x37, },81	.dvbt_7   = { .if_freq = 4000, .agc_mode = 3, .std = 5,82		      .if_lvl = 1, .rfagc_top = 0x37, },83	.dvbt_8   = { .if_freq = 4000, .agc_mode = 3, .std = 6,84		      .if_lvl = 1, .rfagc_top = 0x37, },85};86 87static struct tda18271_std_map mb86a20s_tda18271_config = {88	.dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,89		      .if_lvl = 0, .rfagc_top = 0x37, },90};91 92static struct tda18271_config cnxt_rde253s_tunerconfig = {93	.std_map = &cnxt_rde253s_tda18271_std_map,94	.gate    = TDA18271_GATE_ANALOG,95};96 97static struct s5h1411_config tda18271_s5h1411_config = {98	.output_mode   = S5H1411_SERIAL_OUTPUT,99	.gpio          = S5H1411_GPIO_OFF,100	.vsb_if        = S5H1411_IF_3250,101	.qam_if        = S5H1411_IF_4000,102	.inversion     = S5H1411_INVERSION_ON,103	.status_mode   = S5H1411_DEMODLOCKING,104	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,105};106static struct s5h1411_config xc5000_s5h1411_config = {107	.output_mode   = S5H1411_SERIAL_OUTPUT,108	.gpio          = S5H1411_GPIO_OFF,109	.vsb_if        = S5H1411_IF_3250,110	.qam_if        = S5H1411_IF_3250,111	.inversion     = S5H1411_INVERSION_OFF,112	.status_mode   = S5H1411_DEMODLOCKING,113	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,114};115 116static struct lgdt3305_config hcw_lgdt3305_config = {117	.i2c_addr           = 0x0e,118	.mpeg_mode          = LGDT3305_MPEG_SERIAL,119	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,120	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,121	.deny_i2c_rptr      = 1,122	.spectral_inversion = 1,123	.qam_if_khz         = 4000,124	.vsb_if_khz         = 3250,125};126 127static struct tda18271_std_map hauppauge_tda18271_std_map = {128	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,129		      .if_lvl = 1, .rfagc_top = 0x58, },130	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,131		      .if_lvl = 1, .rfagc_top = 0x58, },132};133 134static struct tda18271_config hcw_tda18271_config = {135	.std_map = &hauppauge_tda18271_std_map,136	.gate    = TDA18271_GATE_DIGITAL,137};138 139static const struct mb86a20s_config pv_mb86a20s_config = {140	.demod_address = 0x10,141	.is_serial = true,142};143 144static struct tda18271_config pv_tda18271_config = {145	.std_map = &mb86a20s_tda18271_config,146	.gate    = TDA18271_GATE_DIGITAL,147	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,148};149 150static const struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = {151	.qam_if_khz         = 4000,152	.vsb_if_khz         = 3250,153	.spectral_inversion = 1,154	.mpeg_mode          = LGDT3306A_MPEG_SERIAL,155	.tpclk_edge         = LGDT3306A_TPCLK_RISING_EDGE,156	.tpvalid_polarity   = LGDT3306A_TP_VALID_HIGH,157	.xtalMHz            = 25,158};159 160static struct r820t_config astrometa_t2hybrid_r820t_config = {161	.i2c_addr		= 0x3a, /* 0x74 >> 1 */162	.xtal			= 16000000,163	.rafael_chip		= CHIP_R828D,164	.max_i2c_msg_len	= 2,165};166 167static inline void print_err_status(struct cx231xx *dev, int packet, int status)168{169	char *errmsg = "Unknown";170 171	switch (status) {172	case -ENOENT:173		errmsg = "unlinked synchronously";174		break;175	case -ECONNRESET:176		errmsg = "unlinked asynchronously";177		break;178	case -ENOSR:179		errmsg = "Buffer error (overrun)";180		break;181	case -EPIPE:182		errmsg = "Stalled (device not responding)";183		break;184	case -EOVERFLOW:185		errmsg = "Babble (bad cable?)";186		break;187	case -EPROTO:188		errmsg = "Bit-stuff error (bad cable?)";189		break;190	case -EILSEQ:191		errmsg = "CRC/Timeout (could be anything)";192		break;193	case -ETIME:194		errmsg = "Device does not respond";195		break;196	}197	if (packet < 0) {198		dev_dbg(dev->dev,199			"URB status %d [%s].\n", status, errmsg);200	} else {201		dev_dbg(dev->dev,202			"URB packet %d, status %d [%s].\n",203			packet, status, errmsg);204	}205}206 207static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)208{209	int i;210 211	if (!dev)212		return 0;213 214	if (dev->state & DEV_DISCONNECTED)215		return 0;216 217	if (urb->status < 0) {218		print_err_status(dev, -1, urb->status);219		if (urb->status == -ENOENT)220			return 0;221	}222 223	for (i = 0; i < urb->number_of_packets; i++) {224		int status = urb->iso_frame_desc[i].status;225 226		if (status < 0) {227			print_err_status(dev, i, status);228			if (urb->iso_frame_desc[i].status != -EPROTO)229				continue;230		}231 232		dvb_dmx_swfilter(&dev->dvb->demux,233				 urb->transfer_buffer +234				urb->iso_frame_desc[i].offset,235				urb->iso_frame_desc[i].actual_length);236	}237 238	return 0;239}240 241static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)242{243	if (!dev)244		return 0;245 246	if (dev->state & DEV_DISCONNECTED)247		return 0;248 249	if (urb->status < 0) {250		print_err_status(dev, -1, urb->status);251		if (urb->status == -ENOENT)252			return 0;253	}254 255	/* Feed the transport payload into the kernel demux */256	dvb_dmx_swfilter(&dev->dvb->demux,257		urb->transfer_buffer, urb->actual_length);258 259	return 0;260}261 262static int start_streaming(struct cx231xx_dvb *dvb)263{264	int rc;265	struct cx231xx *dev = dvb->adapter.priv;266 267	if (dev->USE_ISO) {268		dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");269		cx231xx_set_alt_setting(dev, INDEX_TS1, 5);270		rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);271		if (rc < 0)272			return rc;273		dev->mode_tv = 1;274		return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,275					CX231XX_DVB_NUM_BUFS,276					dev->ts1_mode.max_pkt_size,277					dvb_isoc_copy);278	} else {279		dev_dbg(dev->dev, "DVB transfer mode is BULK.\n");280		cx231xx_set_alt_setting(dev, INDEX_TS1, 0);281		rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);282		if (rc < 0)283			return rc;284		dev->mode_tv = 1;285		return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,286					CX231XX_DVB_NUM_BUFS,287					dev->ts1_mode.max_pkt_size,288					dvb_bulk_copy);289	}290 291}292 293static int stop_streaming(struct cx231xx_dvb *dvb)294{295	struct cx231xx *dev = dvb->adapter.priv;296 297	if (dev->USE_ISO)298		cx231xx_uninit_isoc(dev);299	else300		cx231xx_uninit_bulk(dev);301 302	cx231xx_set_mode(dev, CX231XX_SUSPEND);303 304	return 0;305}306 307static int start_feed(struct dvb_demux_feed *feed)308{309	struct dvb_demux *demux = feed->demux;310	struct cx231xx_dvb *dvb = demux->priv;311	int rc, ret;312 313	if (!demux->dmx.frontend)314		return -EINVAL;315 316	mutex_lock(&dvb->lock);317	dvb->nfeeds++;318	rc = dvb->nfeeds;319 320	if (dvb->nfeeds == 1) {321		ret = start_streaming(dvb);322		if (ret < 0)323			rc = ret;324	}325 326	mutex_unlock(&dvb->lock);327	return rc;328}329 330static int stop_feed(struct dvb_demux_feed *feed)331{332	struct dvb_demux *demux = feed->demux;333	struct cx231xx_dvb *dvb = demux->priv;334	int err = 0;335 336	mutex_lock(&dvb->lock);337	dvb->nfeeds--;338 339	if (0 == dvb->nfeeds)340		err = stop_streaming(dvb);341 342	mutex_unlock(&dvb->lock);343	return err;344}345 346/* ------------------------------------------------------------------ */347static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)348{349	struct cx231xx *dev = fe->dvb->priv;350 351	if (acquire)352		return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);353	else354		return cx231xx_set_mode(dev, CX231XX_SUSPEND);355}356 357/* ------------------------------------------------------------------ */358 359static struct xc5000_config cnxt_rde250_tunerconfig = {360	.i2c_address = 0x61,361	.if_khz = 4000,362};363static struct xc5000_config cnxt_rdu250_tunerconfig = {364	.i2c_address = 0x61,365	.if_khz = 3250,366};367 368/* ------------------------------------------------------------------ */369#if 0370static int attach_xc5000(u8 addr, struct cx231xx *dev)371{372 373	struct dvb_frontend *fe;374	struct xc5000_config cfg;375 376	memset(&cfg, 0, sizeof(cfg));377	cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);378	cfg.i2c_addr = addr;379 380	if (!dev->dvb->frontend[0]) {381		dev_err(dev->dev, "%s/2: dvb frontend not attached. Can't attach xc5000\n",382			dev->name);383		return -EINVAL;384	}385 386	fe = dvb_attach(xc5000_attach, dev->dvb->frontend[0], &cfg);387	if (!fe) {388		dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name);389		dvb_frontend_detach(dev->dvb->frontend[0]);390		dev->dvb->frontend[0] = NULL;391		return -EINVAL;392	}393 394	dev_info(dev->dev, "%s/2: xc5000 attached\n", dev->name);395 396	return 0;397}398#endif399 400int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)401{402	if (dev->dvb && dev->dvb->frontend[0]) {403 404		struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops;405 406		if (dops->set_analog_params != NULL) {407			struct analog_parameters params;408 409			params.frequency = freq;410			params.std = dev->norm;411			params.mode = 0;	/* 0- Air; 1 - cable */412			/*params.audmode = ;       */413 414			/* Set the analog parameters to set the frequency */415			dops->set_analog_params(dev->dvb->frontend[0], &params);416		}417 418	}419 420	return 0;421}422 423int cx231xx_reset_analog_tuner(struct cx231xx *dev)424{425	int status = 0;426 427	if (dev->dvb && dev->dvb->frontend[0]) {428 429		struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops;430 431		if (dops->init != NULL && !dev->xc_fw_load_done) {432 433			dev_dbg(dev->dev,434				"Reloading firmware for XC5000\n");435			status = dops->init(dev->dvb->frontend[0]);436			if (status == 0) {437				dev->xc_fw_load_done = 1;438				dev_dbg(dev->dev,439					"XC5000 firmware download completed\n");440			} else {441				dev->xc_fw_load_done = 0;442				dev_dbg(dev->dev,443					"XC5000 firmware download failed !!!\n");444			}445		}446 447	}448 449	return status;450}451 452/* ------------------------------------------------------------------ */453 454static int register_dvb(struct cx231xx_dvb *dvb,455			struct module *module,456			struct cx231xx *dev, struct device *device)457{458	int result;459 460	mutex_init(&dvb->lock);461 462 463	/* register adapter */464	result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,465				      adapter_nr);466	if (result < 0) {467		dev_warn(dev->dev,468		       "%s: dvb_register_adapter failed (errno = %d)\n",469		       dev->name, result);470		goto fail_adapter;471	}472	dvb_register_media_controller(&dvb->adapter, dev->media_dev);473 474	/* Ensure all frontends negotiate bus access */475	dvb->frontend[0]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;476	if (dvb->frontend[1])477		dvb->frontend[1]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;478 479	dvb->adapter.priv = dev;480 481	/* register frontend */482	result = dvb_register_frontend(&dvb->adapter, dvb->frontend[0]);483	if (result < 0) {484		dev_warn(dev->dev,485		       "%s: dvb_register_frontend failed (errno = %d)\n",486		       dev->name, result);487		goto fail_frontend0;488	}489 490	if (dvb->frontend[1]) {491		result = dvb_register_frontend(&dvb->adapter, dvb->frontend[1]);492		if (result < 0) {493			dev_warn(dev->dev,494				 "%s: 2nd dvb_register_frontend failed (errno = %d)\n",495				dev->name, result);496			goto fail_frontend1;497		}498 499		/* MFE lock */500		dvb->adapter.mfe_shared = 1;501	}502 503	/* register demux stuff */504	dvb->demux.dmx.capabilities =505	    DMX_TS_FILTERING | DMX_SECTION_FILTERING |506	    DMX_MEMORY_BASED_FILTERING;507	dvb->demux.priv = dvb;508	dvb->demux.filternum = 256;509	dvb->demux.feednum = 256;510	dvb->demux.start_feed = start_feed;511	dvb->demux.stop_feed = stop_feed;512 513	result = dvb_dmx_init(&dvb->demux);514	if (result < 0) {515		dev_warn(dev->dev,516			 "%s: dvb_dmx_init failed (errno = %d)\n",517		       dev->name, result);518		goto fail_dmx;519	}520 521	dvb->dmxdev.filternum = 256;522	dvb->dmxdev.demux = &dvb->demux.dmx;523	dvb->dmxdev.capabilities = 0;524	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);525	if (result < 0) {526		dev_warn(dev->dev,527			 "%s: dvb_dmxdev_init failed (errno = %d)\n",528			 dev->name, result);529		goto fail_dmxdev;530	}531 532	dvb->fe_hw.source = DMX_FRONTEND_0;533	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);534	if (result < 0) {535		dev_warn(dev->dev,536		       "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",537		       dev->name, result);538		goto fail_fe_hw;539	}540 541	dvb->fe_mem.source = DMX_MEMORY_FE;542	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);543	if (result < 0) {544		dev_warn(dev->dev,545			 "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",546			 dev->name, result);547		goto fail_fe_mem;548	}549 550	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);551	if (result < 0) {552		dev_warn(dev->dev,553			 "%s: connect_frontend failed (errno = %d)\n",554			 dev->name, result);555		goto fail_fe_conn;556	}557 558	/* register network adapter */559	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);560	result = dvb_create_media_graph(&dvb->adapter,561					dev->tuner_type == TUNER_ABSENT);562	if (result < 0)563		goto fail_create_graph;564 565	return 0;566 567fail_create_graph:568	dvb_net_release(&dvb->net);569fail_fe_conn:570	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);571fail_fe_mem:572	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);573fail_fe_hw:574	dvb_dmxdev_release(&dvb->dmxdev);575fail_dmxdev:576	dvb_dmx_release(&dvb->demux);577fail_dmx:578	if (dvb->frontend[1])579		dvb_unregister_frontend(dvb->frontend[1]);580	dvb_unregister_frontend(dvb->frontend[0]);581fail_frontend1:582	if (dvb->frontend[1])583		dvb_frontend_detach(dvb->frontend[1]);584fail_frontend0:585	dvb_frontend_detach(dvb->frontend[0]);586	dvb_unregister_adapter(&dvb->adapter);587fail_adapter:588	return result;589}590 591static void unregister_dvb(struct cx231xx_dvb *dvb)592{593	dvb_net_release(&dvb->net);594	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);595	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);596	dvb_dmxdev_release(&dvb->dmxdev);597	dvb_dmx_release(&dvb->demux);598	if (dvb->frontend[1])599		dvb_unregister_frontend(dvb->frontend[1]);600	dvb_unregister_frontend(dvb->frontend[0]);601	if (dvb->frontend[1])602		dvb_frontend_detach(dvb->frontend[1]);603	dvb_frontend_detach(dvb->frontend[0]);604	dvb_unregister_adapter(&dvb->adapter);605 606	/* remove I2C tuner */607	dvb_module_release(dvb->i2c_client_tuner);608	dvb->i2c_client_tuner = NULL;609	/* remove I2C demod(s) */610	dvb_module_release(dvb->i2c_client_demod[1]);611	dvb->i2c_client_demod[1] = NULL;612	dvb_module_release(dvb->i2c_client_demod[0]);613	dvb->i2c_client_demod[0] = NULL;614}615 616static int dvb_init(struct cx231xx *dev)617{618	int result;619	struct cx231xx_dvb *dvb;620	struct i2c_adapter *tuner_i2c;621	struct i2c_adapter *demod_i2c;622	struct i2c_client *client;623	struct i2c_adapter *adapter;624 625	if (!dev->board.has_dvb) {626		/* This device does not support the extension */627		return 0;628	}629 630	dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);631 632	if (dvb == NULL) {633		dev_info(dev->dev,634			 "cx231xx_dvb: memory allocation failed\n");635		return -ENOMEM;636	}637	dev->dvb = dvb;638	dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;639	dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;640 641	tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);642	demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);643	mutex_lock(&dev->lock);644	cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);645	cx231xx_demod_reset(dev);646	/* init frontend */647	switch (dev->model) {648	case CX231XX_BOARD_CNXT_CARRAERA:649	case CX231XX_BOARD_CNXT_RDE_250:650 651		dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,652					&dvico_s5h1432_config,653					demod_i2c);654 655		if (!dev->dvb->frontend[0]) {656			dev_err(dev->dev,657				"Failed to attach s5h1432 front end\n");658			result = -EINVAL;659			goto out_free;660		}661 662		/* define general-purpose callback pointer */663		dvb->frontend[0]->callback = cx231xx_tuner_callback;664 665		if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],666			       tuner_i2c,667			       &cnxt_rde250_tunerconfig)) {668			result = -EINVAL;669			goto out_free;670		}671 672		break;673	case CX231XX_BOARD_CNXT_SHELBY:674	case CX231XX_BOARD_CNXT_RDU_250:675 676		dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,677					       &xc5000_s5h1411_config,678					       demod_i2c);679 680		if (!dev->dvb->frontend[0]) {681			dev_err(dev->dev,682				"Failed to attach s5h1411 front end\n");683			result = -EINVAL;684			goto out_free;685		}686 687		/* define general-purpose callback pointer */688		dvb->frontend[0]->callback = cx231xx_tuner_callback;689 690		if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],691			       tuner_i2c,692			       &cnxt_rdu250_tunerconfig)) {693			result = -EINVAL;694			goto out_free;695		}696		break;697	case CX231XX_BOARD_CNXT_RDE_253S:698 699		dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,700					&dvico_s5h1432_config,701					demod_i2c);702 703		if (!dev->dvb->frontend[0]) {704			dev_err(dev->dev,705				"Failed to attach s5h1432 front end\n");706			result = -EINVAL;707			goto out_free;708		}709 710		/* define general-purpose callback pointer */711		dvb->frontend[0]->callback = cx231xx_tuner_callback;712 713		if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],714			       dev->board.tuner_addr, tuner_i2c,715			       &cnxt_rde253s_tunerconfig)) {716			result = -EINVAL;717			goto out_free;718		}719		break;720	case CX231XX_BOARD_CNXT_RDU_253S:721	case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID:722 723		dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,724					       &tda18271_s5h1411_config,725					       demod_i2c);726 727		if (!dev->dvb->frontend[0]) {728			dev_err(dev->dev,729				"Failed to attach s5h1411 front end\n");730			result = -EINVAL;731			goto out_free;732		}733 734		/* define general-purpose callback pointer */735		dvb->frontend[0]->callback = cx231xx_tuner_callback;736 737		if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],738			       dev->board.tuner_addr, tuner_i2c,739			       &cnxt_rde253s_tunerconfig)) {740			result = -EINVAL;741			goto out_free;742		}743		break;744	case CX231XX_BOARD_HAUPPAUGE_EXETER:745 746		dev_info(dev->dev,747			 "%s: looking for tuner / demod on i2c bus: %d\n",748		       __func__, i2c_adapter_id(tuner_i2c));749 750		dev->dvb->frontend[0] = dvb_attach(lgdt3305_attach,751						&hcw_lgdt3305_config,752						demod_i2c);753 754		if (!dev->dvb->frontend[0]) {755			dev_err(dev->dev,756				"Failed to attach LG3305 front end\n");757			result = -EINVAL;758			goto out_free;759		}760 761		/* define general-purpose callback pointer */762		dvb->frontend[0]->callback = cx231xx_tuner_callback;763 764		dvb_attach(tda18271_attach, dev->dvb->frontend[0],765			   dev->board.tuner_addr, tuner_i2c,766			   &hcw_tda18271_config);767		break;768 769	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:770	{771		struct si2165_platform_data si2165_pdata = {};772 773		/* attach demod */774		si2165_pdata.fe = &dev->dvb->frontend[0];775		si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL;776		si2165_pdata.ref_freq_hz = 16000000;777 778		/* perform probe/init/attach */779		client = dvb_module_probe("si2165", NULL, demod_i2c,780						dev->board.demod_addr,781						&si2165_pdata);782		if (!client) {783			result = -ENODEV;784			goto out_free;785		}786		dvb->i2c_client_demod[0] = client;787 788		dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;789 790		/* define general-purpose callback pointer */791		dvb->frontend[0]->callback = cx231xx_tuner_callback;792 793		dvb_attach(tda18271_attach, dev->dvb->frontend[0],794			dev->board.tuner_addr, tuner_i2c,795			&hcw_tda18271_config);796 797		dev->cx231xx_reset_analog_tuner = NULL;798		break;799	}800	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:801	{802		struct si2165_platform_data si2165_pdata = {};803		struct si2157_config si2157_config = {};804 805		/* attach demod */806		si2165_pdata.fe = &dev->dvb->frontend[0];807		si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT;808		si2165_pdata.ref_freq_hz = 24000000;809 810		/* perform probe/init/attach */811		client = dvb_module_probe("si2165", NULL, demod_i2c,812						dev->board.demod_addr,813						&si2165_pdata);814		if (!client) {815			result = -ENODEV;816			goto out_free;817		}818		dvb->i2c_client_demod[0] = client;819 820		dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;821 822		/* define general-purpose callback pointer */823		dvb->frontend[0]->callback = cx231xx_tuner_callback;824 825		/* attach tuner */826		si2157_config.fe = dev->dvb->frontend[0];827#ifdef CONFIG_MEDIA_CONTROLLER_DVB828		si2157_config.mdev = dev->media_dev;829#endif830		si2157_config.if_port = 1;831		si2157_config.inversion = true;832 833		/* perform probe/init/attach */834		client = dvb_module_probe("si2157", NULL, tuner_i2c,835						dev->board.tuner_addr,836						&si2157_config);837		if (!client) {838			result = -ENODEV;839			goto out_free;840		}841		dev->cx231xx_reset_analog_tuner = NULL;842 843		dev->dvb->i2c_client_tuner = client;844		break;845	}846	case CX231XX_BOARD_HAUPPAUGE_955Q:847	{848		struct si2157_config si2157_config = {};849		struct lgdt3306a_config lgdt3306a_config = {};850 851		lgdt3306a_config = hauppauge_955q_lgdt3306a_config;852		lgdt3306a_config.fe = &dev->dvb->frontend[0];853		lgdt3306a_config.i2c_adapter = &adapter;854 855		/* perform probe/init/attach */856		client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,857						dev->board.demod_addr,858						&lgdt3306a_config);859		if (!client) {860			result = -ENODEV;861			goto out_free;862		}863		dvb->i2c_client_demod[0] = client;864 865		dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;866 867		/* define general-purpose callback pointer */868		dvb->frontend[0]->callback = cx231xx_tuner_callback;869 870		/* attach tuner */871		si2157_config.fe = dev->dvb->frontend[0];872#ifdef CONFIG_MEDIA_CONTROLLER_DVB873		si2157_config.mdev = dev->media_dev;874#endif875		si2157_config.if_port = 1;876		si2157_config.inversion = true;877 878		/* perform probe/init/attach */879		client = dvb_module_probe("si2157", NULL, tuner_i2c,880						dev->board.tuner_addr,881						&si2157_config);882		if (!client) {883			result = -ENODEV;884			goto out_free;885		}886		dev->cx231xx_reset_analog_tuner = NULL;887 888		dev->dvb->i2c_client_tuner = client;889		break;890	}891	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:892	case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:893 894		dev_info(dev->dev,895			 "%s: looking for demod on i2c bus: %d\n",896			 __func__, i2c_adapter_id(tuner_i2c));897 898		dev->dvb->frontend[0] = dvb_attach(mb86a20s_attach,899						&pv_mb86a20s_config,900						demod_i2c);901 902		if (!dev->dvb->frontend[0]) {903			dev_err(dev->dev,904				"Failed to attach mb86a20s demod\n");905			result = -EINVAL;906			goto out_free;907		}908 909		/* define general-purpose callback pointer */910		dvb->frontend[0]->callback = cx231xx_tuner_callback;911 912		dvb_attach(tda18271_attach, dev->dvb->frontend[0],913			   dev->board.tuner_addr, tuner_i2c,914			   &pv_tda18271_config);915		break;916 917	case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:918	{919		struct si2157_config si2157_config = {};920		struct si2168_config si2168_config = {};921 922		/* attach demodulator chip */923		si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */924		si2168_config.fe = &dev->dvb->frontend[0];925		si2168_config.i2c_adapter = &adapter;926		si2168_config.ts_clock_inv = true;927 928		/* perform probe/init/attach */929		client = dvb_module_probe("si2168", NULL, demod_i2c,930						dev->board.demod_addr,931						&si2168_config);932		if (!client) {933			result = -ENODEV;934			goto out_free;935		}936		dvb->i2c_client_demod[0] = client;937 938		/* attach tuner chip */939		si2157_config.fe = dev->dvb->frontend[0];940#ifdef CONFIG_MEDIA_CONTROLLER_DVB941		si2157_config.mdev = dev->media_dev;942#endif943		si2157_config.if_port = 1;944		si2157_config.inversion = false;945 946		/* perform probe/init/attach */947		client = dvb_module_probe("si2157", NULL, tuner_i2c,948						dev->board.tuner_addr,949						&si2157_config);950		if (!client) {951			result = -ENODEV;952			goto out_free;953		}954		dev->cx231xx_reset_analog_tuner = NULL;955		dev->dvb->i2c_client_tuner = client;956		break;957	}958	case CX231XX_BOARD_ASTROMETA_T2HYBRID:959	{960		struct mn88473_config mn88473_config = {};961 962		/* attach demodulator chip */963		mn88473_config.i2c_wr_max = 16;964		mn88473_config.xtal = 25000000;965		mn88473_config.fe = &dev->dvb->frontend[0];966 967		/* perform probe/init/attach */968		client = dvb_module_probe("mn88473", NULL, demod_i2c,969						dev->board.demod_addr,970						&mn88473_config);971		if (!client) {972			result = -ENODEV;973			goto out_free;974		}975		dvb->i2c_client_demod[0] = client;976 977		/* define general-purpose callback pointer */978		dvb->frontend[0]->callback = cx231xx_tuner_callback;979 980		/* attach tuner chip */981		dvb_attach(r820t_attach, dev->dvb->frontend[0],982			   tuner_i2c,983			   &astrometa_t2hybrid_r820t_config);984		break;985	}986	case CX231XX_BOARD_HAUPPAUGE_935C:987	{988		struct si2157_config si2157_config = {};989		struct si2168_config si2168_config = {};990 991		/* attach demodulator chip */992		si2168_config.ts_mode = SI2168_TS_SERIAL;993		si2168_config.fe = &dev->dvb->frontend[0];994		si2168_config.i2c_adapter = &adapter;995		si2168_config.ts_clock_inv = true;996 997		/* perform probe/init/attach */998		client = dvb_module_probe("si2168", NULL, demod_i2c,999						dev->board.demod_addr,1000						&si2168_config);1001		if (!client) {1002			result = -ENODEV;1003			goto out_free;1004		}1005		dvb->i2c_client_demod[0] = client;1006		dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;1007 1008		/* define general-purpose callback pointer */1009		dvb->frontend[0]->callback = cx231xx_tuner_callback;1010 1011		/* attach tuner */1012		si2157_config.fe = dev->dvb->frontend[0];1013#ifdef CONFIG_MEDIA_CONTROLLER_DVB1014		si2157_config.mdev = dev->media_dev;1015#endif1016		si2157_config.if_port = 1;1017		si2157_config.inversion = true;1018 1019		/* perform probe/init/attach */1020		client = dvb_module_probe("si2157", NULL, tuner_i2c,1021						dev->board.tuner_addr,1022						&si2157_config);1023		if (!client) {1024			result = -ENODEV;1025			goto out_free;1026		}1027		dev->cx231xx_reset_analog_tuner = NULL;1028		dev->dvb->i2c_client_tuner = client;1029		break;1030	}1031	case CX231XX_BOARD_HAUPPAUGE_975:1032	{1033		struct i2c_adapter *adapter2;1034		struct si2157_config si2157_config = {};1035		struct lgdt3306a_config lgdt3306a_config = {};1036		struct si2168_config si2168_config = {};1037 1038		/* attach first demodulator chip */1039		lgdt3306a_config = hauppauge_955q_lgdt3306a_config;1040		lgdt3306a_config.fe = &dev->dvb->frontend[0];1041		lgdt3306a_config.i2c_adapter = &adapter;1042 1043		/* perform probe/init/attach */1044		client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,1045						dev->board.demod_addr,1046						&lgdt3306a_config);1047		if (!client) {1048			result = -ENODEV;1049			goto out_free;1050		}1051		dvb->i2c_client_demod[0] = client;1052 1053		/* attach second demodulator chip */1054		si2168_config.ts_mode = SI2168_TS_SERIAL;1055		si2168_config.fe = &dev->dvb->frontend[1];1056		si2168_config.i2c_adapter = &adapter2;1057		si2168_config.ts_clock_inv = true;1058 1059		/* perform probe/init/attach */1060		client = dvb_module_probe("si2168", NULL, adapter,1061						dev->board.demod_addr2,1062						&si2168_config);1063		if (!client) {1064			result = -ENODEV;1065			goto out_free;1066		}1067		dvb->i2c_client_demod[1] = client;1068		dvb->frontend[1]->id = 1;1069 1070		/* define general-purpose callback pointer */1071		dvb->frontend[0]->callback = cx231xx_tuner_callback;1072		dvb->frontend[1]->callback = cx231xx_tuner_callback;1073 1074		/* attach tuner */1075		si2157_config.fe = dev->dvb->frontend[0];1076#ifdef CONFIG_MEDIA_CONTROLLER_DVB1077		si2157_config.mdev = dev->media_dev;1078#endif1079		si2157_config.if_port = 1;1080		si2157_config.inversion = true;1081 1082		/* perform probe/init/attach */1083		client = dvb_module_probe("si2157", NULL, adapter,1084						dev->board.tuner_addr,1085						&si2157_config);1086		if (!client) {1087			result = -ENODEV;1088			goto out_free;1089		}1090		dev->cx231xx_reset_analog_tuner = NULL;1091		dvb->i2c_client_tuner = client;1092 1093		dvb->frontend[1]->tuner_priv = dvb->frontend[0]->tuner_priv;1094 1095		memcpy(&dvb->frontend[1]->ops.tuner_ops,1096			&dvb->frontend[0]->ops.tuner_ops,1097			sizeof(struct dvb_tuner_ops));1098		break;1099	}1100	default:1101		dev_err(dev->dev,1102			"%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",1103			dev->name);1104		break;1105	}1106	if (!dvb->frontend[0]) {1107		dev_err(dev->dev,1108		       "%s/2: frontend initialization failed\n", dev->name);1109		result = -EINVAL;1110		goto out_free;1111	}1112 1113	/* register everything */1114	result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);1115 1116	if (result < 0)1117		goto out_free;1118 1119 1120	dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");1121 1122ret:1123	cx231xx_set_mode(dev, CX231XX_SUSPEND);1124	mutex_unlock(&dev->lock);1125	return result;1126 1127out_free:1128	/* remove I2C tuner */1129	dvb_module_release(dvb->i2c_client_tuner);1130	dvb->i2c_client_tuner = NULL;1131	/* remove I2C demod(s) */1132	dvb_module_release(dvb->i2c_client_demod[1]);1133	dvb->i2c_client_demod[1] = NULL;1134	dvb_module_release(dvb->i2c_client_demod[0]);1135	dvb->i2c_client_demod[0] = NULL;1136	kfree(dvb);1137	dev->dvb = NULL;1138	goto ret;1139}1140 1141static int dvb_fini(struct cx231xx *dev)1142{1143	if (!dev->board.has_dvb) {1144		/* This device does not support the extension */1145		return 0;1146	}1147 1148	if (dev->dvb) {1149		unregister_dvb(dev->dvb);1150		kfree(dev->dvb);1151		dev->dvb = NULL;1152	}1153 1154	return 0;1155}1156 1157static struct cx231xx_ops dvb_ops = {1158	.id = CX231XX_DVB,1159	.name = "Cx231xx dvb Extension",1160	.init = dvb_init,1161	.fini = dvb_fini,1162};1163 1164static int __init cx231xx_dvb_register(void)1165{1166	return cx231xx_register_extension(&dvb_ops);1167}1168 1169static void __exit cx231xx_dvb_unregister(void)1170{1171	cx231xx_unregister_extension(&dvb_ops);1172}1173 1174module_init(cx231xx_dvb_register);1175module_exit(cx231xx_dvb_unregister);1176