aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMalcolm Priestley <tvboxspy@gmail.com>2010-10-27 18:50:36 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-29 05:16:29 -0500
commitf23e6616ac2dc560db0ee8733024ebe90de9161a (patch)
treeb6baf41a30063dd82e470fa872386feccfc4fe1e
parentea7c681e899bda3fceb37815d63d201c3b4be920 (diff)
[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: Malcolm Priestley <tvboxspy@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/dvb-usb/lmedm04.c153
1 files changed, 71 insertions, 82 deletions
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index d939fbbf9fe6..3a32c65ee04c 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -112,7 +112,6 @@ struct lme2510_state {
112 u8 i2c_tuner_gate_r; 112 u8 i2c_tuner_gate_r;
113 u8 i2c_tuner_addr; 113 u8 i2c_tuner_addr;
114 u8 stream_on; 114 u8 stream_on;
115 u8 one_tune;
116 void *buffer; 115 void *buffer;
117 struct urb *lme_urb; 116 struct urb *lme_urb;
118 void *usb_buffer; 117 void *usb_buffer;
@@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
182 return (ret < 0) ? -ENODEV : 0; 181 return (ret < 0) ? -ENODEV : 0;
183} 182}
184 183
185static int lme2510_usb_talk_restart(struct dvb_usb_device *d, 184static int lme2510_stream_restart(struct dvb_usb_device *d)
186 u8 *wbuf, int wlen, u8 *rbuf, int rlen) { 185{
187 static u8 stream_on[] = LME_ST_ON_W; 186 static u8 stream_on[] = LME_ST_ON_W;
188 int ret; 187 int ret;
189 u8 rbuff[10]; 188 u8 rbuff[10];
190 /*Send Normal Command*/
191 ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
192 /*Restart Stream Command*/ 189 /*Restart Stream Command*/
193 ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on), 190 ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
194 rbuff, sizeof(rbuff)); 191 rbuff, sizeof(rbuff));
195 return ret; 192 return ret;
196} 193}
@@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb)
254 case TUNER_S7395: 251 case TUNER_S7395:
255 /* Tweak for earlier firmware*/ 252 /* Tweak for earlier firmware*/
256 if (ibuf[1] == 0x03) { 253 if (ibuf[1] == 0x03) {
254 if (ibuf[2] > 1)
255 st->signal_lock = ibuf[2];
257 st->signal_level = ibuf[3]; 256 st->signal_level = ibuf[3];
258 st->signal_sn = ibuf[4]; 257 st->signal_sn = ibuf[4];
259 } else { 258 } else {
260 st->signal_level = ibuf[4]; 259 st->signal_level = ibuf[4];
261 st->signal_sn = ibuf[5]; 260 st->signal_sn = ibuf[5];
261 st->signal_lock =
262 (st->signal_lock & 0xf7) +
263 ((ibuf[2] & 0x01) << 0x03);
262 } 264 }
263 break; 265 break;
264 default: 266 default:
@@ -341,11 +343,10 @@ static int lme2510_msg(struct dvb_usb_device *d,
341 st->signal_lock = rbuf[1]; 343 st->signal_lock = rbuf[1];
342 if ((st->stream_on & 1) && 344 if ((st->stream_on & 1) &&
343 (st->signal_lock & 0x10)) { 345 (st->signal_lock & 0x10)) {
344 lme2510_usb_talk_restart(d, 346 lme2510_stream_restart(d);
345 wbuf, wlen, rbuf, rlen);
346 st->i2c_talk_onoff = 0; 347 st->i2c_talk_onoff = 0;
347 } 348 }
348 msleep(80); 349 msleep(80);
349 } 350 }
350 } 351 }
351 break; 352 break;
@@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_device *d,
355 st->signal_lock = rbuf[1]; 356 st->signal_lock = rbuf[1];
356 if ((st->stream_on & 1) && 357 if ((st->stream_on & 1) &&
357 (st->signal_lock & 0x8)) { 358 (st->signal_lock & 0x8)) {
358 lme2510_usb_talk_restart(d, 359 lme2510_stream_restart(d);
359 wbuf, wlen, rbuf, rlen);
360 st->i2c_talk_onoff = 0; 360 st->i2c_talk_onoff = 0;
361 } 361 }
362 } 362 }
363 if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) 363 if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
364 msleep(5); 364 msleep(5);
365
366
367 } 365 }
368 break; 366 break;
369 default: 367 default:
@@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_device *d,
385 rbuf[0] = 0x55; 383 rbuf[0] = 0x55;
386 rbuf[1] = st->signal_sn; 384 rbuf[1] = st->signal_sn;
387 break; 385 break;
388 /*DiSEqC functions as per TDA10086*/ 386 case 0x15:
389 case 0x36: 387 case 0x16:
390 case 0x48: 388 case 0x17:
391 case 0x49: 389 case 0x18:
392 case 0x4a: 390 rbuf[0] = 0x55;
393 case 0x4b: 391 rbuf[1] = 0x00;
394 case 0x4c: 392 break;
395 case 0x4d:
396 if (wbuf[2] == 0x1c)
397 lme2510_usb_talk_restart(d,
398 wbuf, wlen, rbuf, rlen);
399 default: 393 default:
394 lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
395 st->i2c_talk_onoff = 1;
400 break; 396 break;
401 } 397 }
402 break; 398 break;
@@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_device *d,
413 break; 409 break;
414 case 0x24: 410 case 0x24:
415 rbuf[0] = 0x55; 411 rbuf[0] = 0x55;
416 rbuf[1] = (st->signal_level & 0x80) 412 rbuf[1] = st->signal_lock;
417 ? 0 : st->signal_lock;
418 break;
419 case 0x6:
420 if (wbuf[2] == 0xd0)
421 lme2510_usb_talk(d,
422 wbuf, wlen, rbuf, rlen);
423 break;
424 case 0x1:
425 if (st->one_tune > 0)
426 break;
427 st->one_tune++;
428 st->i2c_talk_onoff = 1;
429 /*DiSEqC functions as per STV0288*/
430 case 0x5:
431 case 0x7:
432 case 0x8:
433 case 0x9:
434 case 0xa:
435 case 0xb:
436 if (wbuf[2] == 0xd0)
437 lme2510_usb_talk_restart(d,
438 wbuf, wlen, rbuf, rlen);
439 break; 413 break;
440 default: 414 case 0x2e:
415 case 0x26:
416 case 0x27:
441 rbuf[0] = 0x55; 417 rbuf[0] = 0x55;
442 rbuf[1] = 0x00; 418 rbuf[1] = 0x00;
443 break; 419 break;
420 default:
421 lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
422 st->i2c_talk_onoff = 1;
423 break;
444 } 424 }
445 break; 425 break;
446 default: 426 default:
447 break; 427 break;
448
449 } 428 }
450 429
451 deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)", 430 deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
@@ -548,35 +527,26 @@ static int lme2510_identify_state(struct usb_device *udev,
548static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 527static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
549{ 528{
550 struct lme2510_state *st = adap->dev->priv; 529 struct lme2510_state *st = adap->dev->priv;
551 static u8 stream_on[] = LME_ST_ON_W;
552 static u8 clear_reg_3[] = LME_CLEAR_PID; 530 static u8 clear_reg_3[] = LME_CLEAR_PID;
553 static u8 rbuf[1]; 531 static u8 rbuf[1];
554 static u8 timeout; 532 int ret = 0, rlen = sizeof(rbuf);
555 int ret = 0, len = 2, rlen = sizeof(rbuf);
556 533
557 deb_info(1, "STM (%02x)", onoff); 534 deb_info(1, "STM (%02x)", onoff);
558 535
559 if (onoff == 1) { 536 /* Streaming is started by FE_HAS_LOCK */
560 st->i2c_talk_onoff = 0; 537 if (onoff == 1)
561 timeout = 0;
562 /* wait for i2C to be free */
563 while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) {
564 timeout++;
565 if (timeout > 5)
566 return -ENODEV;
567 }
568 msleep(100);
569 ret |= lme2510_usb_talk(adap->dev,
570 stream_on, len, rbuf, rlen);
571 st->stream_on = 1; 538 st->stream_on = 1;
572 st->one_tune = 0; 539 else {
573 mutex_unlock(&adap->dev->i2c_mutex);
574 } else {
575 deb_info(1, "STM Steam Off"); 540 deb_info(1, "STM Steam Off");
541 /* mutex is here only to avoid collision with I2C */
542 ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
543
576 ret |= lme2510_usb_talk(adap->dev, clear_reg_3, 544 ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
577 sizeof(clear_reg_3), rbuf, rlen); 545 sizeof(clear_reg_3), rbuf, rlen);
578 st->stream_on = 0; 546 st->stream_on = 0;
579 st->i2c_talk_onoff = 1; 547 st->i2c_talk_onoff = 1;
548
549 mutex_unlock(&adap->dev->i2c_mutex);
580 } 550 }
581 551
582 return (ret < 0) ? -ENODEV : 0; 552 return (ret < 0) ? -ENODEV : 0;
@@ -619,6 +589,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap)
619 ir_input_unregister(input_dev); 589 ir_input_unregister(input_dev);
620 input_free_device(input_dev); 590 input_free_device(input_dev);
621 } 591 }
592
622 return (ret < 0) ? -ENODEV : 0; 593 return (ret < 0) ? -ENODEV : 0;
623} 594}
624 595
@@ -668,6 +639,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
668 ret |= (data[0] == 0x88) ? 0 : -1; 639 ret |= (data[0] == 0x88) ? 0 : -1;
669 } 640 }
670 } 641 }
642
671 usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 643 usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
672 0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000); 644 0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
673 645
@@ -701,6 +673,7 @@ static void lme_coldreset(struct usb_device *dev)
701 info("FRM Firmware Cold Reset"); 673 info("FRM Firmware Cold Reset");
702 ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/ 674 ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
703 ret |= lme2510_bulk_read(dev, data, len_in, 1); 675 ret |= lme2510_bulk_read(dev, data, len_in, 1);
676
704 return; 677 return;
705} 678}
706 679
@@ -712,6 +685,8 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
712 char *firm_msg[] = {"Loading", "Switching to"}; 685 char *firm_msg[] = {"Loading", "Switching to"};
713 int ret; 686 int ret;
714 687
688 cold = (cold > 0) ? (cold & 1) : 0;
689
715 if (udev->descriptor.idProduct == 0x1122) 690 if (udev->descriptor.idProduct == 0x1122)
716 return; 691 return;
717 692
@@ -740,22 +715,26 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
740 cold = 0; 715 cold = 0;
741 break; 716 break;
742 } 717 }
718
743 release_firmware(fw); 719 release_firmware(fw);
720
744 if (cold) 721 if (cold)
745 lme_coldreset(udev); 722 lme_coldreset(udev);
723
746 return; 724 return;
747} 725}
748 726
749static int lme2510_kill_urb(struct usb_data_stream *stream) 727static int lme2510_kill_urb(struct usb_data_stream *stream)
750{ 728{
751 int i; 729 int i;
730
752 for (i = 0; i < stream->urbs_submitted; i++) { 731 for (i = 0; i < stream->urbs_submitted; i++) {
753 deb_info(3, "killing URB no. %d.", i); 732 deb_info(3, "killing URB no. %d.", i);
754
755 /* stop the URB */ 733 /* stop the URB */
756 usb_kill_urb(stream->urb_list[i]); 734 usb_kill_urb(stream->urb_list[i]);
757 } 735 }
758 stream->urbs_submitted = 0; 736 stream->urbs_submitted = 0;
737
759 return 0; 738 return 0;
760} 739}
761 740
@@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
783 fe_sec_voltage_t voltage) 762 fe_sec_voltage_t voltage)
784{ 763{
785 struct dvb_usb_adapter *adap = fe->dvb->priv; 764 struct dvb_usb_adapter *adap = fe->dvb->priv;
786 struct lme2510_state *st = adap->dev->priv;
787 static u8 voltage_low[] = LME_VOLTAGE_L; 765 static u8 voltage_low[] = LME_VOLTAGE_L;
788 static u8 voltage_high[] = LME_VOLTAGE_H; 766 static u8 voltage_high[] = LME_VOLTAGE_H;
789 static u8 lnb_on[] = LNB_ON;
790 static u8 lnb_off[] = LNB_OFF;
791 static u8 rbuf[1]; 767 static u8 rbuf[1];
792 int ret = 0, len = 3, rlen = 1; 768 int ret = 0, len = 3, rlen = 1;
793 769
794 if (st->stream_on == 1) 770 if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
795 return 0; 771 return -EAGAIN;
796
797 ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
798 772
799 switch (voltage) { 773 switch (voltage) {
800 case SEC_VOLTAGE_18: 774 case SEC_VOLTAGE_18:
@@ -803,17 +777,15 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
803 break; 777 break;
804 778
805 case SEC_VOLTAGE_OFF: 779 case SEC_VOLTAGE_OFF:
806 ret |= lme2510_usb_talk(adap->dev,
807 lnb_off, len, rbuf, rlen);
808 case SEC_VOLTAGE_13: 780 case SEC_VOLTAGE_13:
809 default: 781 default:
810 ret |= lme2510_usb_talk(adap->dev, 782 ret |= lme2510_usb_talk(adap->dev,
811 voltage_low, len, rbuf, rlen); 783 voltage_low, len, rbuf, rlen);
812 break; 784 break;
785 }
813 786
787 mutex_unlock(&adap->dev->i2c_mutex);
814 788
815 };
816 st->i2c_talk_onoff = 1;
817 return (ret < 0) ? -ENODEV : 0; 789 return (ret < 0) ? -ENODEV : 0;
818} 790}
819 791
@@ -850,12 +822,14 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
850 if (dvb_usb_lme2510_firmware != 1) { 822 if (dvb_usb_lme2510_firmware != 1) {
851 dvb_usb_lme2510_firmware = 1; 823 dvb_usb_lme2510_firmware = 1;
852 lme_firmware_switch(adap->dev->udev, 1); 824 lme_firmware_switch(adap->dev->udev, 1);
853 } 825 } else /*stops LG/Sharp multi tuner problems*/
826 dvb_usb_lme2510_firmware = 0;
854 return 0; 827 return 0;
855 } 828 }
856 kfree(adap->fe); 829 kfree(adap->fe);
857 adap->fe = NULL; 830 adap->fe = NULL;
858 } 831 }
832
859 st->i2c_gate = 5; 833 st->i2c_gate = 5;
860 adap->fe = dvb_attach(stv0288_attach, &lme_config, 834 adap->fe = dvb_attach(stv0288_attach, &lme_config,
861 &adap->dev->i2c_adap); 835 &adap->dev->i2c_adap);
@@ -889,8 +863,23 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
889static int lme2510_powerup(struct dvb_usb_device *d, int onoff) 863static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
890{ 864{
891 struct lme2510_state *st = d->priv; 865 struct lme2510_state *st = d->priv;
866 static u8 lnb_on[] = LNB_ON;
867 static u8 lnb_off[] = LNB_OFF;
868 static u8 rbuf[1];
869 int ret, len = 3, rlen = 1;
870
871 ret = mutex_lock_interruptible(&d->i2c_mutex);
872
873 if (onoff)
874 ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
875 else
876 ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
877
892 st->i2c_talk_onoff = 1; 878 st->i2c_talk_onoff = 1;
893 return 0; 879
880 mutex_unlock(&d->i2c_mutex);
881
882 return ret;
894} 883}
895 884
896/* DVB USB Driver stuff */ 885/* DVB USB Driver stuff */
@@ -1084,5 +1073,5 @@ module_exit(lme2510_module_exit);
1084 1073
1085MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); 1074MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
1086MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); 1075MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0");
1087MODULE_VERSION("1.60"); 1076MODULE_VERSION("1.70");
1088MODULE_LICENSE("GPL"); 1077MODULE_LICENSE("GPL");