aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorMichael Krufky <mkrufky@linuxtv.org>2008-04-05 19:55:14 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-13 05:15:57 -0400
commitadeeac3b7989ad9f03651e9224c9c63e221d4310 (patch)
treec969ddd4d4ff0c45f2d41e690f6290ca1e0e07fc /drivers/media/dvb
parent641015ab2c452e8e554625e2a8e95218182acb4b (diff)
V4L/DVB (9149): hvr950q: led feedback based on snr
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/frontends/au8522.c133
-rw-r--r--drivers/media/dvb/frontends/au8522.h17
2 files changed, 150 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
index 0b82cc2a1e16..eabf9a68e7ec 100644
--- a/drivers/media/dvb/frontends/au8522.c
+++ b/drivers/media/dvb/frontends/au8522.c
@@ -40,6 +40,8 @@ struct au8522_state {
40 u32 current_frequency; 40 u32 current_frequency;
41 fe_modulation_t current_modulation; 41 fe_modulation_t current_modulation;
42 42
43 u32 fe_status;
44 unsigned int led_state;
43}; 45};
44 46
45static int debug; 47static int debug;
@@ -538,11 +540,98 @@ static int au8522_init(struct dvb_frontend *fe)
538 return 0; 540 return 0;
539} 541}
540 542
543static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
544{
545 struct au8522_led_config *led_config = state->config->led_cfg;
546 u8 val;
547
548 /* bail out if we cant control an LED */
549 if (!led_config || !led_config->gpio_output ||
550 !led_config->gpio_output_enable || !led_config->gpio_output_disable)
551 return 0;
552
553 val = au8522_readreg(state, 0x4000 |
554 (led_config->gpio_output & ~0xc000));
555 if (onoff) {
556 /* enable GPIO output */
557 val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
558 val |= (led_config->gpio_output_enable & 0xff);
559 } else {
560 /* disable GPIO output */
561 val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
562 val |= (led_config->gpio_output_disable & 0xff);
563 }
564 return au8522_writereg(state, 0x8000 |
565 (led_config->gpio_output & ~0xc000), val);
566}
567
568/* led = 0 | off
569 * led = 1 | signal ok
570 * led = 2 | signal strong
571 * led < 0 | only light led if leds are currently off
572 */
573static int au8522_led_ctrl(struct au8522_state *state, int led)
574{
575 struct au8522_led_config *led_config = state->config->led_cfg;
576 int i, ret = 0;
577
578 /* bail out if we cant control an LED */
579 if (!led_config || !led_config->gpio_leds ||
580 !led_config->num_led_states || !led_config->led_states)
581 return 0;
582
583 if (led < 0) {
584 /* if LED is already lit, then leave it as-is */
585 if (state->led_state)
586 return 0;
587 else
588 led *= -1;
589 }
590
591 /* toggle LED if changing state */
592 if (state->led_state != led) {
593 u8 val;
594
595 dprintk("%s: %d\n", __func__, led);
596
597 au8522_led_gpio_enable(state, 1);
598
599 val = au8522_readreg(state, 0x4000 |
600 (led_config->gpio_leds & ~0xc000));
601
602 /* start with all leds off */
603 for (i = 0; i < led_config->num_led_states; i++)
604 val &= ~led_config->led_states[i];
605
606 /* set selected LED state */
607 if (led < led_config->num_led_states)
608 val |= led_config->led_states[led];
609 else if (led_config->num_led_states)
610 val |=
611 led_config->led_states[led_config->num_led_states - 1];
612
613 ret = au8522_writereg(state, 0x8000 |
614 (led_config->gpio_leds & ~0xc000), val);
615 if (ret < 0)
616 return ret;
617
618 state->led_state = led;
619
620 if (led == 0)
621 au8522_led_gpio_enable(state, 0);
622 }
623
624 return 0;
625}
626
541static int au8522_sleep(struct dvb_frontend *fe) 627static int au8522_sleep(struct dvb_frontend *fe)
542{ 628{
543 struct au8522_state *state = fe->demodulator_priv; 629 struct au8522_state *state = fe->demodulator_priv;
544 dprintk("%s()\n", __func__); 630 dprintk("%s()\n", __func__);
545 631
632 /* turn off led */
633 au8522_led_ctrl(state, 0);
634
546 state->current_frequency = 0; 635 state->current_frequency = 0;
547 636
548 return 0; 637 return 0;
@@ -592,12 +681,53 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
592 *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; 681 *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
593 break; 682 break;
594 } 683 }
684 state->fe_status = *status;
685
686 if (*status & FE_HAS_LOCK)
687 /* turn on LED, if it isn't on already */
688 au8522_led_ctrl(state, -1);
689 else
690 /* turn off LED */
691 au8522_led_ctrl(state, 0);
595 692
596 dprintk("%s() status 0x%08x\n", __func__, *status); 693 dprintk("%s() status 0x%08x\n", __func__, *status);
597 694
598 return 0; 695 return 0;
599} 696}
600 697
698static int au8522_led_status(struct au8522_state *state, const u16 *snr)
699{
700 struct au8522_led_config *led_config = state->config->led_cfg;
701 int led;
702 u16 strong;
703
704 /* bail out if we cant control an LED */
705 if (!led_config)
706 return 0;
707
708 if (0 == (state->fe_status & FE_HAS_LOCK))
709 return au8522_led_ctrl(state, 0);
710 else if (state->current_modulation == QAM_256)
711 strong = led_config->qam256_strong;
712 else if (state->current_modulation == QAM_64)
713 strong = led_config->qam64_strong;
714 else /* (state->current_modulation == VSB_8) */
715 strong = led_config->vsb8_strong;
716
717 if (*snr >= strong)
718 led = 2;
719 else
720 led = 1;
721
722 if ((state->led_state) &&
723 (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10))
724 /* snr didn't change enough to bother
725 * changing the color of the led */
726 return 0;
727
728 return au8522_led_ctrl(state, led);
729}
730
601static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) 731static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
602{ 732{
603 struct au8522_state *state = fe->demodulator_priv; 733 struct au8522_state *state = fe->demodulator_priv;
@@ -621,6 +751,9 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
621 au8522_readreg(state, 0x4311), 751 au8522_readreg(state, 0x4311),
622 snr); 752 snr);
623 753
754 if (state->config->led_cfg)
755 au8522_led_status(state, snr);
756
624 return ret; 757 return ret;
625} 758}
626 759
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
index 595915ade8c3..7b94f554a093 100644
--- a/drivers/media/dvb/frontends/au8522.h
+++ b/drivers/media/dvb/frontends/au8522.h
@@ -30,6 +30,21 @@ enum au8522_if_freq {
30 AU8522_IF_3_25MHZ, 30 AU8522_IF_3_25MHZ,
31}; 31};
32 32
33struct au8522_led_config {
34 u16 vsb8_strong;
35 u16 qam64_strong;
36 u16 qam256_strong;
37
38 u16 gpio_output;
39 /* unset hi bits, set low bits */
40 u16 gpio_output_enable;
41 u16 gpio_output_disable;
42
43 u16 gpio_leds;
44 u8 *led_states;
45 unsigned int num_led_states;
46};
47
33struct au8522_config { 48struct au8522_config {
34 /* the demodulator's i2c address */ 49 /* the demodulator's i2c address */
35 u8 demod_address; 50 u8 demod_address;
@@ -39,6 +54,8 @@ struct au8522_config {
39#define AU8522_DEMODLOCKING 1 54#define AU8522_DEMODLOCKING 1
40 u8 status_mode; 55 u8 status_mode;
41 56
57 struct au8522_led_config *led_cfg;
58
42 enum au8522_if_freq vsb_if; 59 enum au8522_if_freq vsb_if;
43 enum au8522_if_freq qam_if; 60 enum au8522_if_freq qam_if;
44}; 61};