|
@@ -61,7 +61,7 @@
|
|
#define DVB_USB_LOG_PREFIX "LME2510(C)"
|
|
#define DVB_USB_LOG_PREFIX "LME2510(C)"
|
|
#include <linux/usb.h>
|
|
#include <linux/usb.h>
|
|
#include <linux/usb/input.h>
|
|
#include <linux/usb/input.h>
|
|
-#include <media/ir-core.h>
|
|
|
|
|
|
+#include <media/rc-core.h>
|
|
|
|
|
|
#include "dvb-usb.h"
|
|
#include "dvb-usb.h"
|
|
#include "lmedm04.h"
|
|
#include "lmedm04.h"
|
|
@@ -112,7 +112,6 @@ struct lme2510_state {
|
|
u8 i2c_tuner_gate_r;
|
|
u8 i2c_tuner_gate_r;
|
|
u8 i2c_tuner_addr;
|
|
u8 i2c_tuner_addr;
|
|
u8 stream_on;
|
|
u8 stream_on;
|
|
- u8 one_tune;
|
|
|
|
void *buffer;
|
|
void *buffer;
|
|
struct urb *lme_urb;
|
|
struct urb *lme_urb;
|
|
void *usb_buffer;
|
|
void *usb_buffer;
|
|
@@ -125,7 +124,7 @@ static int lme2510_bulk_write(struct usb_device *dev,
|
|
int ret, actual_l;
|
|
int ret, actual_l;
|
|
|
|
|
|
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
|
|
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
|
|
- snd, len , &actual_l, 500);
|
|
|
|
|
|
+ snd, len , &actual_l, 100);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -135,7 +134,7 @@ static int lme2510_bulk_read(struct usb_device *dev,
|
|
int ret, actual_l;
|
|
int ret, actual_l;
|
|
|
|
|
|
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
|
|
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
|
|
- rev, len , &actual_l, 500);
|
|
|
|
|
|
+ rev, len , &actual_l, 200);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -167,7 +166,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
|
|
|
|
|
ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
|
|
ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
|
|
|
|
|
|
- msleep(12);
|
|
|
|
|
|
+ msleep(10);
|
|
|
|
|
|
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
|
|
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
|
|
|
|
|
|
@@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int lme2510_usb_talk_restart(struct dvb_usb_device *d,
|
|
|
|
- u8 *wbuf, int wlen, u8 *rbuf, int rlen) {
|
|
|
|
|
|
+static int lme2510_stream_restart(struct dvb_usb_device *d)
|
|
|
|
+{
|
|
static u8 stream_on[] = LME_ST_ON_W;
|
|
static u8 stream_on[] = LME_ST_ON_W;
|
|
int ret;
|
|
int ret;
|
|
u8 rbuff[10];
|
|
u8 rbuff[10];
|
|
- /*Send Normal Command*/
|
|
|
|
- ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
|
|
|
/*Restart Stream Command*/
|
|
/*Restart Stream Command*/
|
|
- ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on),
|
|
|
|
|
|
+ ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
|
|
rbuff, sizeof(rbuff));
|
|
rbuff, sizeof(rbuff));
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -201,7 +198,7 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress)
|
|
deb_info(1, "INT Key Keypress =%04x", keypress);
|
|
deb_info(1, "INT Key Keypress =%04x", keypress);
|
|
|
|
|
|
if (keypress > 0)
|
|
if (keypress > 0)
|
|
- ir_keydown(d->rc_input_dev, keypress, 0);
|
|
|
|
|
|
+ rc_keydown(d->rc_dev, keypress, 0);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb)
|
|
case TUNER_S7395:
|
|
case TUNER_S7395:
|
|
/* Tweak for earlier firmware*/
|
|
/* Tweak for earlier firmware*/
|
|
if (ibuf[1] == 0x03) {
|
|
if (ibuf[1] == 0x03) {
|
|
|
|
+ if (ibuf[2] > 1)
|
|
|
|
+ st->signal_lock = ibuf[2];
|
|
st->signal_level = ibuf[3];
|
|
st->signal_level = ibuf[3];
|
|
st->signal_sn = ibuf[4];
|
|
st->signal_sn = ibuf[4];
|
|
} else {
|
|
} else {
|
|
st->signal_level = ibuf[4];
|
|
st->signal_level = ibuf[4];
|
|
st->signal_sn = ibuf[5];
|
|
st->signal_sn = ibuf[5];
|
|
|
|
+ st->signal_lock =
|
|
|
|
+ (st->signal_lock & 0xf7) +
|
|
|
|
+ ((ibuf[2] & 0x01) << 0x03);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -341,11 +343,10 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|
st->signal_lock = rbuf[1];
|
|
st->signal_lock = rbuf[1];
|
|
if ((st->stream_on & 1) &&
|
|
if ((st->stream_on & 1) &&
|
|
(st->signal_lock & 0x10)) {
|
|
(st->signal_lock & 0x10)) {
|
|
- lme2510_usb_talk_restart(d,
|
|
|
|
- wbuf, wlen, rbuf, rlen);
|
|
|
|
|
|
+ lme2510_stream_restart(d);
|
|
st->i2c_talk_onoff = 0;
|
|
st->i2c_talk_onoff = 0;
|
|
}
|
|
}
|
|
- msleep(80);
|
|
|
|
|
|
+ msleep(80);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|
st->signal_lock = rbuf[1];
|
|
st->signal_lock = rbuf[1];
|
|
if ((st->stream_on & 1) &&
|
|
if ((st->stream_on & 1) &&
|
|
(st->signal_lock & 0x8)) {
|
|
(st->signal_lock & 0x8)) {
|
|
- lme2510_usb_talk_restart(d,
|
|
|
|
- wbuf, wlen, rbuf, rlen);
|
|
|
|
|
|
+ lme2510_stream_restart(d);
|
|
st->i2c_talk_onoff = 0;
|
|
st->i2c_talk_onoff = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
|
|
if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
|
|
msleep(5);
|
|
msleep(5);
|
|
-
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|
rbuf[0] = 0x55;
|
|
rbuf[0] = 0x55;
|
|
rbuf[1] = st->signal_sn;
|
|
rbuf[1] = st->signal_sn;
|
|
break;
|
|
break;
|
|
- /*DiSEqC functions as per TDA10086*/
|
|
|
|
- case 0x36:
|
|
|
|
- case 0x48:
|
|
|
|
- case 0x49:
|
|
|
|
- case 0x4a:
|
|
|
|
- case 0x4b:
|
|
|
|
- case 0x4c:
|
|
|
|
- case 0x4d:
|
|
|
|
- if (wbuf[2] == 0x1c)
|
|
|
|
- lme2510_usb_talk_restart(d,
|
|
|
|
- wbuf, wlen, rbuf, rlen);
|
|
|
|
|
|
+ case 0x15:
|
|
|
|
+ case 0x16:
|
|
|
|
+ case 0x17:
|
|
|
|
+ case 0x18:
|
|
|
|
+ rbuf[0] = 0x55;
|
|
|
|
+ rbuf[1] = 0x00;
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
|
|
+ lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
|
|
|
+ st->i2c_talk_onoff = 1;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|
break;
|
|
break;
|
|
case 0x24:
|
|
case 0x24:
|
|
rbuf[0] = 0x55;
|
|
rbuf[0] = 0x55;
|
|
- rbuf[1] = (st->signal_level & 0x80)
|
|
|
|
- ? 0 : st->signal_lock;
|
|
|
|
- break;
|
|
|
|
- case 0x6:
|
|
|
|
- if (wbuf[2] == 0xd0)
|
|
|
|
- lme2510_usb_talk(d,
|
|
|
|
- wbuf, wlen, rbuf, rlen);
|
|
|
|
- break;
|
|
|
|
- case 0x1:
|
|
|
|
- if (st->one_tune > 0)
|
|
|
|
- break;
|
|
|
|
- st->one_tune++;
|
|
|
|
- st->i2c_talk_onoff = 1;
|
|
|
|
- /*DiSEqC functions as per STV0288*/
|
|
|
|
- case 0x5:
|
|
|
|
- case 0x7:
|
|
|
|
- case 0x8:
|
|
|
|
- case 0x9:
|
|
|
|
- case 0xa:
|
|
|
|
- case 0xb:
|
|
|
|
- if (wbuf[2] == 0xd0)
|
|
|
|
- lme2510_usb_talk_restart(d,
|
|
|
|
- wbuf, wlen, rbuf, rlen);
|
|
|
|
|
|
+ rbuf[1] = st->signal_lock;
|
|
break;
|
|
break;
|
|
- default:
|
|
|
|
|
|
+ case 0x2e:
|
|
|
|
+ case 0x26:
|
|
|
|
+ case 0x27:
|
|
rbuf[0] = 0x55;
|
|
rbuf[0] = 0x55;
|
|
rbuf[1] = 0x00;
|
|
rbuf[1] = 0x00;
|
|
break;
|
|
break;
|
|
|
|
+ default:
|
|
|
|
+ lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
|
|
|
+ st->i2c_talk_onoff = 1;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
|
|
deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
|
|
@@ -548,35 +527,26 @@ static int lme2510_identify_state(struct usb_device *udev,
|
|
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|
{
|
|
{
|
|
struct lme2510_state *st = adap->dev->priv;
|
|
struct lme2510_state *st = adap->dev->priv;
|
|
- static u8 stream_on[] = LME_ST_ON_W;
|
|
|
|
static u8 clear_reg_3[] = LME_CLEAR_PID;
|
|
static u8 clear_reg_3[] = LME_CLEAR_PID;
|
|
static u8 rbuf[1];
|
|
static u8 rbuf[1];
|
|
- static u8 timeout;
|
|
|
|
- int ret = 0, len = 2, rlen = sizeof(rbuf);
|
|
|
|
|
|
+ int ret = 0, rlen = sizeof(rbuf);
|
|
|
|
|
|
deb_info(1, "STM (%02x)", onoff);
|
|
deb_info(1, "STM (%02x)", onoff);
|
|
|
|
|
|
- if (onoff == 1) {
|
|
|
|
- st->i2c_talk_onoff = 0;
|
|
|
|
- timeout = 0;
|
|
|
|
- /* wait for i2C to be free */
|
|
|
|
- while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) {
|
|
|
|
- timeout++;
|
|
|
|
- if (timeout > 5)
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
- msleep(100);
|
|
|
|
- ret |= lme2510_usb_talk(adap->dev,
|
|
|
|
- stream_on, len, rbuf, rlen);
|
|
|
|
|
|
+ /* Streaming is started by FE_HAS_LOCK */
|
|
|
|
+ if (onoff == 1)
|
|
st->stream_on = 1;
|
|
st->stream_on = 1;
|
|
- st->one_tune = 0;
|
|
|
|
- mutex_unlock(&adap->dev->i2c_mutex);
|
|
|
|
- } else {
|
|
|
|
|
|
+ else {
|
|
deb_info(1, "STM Steam Off");
|
|
deb_info(1, "STM Steam Off");
|
|
|
|
+ /* mutex is here only to avoid collision with I2C */
|
|
|
|
+ ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
|
|
|
|
+
|
|
ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
|
|
ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
|
|
sizeof(clear_reg_3), rbuf, rlen);
|
|
sizeof(clear_reg_3), rbuf, rlen);
|
|
st->stream_on = 0;
|
|
st->stream_on = 0;
|
|
st->i2c_talk_onoff = 1;
|
|
st->i2c_talk_onoff = 1;
|
|
|
|
+
|
|
|
|
+ mutex_unlock(&adap->dev->i2c_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
@@ -585,41 +555,40 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|
static int lme2510_int_service(struct dvb_usb_adapter *adap)
|
|
static int lme2510_int_service(struct dvb_usb_adapter *adap)
|
|
{
|
|
{
|
|
struct dvb_usb_device *d = adap->dev;
|
|
struct dvb_usb_device *d = adap->dev;
|
|
- struct input_dev *input_dev;
|
|
|
|
- char *ir_codes = RC_MAP_LME2510;
|
|
|
|
- int ret = 0;
|
|
|
|
|
|
+ struct rc_dev *rc;
|
|
|
|
+ int ret;
|
|
|
|
|
|
info("STA Configuring Remote");
|
|
info("STA Configuring Remote");
|
|
|
|
|
|
- usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
|
|
|
-
|
|
|
|
- strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
|
|
|
-
|
|
|
|
- input_dev = input_allocate_device();
|
|
|
|
- if (!input_dev)
|
|
|
|
|
|
+ rc = rc_allocate_device();
|
|
|
|
+ if (!rc)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- input_dev->name = "LME2510 Remote Control";
|
|
|
|
- input_dev->phys = d->rc_phys;
|
|
|
|
-
|
|
|
|
- usb_to_input_id(d->udev, &input_dev->id);
|
|
|
|
|
|
+ usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
|
|
|
+ strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
|
|
|
|
|
- ret |= ir_input_register(input_dev, ir_codes, NULL, "LME 2510");
|
|
|
|
|
|
+ rc->input_name = "LME2510 Remote Control";
|
|
|
|
+ rc->input_phys = d->rc_phys;
|
|
|
|
+ rc->map_name = RC_MAP_LME2510;
|
|
|
|
+ rc->driver_name = "LME 2510";
|
|
|
|
+ usb_to_input_id(d->udev, &rc->input_id);
|
|
|
|
|
|
|
|
+ ret = rc_register_device(rc);
|
|
if (ret) {
|
|
if (ret) {
|
|
- input_free_device(input_dev);
|
|
|
|
|
|
+ rc_free_device(rc);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+ d->rc_dev = rc;
|
|
|
|
|
|
- d->rc_input_dev = input_dev;
|
|
|
|
/* Start the Interupt */
|
|
/* Start the Interupt */
|
|
ret = lme2510_int_read(adap);
|
|
ret = lme2510_int_read(adap);
|
|
-
|
|
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- ir_input_unregister(input_dev);
|
|
|
|
- input_free_device(input_dev);
|
|
|
|
|
|
+ rc_unregister_device(rc);
|
|
|
|
+ info("INT Unable to start Interupt Service");
|
|
|
|
+ return -ENODEV;
|
|
}
|
|
}
|
|
- return (ret < 0) ? -ENODEV : 0;
|
|
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static u8 check_sum(u8 *p, u8 len)
|
|
static u8 check_sum(u8 *p, u8 len)
|
|
@@ -668,6 +637,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|
ret |= (data[0] == 0x88) ? 0 : -1;
|
|
ret |= (data[0] == 0x88) ? 0 : -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
|
usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
|
0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
|
|
0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
|
|
|
|
|
|
@@ -701,10 +671,11 @@ static void lme_coldreset(struct usb_device *dev)
|
|
info("FRM Firmware Cold Reset");
|
|
info("FRM Firmware Cold Reset");
|
|
ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
|
|
ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
|
|
ret |= lme2510_bulk_read(dev, data, len_in, 1);
|
|
ret |= lme2510_bulk_read(dev, data, len_in, 1);
|
|
|
|
+
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
-static void lme_firmware_switch(struct usb_device *udev, int cold)
|
|
|
|
|
|
+static int lme_firmware_switch(struct usb_device *udev, int cold)
|
|
{
|
|
{
|
|
const struct firmware *fw = NULL;
|
|
const struct firmware *fw = NULL;
|
|
char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
|
|
char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
|
|
@@ -712,8 +683,10 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
|
|
char *firm_msg[] = {"Loading", "Switching to"};
|
|
char *firm_msg[] = {"Loading", "Switching to"};
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ cold = (cold > 0) ? (cold & 1) : 0;
|
|
|
|
+
|
|
if (udev->descriptor.idProduct == 0x1122)
|
|
if (udev->descriptor.idProduct == 0x1122)
|
|
- return;
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
|
switch (dvb_usb_lme2510_firmware) {
|
|
switch (dvb_usb_lme2510_firmware) {
|
|
case 0:
|
|
case 0:
|
|
@@ -740,22 +713,28 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
|
|
cold = 0;
|
|
cold = 0;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+
|
|
release_firmware(fw);
|
|
release_firmware(fw);
|
|
- if (cold)
|
|
|
|
|
|
+
|
|
|
|
+ if (cold) {
|
|
lme_coldreset(udev);
|
|
lme_coldreset(udev);
|
|
- return;
|
|
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int lme2510_kill_urb(struct usb_data_stream *stream)
|
|
static int lme2510_kill_urb(struct usb_data_stream *stream)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
+
|
|
for (i = 0; i < stream->urbs_submitted; i++) {
|
|
for (i = 0; i < stream->urbs_submitted; i++) {
|
|
deb_info(3, "killing URB no. %d.", i);
|
|
deb_info(3, "killing URB no. %d.", i);
|
|
-
|
|
|
|
/* stop the URB */
|
|
/* stop the URB */
|
|
usb_kill_urb(stream->urb_list[i]);
|
|
usb_kill_urb(stream->urb_list[i]);
|
|
}
|
|
}
|
|
stream->urbs_submitted = 0;
|
|
stream->urbs_submitted = 0;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
|
|
fe_sec_voltage_t voltage)
|
|
fe_sec_voltage_t voltage)
|
|
{
|
|
{
|
|
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
|
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
|
- struct lme2510_state *st = adap->dev->priv;
|
|
|
|
static u8 voltage_low[] = LME_VOLTAGE_L;
|
|
static u8 voltage_low[] = LME_VOLTAGE_L;
|
|
static u8 voltage_high[] = LME_VOLTAGE_H;
|
|
static u8 voltage_high[] = LME_VOLTAGE_H;
|
|
- static u8 lnb_on[] = LNB_ON;
|
|
|
|
- static u8 lnb_off[] = LNB_OFF;
|
|
|
|
static u8 rbuf[1];
|
|
static u8 rbuf[1];
|
|
int ret = 0, len = 3, rlen = 1;
|
|
int ret = 0, len = 3, rlen = 1;
|
|
|
|
|
|
- if (st->stream_on == 1)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
|
|
|
|
|
|
+ if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
|
|
|
+ return -EAGAIN;
|
|
|
|
|
|
switch (voltage) {
|
|
switch (voltage) {
|
|
case SEC_VOLTAGE_18:
|
|
case SEC_VOLTAGE_18:
|
|
@@ -803,94 +777,143 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
|
|
break;
|
|
break;
|
|
|
|
|
|
case SEC_VOLTAGE_OFF:
|
|
case SEC_VOLTAGE_OFF:
|
|
- ret |= lme2510_usb_talk(adap->dev,
|
|
|
|
- lnb_off, len, rbuf, rlen);
|
|
|
|
case SEC_VOLTAGE_13:
|
|
case SEC_VOLTAGE_13:
|
|
default:
|
|
default:
|
|
ret |= lme2510_usb_talk(adap->dev,
|
|
ret |= lme2510_usb_talk(adap->dev,
|
|
voltage_low, len, rbuf, rlen);
|
|
voltage_low, len, rbuf, rlen);
|
|
break;
|
|
break;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ mutex_unlock(&adap->dev->i2c_mutex);
|
|
|
|
|
|
- };
|
|
|
|
- st->i2c_talk_onoff = 1;
|
|
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
return (ret < 0) ? -ENODEV : 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int lme_name(struct dvb_usb_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct lme2510_state *st = adap->dev->priv;
|
|
|
|
+ const char *desc = adap->dev->desc->name;
|
|
|
|
+ char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"};
|
|
|
|
+ char *name = adap->fe->ops.info.name;
|
|
|
|
+
|
|
|
|
+ strlcpy(name, desc, 128);
|
|
|
|
+ strlcat(name, fe_name[st->tuner_config], 128);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
|
static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
|
{
|
|
{
|
|
- int ret = 0;
|
|
|
|
struct lme2510_state *st = adap->dev->priv;
|
|
struct lme2510_state *st = adap->dev->priv;
|
|
|
|
|
|
- /* Interupt Start */
|
|
|
|
- ret = lme2510_int_service(adap);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- info("INT Unable to start Interupt Service");
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
st->i2c_talk_onoff = 1;
|
|
st->i2c_talk_onoff = 1;
|
|
- st->i2c_gate = 4;
|
|
|
|
|
|
|
|
|
|
+ st->i2c_gate = 4;
|
|
adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
|
|
adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
|
|
&adap->dev->i2c_adap);
|
|
&adap->dev->i2c_adap);
|
|
|
|
|
|
if (adap->fe) {
|
|
if (adap->fe) {
|
|
info("TUN Found Frontend TDA10086");
|
|
info("TUN Found Frontend TDA10086");
|
|
- memcpy(&adap->fe->ops.info.name,
|
|
|
|
- &"DM04_LG_TDQY-P001F DVB-S", 24);
|
|
|
|
- adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
|
|
|
st->i2c_tuner_gate_w = 4;
|
|
st->i2c_tuner_gate_w = 4;
|
|
st->i2c_tuner_gate_r = 4;
|
|
st->i2c_tuner_gate_r = 4;
|
|
st->i2c_tuner_addr = 0xc0;
|
|
st->i2c_tuner_addr = 0xc0;
|
|
- if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
|
|
|
|
- &adap->dev->i2c_adap, 1)) {
|
|
|
|
- info("TUN TDA8263 Found");
|
|
|
|
- st->tuner_config = TUNER_LG;
|
|
|
|
- if (dvb_usb_lme2510_firmware != 1) {
|
|
|
|
- dvb_usb_lme2510_firmware = 1;
|
|
|
|
- lme_firmware_switch(adap->dev->udev, 1);
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- kfree(adap->fe);
|
|
|
|
- adap->fe = NULL;
|
|
|
|
|
|
+ st->tuner_config = TUNER_LG;
|
|
|
|
+ if (dvb_usb_lme2510_firmware != 1) {
|
|
|
|
+ dvb_usb_lme2510_firmware = 1;
|
|
|
|
+ ret = lme_firmware_switch(adap->dev->udev, 1);
|
|
|
|
+ } else /*stops LG/Sharp multi tuner problems*/
|
|
|
|
+ dvb_usb_lme2510_firmware = 0;
|
|
|
|
+ goto end;
|
|
}
|
|
}
|
|
|
|
+
|
|
st->i2c_gate = 5;
|
|
st->i2c_gate = 5;
|
|
adap->fe = dvb_attach(stv0288_attach, &lme_config,
|
|
adap->fe = dvb_attach(stv0288_attach, &lme_config,
|
|
&adap->dev->i2c_adap);
|
|
&adap->dev->i2c_adap);
|
|
|
|
|
|
if (adap->fe) {
|
|
if (adap->fe) {
|
|
info("FE Found Stv0288");
|
|
info("FE Found Stv0288");
|
|
- memcpy(&adap->fe->ops.info.name,
|
|
|
|
- &"DM04_SHARP:BS2F7HZ7395", 22);
|
|
|
|
- adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
|
|
|
st->i2c_tuner_gate_w = 4;
|
|
st->i2c_tuner_gate_w = 4;
|
|
st->i2c_tuner_gate_r = 5;
|
|
st->i2c_tuner_gate_r = 5;
|
|
st->i2c_tuner_addr = 0xc0;
|
|
st->i2c_tuner_addr = 0xc0;
|
|
- if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
|
|
|
|
- &adap->dev->i2c_adap)) {
|
|
|
|
- st->tuner_config = TUNER_S7395;
|
|
|
|
- info("TUN Sharp IX2505V silicon tuner");
|
|
|
|
- if (dvb_usb_lme2510_firmware != 0) {
|
|
|
|
- dvb_usb_lme2510_firmware = 0;
|
|
|
|
- lme_firmware_switch(adap->dev->udev, 1);
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
|
|
+ st->tuner_config = TUNER_S7395;
|
|
|
|
+ if (dvb_usb_lme2510_firmware != 0) {
|
|
|
|
+ dvb_usb_lme2510_firmware = 0;
|
|
|
|
+ ret = lme_firmware_switch(adap->dev->udev, 1);
|
|
}
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ info("DM04 Not Supported");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+end: if (ret) {
|
|
kfree(adap->fe);
|
|
kfree(adap->fe);
|
|
adap->fe = NULL;
|
|
adap->fe = NULL;
|
|
|
|
+ return -ENODEV;
|
|
}
|
|
}
|
|
|
|
|
|
- info("DM04 Not Supported");
|
|
|
|
- return -ENODEV;
|
|
|
|
|
|
+ adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
|
|
|
+ ret = lme_name(adap);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct lme2510_state *st = adap->dev->priv;
|
|
|
|
+ char *tun_msg[] = {"", "TDA8263", "IX2505V"};
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ switch (st->tuner_config) {
|
|
|
|
+ case TUNER_LG:
|
|
|
|
+ if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
|
|
|
|
+ &adap->dev->i2c_adap, 1))
|
|
|
|
+ ret = st->tuner_config;
|
|
|
|
+ break;
|
|
|
|
+ case TUNER_S7395:
|
|
|
|
+ if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
|
|
|
|
+ &adap->dev->i2c_adap))
|
|
|
|
+ ret = st->tuner_config;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ret)
|
|
|
|
+ info("TUN Found %s tuner", tun_msg[ret]);
|
|
|
|
+ else {
|
|
|
|
+ info("TUN No tuner found --- reseting device");
|
|
|
|
+ lme_coldreset(adap->dev->udev);
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Start the Interupt & Remote*/
|
|
|
|
+ ret = lme2510_int_service(adap);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
|
|
static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
|
|
{
|
|
{
|
|
struct lme2510_state *st = d->priv;
|
|
struct lme2510_state *st = d->priv;
|
|
|
|
+ static u8 lnb_on[] = LNB_ON;
|
|
|
|
+ static u8 lnb_off[] = LNB_OFF;
|
|
|
|
+ static u8 rbuf[1];
|
|
|
|
+ int ret, len = 3, rlen = 1;
|
|
|
|
+
|
|
|
|
+ ret = mutex_lock_interruptible(&d->i2c_mutex);
|
|
|
|
+
|
|
|
|
+ if (onoff)
|
|
|
|
+ ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
|
|
|
|
+ else
|
|
|
|
+ ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
|
|
|
|
+
|
|
st->i2c_talk_onoff = 1;
|
|
st->i2c_talk_onoff = 1;
|
|
- return 0;
|
|
|
|
|
|
+
|
|
|
|
+ mutex_unlock(&d->i2c_mutex);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/* DVB USB Driver stuff */
|
|
/* DVB USB Driver stuff */
|
|
@@ -951,6 +974,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|
{
|
|
{
|
|
.streaming_ctrl = lme2510_streaming_ctrl,
|
|
.streaming_ctrl = lme2510_streaming_ctrl,
|
|
.frontend_attach = dm04_lme2510_frontend_attach,
|
|
.frontend_attach = dm04_lme2510_frontend_attach,
|
|
|
|
+ .tuner_attach = dm04_lme2510_tuner,
|
|
/* parameter for the MPEG2-data transfer */
|
|
/* parameter for the MPEG2-data transfer */
|
|
.stream = {
|
|
.stream = {
|
|
.type = USB_BULK,
|
|
.type = USB_BULK,
|
|
@@ -971,7 +995,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|
.generic_bulk_ctrl_endpoint = 0,
|
|
.generic_bulk_ctrl_endpoint = 0,
|
|
.num_device_descs = 1,
|
|
.num_device_descs = 1,
|
|
.devices = {
|
|
.devices = {
|
|
- { "DM04 LME2510 DVB-S USB 2.0",
|
|
|
|
|
|
+ { "DM04_LME2510_DVB-S",
|
|
{ &lme2510_table[0], NULL },
|
|
{ &lme2510_table[0], NULL },
|
|
},
|
|
},
|
|
|
|
|
|
@@ -989,6 +1013,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|
{
|
|
{
|
|
.streaming_ctrl = lme2510_streaming_ctrl,
|
|
.streaming_ctrl = lme2510_streaming_ctrl,
|
|
.frontend_attach = dm04_lme2510_frontend_attach,
|
|
.frontend_attach = dm04_lme2510_frontend_attach,
|
|
|
|
+ .tuner_attach = dm04_lme2510_tuner,
|
|
/* parameter for the MPEG2-data transfer */
|
|
/* parameter for the MPEG2-data transfer */
|
|
.stream = {
|
|
.stream = {
|
|
.type = USB_BULK,
|
|
.type = USB_BULK,
|
|
@@ -1009,7 +1034,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
|
.generic_bulk_ctrl_endpoint = 0,
|
|
.generic_bulk_ctrl_endpoint = 0,
|
|
.num_device_descs = 1,
|
|
.num_device_descs = 1,
|
|
.devices = {
|
|
.devices = {
|
|
- { "DM04 LME2510C USB2.0",
|
|
|
|
|
|
+ { "DM04_LME2510C_DVB-S",
|
|
{ &lme2510_table[1], NULL },
|
|
{ &lme2510_table[1], NULL },
|
|
},
|
|
},
|
|
}
|
|
}
|
|
@@ -1036,7 +1061,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d)
|
|
usb_free_coherent(d->udev, 5000, st->buffer,
|
|
usb_free_coherent(d->udev, 5000, st->buffer,
|
|
st->lme_urb->transfer_dma);
|
|
st->lme_urb->transfer_dma);
|
|
info("Interupt Service Stopped");
|
|
info("Interupt Service Stopped");
|
|
- ir_input_unregister(d->rc_input_dev);
|
|
|
|
|
|
+ rc_unregister_device(d->rc_dev);
|
|
info("Remote Stopped");
|
|
info("Remote Stopped");
|
|
}
|
|
}
|
|
return buffer;
|
|
return buffer;
|
|
@@ -1055,7 +1080,7 @@ void lme2510_exit(struct usb_interface *intf)
|
|
}
|
|
}
|
|
|
|
|
|
static struct usb_driver lme2510_driver = {
|
|
static struct usb_driver lme2510_driver = {
|
|
- .name = "LME2510C_DVBS",
|
|
|
|
|
|
+ .name = "LME2510C_DVB-S",
|
|
.probe = lme2510_probe,
|
|
.probe = lme2510_probe,
|
|
.disconnect = lme2510_exit,
|
|
.disconnect = lme2510_exit,
|
|
.id_table = lme2510_table,
|
|
.id_table = lme2510_table,
|
|
@@ -1083,6 +1108,6 @@ module_init(lme2510_module_init);
|
|
module_exit(lme2510_module_exit);
|
|
module_exit(lme2510_module_exit);
|
|
|
|
|
|
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
|
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
|
-MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0");
|
|
|
|
-MODULE_VERSION("1.60");
|
|
|
|
|
|
+MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
|
|
|
|
+MODULE_VERSION("1.74");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|