aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorNooneImportant <nxhxzi702@sneakemail.com>2005-11-09 00:35:27 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:03 -0500
commit83b75b049be981e579ba2cb88aa9bf3534bbbdb1 (patch)
treec7d6199e9c6b5373b373439148da7dc4f48a0698 /drivers/media/dvb
parentb90ed914e513a6ad6184f7a46a0df0888dcfc177 (diff)
[PATCH] dvb: let other frontends support FE_DISHNETWORK_SEND_LEGACY_CMD
Add support to FE_DISHNETWORK_SEND_LEGACY_CMD code to support other frontends besides stv0299. The generic code is a fallback in the case that it doesn't work for some specific frontends (again stv0299 being a good example). Signed-off-by: NooneImportant <nxhxzi702@sneakemail.com> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Cc: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c97
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h3
-rw-r--r--drivers/media/dvb/frontends/stv0299.c38
3 files changed, 104 insertions, 34 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index a8bc84240b50..e36dbd9c4cc5 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -577,6 +577,49 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
577 fepriv->thread_pid); 577 fepriv->thread_pid);
578} 578}
579 579
580s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
581{
582 return ((curtime.tv_usec < lasttime.tv_usec) ?
583 1000000 - lasttime.tv_usec + curtime.tv_usec :
584 curtime.tv_usec - lasttime.tv_usec);
585}
586EXPORT_SYMBOL(timeval_usec_diff);
587
588static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
589{
590 curtime->tv_usec += add_usec;
591 if (curtime->tv_usec >= 1000000) {
592 curtime->tv_usec -= 1000000;
593 curtime->tv_sec++;
594 }
595}
596
597/*
598 * Sleep until gettimeofday() > waketime + add_usec
599 * This needs to be as precise as possible, but as the delay is
600 * usually between 2ms and 32ms, it is done using a scheduled msleep
601 * followed by usleep (normally a busy-wait loop) for the remainder
602 */
603void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
604{
605 struct timeval lasttime;
606 s32 delta, newdelta;
607
608 timeval_usec_add(waketime, add_usec);
609
610 do_gettimeofday(&lasttime);
611 delta = timeval_usec_diff(lasttime, *waketime);
612 if (delta > 2500) {
613 msleep((delta - 1500) / 1000);
614 do_gettimeofday(&lasttime);
615 newdelta = timeval_usec_diff(lasttime, *waketime);
616 delta = (newdelta > delta) ? 0 : newdelta;
617 }
618 if (delta > 0)
619 udelay(delta);
620}
621EXPORT_SYMBOL(dvb_frontend_sleep_until);
622
580static int dvb_frontend_start(struct dvb_frontend *fe) 623static int dvb_frontend_start(struct dvb_frontend *fe)
581{ 624{
582 int ret; 625 int ret;
@@ -728,6 +771,60 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
728 err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg); 771 err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
729 fepriv->state = FESTATE_DISEQC; 772 fepriv->state = FESTATE_DISEQC;
730 fepriv->status = 0; 773 fepriv->status = 0;
774 } else if (fe->ops->set_voltage) {
775 /*
776 * NOTE: This is a fallback condition. Some frontends
777 * (stv0299 for instance) take longer than 8msec to
778 * respond to a set_voltage command. Those switches
779 * need custom routines to switch properly. For all
780 * other frontends, the following shoule work ok.
781 * Dish network legacy switches (as used by Dish500)
782 * are controlled by sending 9-bit command words
783 * spaced 8msec apart.
784 * the actual command word is switch/port dependant
785 * so it is up to the userspace application to send
786 * the right command.
787 * The command must always start with a '0' after
788 * initialization, so parg is 8 bits and does not
789 * include the initialization or start bit
790 */
791 unsigned int cmd = ((unsigned int) parg) << 1;
792 struct timeval nexttime;
793 struct timeval tv[10];
794 int i;
795 u8 last = 1;
796 if (dvb_frontend_debug)
797 printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
798 do_gettimeofday(&nexttime);
799 if (dvb_frontend_debug)
800 memcpy(&tv[0], &nexttime, sizeof(struct timeval));
801 /* before sending a command, initialize by sending
802 * a 32ms 18V to the switch
803 */
804 fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
805 dvb_frontend_sleep_until(&nexttime, 32000);
806
807 for (i = 0; i < 9; i++) {
808 if (dvb_frontend_debug)
809 do_gettimeofday(&tv[i + 1]);
810 if ((cmd & 0x01) != last) {
811 /* set voltage to (last ? 13V : 18V) */
812 fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
813 last = (last) ? 0 : 1;
814 }
815 cmd = cmd >> 1;
816 if (i != 8)
817 dvb_frontend_sleep_until(&nexttime, 8000);
818 }
819 if (dvb_frontend_debug) {
820 printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
821 __FUNCTION__, fe->dvb->num);
822 for (i = 1; i < 10; i++)
823 printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
824 }
825 err = 0;
826 fepriv->state = FESTATE_DISEQC;
827 fepriv->status = 0;
731 } 828 }
732 break; 829 break;
733 830
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 9c2c1d1136bd..348c9b0b988a 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -101,4 +101,7 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
101 101
102extern int dvb_unregister_frontend(struct dvb_frontend* fe); 102extern int dvb_unregister_frontend(struct dvb_frontend* fe);
103 103
104extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
105extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
106
104#endif 107#endif
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index b1876618a37d..ae00d7a40d7c 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -387,36 +387,6 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
387 }; 387 };
388} 388}
389 389
390static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime)
391{
392 return ((curtime.tv_usec < lasttime.tv_usec) ?
393 1000000 - lasttime.tv_usec + curtime.tv_usec :
394 curtime.tv_usec - lasttime.tv_usec);
395}
396
397static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec)
398{
399 struct timeval lasttime;
400 s32 delta, newdelta;
401
402 waketime->tv_usec += add_usec;
403 if (waketime->tv_usec >= 1000000) {
404 waketime->tv_usec -= 1000000;
405 waketime->tv_sec++;
406 }
407
408 do_gettimeofday (&lasttime);
409 delta = stv0299_calc_usec_delay (lasttime, *waketime);
410 if (delta > 2500) {
411 msleep ((delta - 1500) / 1000);
412 do_gettimeofday (&lasttime);
413 newdelta = stv0299_calc_usec_delay (lasttime, *waketime);
414 delta = (newdelta > delta) ? 0 : newdelta;
415 }
416 if (delta > 0)
417 udelay (delta);
418}
419
420static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) 390static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
421{ 391{
422 struct stv0299_state* state = fe->demodulator_priv; 392 struct stv0299_state* state = fe->demodulator_priv;
@@ -444,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
444 memcpy (&tv[0], &nexttime, sizeof (struct timeval)); 414 memcpy (&tv[0], &nexttime, sizeof (struct timeval));
445 stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ 415 stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
446 416
447 stv0299_sleep_until (&nexttime, 32000); 417 dvb_frontend_sleep_until(&nexttime, 32000);
448 418
449 for (i=0; i<9; i++) { 419 for (i=0; i<9; i++) {
450 if (debug_legacy_dish_switch) 420 if (debug_legacy_dish_switch)
@@ -458,13 +428,13 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
458 cmd = cmd >> 1; 428 cmd = cmd >> 1;
459 429
460 if (i != 8) 430 if (i != 8)
461 stv0299_sleep_until (&nexttime, 8000); 431 dvb_frontend_sleep_until(&nexttime, 8000);
462 } 432 }
463 if (debug_legacy_dish_switch) { 433 if (debug_legacy_dish_switch) {
464 printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", 434 printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
465 __FUNCTION__, fe->dvb->num); 435 __FUNCTION__, fe->dvb->num);
466 for (i=1; i < 10; i++) 436 for (i = 1; i < 10; i++)
467 printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i])); 437 printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
468 } 438 }
469 439
470 return 0; 440 return 0;