2 Auvitek AU8522 QAM/8VSB demodulator driver
4 Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/string.h>
26 #include <linux/delay.h>
27 #include "dvb_frontend.h"
29 #include "au8522_priv.h"
33 /* Despite the name "hybrid_tuner", the framework works just as well for
34 hybrid demodulators as well... */
35 static LIST_HEAD(hybrid_tuner_instance_list
);
36 static DEFINE_MUTEX(au8522_list_mutex
);
38 #define dprintk(arg...)\
43 /* 16 bit registers, 8 bit values */
44 int au8522_writereg(struct au8522_state
*state
, u16 reg
, u8 data
)
47 u8 buf
[] = { (reg
>> 8) | 0x80, reg
& 0xff, data
};
49 struct i2c_msg msg
= { .addr
= state
->config
->demod_address
,
50 .flags
= 0, .buf
= buf
, .len
= 3 };
52 ret
= i2c_transfer(state
->i2c
, &msg
, 1);
55 printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
56 "ret == %i)\n", __func__
, reg
, data
, ret
);
58 return (ret
!= 1) ? -1 : 0;
61 u8
au8522_readreg(struct au8522_state
*state
, u16 reg
)
64 u8 b0
[] = { (reg
>> 8) | 0x40, reg
& 0xff };
67 struct i2c_msg msg
[] = {
68 { .addr
= state
->config
->demod_address
, .flags
= 0,
69 .buf
= b0
, .len
= 2 },
70 { .addr
= state
->config
->demod_address
, .flags
= I2C_M_RD
,
71 .buf
= b1
, .len
= 1 } };
73 ret
= i2c_transfer(state
->i2c
, msg
, 2);
76 printk(KERN_ERR
"%s: readreg error (ret == %i)\n",
81 static int au8522_i2c_gate_ctrl(struct dvb_frontend
*fe
, int enable
)
83 struct au8522_state
*state
= fe
->demodulator_priv
;
85 dprintk("%s(%d)\n", __func__
, enable
);
87 if (state
->operational_mode
== AU8522_ANALOG_MODE
) {
88 /* We're being asked to manage the gate even though we're
89 not in digital mode. This can occur if we get switched
90 over to analog mode before the dvb_frontend kernel thread
91 has completely shutdown */
96 return au8522_writereg(state
, 0x106, 1);
98 return au8522_writereg(state
, 0x106, 0);
106 /* VSB SNR lookup table */
107 static struct mse2snr_tab vsb_mse2snr_tab
[] = {
140 /* QAM64 SNR lookup table */
141 static struct mse2snr_tab qam64_mse2snr_tab
[] = {
221 /* QAM256 SNR lookup table */
222 static struct mse2snr_tab qam256_mse2snr_tab
[] = {
289 static int au8522_mse2snr_lookup(struct mse2snr_tab
*tab
, int sz
, int mse
,
292 int i
, ret
= -EINVAL
;
293 dprintk("%s()\n", __func__
);
295 for (i
= 0; i
< sz
; i
++) {
296 if (mse
< tab
[i
].val
) {
302 dprintk("%s() snr=%d\n", __func__
, *snr
);
306 static int au8522_set_if(struct dvb_frontend
*fe
, enum au8522_if_freq if_freq
)
308 struct au8522_state
*state
= fe
->demodulator_priv
;
313 case AU8522_IF_3_25MHZ
:
332 dprintk("%s() IF Frequency not supported\n", __func__
);
335 dprintk("%s() %s MHz\n", __func__
, ifmhz
);
336 au8522_writereg(state
, 0x80b5, r0b5
);
337 au8522_writereg(state
, 0x80b6, r0b6
);
338 au8522_writereg(state
, 0x80b7, r0b7
);
343 /* VSB Modulation table */
377 /* QAM64 Modulation table */
381 } QAM64_mod_tab
[] = {
456 /* QAM256 Modulation table */
460 } QAM256_mod_tab
[] = {
535 static int au8522_enable_modulation(struct dvb_frontend
*fe
,
538 struct au8522_state
*state
= fe
->demodulator_priv
;
541 dprintk("%s(0x%08x)\n", __func__
, m
);
545 dprintk("%s() VSB_8\n", __func__
);
546 for (i
= 0; i
< ARRAY_SIZE(VSB_mod_tab
); i
++)
547 au8522_writereg(state
,
549 VSB_mod_tab
[i
].data
);
550 au8522_set_if(fe
, state
->config
->vsb_if
);
553 dprintk("%s() QAM 64\n", __func__
);
554 for (i
= 0; i
< ARRAY_SIZE(QAM64_mod_tab
); i
++)
555 au8522_writereg(state
,
556 QAM64_mod_tab
[i
].reg
,
557 QAM64_mod_tab
[i
].data
);
558 au8522_set_if(fe
, state
->config
->qam_if
);
561 dprintk("%s() QAM 256\n", __func__
);
562 for (i
= 0; i
< ARRAY_SIZE(QAM256_mod_tab
); i
++)
563 au8522_writereg(state
,
564 QAM256_mod_tab
[i
].reg
,
565 QAM256_mod_tab
[i
].data
);
566 au8522_set_if(fe
, state
->config
->qam_if
);
569 dprintk("%s() Invalid modulation\n", __func__
);
573 state
->current_modulation
= m
;
578 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
579 static int au8522_set_frontend(struct dvb_frontend
*fe
)
581 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
582 struct au8522_state
*state
= fe
->demodulator_priv
;
585 dprintk("%s(frequency=%d)\n", __func__
, c
->frequency
);
587 if ((state
->current_frequency
== c
->frequency
) &&
588 (state
->current_modulation
== c
->modulation
))
591 au8522_enable_modulation(fe
, c
->modulation
);
593 /* Allow the demod to settle */
596 if (fe
->ops
.tuner_ops
.set_params
) {
597 if (fe
->ops
.i2c_gate_ctrl
)
598 fe
->ops
.i2c_gate_ctrl(fe
, 1);
599 ret
= fe
->ops
.tuner_ops
.set_params(fe
);
600 if (fe
->ops
.i2c_gate_ctrl
)
601 fe
->ops
.i2c_gate_ctrl(fe
, 0);
607 state
->current_frequency
= c
->frequency
;
612 /* Reset the demod hardware and reset all of the configuration registers
613 to a default state. */
614 int au8522_init(struct dvb_frontend
*fe
)
616 struct au8522_state
*state
= fe
->demodulator_priv
;
617 dprintk("%s()\n", __func__
);
619 state
->operational_mode
= AU8522_DIGITAL_MODE
;
621 /* Clear out any state associated with the digital side of the
622 chip, so that when it gets powered back up it won't think
623 that it is already tuned */
624 state
->current_frequency
= 0;
626 au8522_writereg(state
, 0xa4, 1 << 5);
628 au8522_i2c_gate_ctrl(fe
, 1);
633 static int au8522_led_gpio_enable(struct au8522_state
*state
, int onoff
)
635 struct au8522_led_config
*led_config
= state
->config
->led_cfg
;
638 /* bail out if we can't control an LED */
639 if (!led_config
|| !led_config
->gpio_output
||
640 !led_config
->gpio_output_enable
|| !led_config
->gpio_output_disable
)
643 val
= au8522_readreg(state
, 0x4000 |
644 (led_config
->gpio_output
& ~0xc000));
646 /* enable GPIO output */
647 val
&= ~((led_config
->gpio_output_enable
>> 8) & 0xff);
648 val
|= (led_config
->gpio_output_enable
& 0xff);
650 /* disable GPIO output */
651 val
&= ~((led_config
->gpio_output_disable
>> 8) & 0xff);
652 val
|= (led_config
->gpio_output_disable
& 0xff);
654 return au8522_writereg(state
, 0x8000 |
655 (led_config
->gpio_output
& ~0xc000), val
);
659 * led = 1 | signal ok
660 * led = 2 | signal strong
661 * led < 0 | only light led if leds are currently off
663 static int au8522_led_ctrl(struct au8522_state
*state
, int led
)
665 struct au8522_led_config
*led_config
= state
->config
->led_cfg
;
668 /* bail out if we can't control an LED */
669 if (!led_config
|| !led_config
->gpio_leds
||
670 !led_config
->num_led_states
|| !led_config
->led_states
)
674 /* if LED is already lit, then leave it as-is */
675 if (state
->led_state
)
681 /* toggle LED if changing state */
682 if (state
->led_state
!= led
) {
685 dprintk("%s: %d\n", __func__
, led
);
687 au8522_led_gpio_enable(state
, 1);
689 val
= au8522_readreg(state
, 0x4000 |
690 (led_config
->gpio_leds
& ~0xc000));
692 /* start with all leds off */
693 for (i
= 0; i
< led_config
->num_led_states
; i
++)
694 val
&= ~led_config
->led_states
[i
];
696 /* set selected LED state */
697 if (led
< led_config
->num_led_states
)
698 val
|= led_config
->led_states
[led
];
699 else if (led_config
->num_led_states
)
701 led_config
->led_states
[led_config
->num_led_states
- 1];
703 ret
= au8522_writereg(state
, 0x8000 |
704 (led_config
->gpio_leds
& ~0xc000), val
);
708 state
->led_state
= led
;
711 au8522_led_gpio_enable(state
, 0);
717 int au8522_sleep(struct dvb_frontend
*fe
)
719 struct au8522_state
*state
= fe
->demodulator_priv
;
720 dprintk("%s()\n", __func__
);
722 /* Only power down if the digital side is currently using the chip */
723 if (state
->operational_mode
== AU8522_ANALOG_MODE
) {
724 /* We're not in one of the expected power modes, which means
725 that the DVB thread is probably telling us to go to sleep
726 even though the analog frontend has already started using
727 the chip. So ignore the request */
732 au8522_led_ctrl(state
, 0);
734 /* Power down the chip */
735 au8522_writereg(state
, 0xa4, 1 << 5);
737 state
->current_frequency
= 0;
742 static int au8522_read_status(struct dvb_frontend
*fe
, fe_status_t
*status
)
744 struct au8522_state
*state
= fe
->demodulator_priv
;
746 u32 tuner_status
= 0;
750 if (state
->current_modulation
== VSB_8
) {
751 dprintk("%s() Checking VSB_8\n", __func__
);
752 reg
= au8522_readreg(state
, 0x4088);
753 if ((reg
& 0x03) == 0x03)
754 *status
|= FE_HAS_LOCK
| FE_HAS_SYNC
| FE_HAS_VITERBI
;
756 dprintk("%s() Checking QAM\n", __func__
);
757 reg
= au8522_readreg(state
, 0x4541);
759 *status
|= FE_HAS_VITERBI
;
761 *status
|= FE_HAS_LOCK
| FE_HAS_SYNC
;
764 switch (state
->config
->status_mode
) {
765 case AU8522_DEMODLOCKING
:
766 dprintk("%s() DEMODLOCKING\n", __func__
);
767 if (*status
& FE_HAS_VITERBI
)
768 *status
|= FE_HAS_CARRIER
| FE_HAS_SIGNAL
;
770 case AU8522_TUNERLOCKING
:
771 /* Get the tuner status */
772 dprintk("%s() TUNERLOCKING\n", __func__
);
773 if (fe
->ops
.tuner_ops
.get_status
) {
774 if (fe
->ops
.i2c_gate_ctrl
)
775 fe
->ops
.i2c_gate_ctrl(fe
, 1);
777 fe
->ops
.tuner_ops
.get_status(fe
, &tuner_status
);
779 if (fe
->ops
.i2c_gate_ctrl
)
780 fe
->ops
.i2c_gate_ctrl(fe
, 0);
783 *status
|= FE_HAS_CARRIER
| FE_HAS_SIGNAL
;
786 state
->fe_status
= *status
;
788 if (*status
& FE_HAS_LOCK
)
789 /* turn on LED, if it isn't on already */
790 au8522_led_ctrl(state
, -1);
793 au8522_led_ctrl(state
, 0);
795 dprintk("%s() status 0x%08x\n", __func__
, *status
);
800 static int au8522_led_status(struct au8522_state
*state
, const u16
*snr
)
802 struct au8522_led_config
*led_config
= state
->config
->led_cfg
;
806 /* bail out if we can't control an LED */
810 if (0 == (state
->fe_status
& FE_HAS_LOCK
))
811 return au8522_led_ctrl(state
, 0);
812 else if (state
->current_modulation
== QAM_256
)
813 strong
= led_config
->qam256_strong
;
814 else if (state
->current_modulation
== QAM_64
)
815 strong
= led_config
->qam64_strong
;
816 else /* (state->current_modulation == VSB_8) */
817 strong
= led_config
->vsb8_strong
;
824 if ((state
->led_state
) &&
825 (((strong
< *snr
) ? (*snr
- strong
) : (strong
- *snr
)) <= 10))
826 /* snr didn't change enough to bother
827 * changing the color of the led */
830 return au8522_led_ctrl(state
, led
);
833 static int au8522_read_snr(struct dvb_frontend
*fe
, u16
*snr
)
835 struct au8522_state
*state
= fe
->demodulator_priv
;
838 dprintk("%s()\n", __func__
);
840 if (state
->current_modulation
== QAM_256
)
841 ret
= au8522_mse2snr_lookup(qam256_mse2snr_tab
,
842 ARRAY_SIZE(qam256_mse2snr_tab
),
843 au8522_readreg(state
, 0x4522),
845 else if (state
->current_modulation
== QAM_64
)
846 ret
= au8522_mse2snr_lookup(qam64_mse2snr_tab
,
847 ARRAY_SIZE(qam64_mse2snr_tab
),
848 au8522_readreg(state
, 0x4522),
851 ret
= au8522_mse2snr_lookup(vsb_mse2snr_tab
,
852 ARRAY_SIZE(vsb_mse2snr_tab
),
853 au8522_readreg(state
, 0x4311),
856 if (state
->config
->led_cfg
)
857 au8522_led_status(state
, snr
);
862 static int au8522_read_signal_strength(struct dvb_frontend
*fe
,
863 u16
*signal_strength
)
865 /* borrowed from lgdt330x.c
867 * Calculate strength from SNR up to 35dB
868 * Even though the SNR can go higher than 35dB,
869 * there is some comfort factor in having a range of
870 * strong signals that can show at 100%
874 int ret
= au8522_read_snr(fe
, &snr
);
876 *signal_strength
= 0;
879 /* The following calculation method was chosen
880 * purely for the sake of code re-use from the
881 * other demod drivers that use this method */
883 /* Convert from SNR in dB * 10 to 8.24 fixed-point */
884 tmp
= (snr
* ((1 << 24) / 10));
886 /* Convert from 8.24 fixed-point to
887 * scale the range 0 - 35*2^24 into 0 - 65535*/
888 if (tmp
>= 8960 * 0x10000)
889 *signal_strength
= 0xffff;
891 *signal_strength
= tmp
/ 8960;
897 static int au8522_read_ucblocks(struct dvb_frontend
*fe
, u32
*ucblocks
)
899 struct au8522_state
*state
= fe
->demodulator_priv
;
901 if (state
->current_modulation
== VSB_8
)
902 *ucblocks
= au8522_readreg(state
, 0x4087);
904 *ucblocks
= au8522_readreg(state
, 0x4543);
909 static int au8522_read_ber(struct dvb_frontend
*fe
, u32
*ber
)
911 return au8522_read_ucblocks(fe
, ber
);
914 static int au8522_get_frontend(struct dvb_frontend
*fe
)
916 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
917 struct au8522_state
*state
= fe
->demodulator_priv
;
919 c
->frequency
= state
->current_frequency
;
920 c
->modulation
= state
->current_modulation
;
925 static int au8522_get_tune_settings(struct dvb_frontend
*fe
,
926 struct dvb_frontend_tune_settings
*tune
)
928 tune
->min_delay_ms
= 1000;
932 static struct dvb_frontend_ops au8522_ops
;
934 int au8522_get_state(struct au8522_state
**state
, struct i2c_adapter
*i2c
,
939 mutex_lock(&au8522_list_mutex
);
940 ret
= hybrid_tuner_request_state(struct au8522_state
, (*state
),
941 hybrid_tuner_instance_list
,
942 i2c
, client_address
, "au8522");
943 mutex_unlock(&au8522_list_mutex
);
948 void au8522_release_state(struct au8522_state
*state
)
950 mutex_lock(&au8522_list_mutex
);
952 hybrid_tuner_release_state(state
);
953 mutex_unlock(&au8522_list_mutex
);
957 static void au8522_release(struct dvb_frontend
*fe
)
959 struct au8522_state
*state
= fe
->demodulator_priv
;
960 au8522_release_state(state
);
963 struct dvb_frontend
*au8522_attach(const struct au8522_config
*config
,
964 struct i2c_adapter
*i2c
)
966 struct au8522_state
*state
= NULL
;
969 /* allocate memory for the internal state */
970 instance
= au8522_get_state(&state
, i2c
, config
->demod_address
);
973 dprintk("%s state allocation failed\n", __func__
);
976 /* new demod instance */
977 dprintk("%s using new instance\n", __func__
);
980 /* existing demod instance */
981 dprintk("%s using existing instance\n", __func__
);
985 /* setup the state */
986 state
->config
= config
;
988 state
->operational_mode
= AU8522_DIGITAL_MODE
;
990 /* create dvb_frontend */
991 memcpy(&state
->frontend
.ops
, &au8522_ops
,
992 sizeof(struct dvb_frontend_ops
));
993 state
->frontend
.demodulator_priv
= state
;
995 if (au8522_init(&state
->frontend
) != 0) {
996 printk(KERN_ERR
"%s: Failed to initialize correctly\n",
1001 /* Note: Leaving the I2C gate open here. */
1002 au8522_i2c_gate_ctrl(&state
->frontend
, 1);
1004 return &state
->frontend
;
1007 au8522_release_state(state
);
1010 EXPORT_SYMBOL(au8522_attach
);
1012 static struct dvb_frontend_ops au8522_ops
= {
1013 .delsys
= { SYS_ATSC
, SYS_DVBC_ANNEX_B
},
1015 .name
= "Auvitek AU8522 QAM/8VSB Frontend",
1016 .frequency_min
= 54000000,
1017 .frequency_max
= 858000000,
1018 .frequency_stepsize
= 62500,
1019 .caps
= FE_CAN_QAM_64
| FE_CAN_QAM_256
| FE_CAN_8VSB
1022 .init
= au8522_init
,
1023 .sleep
= au8522_sleep
,
1024 .i2c_gate_ctrl
= au8522_i2c_gate_ctrl
,
1025 .set_frontend
= au8522_set_frontend
,
1026 .get_frontend
= au8522_get_frontend
,
1027 .get_tune_settings
= au8522_get_tune_settings
,
1028 .read_status
= au8522_read_status
,
1029 .read_ber
= au8522_read_ber
,
1030 .read_signal_strength
= au8522_read_signal_strength
,
1031 .read_snr
= au8522_read_snr
,
1032 .read_ucblocks
= au8522_read_ucblocks
,
1033 .release
= au8522_release
,
1036 module_param(debug
, int, 0644);
1037 MODULE_PARM_DESC(debug
, "Enable verbose debug messages");
1039 MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
1040 MODULE_AUTHOR("Steven Toth");
1041 MODULE_LICENSE("GPL");