Updated driver for DM04/QQBOX USB DVB-S BOXES to version 1.50 These include -later kill of usb_buffer to avoid kernel crash on hot unplugging. -DiSEqC functions. -LNB Power switch -Faster channel change. Signed-off-by: Malcolm Priestley <tvboxspy@xxxxxxxxx> http://mercurial.intuxication.org/hg/tvboxspy/summary --- diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 794b16d..3569e34 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -51,10 +51,7 @@ * LME2510: Non Intel USB chipsets fail to maintain High Speed on * Boot or Hot Plug. * - * DiSEqC functions are not fully supported in this driver. The main - * reason is the frontend is cut off during streaming. Allowing frontend - * access will stall the driver. Applications that attempt to this, the - * commands are ignored. + * QQbox suffers from noise on LNB voltage. * * PID functions mave been removed from this driver version due to * problems with different firmware and application versions. @@ -154,15 +151,15 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, return -EAGAIN; ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); - msleep(5); - ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x1); - msleep(5); - ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x1)); + ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); + + msleep(12); + + ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); - msleep(5); ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ? - 512 : rlen , 0x1); + 512 : rlen , 0x01); if (rlen > 0) memcpy(rbuf, buff, rlen); @@ -172,6 +169,19 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, 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 u8 stream_on[] = LME_ST_ON_W; + int ret; + u8 rbuff[1]; + /*Send Normal Command*/ + ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); + /*Restart Stream Command*/ + ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on), + rbuff, sizeof(rbuff)); + return ret; +} + static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress) { struct dvb_usb_device *d = adap->dev; @@ -233,7 +243,7 @@ static void lme2510_int_response(struct urb *lme_urb) /* Tweak for earlier firmware*/ if (ibuf[1] == 0x03) { st->signal_level = ibuf[3]; - st->signal_sn = ibuf[2]; + st->signal_sn = ibuf[4]; } else { st->signal_level = ibuf[4]; st->signal_sn = ibuf[5]; @@ -318,6 +328,7 @@ static int lme2510_msg(struct dvb_usb_device *d, case TUNER_S7395: if (wbuf[3] == 0x24) st->signal_lock = rbuf[1]; + msleep(5); break; default: break; @@ -358,6 +369,18 @@ static int lme2510_msg(struct dvb_usb_device *d, rbuf[0] = 0x55; rbuf[1] = (st->signal_level & 0x80) ? 0 : st->signal_lock; + break; + /*DiSEqC functions as per STV0288*/ + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + case 0xa: + case 0xb: + if (wbuf[2] == 0xd0) + lme2510_usb_talk_restart(d, + wbuf, wlen, rbuf, rlen); default: break; } @@ -472,7 +495,6 @@ static int lme2510_identify_state(struct usb_device *udev, static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; - static u8 reset[] = LME_RESET; static u8 stream_on[] = LME_ST_ON_W; static u8 clear_reg_3[] = LME_CLEAR_PID; static u8 rbuf[1]; @@ -481,19 +503,14 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) if (onoff == 1) { st->i2c_talk_onoff = 0; - msleep(400); /* give enough time for i2c to stop */ + msleep(40); /* give enough time for i2c to stop */ ret |= lme2510_usb_talk(adap->dev, stream_on, len, rbuf, rlen); } else { deb_info(1, "STM Steam Off"); - if (st->tuner_config == TUNER_LG) - ret |= lme2510_usb_talk(adap->dev, clear_reg_3, + ret |= lme2510_usb_talk(adap->dev, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); - else - ret |= lme2510_usb_talk(adap->dev, - reset, sizeof(reset), rbuf, rlen); - - msleep(400); + msleep(40); st->i2c_talk_onoff = 1; } @@ -640,7 +657,6 @@ static struct ix2505v_config lme_tuner = { .tuner_chargepump = 0x3, }; - static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { @@ -648,19 +664,12 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, struct lme2510_state *st = adap->dev->priv; static u8 voltage_low[] = LME_VOLTAGE_L; static u8 voltage_high[] = LME_VOLTAGE_H; - static u8 reset[] = LME_RESET; - static u8 clear_reg_3[] = LME_CLEAR_PID; + static u8 lnb_on[] = LNB_ON; + static u8 lnb_off[] = LNB_OFF; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; msleep(100); - if (st->tuner_config == TUNER_LG) - ret |= lme2510_usb_talk(adap->dev, clear_reg_3, - sizeof(clear_reg_3), rbuf, rlen); - else - ret |= lme2510_usb_talk(adap->dev, - reset, sizeof(reset), rbuf, rlen); - /*always check & stop streaming*/ lme2510_kill_urb(&adap->stream); adap->feedcount = 0; @@ -668,13 +677,24 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, switch (voltage) { case SEC_VOLTAGE_18: + if (st->tuner_config == TUNER_S7395) + ret |= lme2510_usb_talk(adap->dev, + lnb_on, len, rbuf, rlen); ret |= lme2510_usb_talk(adap->dev, voltage_high, len, rbuf, rlen); break; case SEC_VOLTAGE_OFF: + if (st->tuner_config == TUNER_S7395) { + ret |= lme2510_usb_talk(adap->dev, + lnb_off, len, rbuf, rlen); + break; + } case SEC_VOLTAGE_13: default: + if (st->tuner_config == TUNER_S7395) + ret |= lme2510_usb_talk(adap->dev, + lnb_on, len, rbuf, rlen); ret |= lme2510_usb_talk(adap->dev, voltage_low, len, rbuf, rlen); break; @@ -873,15 +893,23 @@ static struct dvb_usb_device_properties lme2510c_properties = { } }; -void lme2510_exit_int(struct dvb_usb_device *d) +void *lme2510_exit_int(struct dvb_usb_device *d) { struct lme2510_state *st = d->priv; + struct dvb_usb_adapter *adap = &d->adapter[0]; + void *buffer = NULL; + + if (adap != NULL) { + lme2510_kill_urb(&adap->stream); + adap->feedcount = 0; + } + if (st->lme_urb != NULL) { - st->i2c_talk_onoff = 0; + st->i2c_talk_onoff = 1; st->signal_lock = 0; st->signal_level = 0; st->signal_sn = 0; - kfree(st->usb_buffer); + buffer = st->usb_buffer; usb_kill_urb(st->lme_urb); usb_buffer_free(d->udev, 5000, st->buffer, st->lme_urb->transfer_dma); @@ -889,18 +917,19 @@ void lme2510_exit_int(struct dvb_usb_device *d) ir_input_unregister(d->rc_input_dev); info("Remote Stopped"); } - return; + return buffer; } void lme2510_exit(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); + void *usb_buffer; + if (d != NULL) { - d->adapter[0].feedcount = 0; - lme2510_exit_int(d); + usb_buffer = lme2510_exit_int(d); dvb_usb_device_exit(intf); + kfree(usb_buffer); } - } static struct usb_driver lme2510_driver = { @@ -933,5 +962,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley <tvboxspy@xxxxxxxxx>"); MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.4"); +MODULE_VERSION("1.50"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h index da7947f..cd8299a 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.h +++ b/drivers/media/dvb/dvb-usb/lmedm04.h @@ -1,12 +1,12 @@ /* DVB USB compliant linux driver for * * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 - * LME2510C + LGTDQT-P001F + * LME2510 + LGTDQT-P001F * * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) * - * MVB0001F (LME2510C+LGTDQT-P001F) + * MVB001F (LME2510+LGTDQT-P001F) * LG TDQY - P001F =(TDA8263 + TDA10086H) * * @@ -35,35 +35,33 @@ * end byte -1 = 20 * end byte = clear pid always a0, other wise 9c, 9a ?? * - * RESET (also clears PID filter) - * 3a 01 00 */ #define LME_ST_ON_W {0x06, 0x00} -#define LME_RESET {0x3a, 0x01, 0x00} #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} - -/* LME Power Control +/* LNB Voltage * 07 XX XX - * offset 1 = 01 Power? my device cannot be powered down + * offset 1 = 01 * offset 2 = 00=Voltage low 01=Voltage high + * + * LNB Power + * 03 01 XX + * offset 2 = 00=ON 01=OFF */ #define LME_VOLTAGE_L {0x07, 0x01, 0x00} #define LME_VOLTAGE_H {0x07, 0x01, 0x01} - +#define LNB_ON {0x3a, 0x01, 0x00} +#define LNB_OFF {0x3a, 0x01, 0x01} /* Initial stv0288 settings for 7395 Frontend */ static u8 s7395_inittab[] = { - 0x00, 0x11, 0x01, 0x15, 0x02, 0x20, - 0x03, 0x8e, - 0x04, 0x8e, + 0x03, 0xa0, + 0x04, 0xa0, 0x05, 0x12, - 0x06, 0xff, - 0x07, 0x20, - 0x08, 0x00, + 0x06, 0x00, 0x09, 0x00, 0x0a, 0x04, 0x0b, 0x00, @@ -71,7 +69,6 @@ static u8 s7395_inittab[] = { 0x0d, 0x00, 0x0e, 0xc1, 0x0f, 0x54, - 0x10, 0x40, 0x11, 0x7a, 0x12, 0x03, 0x13, 0x48, @@ -84,23 +81,15 @@ static u8 s7395_inittab[] = { 0x1a, 0x88, 0x1b, 0x8f, 0x1c, 0xf0, - 0x1e, 0x80, 0x20, 0x0b, 0x21, 0x54, 0x22, 0xff, 0x23, 0x01, - 0x24, 0x9a, - 0x25, 0x7f, - 0x26, 0x00, - 0x27, 0x00, 0x28, 0x46, 0x29, 0x66, 0x2a, 0x90, 0x2b, 0xfa, 0x2c, 0xd9, - 0x2d, 0x02, - 0x2e, 0xb1, - 0x2f, 0x00, 0x30, 0x0, 0x31, 0x1e, 0x32, 0x14, @@ -115,8 +104,6 @@ static u8 s7395_inittab[] = { 0x3b, 0x13, 0x3c, 0x11, 0x3d, 0x30, - 0x3e, 0x00, - 0x3f, 0x00, 0x40, 0x63, 0x41, 0x04, 0x42, 0x60, @@ -126,8 +113,6 @@ static u8 s7395_inittab[] = { 0x46, 0x00, 0x47, 0x00, 0x4a, 0x00, - 0x4b, 0xd1, - 0x4c, 0x33, 0x50, 0x12, 0x51, 0x36, 0x52, 0x21, @@ -183,5 +168,4 @@ static u8 s7395_inittab[] = { 0xf2, 0xc0, 0xff, 0xff, }; - #endif -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html