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

saa7164-dvb.c (21482B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Driver for the NXP SAA7164 PCIe bridge
      4 *
      5 *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
      6 */
      7
      8#include "saa7164.h"
      9
     10#include "tda10048.h"
     11#include "tda18271.h"
     12#include "s5h1411.h"
     13#include "si2157.h"
     14#include "si2168.h"
     15#include "lgdt3306a.h"
     16
     17#define DRIVER_NAME "saa7164"
     18
     19DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
     20
     21/* addr is in the card struct, get it from there */
     22static struct tda10048_config hauppauge_hvr2200_1_config = {
     23	.demod_address    = 0x10 >> 1,
     24	.output_mode      = TDA10048_SERIAL_OUTPUT,
     25	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
     26	.inversion        = TDA10048_INVERSION_ON,
     27	.dtv6_if_freq_khz = TDA10048_IF_3300,
     28	.dtv7_if_freq_khz = TDA10048_IF_3500,
     29	.dtv8_if_freq_khz = TDA10048_IF_4000,
     30	.clk_freq_khz     = TDA10048_CLK_16000,
     31};
     32static struct tda10048_config hauppauge_hvr2200_2_config = {
     33	.demod_address    = 0x12 >> 1,
     34	.output_mode      = TDA10048_SERIAL_OUTPUT,
     35	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
     36	.inversion        = TDA10048_INVERSION_ON,
     37	.dtv6_if_freq_khz = TDA10048_IF_3300,
     38	.dtv7_if_freq_khz = TDA10048_IF_3500,
     39	.dtv8_if_freq_khz = TDA10048_IF_4000,
     40	.clk_freq_khz     = TDA10048_CLK_16000,
     41};
     42
     43static struct tda18271_std_map hauppauge_tda18271_std_map = {
     44	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 3,
     45		      .if_lvl = 6, .rfagc_top = 0x37 },
     46	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
     47		      .if_lvl = 6, .rfagc_top = 0x37 },
     48};
     49
     50static struct tda18271_config hauppauge_hvr22x0_tuner_config = {
     51	.std_map	= &hauppauge_tda18271_std_map,
     52	.gate		= TDA18271_GATE_ANALOG,
     53	.role		= TDA18271_MASTER,
     54};
     55
     56static struct tda18271_config hauppauge_hvr22x0s_tuner_config = {
     57	.std_map	= &hauppauge_tda18271_std_map,
     58	.gate		= TDA18271_GATE_ANALOG,
     59	.role		= TDA18271_SLAVE,
     60	.output_opt     = TDA18271_OUTPUT_LT_OFF,
     61	.rf_cal_on_startup = 1
     62};
     63
     64static struct s5h1411_config hauppauge_s5h1411_config = {
     65	.output_mode   = S5H1411_SERIAL_OUTPUT,
     66	.gpio          = S5H1411_GPIO_ON,
     67	.qam_if        = S5H1411_IF_4000,
     68	.vsb_if        = S5H1411_IF_3250,
     69	.inversion     = S5H1411_INVERSION_ON,
     70	.status_mode   = S5H1411_DEMODLOCKING,
     71	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,
     72};
     73
     74static struct lgdt3306a_config hauppauge_hvr2255a_config = {
     75	.i2c_addr               = 0xb2 >> 1,
     76	.qam_if_khz             = 4000,
     77	.vsb_if_khz             = 3250,
     78	.deny_i2c_rptr          = 1, /* Disabled */
     79	.spectral_inversion     = 0, /* Disabled */
     80	.mpeg_mode              = LGDT3306A_MPEG_SERIAL,
     81	.tpclk_edge             = LGDT3306A_TPCLK_RISING_EDGE,
     82	.tpvalid_polarity       = LGDT3306A_TP_VALID_HIGH,
     83	.xtalMHz                = 25, /* 24 or 25 */
     84};
     85
     86static struct lgdt3306a_config hauppauge_hvr2255b_config = {
     87	.i2c_addr               = 0x1c >> 1,
     88	.qam_if_khz             = 4000,
     89	.vsb_if_khz             = 3250,
     90	.deny_i2c_rptr          = 1, /* Disabled */
     91	.spectral_inversion     = 0, /* Disabled */
     92	.mpeg_mode              = LGDT3306A_MPEG_SERIAL,
     93	.tpclk_edge             = LGDT3306A_TPCLK_RISING_EDGE,
     94	.tpvalid_polarity       = LGDT3306A_TP_VALID_HIGH,
     95	.xtalMHz                = 25, /* 24 or 25 */
     96};
     97
     98static struct si2157_config hauppauge_hvr2255_tuner_config = {
     99	.inversion = 1,
    100	.if_port = 1,
    101};
    102
    103static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter,
    104	struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg)
    105{
    106	struct i2c_board_info bi;
    107	struct i2c_client *tuner;
    108
    109	cfg->fe = fe;
    110
    111	memset(&bi, 0, sizeof(bi));
    112
    113	strscpy(bi.type, "si2157", I2C_NAME_SIZE);
    114	bi.platform_data = cfg;
    115	bi.addr = addr8bit >> 1;
    116
    117	request_module(bi.type);
    118
    119	tuner = i2c_new_client_device(adapter, &bi);
    120	if (!i2c_client_has_driver(tuner))
    121		return -ENODEV;
    122
    123	if (!try_module_get(tuner->dev.driver->owner)) {
    124		i2c_unregister_device(tuner);
    125		return -ENODEV;
    126	}
    127
    128	port->i2c_client_tuner = tuner;
    129
    130	return 0;
    131}
    132
    133static int saa7164_dvb_stop_port(struct saa7164_port *port)
    134{
    135	struct saa7164_dev *dev = port->dev;
    136	int ret;
    137
    138	ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
    139	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    140		printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
    141			__func__, ret);
    142		ret = -EIO;
    143	} else {
    144		dprintk(DBGLVL_DVB, "%s()    Stopped\n", __func__);
    145		ret = 0;
    146	}
    147
    148	return ret;
    149}
    150
    151static int saa7164_dvb_acquire_port(struct saa7164_port *port)
    152{
    153	struct saa7164_dev *dev = port->dev;
    154	int ret;
    155
    156	ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
    157	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    158		printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
    159			__func__, ret);
    160		ret = -EIO;
    161	} else {
    162		dprintk(DBGLVL_DVB, "%s() Acquired\n", __func__);
    163		ret = 0;
    164	}
    165
    166	return ret;
    167}
    168
    169static int saa7164_dvb_pause_port(struct saa7164_port *port)
    170{
    171	struct saa7164_dev *dev = port->dev;
    172	int ret;
    173
    174	ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
    175	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
    176		printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
    177			__func__, ret);
    178		ret = -EIO;
    179	} else {
    180		dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
    181		ret = 0;
    182	}
    183
    184	return ret;
    185}
    186
    187/* Firmware is very windows centric, meaning you have to transition
    188 * the part through AVStream / KS Windows stages, forwards or backwards.
    189 * States are: stopped, acquired (h/w), paused, started.
    190 */
    191static int saa7164_dvb_stop_streaming(struct saa7164_port *port)
    192{
    193	struct saa7164_dev *dev = port->dev;
    194	struct saa7164_buffer *buf;
    195	struct list_head *p, *q;
    196	int ret;
    197
    198	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
    199
    200	ret = saa7164_dvb_pause_port(port);
    201	ret = saa7164_dvb_acquire_port(port);
    202	ret = saa7164_dvb_stop_port(port);
    203
    204	/* Mark the hardware buffers as free */
    205	mutex_lock(&port->dmaqueue_lock);
    206	list_for_each_safe(p, q, &port->dmaqueue.list) {
    207		buf = list_entry(p, struct saa7164_buffer, list);
    208		buf->flags = SAA7164_BUFFER_FREE;
    209	}
    210	mutex_unlock(&port->dmaqueue_lock);
    211
    212	return ret;
    213}
    214
    215static int saa7164_dvb_start_port(struct saa7164_port *port)
    216{
    217	struct saa7164_dev *dev = port->dev;
    218	int ret = 0, result;
    219
    220	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
    221
    222	saa7164_buffer_cfg_port(port);
    223
    224	/* Acquire the hardware */
    225	result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
    226	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    227		printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
    228			__func__, result);
    229
    230		/* Stop the hardware, regardless */
    231		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
    232		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    233			printk(KERN_ERR "%s() acquire/forced stop transition failed, res = 0x%x\n",
    234			       __func__, result);
    235		}
    236		ret = -EIO;
    237		goto out;
    238	} else
    239		dprintk(DBGLVL_DVB, "%s()   Acquired\n", __func__);
    240
    241	/* Pause the hardware */
    242	result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
    243	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    244		printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
    245				__func__, result);
    246
    247		/* Stop the hardware, regardless */
    248		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
    249		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    250			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
    251			       __func__, result);
    252		}
    253
    254		ret = -EIO;
    255		goto out;
    256	} else
    257		dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
    258
    259	/* Start the hardware */
    260	result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
    261	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    262		printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
    263				__func__, result);
    264
    265		/* Stop the hardware, regardless */
    266		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
    267		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
    268			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
    269			       __func__, result);
    270		}
    271
    272		ret = -EIO;
    273	} else
    274		dprintk(DBGLVL_DVB, "%s()   Running\n", __func__);
    275
    276out:
    277	return ret;
    278}
    279
    280static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
    281{
    282	struct dvb_demux *demux = feed->demux;
    283	struct saa7164_port *port = (struct saa7164_port *) demux->priv;
    284	struct saa7164_dvb *dvb = &port->dvb;
    285	struct saa7164_dev *dev = port->dev;
    286	int ret = 0;
    287
    288	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
    289
    290	if (!demux->dmx.frontend)
    291		return -EINVAL;
    292
    293	if (dvb) {
    294		mutex_lock(&dvb->lock);
    295		if (dvb->feeding++ == 0) {
    296			/* Start transport */
    297			ret = saa7164_dvb_start_port(port);
    298		}
    299		mutex_unlock(&dvb->lock);
    300		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
    301			__func__, port->nr, dvb->feeding);
    302	}
    303
    304	return ret;
    305}
    306
    307static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
    308{
    309	struct dvb_demux *demux = feed->demux;
    310	struct saa7164_port *port = (struct saa7164_port *) demux->priv;
    311	struct saa7164_dvb *dvb = &port->dvb;
    312	struct saa7164_dev *dev = port->dev;
    313	int ret = 0;
    314
    315	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
    316
    317	if (dvb) {
    318		mutex_lock(&dvb->lock);
    319		if (--dvb->feeding == 0) {
    320			/* Stop transport */
    321			ret = saa7164_dvb_stop_streaming(port);
    322		}
    323		mutex_unlock(&dvb->lock);
    324		dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
    325			__func__, port->nr, dvb->feeding);
    326	}
    327
    328	return ret;
    329}
    330
    331static int dvb_register(struct saa7164_port *port)
    332{
    333	struct saa7164_dvb *dvb = &port->dvb;
    334	struct saa7164_dev *dev = port->dev;
    335	struct saa7164_buffer *buf;
    336	int result, i;
    337
    338	dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
    339
    340	BUG_ON(port->type != SAA7164_MPEG_DVB);
    341
    342	/* Sanity check that the PCI configuration space is active */
    343	if (port->hwcfg.BARLocation == 0) {
    344		result = -ENOMEM;
    345		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), NO PCI configuration\n",
    346			DRIVER_NAME, result);
    347		goto fail_adapter;
    348	}
    349
    350	/* Init and establish defaults */
    351	port->hw_streamingparams.bitspersample = 8;
    352	port->hw_streamingparams.samplesperline = 188;
    353	port->hw_streamingparams.numberoflines =
    354		(SAA7164_TS_NUMBER_OF_LINES * 188) / 188;
    355
    356	port->hw_streamingparams.pitch = 188;
    357	port->hw_streamingparams.linethreshold = 0;
    358	port->hw_streamingparams.pagetablelistvirt = NULL;
    359	port->hw_streamingparams.pagetablelistphys = NULL;
    360	port->hw_streamingparams.numpagetables = 2 +
    361		((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
    362
    363	port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount;
    364
    365	/* Allocate the PCI resources */
    366	for (i = 0; i < port->hwcfg.buffercount; i++) {
    367		buf = saa7164_buffer_alloc(port,
    368			port->hw_streamingparams.numberoflines *
    369			port->hw_streamingparams.pitch);
    370
    371		if (!buf) {
    372			result = -ENOMEM;
    373			printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), unable to allocate buffers\n",
    374				DRIVER_NAME, result);
    375			goto fail_adapter;
    376		}
    377
    378		mutex_lock(&port->dmaqueue_lock);
    379		list_add_tail(&buf->list, &port->dmaqueue.list);
    380		mutex_unlock(&port->dmaqueue_lock);
    381	}
    382
    383	/* register adapter */
    384	result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
    385			&dev->pci->dev, adapter_nr);
    386	if (result < 0) {
    387		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d)\n",
    388		       DRIVER_NAME, result);
    389		goto fail_adapter;
    390	}
    391	dvb->adapter.priv = port;
    392
    393	/* register frontend */
    394	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
    395	if (result < 0) {
    396		printk(KERN_ERR "%s: dvb_register_frontend failed (errno = %d)\n",
    397		       DRIVER_NAME, result);
    398		goto fail_frontend;
    399	}
    400
    401	/* register demux stuff */
    402	dvb->demux.dmx.capabilities =
    403		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
    404		DMX_MEMORY_BASED_FILTERING;
    405	dvb->demux.priv       = port;
    406	dvb->demux.filternum  = 256;
    407	dvb->demux.feednum    = 256;
    408	dvb->demux.start_feed = saa7164_dvb_start_feed;
    409	dvb->demux.stop_feed  = saa7164_dvb_stop_feed;
    410	result = dvb_dmx_init(&dvb->demux);
    411	if (result < 0) {
    412		printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
    413		       DRIVER_NAME, result);
    414		goto fail_dmx;
    415	}
    416
    417	dvb->dmxdev.filternum    = 256;
    418	dvb->dmxdev.demux        = &dvb->demux.dmx;
    419	dvb->dmxdev.capabilities = 0;
    420	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
    421	if (result < 0) {
    422		printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
    423		       DRIVER_NAME, result);
    424		goto fail_dmxdev;
    425	}
    426
    427	dvb->fe_hw.source = DMX_FRONTEND_0;
    428	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
    429	if (result < 0) {
    430		printk(KERN_ERR "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
    431		       DRIVER_NAME, result);
    432		goto fail_fe_hw;
    433	}
    434
    435	dvb->fe_mem.source = DMX_MEMORY_FE;
    436	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
    437	if (result < 0) {
    438		printk(KERN_ERR "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
    439		       DRIVER_NAME, result);
    440		goto fail_fe_mem;
    441	}
    442
    443	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
    444	if (result < 0) {
    445		printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
    446		       DRIVER_NAME, result);
    447		goto fail_fe_conn;
    448	}
    449
    450	/* register network adapter */
    451	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
    452	return 0;
    453
    454fail_fe_conn:
    455	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
    456fail_fe_mem:
    457	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
    458fail_fe_hw:
    459	dvb_dmxdev_release(&dvb->dmxdev);
    460fail_dmxdev:
    461	dvb_dmx_release(&dvb->demux);
    462fail_dmx:
    463	dvb_unregister_frontend(dvb->frontend);
    464fail_frontend:
    465	dvb_frontend_detach(dvb->frontend);
    466	dvb_unregister_adapter(&dvb->adapter);
    467fail_adapter:
    468	return result;
    469}
    470
    471int saa7164_dvb_unregister(struct saa7164_port *port)
    472{
    473	struct saa7164_dvb *dvb = &port->dvb;
    474	struct saa7164_dev *dev = port->dev;
    475	struct saa7164_buffer *b;
    476	struct list_head *c, *n;
    477	struct i2c_client *client;
    478
    479	dprintk(DBGLVL_DVB, "%s()\n", __func__);
    480
    481	BUG_ON(port->type != SAA7164_MPEG_DVB);
    482
    483	/* Remove any allocated buffers */
    484	mutex_lock(&port->dmaqueue_lock);
    485	list_for_each_safe(c, n, &port->dmaqueue.list) {
    486		b = list_entry(c, struct saa7164_buffer, list);
    487		list_del(c);
    488		saa7164_buffer_dealloc(b);
    489	}
    490	mutex_unlock(&port->dmaqueue_lock);
    491
    492	if (dvb->frontend == NULL)
    493		return 0;
    494
    495	/* remove I2C client for tuner */
    496	client = port->i2c_client_tuner;
    497	if (client) {
    498		module_put(client->dev.driver->owner);
    499		i2c_unregister_device(client);
    500	}
    501
    502	/* remove I2C client for demodulator */
    503	client = port->i2c_client_demod;
    504	if (client) {
    505		module_put(client->dev.driver->owner);
    506		i2c_unregister_device(client);
    507	}
    508
    509	dvb_net_release(&dvb->net);
    510	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
    511	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
    512	dvb_dmxdev_release(&dvb->dmxdev);
    513	dvb_dmx_release(&dvb->demux);
    514	dvb_unregister_frontend(dvb->frontend);
    515	dvb_frontend_detach(dvb->frontend);
    516	dvb_unregister_adapter(&dvb->adapter);
    517	return 0;
    518}
    519
    520/* All the DVB attach calls go here, this function gets modified
    521 * for each new card.
    522 */
    523int saa7164_dvb_register(struct saa7164_port *port)
    524{
    525	struct saa7164_dev *dev = port->dev;
    526	struct saa7164_dvb *dvb = &port->dvb;
    527	struct saa7164_i2c *i2c_bus = NULL;
    528	struct si2168_config si2168_config;
    529	struct si2157_config si2157_config;
    530	struct i2c_adapter *adapter;
    531	struct i2c_board_info info;
    532	struct i2c_client *client_demod;
    533	struct i2c_client *client_tuner;
    534	int ret;
    535
    536	dprintk(DBGLVL_DVB, "%s()\n", __func__);
    537
    538	/* init frontend */
    539	switch (dev->board) {
    540	case SAA7164_BOARD_HAUPPAUGE_HVR2200:
    541	case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
    542	case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
    543	case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
    544	case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
    545		i2c_bus = &dev->i2c_bus[port->nr + 1];
    546		switch (port->nr) {
    547		case 0:
    548			port->dvb.frontend = dvb_attach(tda10048_attach,
    549				&hauppauge_hvr2200_1_config,
    550				&i2c_bus->i2c_adap);
    551
    552			if (port->dvb.frontend != NULL) {
    553				/* TODO: addr is in the card struct */
    554				dvb_attach(tda18271_attach, port->dvb.frontend,
    555					0xc0 >> 1, &i2c_bus->i2c_adap,
    556					&hauppauge_hvr22x0_tuner_config);
    557			}
    558
    559			break;
    560		case 1:
    561			port->dvb.frontend = dvb_attach(tda10048_attach,
    562				&hauppauge_hvr2200_2_config,
    563				&i2c_bus->i2c_adap);
    564
    565			if (port->dvb.frontend != NULL) {
    566				/* TODO: addr is in the card struct */
    567				dvb_attach(tda18271_attach, port->dvb.frontend,
    568					0xc0 >> 1, &i2c_bus->i2c_adap,
    569					&hauppauge_hvr22x0s_tuner_config);
    570			}
    571
    572			break;
    573		}
    574		break;
    575	case SAA7164_BOARD_HAUPPAUGE_HVR2250:
    576	case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
    577	case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
    578		i2c_bus = &dev->i2c_bus[port->nr + 1];
    579
    580		port->dvb.frontend = dvb_attach(s5h1411_attach,
    581			&hauppauge_s5h1411_config,
    582			&i2c_bus->i2c_adap);
    583
    584		if (port->dvb.frontend != NULL) {
    585			if (port->nr == 0) {
    586				/* Master TDA18271 */
    587				/* TODO: addr is in the card struct */
    588				dvb_attach(tda18271_attach, port->dvb.frontend,
    589					0xc0 >> 1, &i2c_bus->i2c_adap,
    590					&hauppauge_hvr22x0_tuner_config);
    591			} else {
    592				/* Slave TDA18271 */
    593				dvb_attach(tda18271_attach, port->dvb.frontend,
    594					0xc0 >> 1, &i2c_bus->i2c_adap,
    595					&hauppauge_hvr22x0s_tuner_config);
    596			}
    597		}
    598
    599		break;
    600	case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
    601	case SAA7164_BOARD_HAUPPAUGE_HVR2255:
    602		i2c_bus = &dev->i2c_bus[2];
    603
    604		if (port->nr == 0) {
    605			port->dvb.frontend = dvb_attach(lgdt3306a_attach,
    606				&hauppauge_hvr2255a_config, &i2c_bus->i2c_adap);
    607		} else {
    608			port->dvb.frontend = dvb_attach(lgdt3306a_attach,
    609				&hauppauge_hvr2255b_config, &i2c_bus->i2c_adap);
    610		}
    611
    612		if (port->dvb.frontend != NULL) {
    613
    614			if (port->nr == 0) {
    615				si2157_attach(port, &dev->i2c_bus[0].i2c_adap,
    616					      port->dvb.frontend, 0xc0,
    617					      &hauppauge_hvr2255_tuner_config);
    618			} else {
    619				si2157_attach(port, &dev->i2c_bus[1].i2c_adap,
    620					      port->dvb.frontend, 0xc0,
    621					      &hauppauge_hvr2255_tuner_config);
    622			}
    623		}
    624		break;
    625	case SAA7164_BOARD_HAUPPAUGE_HVR2205:
    626
    627		if (port->nr == 0) {
    628			/* attach frontend */
    629			memset(&si2168_config, 0, sizeof(si2168_config));
    630			si2168_config.i2c_adapter = &adapter;
    631			si2168_config.fe = &port->dvb.frontend;
    632			si2168_config.ts_mode = SI2168_TS_SERIAL;
    633			memset(&info, 0, sizeof(struct i2c_board_info));
    634			strscpy(info.type, "si2168", I2C_NAME_SIZE);
    635			info.addr = 0xc8 >> 1;
    636			info.platform_data = &si2168_config;
    637			request_module(info.type);
    638			client_demod = i2c_new_client_device(&dev->i2c_bus[2].i2c_adap, &info);
    639			if (!i2c_client_has_driver(client_demod))
    640				goto frontend_detach;
    641
    642			if (!try_module_get(client_demod->dev.driver->owner)) {
    643				i2c_unregister_device(client_demod);
    644				goto frontend_detach;
    645			}
    646			port->i2c_client_demod = client_demod;
    647
    648			/* attach tuner */
    649			memset(&si2157_config, 0, sizeof(si2157_config));
    650			si2157_config.if_port = 1;
    651			si2157_config.fe = port->dvb.frontend;
    652			memset(&info, 0, sizeof(struct i2c_board_info));
    653			strscpy(info.type, "si2157", I2C_NAME_SIZE);
    654			info.addr = 0xc0 >> 1;
    655			info.platform_data = &si2157_config;
    656			request_module(info.type);
    657			client_tuner = i2c_new_client_device(&dev->i2c_bus[0].i2c_adap, &info);
    658			if (!i2c_client_has_driver(client_tuner)) {
    659				module_put(client_demod->dev.driver->owner);
    660				i2c_unregister_device(client_demod);
    661				goto frontend_detach;
    662			}
    663			if (!try_module_get(client_tuner->dev.driver->owner)) {
    664				i2c_unregister_device(client_tuner);
    665				module_put(client_demod->dev.driver->owner);
    666				i2c_unregister_device(client_demod);
    667				goto frontend_detach;
    668			}
    669			port->i2c_client_tuner = client_tuner;
    670		} else {
    671			/* attach frontend */
    672			memset(&si2168_config, 0, sizeof(si2168_config));
    673			si2168_config.i2c_adapter = &adapter;
    674			si2168_config.fe = &port->dvb.frontend;
    675			si2168_config.ts_mode = SI2168_TS_SERIAL;
    676			memset(&info, 0, sizeof(struct i2c_board_info));
    677			strscpy(info.type, "si2168", I2C_NAME_SIZE);
    678			info.addr = 0xcc >> 1;
    679			info.platform_data = &si2168_config;
    680			request_module(info.type);
    681			client_demod = i2c_new_client_device(&dev->i2c_bus[2].i2c_adap, &info);
    682			if (!i2c_client_has_driver(client_demod))
    683				goto frontend_detach;
    684
    685			if (!try_module_get(client_demod->dev.driver->owner)) {
    686				i2c_unregister_device(client_demod);
    687				goto frontend_detach;
    688			}
    689			port->i2c_client_demod = client_demod;
    690
    691			/* attach tuner */
    692			memset(&si2157_config, 0, sizeof(si2157_config));
    693			si2157_config.fe = port->dvb.frontend;
    694			si2157_config.if_port = 1;
    695			memset(&info, 0, sizeof(struct i2c_board_info));
    696			strscpy(info.type, "si2157", I2C_NAME_SIZE);
    697			info.addr = 0xc0 >> 1;
    698			info.platform_data = &si2157_config;
    699			request_module(info.type);
    700			client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
    701			if (!i2c_client_has_driver(client_tuner)) {
    702				module_put(client_demod->dev.driver->owner);
    703				i2c_unregister_device(client_demod);
    704				goto frontend_detach;
    705			}
    706			if (!try_module_get(client_tuner->dev.driver->owner)) {
    707				i2c_unregister_device(client_tuner);
    708				module_put(client_demod->dev.driver->owner);
    709				i2c_unregister_device(client_demod);
    710				goto frontend_detach;
    711			}
    712			port->i2c_client_tuner = client_tuner;
    713		}
    714
    715		break;
    716	default:
    717		printk(KERN_ERR "%s: The frontend isn't supported\n",
    718		       dev->name);
    719		break;
    720	}
    721	if (NULL == dvb->frontend) {
    722		printk(KERN_ERR "%s() Frontend initialization failed\n",
    723		       __func__);
    724		return -1;
    725	}
    726
    727	/* register everything */
    728	ret = dvb_register(port);
    729	if (ret < 0) {
    730		if (dvb->frontend->ops.release)
    731			dvb->frontend->ops.release(dvb->frontend);
    732		return ret;
    733	}
    734
    735	return 0;
    736
    737frontend_detach:
    738	printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__);
    739	return -1;
    740}