diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-03-17 17:19:42 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-03-17 17:19:42 -0200 |
commit | 01d687a75155f9c9181e46572a60c71040d9133d (patch) | |
tree | 23a5939cfc6b1f24d0730c5c70a3d43c96063d6e /linux/drivers/media/dvb/dvb-usb | |
parent | 806e8a78b6b2b8bbab30dafd89ada8402e9564ed (diff) | |
parent | 13f01356dce8354c14e7e1a3f25162a24a002fff (diff) | |
download | mediapointer-dvb-s2-01d687a75155f9c9181e46572a60c71040d9133d.tar.gz mediapointer-dvb-s2-01d687a75155f9c9181e46572a60c71040d9133d.tar.bz2 |
merge: http://linuxtv.org/hg/~endriss/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/dvb/dvb-usb')
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/au6610.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/gl861.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/m920x.c | 141 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/m920x.h | 46 |
4 files changed, 108 insertions, 91 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/au6610.c b/linux/drivers/media/dvb/dvb-usb/au6610.c index 91079891d..3314f8c0c 100644 --- a/linux/drivers/media/dvb/dvb-usb/au6610.c +++ b/linux/drivers/media/dvb/dvb-usb/au6610.c @@ -40,7 +40,7 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, } ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, - USB_TYPE_VENDOR|USB_DIR_IN, addr, index, usb_buf, + USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT); if (ret < 0) @@ -124,7 +124,7 @@ static int au6610_identify_state(struct usb_device *udev, } static struct zl10353_config au6610_zl10353_config = { - .demod_address = 0x1e, + .demod_address = 0x0f, .no_tuner = 1, .parallel_ts = 1, }; @@ -140,7 +140,7 @@ static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) } static struct qt1010_config au6610_qt1010_config = { - .i2c_address = 0xc4 + .i2c_address = 0x62 }; static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap) diff --git a/linux/drivers/media/dvb/dvb-usb/gl861.c b/linux/drivers/media/dvb/dvb-usb/gl861.c index 1e5e2c1b9..ce06395b8 100644 --- a/linux/drivers/media/dvb/dvb-usb/gl861.c +++ b/linux/drivers/media/dvb/dvb-usb/gl861.c @@ -20,7 +20,7 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { u16 index; - u16 value = addr << 8; + u16 value = addr << (8 + 1); int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 req, type; @@ -101,7 +101,7 @@ static int gl861_identify_state(struct usb_device *udev, } static struct zl10353_config gl861_zl10353_config = { - .demod_address = 0x1e, + .demod_address = 0x0f, .no_tuner = 1, .parallel_ts = 1, }; @@ -117,7 +117,7 @@ static int gl861_frontend_attach(struct dvb_usb_adapter *adap) } static struct qt1010_config gl861_qt1010_config = { - .i2c_address = 0xc4 + .i2c_address = 0x62 }; static int gl861_tuner_attach(struct dvb_usb_adapter *adap) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 1a411316f..e63f1edba 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -67,16 +67,18 @@ static inline int m9206_write(struct usb_device *udev, u8 request, return ret; } -static int m9206_rc_init(struct usb_device *udev) +static int m9206_init(struct dvb_usb_device *d) { int ret = 0; /* Remote controller init. */ - if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) - return ret; + if (d->props.rc_query) { + if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) + return ret; - if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) - return ret; + if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) + return ret; + } return ret; } @@ -87,20 +89,15 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) int i, ret = 0; u8 rc_state[2]; -#if 0 - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; -#endif - if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) goto unlock; if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) goto unlock; - for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) - if (megasky_rc_keys[i].data == rc_state[1]) { - *event = megasky_rc_keys[i].event; + for (i = 0; i < d->props.rc_key_map_size; i++) + if (d->props.rc_key_map[i].data == rc_state[1]) { + *event = d->props.rc_key_map[i].event; switch(rc_state[0]) { case 0x80: @@ -132,9 +129,6 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; unlock: -#if 0 - mutex_unlock(&d->i2c_mutex); -#endif return ret; } @@ -144,53 +138,51 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - struct m9206_state *m = d->priv; - int i; + int i, j; int ret = 0; + if (!num) + return -EINVAL; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; - if (num > 2) - return -EINVAL; - for (i = 0; i < num; i++) { - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0) + if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) || + msg[i].len == 0) { + /* For a 0 byte message, I think sending the address to index 0x80|0x40 + * would be the correct thing to do. However, zero byte messages are + * only used for probing, and since we don't know how to get the slave's + * ack, we can't probe. */ + ret = -ENOTSUPP; goto unlock; - - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0) - goto unlock; - - if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { - int i2c_i; - - for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++) - if (msg[i].addr == m->i2c_r[i2c_i].addr) - break; - - if (i2c_i >= M9206_I2C_MAX) { - deb_rc("No magic for i2c addr!\n"); - ret = -EINVAL; + } + /* Send START & address/RW bit */ + if (!(msg[i].flags & I2C_M_NOSTART)) { + if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0) goto unlock; + /* Should check for ack here, if we knew how. */ + } + if (msg[i].flags & I2C_M_RD) { + for (j = 0; j < msg[i].len; j++) { + /* Last byte of transaction? Send STOP, otherwise send ACK. */ + int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01; + if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0) + goto unlock; } - - if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0) - goto unlock; - - if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) - goto unlock; - - i++; } else { - if (msg[i].len != 2) - return -EINVAL; - - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0) - goto unlock; + for (j = 0; j < msg[i].len; j++) { + /* Last byte of transaction? Then send STOP. */ + int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00; + if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) + goto unlock; + /* Should check for ack here too. */ + } } } - ret = i; - unlock: + ret = num; + +unlock: mutex_unlock(&d->i2c_mutex); return ret; @@ -388,20 +380,15 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) } static struct mt352_config megasky_mt352_config = { - .demod_address = 0x1e, + .demod_address = 0x0f, .no_tuner = 1, .demod_init = megasky_mt352_demod_init, }; static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) { - struct m9206_state *m = adap->dev->priv; - deb_rc("megasky_frontend_attach!\n"); - m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; - m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) return -EIO; @@ -409,16 +396,11 @@ static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) } static struct qt1010_config megasky_qt1010_config = { - .i2c_address = 0xc4 + .i2c_address = 0x62 }; static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { - struct m9206_state *m = adap->dev->priv; - - m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address; - m->i2c_r[M9206_I2C_TUNER].magic = 0xc5; - if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &megasky_qt1010_config) == NULL) return -ENODEV; @@ -436,25 +418,28 @@ static int m920x_probe(struct usb_interface *intf, struct usb_host_interface *alt; int ret; - if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { - deb_rc("probed!\n"); + deb_rc("Probed!\n"); - alt = usb_altnum_to_altsetting(intf, 1); - if (alt == NULL) { - deb_rc("not alt found!\n"); - return -ENODEV; - } - - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, - alt->desc.bAlternateSetting); - if (ret < 0) - return ret; + if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) + goto found; - deb_rc("Changed to alternate setting!\n"); + return ret; - if ((ret = m9206_rc_init(d->udev)) != 0) - return ret; +found: + alt = usb_altnum_to_altsetting(intf, 1); + if (alt == NULL) { + deb_rc("No alt found!\n"); + return -ENODEV; } + + ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); + if (ret < 0) + return ret; + + if ((ret = m9206_init(d)) != 0) + return ret; + return ret; } diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h index c354196ff..7dd3db65c 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.h +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -19,17 +19,49 @@ #define M9206_MAX_FILTERS 8 -#define M9206_I2C_TUNER 0 -#define M9206_I2C_DEMOD 1 -#define M9206_I2C_MAX 2 +/* +sequences found in logs: +[index value] +0x80 write addr +(0x00 out byte)* +0x40 out byte + +0x80 write addr +(0x00 out byte)* +0x80 read addr +(0x21 in byte)* +0x60 in byte + +this sequence works: +0x80 read addr +(0x21 in byte)* +0x60 in byte + +Guess at API of the I2C function: +I2C operation is done one byte at a time with USB control messages. The +index the messages is sent to is made up of a set of flags that control +the I2C bus state: +0x80: Send START condition. After a START condition, one would normally + always send the 7-bit slave I2C address as the 7 MSB, followed by + the read/write bit as the LSB. +0x40: Send STOP condition. This should be set on the last byte of an + I2C transaction. +0x20: Read a byte from the slave. As opposed to writing a byte to the + slave. The slave will normally not produce any data unless you + set the R/W bit to 1 when sending the slave's address after the + START condition. +0x01: Respond with ACK, as opposed to a NACK. For a multi-byte read, + the master should send an ACK, that is pull SDA low during the 9th + clock cycle, after every byte but the last. This flags only makes + sense when bit 0x20 is set, indicating a read. + +What any other bits might mean, or how to get the slave's ACK/NACK +response to a write, is unknown. +*/ struct m9206_state { u16 filters[M9206_MAX_FILTERS]; int filtering_enabled; int rep_count; - struct { - unsigned char addr; - unsigned char magic; - }i2c_r[M9206_I2C_MAX]; }; #endif |