Path: blob/master/drivers/media/dvb/bt8xx/dvb-bt8xx.c
15112 views
/*1* Bt8xx based DVB adapter driver2*3* Copyright (C) 2002,2003 Florian Schirmer <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.18*19*/2021#include <linux/bitops.h>22#include <linux/module.h>23#include <linux/init.h>24#include <linux/kernel.h>25#include <linux/device.h>26#include <linux/delay.h>27#include <linux/slab.h>28#include <linux/i2c.h>2930#include "dmxdev.h"31#include "dvbdev.h"32#include "dvb_demux.h"33#include "dvb_frontend.h"34#include "dvb-bt8xx.h"35#include "bt878.h"3637static int debug;3839module_param(debug, int, 0644);40MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");4142DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);4344#define dprintk( args... ) \45do { \46if (debug) printk(KERN_DEBUG args); \47} while (0)4849#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */5051static void dvb_bt8xx_task(unsigned long data)52{53struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;5455//printk("%d ", card->bt->finished_block);5657while (card->bt->last_block != card->bt->finished_block) {58(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)59(&card->demux,60&card->bt->buf_cpu[card->bt->last_block *61card->bt->block_bytes],62card->bt->block_bytes);63card->bt->last_block = (card->bt->last_block + 1) %64card->bt->block_count;65}66}6768static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)69{70struct dvb_demux*dvbdmx = dvbdmxfeed->demux;71struct dvb_bt8xx_card *card = dvbdmx->priv;72int rc;7374dprintk("dvb_bt8xx: start_feed\n");7576if (!dvbdmx->dmx.frontend)77return -EINVAL;7879mutex_lock(&card->lock);80card->nfeeds++;81rc = card->nfeeds;82if (card->nfeeds == 1)83bt878_start(card->bt, card->gpio_mode,84card->op_sync_orin, card->irq_err_ignore);85mutex_unlock(&card->lock);86return rc;87}8889static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)90{91struct dvb_demux *dvbdmx = dvbdmxfeed->demux;92struct dvb_bt8xx_card *card = dvbdmx->priv;9394dprintk("dvb_bt8xx: stop_feed\n");9596if (!dvbdmx->dmx.frontend)97return -EINVAL;9899mutex_lock(&card->lock);100card->nfeeds--;101if (card->nfeeds == 0)102bt878_stop(card->bt);103mutex_unlock(&card->lock);104105return 0;106}107108static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)109{110if ((adev->subsystem_vendor == bdev->subsystem_vendor) &&111(adev->subsystem_device == bdev->subsystem_device) &&112(adev->bus->number == bdev->bus->number) &&113(PCI_SLOT(adev->devfn) == PCI_SLOT(bdev->devfn)))114return 1;115return 0;116}117118static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)119{120unsigned int card_nr;121122/* Hmm, n squared. Hope n is small */123for (card_nr = 0; card_nr < bt878_num; card_nr++)124if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))125return &bt878[card_nr];126return NULL;127}128129static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)130{131static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };132static u8 mt352_reset [] = { 0x50, 0x80 };133static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };134static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 };135static u8 mt352_gpp_ctl_cfg [] = { 0x8C, 0x33 };136static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };137138mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));139udelay(2000);140mt352_write(fe, mt352_reset, sizeof(mt352_reset));141mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));142143mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));144mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));145mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));146147return 0;148}149150static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)151{152u32 div;153unsigned char bs = 0;154unsigned char cp = 0;155156if (buf_len < 5)157return -EINVAL;158159div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;160161if (params->frequency < 542000000)162cp = 0xb4;163else if (params->frequency < 771000000)164cp = 0xbc;165else166cp = 0xf4;167168if (params->frequency == 0)169bs = 0x03;170else if (params->frequency < 443250000)171bs = 0x02;172else173bs = 0x08;174175pllbuf[0] = 0x60;176pllbuf[1] = div >> 8;177pllbuf[2] = div & 0xff;178pllbuf[3] = cp;179pllbuf[4] = bs;180181return 5;182}183184static struct mt352_config thomson_dtt7579_config = {185.demod_address = 0x0f,186.demod_init = thomson_dtt7579_demod_init,187};188189static struct zl10353_config thomson_dtt7579_zl10353_config = {190.demod_address = 0x0f,191};192193static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)194{195u32 freq = params->frequency;196197int i, a, n, pump;198u32 band, pll;199200u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,2011576000,1718000,1856000,2036000,2150000};202u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,2030x00102000,0x00104000,0x00108000,0x00110000,2040x00120000,0x00140000};205206#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */207printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);208209/* This is really the bit driving the tuner chip cx24108 */210211if (freq<950000)212freq = 950000; /* kHz */213else if (freq>2150000)214freq = 2150000; /* satellite IF is 950..2150MHz */215216/* decide which VCO to use for the input frequency */217for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++);218printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);219band=bandsel[i];220/* the gain values must be set by SetSymbolrate */221/* compute the pll divider needed, from Conexant data sheet,222resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,223depending on the divider bit. It is set to /4 on the 2 lowest224bands */225n=((i<=2?2:1)*freq*10L)/(XTAL/100);226a=n%32; n/=32; if(a==0) n--;227pump=(freq<(osci[i-1]+osci[i])/2);228pll=0xf8000000|229((pump?1:2)<<(14+11))|230((n&0x1ff)<<(5+11))|231((a&0x1f)<<11);232/* everything is shifted left 11 bits to left-align the bits in the23332bit word. Output to the tuner goes MSB-aligned, after all */234printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);235cx24110_pll_write(fe,band);236/* set vga and vca to their widest-band settings, as a precaution.237SetSymbolrate might not be called to set this up */238cx24110_pll_write(fe,0x500c0000);239cx24110_pll_write(fe,0x83f1f800);240cx24110_pll_write(fe,pll);241//writereg(client,0x56,0x7f);242243return 0;244}245246static int pinnsat_tuner_init(struct dvb_frontend* fe)247{248struct dvb_bt8xx_card *card = fe->dvb->priv;249250bttv_gpio_enable(card->bttv_nr, 1, 1); /* output */251bttv_write_gpio(card->bttv_nr, 1, 1); /* relay on */252253return 0;254}255256static int pinnsat_tuner_sleep(struct dvb_frontend* fe)257{258struct dvb_bt8xx_card *card = fe->dvb->priv;259260bttv_write_gpio(card->bttv_nr, 1, 0); /* relay off */261262return 0;263}264265static struct cx24110_config pctvsat_config = {266.demod_address = 0x55,267};268269static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)270{271struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;272u8 cfg, cpump, band_select;273u8 data[4];274u32 div;275struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };276277div = (36000000 + params->frequency + 83333) / 166666;278cfg = 0x88;279280if (params->frequency < 175000000)281cpump = 2;282else if (params->frequency < 390000000)283cpump = 1;284else if (params->frequency < 470000000)285cpump = 2;286else if (params->frequency < 750000000)287cpump = 2;288else289cpump = 3;290291if (params->frequency < 175000000)292band_select = 0x0e;293else if (params->frequency < 470000000)294band_select = 0x05;295else296band_select = 0x03;297298data[0] = (div >> 8) & 0x7f;299data[1] = div & 0xff;300data[2] = ((div >> 10) & 0x60) | cfg;301data[3] = (cpump << 6) | band_select;302303if (fe->ops.i2c_gate_ctrl)304fe->ops.i2c_gate_ctrl(fe, 1);305i2c_transfer(card->i2c_adapter, &msg, 1);306return (div * 166666 - 36000000);307}308309static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)310{311struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;312313return request_firmware(fw, name, &bt->bt->dev->dev);314}315316static struct sp887x_config microtune_mt7202dtf_config = {317.demod_address = 0x70,318.request_firmware = microtune_mt7202dtf_request_firmware,319};320321static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)322{323static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };324static u8 mt352_reset [] = { 0x50, 0x80 };325static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };326static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,3270x00, 0xFF, 0x00, 0x40, 0x40 };328static u8 mt352_av771_extra[] = { 0xB5, 0x7A };329static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };330331mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));332udelay(2000);333mt352_write(fe, mt352_reset, sizeof(mt352_reset));334mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));335336mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));337udelay(2000);338mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra));339mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));340341return 0;342}343344static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)345{346u32 div;347unsigned char bs = 0;348unsigned char cp = 0;349350if (buf_len < 5) return -EINVAL;351352div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;353354if (params->frequency < 150000000)355cp = 0xB4;356else if (params->frequency < 173000000)357cp = 0xBC;358else if (params->frequency < 250000000)359cp = 0xB4;360else if (params->frequency < 400000000)361cp = 0xBC;362else if (params->frequency < 420000000)363cp = 0xF4;364else if (params->frequency < 470000000)365cp = 0xFC;366else if (params->frequency < 600000000)367cp = 0xBC;368else if (params->frequency < 730000000)369cp = 0xF4;370else371cp = 0xFC;372373if (params->frequency < 150000000)374bs = 0x01;375else if (params->frequency < 173000000)376bs = 0x01;377else if (params->frequency < 250000000)378bs = 0x02;379else if (params->frequency < 400000000)380bs = 0x02;381else if (params->frequency < 420000000)382bs = 0x02;383else if (params->frequency < 470000000)384bs = 0x02;385else if (params->frequency < 600000000)386bs = 0x08;387else if (params->frequency < 730000000)388bs = 0x08;389else390bs = 0x08;391392pllbuf[0] = 0x61;393pllbuf[1] = div >> 8;394pllbuf[2] = div & 0xff;395pllbuf[3] = cp;396pllbuf[4] = bs;397398return 5;399}400401static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {402.demod_address = 0x0f,403.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,404};405406static struct dst_config dst_config = {407.demod_address = 0x55,408};409410static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)411{412struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;413414return request_firmware(fw, name, &bt->bt->dev->dev);415}416417static void or51211_setmode(struct dvb_frontend * fe, int mode)418{419struct dvb_bt8xx_card *bt = fe->dvb->priv;420bttv_write_gpio(bt->bttv_nr, 0x0002, mode); /* Reset */421msleep(20);422}423424static void or51211_reset(struct dvb_frontend * fe)425{426struct dvb_bt8xx_card *bt = fe->dvb->priv;427428/* RESET DEVICE429* reset is controlled by GPIO-0430* when set to 0 causes reset and when to 1 for normal op431* must remain reset for 128 clock cycles on a 50Mhz clock432* also PRM1 PRM2 & PRM4 are controlled by GPIO-1,GPIO-2 & GPIO-4433* We assume that the reset has be held low long enough or we434* have been reset by a power on. When the driver is unloaded435* reset set to 0 so if reloaded we have been reset.436*/437/* reset & PRM1,2&4 are outputs */438int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);439if (ret != 0)440printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);441bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000); /* Reset */442msleep(20);443/* Now set for normal operation */444bttv_write_gpio(bt->bttv_nr, 0x0001F, 0x0001);445/* wait for operation to begin */446msleep(500);447}448449static void or51211_sleep(struct dvb_frontend * fe)450{451struct dvb_bt8xx_card *bt = fe->dvb->priv;452bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000);453}454455static struct or51211_config or51211_config = {456.demod_address = 0x15,457.request_firmware = or51211_request_firmware,458.setmode = or51211_setmode,459.reset = or51211_reset,460.sleep = or51211_sleep,461};462463static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)464{465struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;466u8 buf[4];467u32 div;468struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };469470div = (params->frequency + 36166667) / 166667;471472buf[0] = (div >> 8) & 0x7F;473buf[1] = div & 0xFF;474buf[2] = 0x85;475if ((params->frequency >= 47000000) && (params->frequency < 153000000))476buf[3] = 0x01;477else if ((params->frequency >= 153000000) && (params->frequency < 430000000))478buf[3] = 0x02;479else if ((params->frequency >= 430000000) && (params->frequency < 824000000))480buf[3] = 0x0C;481else if ((params->frequency >= 824000000) && (params->frequency < 863000000))482buf[3] = 0x8C;483else484return -EINVAL;485486if (fe->ops.i2c_gate_ctrl)487fe->ops.i2c_gate_ctrl(fe, 1);488i2c_transfer(card->i2c_adapter, &msg, 1);489return 0;490}491492static struct nxt6000_config vp3021_alps_tded4_config = {493.demod_address = 0x0a,494.clock_inversion = 1,495};496497static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)498{499static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };500static u8 mt352_reset [] = { 0x50, 0x80 };501static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };502static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };503static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };504505mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));506udelay(2000);507mt352_write(fe, mt352_reset, sizeof(mt352_reset));508mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));509mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));510mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));511512return 0;513}514515static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)516{517u32 div;518struct dvb_ofdm_parameters *op = ¶ms->u.ofdm;519520if (buf_len < 5)521return -EINVAL;522523div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;524525pllbuf[0] = 0x61;526pllbuf[1] = (div >> 8) & 0x7F;527pllbuf[2] = div & 0xFF;528pllbuf[3] = 0x85;529530dprintk("frequency %u, div %u\n", params->frequency, div);531532if (params->frequency < 470000000)533pllbuf[4] = 0x02;534else if (params->frequency > 823000000)535pllbuf[4] = 0x88;536else537pllbuf[4] = 0x08;538539if (op->bandwidth == 8)540pllbuf[4] |= 0x04;541542return 5;543}544545static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)546{547/*548* Reset the frontend, must be called before trying549* to initialise the MT352 or mt352_attach550* will fail. Same goes for the nxt6000 frontend.551*552*/553554int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);555if (ret != 0)556printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);557558/* Pulse the reset line */559bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */560bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low */561msleep(100);562563bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */564}565566static struct mt352_config digitv_alps_tded4_config = {567.demod_address = 0x0a,568.demod_init = digitv_alps_tded4_demod_init,569};570571static struct lgdt330x_config tdvs_tua6034_config = {572.demod_address = 0x0e,573.demod_chip = LGDT3303,574.serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */575};576577static void lgdt330x_reset(struct dvb_bt8xx_card *bt)578{579/* Set pin 27 of the lgdt3303 chip high to reset the frontend */580581/* Pulse the reset line */582bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */583bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000000); /* Low */584msleep(100);585586bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */587msleep(100);588}589590static void frontend_init(struct dvb_bt8xx_card *card, u32 type)591{592struct dst_state* state = NULL;593594switch(type) {595case BTTV_BOARD_DVICO_DVBT_LITE:596card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);597598if (card->fe == NULL)599card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,600card->i2c_adapter);601602if (card->fe != NULL) {603card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;604card->fe->ops.info.frequency_min = 174000000;605card->fe->ops.info.frequency_max = 862000000;606}607break;608609case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:610lgdt330x_reset(card);611card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);612if (card->fe != NULL) {613dvb_attach(simple_tuner_attach, card->fe,614card->i2c_adapter, 0x61,615TUNER_LG_TDVS_H06XF);616dprintk ("dvb_bt8xx: lgdt330x detected\n");617}618break;619620case BTTV_BOARD_NEBULA_DIGITV:621/*622* It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);623* this would be a cleaner solution than trying each frontend in turn.624*/625626/* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */627digitv_alps_tded4_reset(card);628card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);629if (card->fe != NULL) {630card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;631dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");632break;633}634635/* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */636digitv_alps_tded4_reset(card);637card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);638639if (card->fe != NULL) {640card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;641dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");642}643break;644645case BTTV_BOARD_AVDVBT_761:646card->fe = dvb_attach(sp887x_attach, µtune_mt7202dtf_config, card->i2c_adapter);647if (card->fe) {648card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;649}650break;651652case BTTV_BOARD_AVDVBT_771:653card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);654if (card->fe != NULL) {655card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;656card->fe->ops.info.frequency_min = 174000000;657card->fe->ops.info.frequency_max = 862000000;658}659break;660661case BTTV_BOARD_TWINHAN_DST:662/* DST is not a frontend driver !!! */663state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);664if (!state) {665printk("dvb_bt8xx: No memory\n");666break;667}668/* Setup the Card */669state->config = &dst_config;670state->i2c = card->i2c_adapter;671state->bt = card->bt;672state->dst_ca = NULL;673/* DST is not a frontend, attaching the ASIC */674if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {675printk("%s: Could not find a Twinhan DST.\n", __func__);676break;677}678/* Attach other DST peripherals if any */679/* Conditional Access device */680card->fe = &state->frontend;681if (state->dst_hw_cap & DST_TYPE_HAS_CA)682dvb_attach(dst_ca_attach, state, &card->dvb_adapter);683break;684685case BTTV_BOARD_PINNACLESAT:686card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);687if (card->fe) {688card->fe->ops.tuner_ops.init = pinnsat_tuner_init;689card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;690card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;691}692break;693694case BTTV_BOARD_PC_HDTV:695card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);696if (card->fe != NULL)697dvb_attach(simple_tuner_attach, card->fe,698card->i2c_adapter, 0x61,699TUNER_PHILIPS_FCV1236D);700break;701}702703if (card->fe == NULL)704printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",705card->bt->dev->vendor,706card->bt->dev->device,707card->bt->dev->subsystem_vendor,708card->bt->dev->subsystem_device);709else710if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {711printk("dvb-bt8xx: Frontend registration failed!\n");712dvb_frontend_detach(card->fe);713card->fe = NULL;714}715}716717static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)718{719int result;720721result = dvb_register_adapter(&card->dvb_adapter, card->card_name,722THIS_MODULE, &card->bt->dev->dev,723adapter_nr);724if (result < 0) {725printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);726return result;727}728card->dvb_adapter.priv = card;729730card->bt->adapter = card->i2c_adapter;731732memset(&card->demux, 0, sizeof(struct dvb_demux));733734card->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING;735736card->demux.priv = card;737card->demux.filternum = 256;738card->demux.feednum = 256;739card->demux.start_feed = dvb_bt8xx_start_feed;740card->demux.stop_feed = dvb_bt8xx_stop_feed;741card->demux.write_to_decoder = NULL;742743if ((result = dvb_dmx_init(&card->demux)) < 0) {744printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);745746dvb_unregister_adapter(&card->dvb_adapter);747return result;748}749750card->dmxdev.filternum = 256;751card->dmxdev.demux = &card->demux.dmx;752card->dmxdev.capabilities = 0;753754if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) {755printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);756757dvb_dmx_release(&card->demux);758dvb_unregister_adapter(&card->dvb_adapter);759return result;760}761762card->fe_hw.source = DMX_FRONTEND_0;763764if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {765printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);766767dvb_dmxdev_release(&card->dmxdev);768dvb_dmx_release(&card->demux);769dvb_unregister_adapter(&card->dvb_adapter);770return result;771}772773card->fe_mem.source = DMX_MEMORY_FE;774775if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {776printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);777778card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);779dvb_dmxdev_release(&card->dmxdev);780dvb_dmx_release(&card->demux);781dvb_unregister_adapter(&card->dvb_adapter);782return result;783}784785if ((result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {786printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);787788card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);789card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);790dvb_dmxdev_release(&card->dmxdev);791dvb_dmx_release(&card->demux);792dvb_unregister_adapter(&card->dvb_adapter);793return result;794}795796dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);797798tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);799800frontend_init(card, type);801802return 0;803}804805static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)806{807struct dvb_bt8xx_card *card;808struct pci_dev* bttv_pci_dev;809int ret;810811if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))812return -ENOMEM;813814mutex_init(&card->lock);815card->bttv_nr = sub->core->nr;816strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));817card->i2c_adapter = &sub->core->i2c_adap;818819switch(sub->core->type) {820case BTTV_BOARD_PINNACLESAT:821card->gpio_mode = 0x0400c060;822/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,823BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */824card->op_sync_orin = BT878_RISC_SYNC_MASK;825card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;826break;827828case BTTV_BOARD_DVICO_DVBT_LITE:829card->gpio_mode = 0x0400C060;830card->op_sync_orin = BT878_RISC_SYNC_MASK;831card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;832/* 26, 15, 14, 6, 5833* A_PWRDN DA_DPM DA_SBR DA_IOM_DA834* DA_APP(parallel) */835break;836837case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:838card->gpio_mode = 0x0400c060;839card->op_sync_orin = BT878_RISC_SYNC_MASK;840card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;841break;842843case BTTV_BOARD_NEBULA_DIGITV:844case BTTV_BOARD_AVDVBT_761:845card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);846card->op_sync_orin = BT878_RISC_SYNC_MASK;847card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;848/* A_PWRDN DA_SBR DA_APP (high speed serial) */849break;850851case BTTV_BOARD_AVDVBT_771: //case 0x07711461:852card->gpio_mode = 0x0400402B;853card->op_sync_orin = BT878_RISC_SYNC_MASK;854card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;855/* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/856break;857858case BTTV_BOARD_TWINHAN_DST:859card->gpio_mode = 0x2204f2c;860card->op_sync_orin = BT878_RISC_SYNC_MASK;861card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |862BT878_APPERR | BT878_AFBUS;863/* 25,21,14,11,10,9,8,3,2 then864* 0x33 = 5,4,1,0865* A_SEL=SML, DA_MLB, DA_SBR,866* DA_SDR=f, fifo trigger = 32 DWORDS867* IOM = 0 == audio A/D868* DPM = 0 == digital audio mode869* == async data parallel port870* then 0x33 (13 is set by start_capture)871* DA_APP = async data parallel port,872* ACAP_EN = 1,873* RISC+FIFO ENABLE */874break;875876case BTTV_BOARD_PC_HDTV:877card->gpio_mode = 0x0100EC7B;878card->op_sync_orin = BT878_RISC_SYNC_MASK;879card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;880break;881882default:883printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n",884sub->core->type);885kfree(card);886return -ENODEV;887}888889dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);890891if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {892printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);893kfree(card);894return -EFAULT;895}896897if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {898printk("dvb_bt8xx: unable to determine DMA core of card %d,\n",899card->bttv_nr);900printk("dvb_bt8xx: if you have the ALSA bt87x audio driver "901"installed, try removing it.\n");902903kfree(card);904return -EFAULT;905}906907mutex_init(&card->bt->gpio_lock);908card->bt->bttv_nr = sub->core->nr;909910if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) {911kfree(card);912return ret;913}914915dev_set_drvdata(&sub->dev, card);916return 0;917}918919static void dvb_bt8xx_remove(struct bttv_sub_device *sub)920{921struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);922923dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);924925bt878_stop(card->bt);926tasklet_kill(&card->bt->tasklet);927dvb_net_release(&card->dvbnet);928card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);929card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);930dvb_dmxdev_release(&card->dmxdev);931dvb_dmx_release(&card->demux);932if (card->fe) {933dvb_unregister_frontend(card->fe);934dvb_frontend_detach(card->fe);935}936dvb_unregister_adapter(&card->dvb_adapter);937938kfree(card);939}940941static struct bttv_sub_driver driver = {942.drv = {943.name = "dvb-bt8xx",944},945.probe = dvb_bt8xx_probe,946.remove = dvb_bt8xx_remove,947/* FIXME:948* .shutdown = dvb_bt8xx_shutdown,949* .suspend = dvb_bt8xx_suspend,950* .resume = dvb_bt8xx_resume,951*/952};953954static int __init dvb_bt8xx_init(void)955{956return bttv_sub_register(&driver, "dvb");957}958959static void __exit dvb_bt8xx_exit(void)960{961bttv_sub_unregister(&driver);962}963964module_init(dvb_bt8xx_init);965module_exit(dvb_bt8xx_exit);966967MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");968MODULE_AUTHOR("Florian Schirmer <[email protected]>");969MODULE_LICENSE("GPL");970971972