diff options
author | Patrick Boettcher <devnull@localhost> | 2005-01-09 15:50:44 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2005-01-09 15:50:44 +0000 |
commit | ff21bded4892d260edde81df8e8f108aa229c7fc (patch) | |
tree | 8c41925392ce0aa76a48c0b973569af877414ff8 /linux/drivers/media/dvb | |
parent | 9b432f78f4e082705fe90c5d8885d9f7ced755d0 (diff) | |
download | mediapointer-dvb-s2-ff21bded4892d260edde81df8e8f108aa229c7fc.tar.gz mediapointer-dvb-s2-ff21bded4892d260edde81df8e8f108aa229c7fc.tar.bz2 |
internal refactoring step 3/3
- added tuner and demod types for easier extension of new devices
- added a check for some artec devices which have another tuner
onboard, but don't know it, pll_addr is now a callback because of that
- general callbacks for pll_set, pll_init and demod_init. They decide which
pll-programming function is used and so on
- added tuner passthru callback to xfer_ops. now dibusb can en/disable the
tuner passthru of the dib3000m*-frontends; necessary for tuner probing
- remote type determination (no for hanftek, nec for others), was not planned
- fixed a bug in start_feed, which was introduced in step 2/3 but wasn't critical
- added pll-programming for lg_tdtp_e102p_tua6034 (it has the tua6034 as pll)
- added pll-programming and initialization for PANASONIC ENV77H11D5
- understood the i2c-address problem, now it is more logical
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c | 59 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c | 363 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb.h | 55 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000-common.h | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000.h | 13 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000mb.c | 32 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000mc.c | 34 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib3000mc_priv.h | 2 |
10 files changed, 368 insertions, 206 deletions
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c index 1d5e3b166..a8ff62054 100644 --- a/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c @@ -4,7 +4,7 @@ * * dvb-dibusb-core.c * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DiBcom, which has * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) @@ -144,7 +144,6 @@ static struct usb_device_id dib_table [] = { /* 32 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) }, /* 33 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) }, #endif - { } /* Terminating entry */ }; @@ -156,43 +155,65 @@ static struct dibusb_usb_controller dibusb_usb_ctrl[] = { { .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, }; -int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep); - -int thomson_cable_eu_pll_set(struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep); +struct dibusb_tuner dibusb_tuner[] = { + { DIBUSB_TUNER_CABLE_THOMSON, + 0x61 + }, + { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5, + 0x60 + }, + { DIBUSB_TUNER_CABLE_LG_TDTP_E102P, + 0x61 + }, + { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5, + 0x60 + }, +}; -int lg_tdtp_e102p_tua6034(struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep, u8 *pllbuf); +static struct dibusb_demod dibusb_demod[] = { + { DIBUSB_DIB3000MB, + { 0x8, 0 }, + }, + { DIBUSB_DIB3000MC, + { 0x9, 0xa, 0xb, 0xc }, + }, + { DIBUSB_MT352, + { 0xf, 0 }, + }, +}; static struct dibusb_device_class dibusb_device_classes[] = { { .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0], .firmware = "dvb-dibusb-5.0.0.11.fw", .pipe_cmd = 0x01, .pipe_data = 0x02, .urb_count = 3, .urb_buffer_size = 4096, - .pll_set = thomson_cable_eu_pll_set, .pll_addr = 194, - .demod_i2c_addrs = { 0x10, 0 }, + DIBUSB_RC_NEC_PROTOCOL, + &dibusb_demod[DIBUSB_DIB3000MB], + &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], }, { DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1], "dvb-dibusb-an2235-1.fw", 0x01, 0x02, 3, 4096, - thomson_cable_eu_pll_set, 194, - { 0x10, 0 }, + DIBUSB_RC_NEC_PROTOCOL, + &dibusb_demod[DIBUSB_DIB3000MB], + &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON], }, { DIBUSB2_0,&dibusb_usb_ctrl[2], "dvb-dibusb-6.0.0.5.fw", 0x01, 0x06, - 3, 188*210, - panasonic_cofdm_env57h1xd5_pll_set, 192, - { 0x12, 0x14, 0x16, 0x18 }, + 3, 188*210, + DIBUSB_RC_NEC_PROTOCOL, + &dibusb_demod[DIBUSB_DIB3000MC], + &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5], }, { UMT2_0, &dibusb_usb_ctrl[2], "dvb-dibusb-umt-1.fw", 0x01, 0x02, - 3, 200, // TODO - NULL, 192, - { 0x1e }, + 15, 4096, + DIBUSB_RC_NO, + &dibusb_demod[DIBUSB_MT352], + &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P], }, }; diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c index 2683f4559..78adf48f4 100644 --- a/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c @@ -93,8 +93,8 @@ static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff) * reception. */ -// if ((dib->dibdev->parm->firmware_bug || dib->feedcount == onoff) && - if (dib->feedcount > 0) { +// if ((dib->dibdev->parm->firmware_bug) + if (dib->feedcount == onoff && dib->feedcount > 0) { deb_ts("controlling pid parser\n"); if (dib->xfer_ops.pid_parse != NULL) { diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c index ee476baa1..19191a3ae 100644 --- a/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c @@ -23,7 +23,7 @@ static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr, len = 2 + wlen + (wo ? 0 : 2); sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; - sndbuf[1] = (addr & 0xfe) | (wo ? 0 : 1); + sndbuf[1] = (addr << 1) | (wo ? 0 : 1); memcpy(&sndbuf[2],wbuf,wlen); @@ -70,34 +70,6 @@ static u32 dibusb_i2c_func(struct i2c_adapter *adapter) return I2C_FUNC_I2C; } -int lg_tdtp_e102p_tua6034(struct dvb_frontend *fe, struct - dvb_frontend_parameters* fep, u8 *pllbuf); - -static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe) -{ - static u8 mt352_clock_config [] = { 0x89, 0xb0, 0x2d }; - static u8 mt352_reset [] = { 0x50, 0x80 }; - static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static u8 mt352_agc_cfg [] = { 0x67, 0x14, 0x22 }; - static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; - - mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); - udelay(2000); - mt352_write(fe, mt352_reset, sizeof(mt352_reset)); - mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); - - mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); - mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - - return 0; -} - -static struct mt352_config lg_tdtp_e102p_tua6034_config = { - .demod_address = 0x1e, - .demod_init = lg_tdtp_e102p_mt352_demod_init, - .pll_set = lg_tdtp_e102p_tua6034, -}; - static struct i2c_algorithm dibusb_algo = { .name = "DiBcom USB i2c algorithm", .id = I2C_ALGO_BIT, @@ -105,38 +77,92 @@ static struct i2c_algorithm dibusb_algo = { .functionality = dibusb_i2c_func, }; +static int dibusb_general_demod_init(struct dvb_frontend *fe); +static u8 dibusb_general_pll_addr(struct dvb_frontend *fe); +static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]); +static int dibusb_general_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters* params, u8 pll_buf[5]); + +static struct mt352_config mt352_hanftek_umt_010_config = { + .demod_address = 0x1e, + .demod_init = dibusb_general_demod_init, + .pll_set = dibusb_general_pll_set, +}; + +static int dibusb_tuner_quirk(struct usb_dibusb *dib) +{ + switch (dib->dibdev->dev_cl->id) { + case DIBUSB1_1_AN2235: { /* some these device have the ENV77H11D5 and some the THOMSON CABLE */ + struct dibusb_tuner *t; + u8 b[2] = { 0,0 } ,b2[1]; + struct i2c_msg msg[2] = { + { .flags = 0, .buf = b, .len = 2 }, + { .flags = I2C_M_RD, .buf = b2, .len = 1}, + }; + + t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5]; + + msg[0].addr = (t->pll_addr << 1) | 1; + msg[1].addr = (t->pll_addr << 1) | 1; + + if (dib->xfer_ops.tuner_pass_ctrl != NULL) + dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr); + deb_info("ret: %d\n",dibusb_i2c_xfer(&dib->i2c_adap,msg,2)); + if (dib->xfer_ops.tuner_pass_ctrl != NULL) + dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr); + + if (b2[0] == 0xfe) + info("this device has the Thomson Cable onboard. Which is default."); + else { + dib->tuner = t; + info("this device has the Panasonic ENV77H11D5 onboard."); + } + break; + } + default: + break; + } + return 0; +} + int dibusb_fe_init(struct usb_dibusb* dib) { struct dib3000_config demod_cfg; int i; - if (dib->init_state & DIBUSB_STATE_I2C) - for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod_i2c_addrs) / sizeof(unsigned char) && - dib->dibdev->dev_cl->demod_i2c_addrs[i] != 0; i++) { - - demod_cfg.demod_address = dib->dibdev->dev_cl->demod_i2c_addrs[i]; - demod_cfg.pll_addr = dib->dibdev->dev_cl->pll_addr; - demod_cfg.pll_set = dib->dibdev->dev_cl->pll_set; - demod_cfg.pll_init = NULL; - - switch (dib->dibdev->dev_cl->id) { - case DIBUSB1_1: - case DIBUSB1_1_AN2235: + if (dib->init_state & DIBUSB_STATE_I2C) { + for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) && + dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) { + + demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i]; + demod_cfg.pll_addr = dibusb_general_pll_addr; + demod_cfg.pll_set = dibusb_general_pll_set; + demod_cfg.pll_init = dibusb_general_pll_init; + + switch (dib->dibdev->dev_cl->demod->id) { + case DIBUSB_DIB3000MB: dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops); break; - case DIBUSB2_0: + case DIBUSB_DIB3000MC: dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops); break; - case UMT2_0: - dib->fe = mt352_attach(&lg_tdtp_e102p_tua6034_config, &dib->i2c_adap); + case DIBUSB_MT352: + mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i]; + dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap); break; } if (dib->fe != NULL) { - info("found demodulator at i2c address 0x%x",demod_cfg.demod_address); + info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]); break; } } + + /* setting the default tuner */ + dib->tuner = dib->dibdev->dev_cl->tuner; + /* check which tuner is mounted on this device, in case this is unsure */ + dibusb_tuner_quirk(dib); + } if (dib->fe == NULL) { err("A frontend driver was not found for device '%s'.", dib->dibdev->name); @@ -160,8 +186,6 @@ int dibusb_fe_exit(struct usb_dibusb *dib) return 0; } - - int dibusb_i2c_init(struct usb_dibusb *dib) { int ret = 0; @@ -184,13 +208,6 @@ int dibusb_i2c_init(struct usb_dibusb *dib) err("could not add i2c adapter"); dib->init_state |= DIBUSB_STATE_I2C; - - u8 b[2] = { 0xff , 0xff }; - dibusb_i2c_msg(dib, 0x10, b,2, NULL, 0); - - b[0] = 0x05; - b[1] = 0x01; - dibusb_i2c_msg(dib, 0x10, b,2, NULL, 0); return ret; } @@ -204,17 +221,8 @@ int dibusb_i2c_exit(struct usb_dibusb *dib) /* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */ -int thomson_cable_eu_pll_set(struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep) +static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]) { - struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = { - .addr = dib->dibdev->dev_cl->pll_addr, - .flags = 0, - .buf = buf, - .len = sizeof(buf) - }; u32 tfreq = (fep->frequency + 36125000) / 62500; int vu,p0,p1,p2; @@ -227,33 +235,18 @@ int thomson_cable_eu_pll_set(struct dvb_frontend *fe, struct else return -EINVAL; - buf[0] = (tfreq >> 8) & 0x7f; - buf[1] = tfreq & 0xff; - buf[2] = 0x8e; - buf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0; - - if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) - return -EIO; - - msleep(1); + pllbuf[0] = (tfreq >> 8) & 0x7f; + pllbuf[1] = tfreq & 0xff; + pllbuf[2] = 0x8e; + pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0; return 0; } -int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep) +static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]) { - struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; - u8 buf[4]; u32 freq = fep->frequency; u32 tfreq = ((freq + 36125000)*6 + 500000) / 1000000; u8 TA, T210, R210, ctrl1, cp210, p4321; - struct i2c_msg msg = { - .addr = dib->dibdev->dev_cl->pll_addr, - .flags = 0, - .buf = buf, - .len = sizeof(buf) - }; - if (freq > 858000000) { err("frequency cannot be larger than 858 MHz."); return -EINVAL; @@ -281,15 +274,11 @@ int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct else // if (freq < 862000000) p4321 = 4; // BW selection for UHF E21 to E69 - buf[0] = (tfreq >> 8) & 0xff; - buf[1] = (tfreq >> 0) & 0xff; - buf[2] = 0xff & ctrl1; - buf[3] = (cp210 << 5) | (p4321); - - if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) - return -EIO; + pllbuf[0] = (tfreq >> 8) & 0xff; + pllbuf[1] = (tfreq >> 0) & 0xff; + pllbuf[2] = 0xff & ctrl1; + pllbuf[3] = (cp210 << 5) | (p4321); - msleep(1); return 0; } @@ -323,26 +312,23 @@ int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct * BSn = 1 corresponding port is on */ -/* -int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4]) -{ - +static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4]) +{ + pllbuf[0] = 0x0b; + pllbuf[1] = 0xf5; + pllbuf[2] = 0x85; + pllbuf[3] = 0xab; + return 0; } -*/ -/* -int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend *fe, struct - dvb_frontend_parameters *fep,u8 pllbuf[4]) +static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4]) { - u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = - sizeof(tuner_buf) }; int tuner_frequency = 0; u8 band, cp, filter; // determine charge pump - tuner_frequency = params->frequency + 36166000; + tuner_frequency = fep->frequency + 36166000; if (tuner_frequency < 87000000) return -EINVAL; else if (tuner_frequency < 130000000) @@ -367,46 +353,42 @@ int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend *fe, struct return -EINVAL; // determine band - if (params->frequency < 49000000) + if (fep->frequency < 49000000) return -EINVAL; - else if (params->frequency < 161000000) + else if (fep->frequency < 161000000) band = 1; - else if (params->frequency < 444000000) + else if (fep->frequency < 444000000) band = 2; - else if (params->frequency < 861000000) + else if (fep->frequency < 861000000) band = 4; else return -EINVAL; // setup PLL filter - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - filter = 0; - break; - - case BANDWIDTH_7_MHZ: - filter = 0; - break; - - case BANDWIDTH_8_MHZ: - filter = 1; - break; - - default: - return -EINVAL; + switch (fep->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + case BANDWIDTH_7_MHZ: + filter = 0; + break; + case BANDWIDTH_8_MHZ: + filter = 1; + break; + default: + return -EINVAL; } // calculate divisor // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; + tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000; // setup tuner buffer - tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; - tuner_buf[1] = tuner_frequency & 0xff; - tuner_buf[2] = 0xca; - tuner_buf[3] = (cp << 5) | (filter << 3) | band; + pllbuf[0] = (tuner_frequency >> 8) & 0x7f; + pllbuf[1] = tuner_frequency & 0xff; + pllbuf[2] = 0xca; + pllbuf[3] = (cp << 5) | (filter << 3) | band; + return 0; +} -*/ /* * 7 6 5 4 3 2 1 0 * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0 @@ -430,8 +412,7 @@ int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend *fe, struct * */ -int lg_tdtp_e102p_tua6034(struct dvb_frontend *fe, struct - dvb_frontend_parameters* fep, u8 *pllbuf) +static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4]) { u32 div; u8 p3210, p4; @@ -442,11 +423,6 @@ int lg_tdtp_e102p_tua6034(struct dvb_frontend *fe, struct div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; - pllbuf[0] = 0xc2; - pllbuf[1] = (div >> 8) & 0x7f; - pllbuf[2] = div & 0xff; - pllbuf[3] = 0xce; - if (fep->frequency < 174500000) p3210 = 1; // not supported by the tdtp_e102p else if (fep->frequency < 230000000) // VHF @@ -459,8 +435,121 @@ int lg_tdtp_e102p_tua6034(struct dvb_frontend *fe, struct else p4 = 1; - pllbuf[4] = (p4 << 4) | p3210; + pllbuf[0] = (div >> 8) & 0x7f; + pllbuf[1] = div & 0xff; + pllbuf[2] = 0xce; + pllbuf[3] = (p4 << 4) | p3210; + deb_info("pllbuf[4] = %x\n",pllbuf[4]); return 0; } + +static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe) +{ + static u8 mt352_clock_config [] = { 0x89, 0xb0, 0x2d }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x14, 0x22 }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); + + return 0; +} + +static int dibusb_general_demod_init(struct dvb_frontend *fe) +{ + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + switch (dib->dibdev->dev_cl->id) { + case UMT2_0: + return lg_tdtp_e102p_mt352_demod_init(fe); + default: /* other device classes do not have device specific demod inits */ + break; + } + return 0; +} + +static u8 dibusb_general_pll_addr(struct dvb_frontend *fe) +{ + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + return dib->tuner->pll_addr; +} + +static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4]) +{ + if (pll_buf == NULL) { + struct i2c_msg msg = { + .addr = dib->tuner->pll_addr, + .flags = 0, + .buf = buf, + .len = sizeof(buf) + }; + if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) + return -EIO; + msleep(1); + } else { + pll_buf[0] = dib->tuner->pll_addr << 1; + memcpy(&pll_buf[1],buf,4); + } + + return 0; +} + +static int dibusb_general_pll_init(struct dvb_frontend *fe, + u8 pll_buf[5]) +{ + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + u8 buf[4]; + int ret=0; + switch (dib->tuner->id) { + case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5: + ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf); + break; + default: + break; + } + + if (ret) + return ret; + + return dibusb_pll_i2c_helper(dib,pll_buf,buf); +} + +static int dibusb_general_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep, u8 pll_buf[5]) +{ + struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv; + u8 buf[4]; + int ret=0; + + switch (dib->tuner->id) { + case DIBUSB_TUNER_CABLE_THOMSON: + ret = thomson_cable_eu_pll_set(fep, buf); + break; + case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5: + ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf); + break; + case DIBUSB_TUNER_CABLE_LG_TDTP_E102P: + ret = lg_tdtp_e102p_tua6034(fep, buf); + break; + case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5: + ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf); + break; + default: + warn("no pll programming routine found for tuner %d.\n",dib->tuner->id); + ret = -ENODEV; + break; + } + + if (ret) + return ret; + + return dibusb_pll_i2c_helper(dib,pll_buf,buf); +} diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c index 82931c0c9..95a850f0b 100644 --- a/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c @@ -150,6 +150,9 @@ int dibusb_remote_init(struct usb_dibusb *dib) { int i; + if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) + return 0; + /* Initialise the remote-control structures.*/ init_input_dev(&dib->rc_input_dev); @@ -181,6 +184,9 @@ int dibusb_remote_init(struct usb_dibusb *dib) int dibusb_remote_exit(struct usb_dibusb *dib) { + if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO) + return 0; + if (dib->init_state & DIBUSB_STATE_REMOTE) { cancel_delayed_work(&dib->rc_query_work); flush_scheduled_work(); diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h index 9b54f5d4c..201e20ebd 100644 --- a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h @@ -1,7 +1,7 @@ /* * dvb-dibusb.h * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -74,20 +74,46 @@ typedef enum { DIBUSB1_1_AN2235, DIBUSB2_0, UMT2_0, + DIBUSB1_1_AN2235_WITH } dibusb_class_t; +typedef enum { + DIBUSB_TUNER_CABLE_THOMSON = 0, + DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5, + DIBUSB_TUNER_CABLE_LG_TDTP_E102P, + DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5, +} dibusb_tuner_t; + +typedef enum { + DIBUSB_DIB3000MB = 0, + DIBUSB_DIB3000MC, + DIBUSB_MT352, +} dibusb_demodulator_t; + +typedef enum { + DIBUSB_RC_NO = 0, + DIBUSB_RC_NEC_PROTOCOL = 1, +} dibusb_remote_t; + +struct dibusb_tuner { + dibusb_tuner_t id; + + u8 pll_addr; /* tuner i2c address */ +}; +extern struct dibusb_tuner dibusb_tuner[]; + #define DIBUSB_POSSIBLE_I2C_ADDR_NUM 4 -struct dibusb_frontend_tuner_combi { - int (*pll_set) (struct dvb_frontend *,struct dvb_frontend_parameters *, u8 - pll_buf[5]); /* pll_set function callback */ - unsigned char pll_addr; /* tuner i2c address */ - unsigned char demod_i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */ +struct dibusb_demod { + dibusb_demodulator_t id; + + u8 i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */ }; +#define DIBUSB_MAX_TUNER_NUM 2 struct dibusb_device_class { dibusb_class_t id; - const struct dibusb_usb_controller *usb_ctrl; /* usb controller */ + const struct dibusb_usb_controller *usb_ctrl; /* usb controller */ const char *firmware; /* valid firmware filenames */ int pipe_cmd; /* command pipe (read/write) */ @@ -95,12 +121,11 @@ struct dibusb_device_class { int urb_count; /* number of data URBs to be submitted */ int urb_buffer_size; /* the size of the buffer for each URB */ - -// struct dibusb_frontend_tuner_combi *fe_tuner; /* appropriate frontend and tuner combination */ - int (*pll_set) (struct dvb_frontend *,struct dvb_frontend_parameters *); - u8 pll_addr; /* tuner i2c address */ - u8 demod_i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */ + dibusb_remote_t remote_type; /* does this device have a ir-receiver */ + + struct dibusb_demod *demod; /* which demodulator is mount */ + struct dibusb_tuner *tuner; /* which tuner can be found here */ }; #define DIBUSB_ID_MAX_NUM 15 @@ -131,6 +156,8 @@ struct usb_dibusb { int feedcount; int pid_parse; struct dib3000_xfer_ops xfer_ops; + + struct dibusb_tuner *tuner; struct urb **urb_list; u8 *buffer; @@ -206,14 +233,14 @@ int dibusb_urb_exit(struct usb_dibusb *dib); /* * i2c read - * bulk write: 0x02 (i2c_addr & 0x01) register_bytes length_word + * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word * bulk read: byte_buffer (length_word bytes) */ #define DIBUSB_REQ_I2C_READ 0x02 /* * i2c write - * bulk write: 0x03 i2c_addr register_bytes value_bytes + * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes */ #define DIBUSB_REQ_I2C_WRITE 0x03 diff --git a/linux/drivers/media/dvb/frontends/dib3000-common.h b/linux/drivers/media/dvb/frontends/dib3000-common.h index e23acbc29..1e65c301a 100644 --- a/linux/drivers/media/dvb/frontends/dib3000-common.h +++ b/linux/drivers/media/dvb/frontends/dib3000-common.h @@ -4,7 +4,7 @@ * * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DibCom, which has * @@ -136,8 +136,8 @@ extern int dib3000_search_status(u16 irq,u16 lock); #define DIB3000_DDS_INVERSION_OFF ( 0) #define DIB3000_DDS_INVERSION_ON ( 1) -#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 7)) -#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 7) | (1 << 7))) +#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8)) +#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7))) /* for auto search */ extern u16 dib3000_seq[2][2][2]; diff --git a/linux/drivers/media/dvb/frontends/dib3000.h b/linux/drivers/media/dvb/frontends/dib3000.h index b1fa889ab..29b4bdd83 100644 --- a/linux/drivers/media/dvb/frontends/dib3000.h +++ b/linux/drivers/media/dvb/frontends/dib3000.h @@ -2,7 +2,7 @@ * public header file of the frontend drivers for mobile DVB-T demodulators * DiBcom 3000-MB and DiBcom 3000-MC/P (http://www.dibcom.fr/) * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DibCom, which has * @@ -31,12 +31,10 @@ struct dib3000_config /* the demodulator's i2c address */ u8 demod_address; - /* The i2c address of the PLL */ - u8 pll_addr; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend *fe); - int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params); + /* PLL maintenance and the i2c address of the PLL */ + u8 (*pll_addr)(struct dvb_frontend *fe); + int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]); + int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]); }; struct dib3000_xfer_ops @@ -45,6 +43,7 @@ struct dib3000_xfer_ops int (*pid_parse)(struct dvb_frontend *fe, int onoff); int (*fifo_ctrl)(struct dvb_frontend *fe, int onoff); int (*pid_ctrl)(struct dvb_frontend *fe, int pid, int onoff); + int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); }; extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, diff --git a/linux/drivers/media/dvb/frontends/dib3000mb.c b/linux/drivers/media/dvb/frontends/dib3000mb.c index ec076cd4b..5caaed1ee 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mb.c +++ b/linux/drivers/media/dvb/frontends/dib3000mb.c @@ -2,7 +2,7 @@ * Frontend driver for mobile DVB-T demodulator DiBcom 3000-MB * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DibCom, which has * @@ -47,6 +47,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a #define deb_setf(args...) dprintk(0x04,args) #define deb_getf(args...) dprintk(0x08,args) +static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr); + static int dib3000mb_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep); @@ -59,11 +61,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe, int search_state, seq; if (tuner) { - wr(DIB3000MB_REG_TUNER, - DIB3000_TUNER_WRITE_ENABLE(state->config.pll_addr)); - state->config.pll_set(fe, fep); - wr(DIB3000MB_REG_TUNER, - DIB3000_TUNER_WRITE_DISABLE(state->config.pll_addr)); + dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); + state->config.pll_set(fe, fep, NULL); + dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); deb_setf("bandwidth: "); switch (ofdm->bandwidth) { @@ -388,11 +388,9 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); if (state->config.pll_init) { - wr(DIB3000MB_REG_TUNER, - DIB3000_TUNER_WRITE_ENABLE(state->config.pll_addr)); - state->config.pll_init(fe); - wr(DIB3000MB_REG_TUNER, - DIB3000_TUNER_WRITE_DISABLE(state->config.pll_addr)); + dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); + state->config.pll_init(fe,NULL); + dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); } return 0; @@ -749,6 +747,17 @@ static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff) return 0; } +static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr) +{ + struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv; + if (onoff) { + wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr)); + } else { + wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr)); + } + return 0; +} + static struct dvb_frontend_ops dib3000mb_ops; struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, @@ -784,6 +793,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, xfer_ops->pid_parse = dib3000mb_pid_parse; xfer_ops->fifo_ctrl = dib3000mb_fifo_control; xfer_ops->pid_ctrl = dib3000mb_pid_control; + xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl; return &state->frontend; diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.c b/linux/drivers/media/dvb/frontends/dib3000mc.c index e5ca4b42a..000f15bfd 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.c +++ b/linux/drivers/media/dvb/frontends/dib3000mc.c @@ -2,7 +2,7 @@ * Frontend driver for mobile DVB-T demodulator DiBcom 3000-MC/P * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DiBCom, which has * @@ -48,6 +48,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=s #define deb_getf(args...) dprintk(0x08,args) #define deb_stat(args...) dprintk(0x10,args) +static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr); + static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode, fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth) { @@ -462,11 +464,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe, u16 val; if (tuner) { /* initial call from dvb */ - wr(DIB3000MC_REG_TUNER, - DIB3000_TUNER_WRITE_ENABLE(state->config.pll_addr)); - state->config.pll_set(fe, fep); - wr(DIB3000MC_REG_TUNER, - DIB3000_TUNER_WRITE_DISABLE(state->config.pll_addr)); + dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); + state->config.pll_set(fe,fep,NULL); + dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); state->last_tuned_freq = fep->frequency; // if (!scanboost) { @@ -648,11 +648,9 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); /* if (state->config->pll_init) { - wr(DIB3000MC_REG_TUNER, - DIB3000_TUNER_WRITE_ENABLE(state->config->pll_addr)); - state->config->pll_init(fe); - wr(DIB3000MC_REG_TUNER, - DIB3000_TUNER_WRITE_DISABLE(state->config->pll_addr)); + dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); + state->config->pll_init(fe,NULL); + dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe)); }*/ deb_info("init end\n"); return 0; @@ -813,9 +811,20 @@ static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff) return 0; } +static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr) +{ + struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv; + if (onoff) { + wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr)); + } else { + wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr)); + } + return 0; +} + static int dib3000mc_demod_init(struct dib3000_state *state) { - u16 default_addr = 0x14; + u16 default_addr = 0x0a; /* first init */ if (state->config.demod_address != default_addr) { deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr); @@ -882,6 +891,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config, xfer_ops->pid_parse = dib3000mc_pid_parse; xfer_ops->fifo_ctrl = dib3000mc_fifo_control; xfer_ops->pid_ctrl = dib3000mc_pid_control; + xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl; dib3000mc_demod_init(state); diff --git a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h b/linux/drivers/media/dvb/frontends/dib3000mc_priv.h index 53766d25a..5dd2c99ed 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h +++ b/linux/drivers/media/dvb/frontends/dib3000mc_priv.h @@ -381,7 +381,7 @@ static u16 dib3000mc_mobile_mode[][5] = { #define DIB3000MC_REG_RST_I2C_ADDR ( 1024) #define DIB3000MC_DEMOD_ADDR_ON ( 1) -#define DIB3000MC_DEMOD_ADDR(a) ((a << 3) & 0x03F0) +#define DIB3000MC_DEMOD_ADDR(a) ((a << 4) & 0x03F0) #define DIB3000MC_REG_RESTART ( 1027) #define DIB3000MC_RESTART_OFF (0x0000) |