diff options
author | Patrick Boettcher <devnull@localhost> | 2005-04-17 14:37:15 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2005-04-17 14:37:15 +0000 |
commit | 4e4da24aa36487071bd874fc63d387258299ceb0 (patch) | |
tree | b048f438139994b1842b269838bc85d2eebf2d63 /linux/drivers/media/dvb/dvb-usb/dibusb-common.c | |
parent | b5833bcf1184221ce9ff84d4787d77ce1cbacafa (diff) | |
download | mediapointer-dvb-s2-4e4da24aa36487071bd874fc63d387258299ceb0.tar.gz mediapointer-dvb-s2-4e4da24aa36487071bd874fc63d387258299ceb0.tar.bz2 |
- ported all dibusb drivers to fit into the dvb-usb-frameword
- created dvb-pll-entries for the tuner used with the dibusb-drivers
- removed all traces of the dibusb driver
- adapted the dib3000-frontends to get along with the dvb-pll-changes
Diffstat (limited to 'linux/drivers/media/dvb/dvb-usb/dibusb-common.c')
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dibusb-common.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c new file mode 100644 index 000000000..fdec9e459 --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -0,0 +1,252 @@ +/* Common methods for dibusb-based-receivers. + * + * 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 published by the Free + * Software Foundation, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "dibusb.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS); + +#define deb_info(args...) dprintk(debug,0x01,args) + +/* common stuff used by the different dibusb modules */ +int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) +{ + if (d->priv != NULL) { + struct dib_fe_xfer_ops *ops = d->priv; + if (ops->fifo_ctrl != NULL) + if (ops->fifo_ctrl(d->fe,onoff)) { + err("error while controlling the fifo of the demod."); + return -ENODEV; + } + } + return 0; +} +EXPORT_SYMBOL(dibusb_streaming_ctrl); + +int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) +{ + if (d->priv != NULL) { + struct dib_fe_xfer_ops *ops = d->priv; + if (d->pid_filtering && ops->pid_ctrl != NULL) + ops->pid_ctrl(d->fe,index,pid,onoff); + } + return 0; +} +EXPORT_SYMBOL(dibusb_pid_filter); + +int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) +{ + if (d->priv != NULL) { + struct dib_fe_xfer_ops *ops = d->priv; + if (ops->pid_parse != NULL) + if (ops->pid_parse(d->fe,onoff) < 0) + err("could not handle pid_parser"); + } + return 0; +} +EXPORT_SYMBOL(dibusb_pid_filter_ctrl); + +int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 b[3]; + b[0] = DIBUSB_REQ_SET_IOCTL; + b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; + b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; + return dvb_usb_generic_write(d,b,3); +} +EXPORT_SYMBOL(dibusb_power_ctrl); + +int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 b[2]; + b[0] = DIBUSB_REQ_SET_IOCTL; + b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; + + dvb_usb_generic_write(d,b,3); + + return dibusb_streaming_ctrl(d,onoff); +} +EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); + +int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + if (onoff) { + u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; + return dvb_usb_generic_write(d,b,3); + } else + return 0; +} +EXPORT_SYMBOL(dibusb2_0_power_ctrl); + +int dibusb_rc_init(struct dvb_usb_device *d) +{ + return 0; +} +EXPORT_SYMBOL(dibusb_rc_init); + +int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; + dvb_usb_generic_rw(d,&cmd,1,key,5); +/* dvb_usb_nec_rc_key_to_event(d,dtt200u_rc_keys,sizeof(dtt200u_rc_keys)/sizeof(struct dvb_usb_nec_rc_key), + key,event,state);*/ + if (key[0] != 0) + deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); + return 0; +} +EXPORT_SYMBOL(dibusb_rc_query); + +static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) +{ + u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ + /* write only ? */ + int wo = (rbuf == NULL || rlen == 0), + len = 2 + wlen + (wo ? 0 : 2); + + sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; + sndbuf[1] = (addr << 1) | (wo ? 0 : 1); + + memcpy(&sndbuf[2],wbuf,wlen); + + if (!wo) { + sndbuf[wlen+2] = (rlen >> 8) & 0xff; + sndbuf[wlen+3] = rlen & 0xff; + } + + return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen); +} + +/* + * I2C master xfer function + */ +static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i; + + if (down_interruptible(&d->i2c_sem) < 0) + return -EAGAIN; + + if (num > 2) + warn("more than 2 i2c messages at a time is not handled yet. TODO."); + + for (i = 0; i < num; i++) { + /* write/read request */ + if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { + if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, + msg[i+1].buf,msg[i+1].len) < 0) + break; + i++; + } else + if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) + break; + } + + up(&d->i2c_sem); + return i; +} + +static u32 dibusb_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +struct i2c_algorithm dibusb_i2c_algo = { + .name = "DiBcom USB I2C algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = dibusb_i2c_xfer, + .functionality = dibusb_i2c_func, +}; +EXPORT_SYMBOL(dibusb_i2c_algo); + +int dibusb_pll_init_i2c(struct dvb_frontend *fe) +{ + struct dvb_usb_device *d = fe->dvb->priv; + struct dibusb_state *st = d->priv; + if (st && st->ops.tuner_pass_ctrl) + st->ops.tuner_pass_ctrl(d->fe,1,st->pll_addr); + +// init; + + if (st && st->ops.tuner_pass_ctrl) + st->ops.tuner_pass_ctrl(d->fe,0,st->pll_addr); + return 0; +} +EXPORT_SYMBOL(dibusb_pll_init_i2c); + +int dibusb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5]) +{ + struct dvb_usb_device *d = fe->dvb->priv; + struct dibusb_state *st = d->priv; + b[0] = st->pll_addr << 1; + + deb_info("pll addr: %x, freq: %d\n",st->pll_addr,fep->frequency); + + dvb_pll_configure(st->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth); + + deb_info("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]); + + return 0; +} +EXPORT_SYMBOL(dibusb_pll_set); + +int dibusb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_device *d = fe->dvb->priv; + struct dibusb_state *st = d->priv; + int ret = 0; + u8 b[5]; + struct i2c_msg msg = { .addr = st->pll_addr, .flags = 0, .buf = &b[1], .len = 4 }; + + dibusb_pll_set(fe,fep,b); + + if (st && st->ops.tuner_pass_ctrl) + st->ops.tuner_pass_ctrl(d->fe,1,st->pll_addr); + + if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { + err("tuner i2c write failed."); + ret = -EREMOTEIO; + } + + msleep(1); + + if (st && st->ops.tuner_pass_ctrl) + st->ops.tuner_pass_ctrl(d->fe,0,st->pll_addr); + + return ret; +} +EXPORT_SYMBOL(dibusb_pll_set_i2c); + +int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d) +{ + struct dib3000_config demod_cfg; + struct dibusb_state *st = d->priv; + + demod_cfg.pll_set = dibusb_pll_set_i2c; /* dibusb_general_pll_set; */ + demod_cfg.pll_init = dibusb_pll_init_i2c; /* dibusb_general_pll_init; */ + + for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++) + if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) + return 0; + + return -ENODEV; +} +EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); + +int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d) +{ + struct dibusb_state *st = d->priv; + st->pll_addr = 0x60; + st->pll_desc = &dvb_pll_env57h1xd5; + return 0; +} +EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); |