Commit f23e6616 authored by Malcolm Priestley's avatar Malcolm Priestley Committed by Mauro Carvalho Chehab

[media] lmed04: Improve frontend handling

Improved frontend handling.

Frontend now remains open at all times, with signal lock, snr & signal level
polled from Interupt.

Updated driver for DM04/QQBOX USB DVB-S BOXES to version 1.70.
Signed-off-by: default avatarMalcolm Priestley <tvboxspy@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ea7c681e
...@@ -112,7 +112,6 @@ struct lme2510_state { ...@@ -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;
...@@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, ...@@ -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, static int lme2510_stream_restart(struct dvb_usb_device *d)
u8 *wbuf, int wlen, u8 *rbuf, int rlen) { {
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;
} }
...@@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb) ...@@ -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, ...@@ -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, lme2510_stream_restart(d);
wbuf, wlen, rbuf, rlen);
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, ...@@ -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, lme2510_stream_restart(d);
wbuf, wlen, rbuf, rlen);
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, ...@@ -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 0x15:
case 0x36: case 0x16:
case 0x48: case 0x17:
case 0x49: case 0x18:
case 0x4a: rbuf[0] = 0x55;
case 0x4b: rbuf[1] = 0x00;
case 0x4c: break;
case 0x4d:
if (wbuf[2] == 0x1c)
lme2510_usb_talk_restart(d,
wbuf, wlen, rbuf, rlen);
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, ...@@ -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) rbuf[1] = st->signal_lock;
? 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);
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, ...@@ -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, rlen = sizeof(rbuf);
int ret = 0, len = 2, rlen = sizeof(rbuf);
deb_info(1, "STM (%02x)", onoff); deb_info(1, "STM (%02x)", onoff);
if (onoff == 1) { /* Streaming is started by FE_HAS_LOCK */
st->i2c_talk_onoff = 0; if (onoff == 1)
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);
st->stream_on = 1; st->stream_on = 1;
st->one_tune = 0; else {
mutex_unlock(&adap->dev->i2c_mutex);
} 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;
...@@ -619,6 +589,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap) ...@@ -619,6 +589,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap)
ir_input_unregister(input_dev); ir_input_unregister(input_dev);
input_free_device(input_dev); input_free_device(input_dev);
} }
return (ret < 0) ? -ENODEV : 0; return (ret < 0) ? -ENODEV : 0;
} }
...@@ -668,6 +639,7 @@ static int lme2510_download_firmware(struct usb_device *dev, ...@@ -668,6 +639,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,6 +673,7 @@ static void lme_coldreset(struct usb_device *dev) ...@@ -701,6 +673,7 @@ 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;
} }
...@@ -712,6 +685,8 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) ...@@ -712,6 +685,8 @@ 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;
...@@ -740,22 +715,26 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) ...@@ -740,22 +715,26 @@ 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;
} }
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, ...@@ -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) if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
return 0; return -EAGAIN;
ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
switch (voltage) { switch (voltage) {
case SEC_VOLTAGE_18: case SEC_VOLTAGE_18:
...@@ -803,17 +777,15 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, ...@@ -803,17 +777,15 @@ 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;
} }
...@@ -850,12 +822,14 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) ...@@ -850,12 +822,14 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
if (dvb_usb_lme2510_firmware != 1) { if (dvb_usb_lme2510_firmware != 1) {
dvb_usb_lme2510_firmware = 1; dvb_usb_lme2510_firmware = 1;
lme_firmware_switch(adap->dev->udev, 1); lme_firmware_switch(adap->dev->udev, 1);
} } else /*stops LG/Sharp multi tuner problems*/
dvb_usb_lme2510_firmware = 0;
return 0; return 0;
} }
kfree(adap->fe); kfree(adap->fe);
adap->fe = NULL; adap->fe = NULL;
} }
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);
...@@ -889,8 +863,23 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) ...@@ -889,8 +863,23 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
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 */
...@@ -1084,5 +1073,5 @@ module_exit(lme2510_module_exit); ...@@ -1084,5 +1073,5 @@ 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_DESCRIPTION("LM2510(C) DVB-S USB2.0");
MODULE_VERSION("1.60"); MODULE_VERSION("1.70");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment