V4L/DVB (11065): au8522: add support for analog side of demodulator
authorDevin Heitmueller <dheitmueller@linuxtv.org>
Wed, 11 Mar 2009 06:00:38 +0000 (03:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:25 +0000 (12:43 -0300)
Add support for the analog functionality in the au8522 analog/digital
demodulator

Thanks to Michael Krufky <mkrufky@linuxtv.org> and Steven Toth
<stoth@linuxtv.org> for providing sample hardware, engineering level support,
and testing.

Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
[mchehab: renamed drivers/media/video/au8522_decoder.c as drivers/media/dvb/frontends/au8522_decoder.c to avoid breaking bisect]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/au8522.h
drivers/media/dvb/frontends/au8522_decoder.c [new file with mode: 0644]
drivers/media/dvb/frontends/au8522_priv.h
include/linux/i2c-id.h

index 7428265..65a336a 100644 (file)
@@ -8,7 +8,7 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 s921-objs := s921_module.o s921_core.o
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
-au8522-objs = au8522_dig.o
+au8522-objs = au8522_dig.o au8522_decoder.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
index 7b94f55..565dcf3 100644 (file)
@@ -74,6 +74,22 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
 }
 #endif /* CONFIG_DVB_AU8522 */
 
+/* Other modes may need to be added later */
+enum au8522_video_input {
+       AU8522_COMPOSITE_CH1 = 1,
+       AU8522_COMPOSITE_CH2,
+       AU8522_COMPOSITE_CH3,
+       AU8522_COMPOSITE_CH4,
+       AU8522_COMPOSITE_CH4_SIF,
+       AU8522_SVIDEO_CH13,
+       AU8522_SVIDEO_CH24,
+};
+
+enum au8522_audio_input {
+       AU8522_AUDIO_NONE,
+       AU8522_AUDIO_SIF,
+};
+
 #endif /* __AU8522_H__ */
 
 /*
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
new file mode 100644 (file)
index 0000000..e2927c1
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
+ *
+ * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
+ * Copyright (C) 2005-2008 Auvitek International, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * As published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Developer notes:
+ *
+ * VBI support is not yet working
+ * Saturation and hue setting are not yet working
+ * Enough is implemented here for CVBS and S-Video inputs, but the actual
+ *  analog demodulator code isn't implemented (not needed for xc5000 since it
+ *  has its own demodulator and outputs CVBS)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-device.h>
+#include "au8522.h"
+#include "au8522_priv.h"
+
+MODULE_AUTHOR("Devin Heitmueller");
+MODULE_LICENSE("GPL");
+
+static int au8522_analog_debug;
+
+static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END };
+
+module_param_named(analog_debug, au8522_analog_debug, int, 0644);
+
+MODULE_PARM_DESC(analog_debug,
+                "Analog debugging messages [0=Off (default) 1=On]");
+
+I2C_CLIENT_INSMOD;
+
+struct au8522_register_config {
+       u16 reg_name;
+       u8 reg_val[8];
+};
+
+
+/* Video Decoder Filter Coefficients
+   The values are as follows from left to right
+   0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
+*/
+struct au8522_register_config filter_coef[] = {
+       {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00}},
+       {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40}},
+       {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09}},
+       {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38}},
+       {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff}},
+       {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7}},
+       {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf}},
+       {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06}},
+       {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30}},
+       {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01}},
+       {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd}},
+       {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf}},
+       {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7}},
+       {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb}},
+       {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0}},
+       {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f}},
+       {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8}},
+       {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb}},
+       {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5}},
+       {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e}},
+       {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15}},
+       {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34}},
+
+};
+#define NUM_FILTER_COEF (sizeof (filter_coef) / sizeof(struct au8522_register_config))
+
+
+/* Registers 0x060b through 0x0652 are the LP Filter coefficients
+   The values are as follows from left to right
+   0="SIF" 1="ATVRF/ATVRF13"
+   Note: the "ATVRF/ATVRF13" mode has never been tested
+*/
+struct au8522_register_config lpfilter_coef[] = {
+       {0x060b, {0x21, 0x0b}},
+       {0x060c, {0xad, 0xad}},
+       {0x060d, {0x70, 0xf0}},
+       {0x060e, {0xea, 0xe9}},
+       {0x060f, {0xdd, 0xdd}},
+       {0x0610, {0x08, 0x64}},
+       {0x0611, {0x60, 0x60}},
+       {0x0612, {0xf8, 0xb2}},
+       {0x0613, {0x01, 0x02}},
+       {0x0614, {0xe4, 0xb4}},
+       {0x0615, {0x19, 0x02}},
+       {0x0616, {0xae, 0x2e}},
+       {0x0617, {0xee, 0xc5}},
+       {0x0618, {0x56, 0x56}},
+       {0x0619, {0x30, 0x58}},
+       {0x061a, {0xf9, 0xf8}},
+       {0x061b, {0x24, 0x64}},
+       {0x061c, {0x07, 0x07}},
+       {0x061d, {0x30, 0x30}},
+       {0x061e, {0xa9, 0xed}},
+       {0x061f, {0x09, 0x0b}},
+       {0x0620, {0x42, 0xc2}},
+       {0x0621, {0x1d, 0x2a}},
+       {0x0622, {0xd6, 0x56}},
+       {0x0623, {0x95, 0x8b}},
+       {0x0624, {0x2b, 0x2b}},
+       {0x0625, {0x30, 0x24}},
+       {0x0626, {0x3e, 0x3e}},
+       {0x0627, {0x62, 0xe2}},
+       {0x0628, {0xe9, 0xf5}},
+       {0x0629, {0x99, 0x19}},
+       {0x062a, {0xd4, 0x11}},
+       {0x062b, {0x03, 0x04}},
+       {0x062c, {0xb5, 0x85}},
+       {0x062d, {0x1e, 0x20}},
+       {0x062e, {0x2a, 0xea}},
+       {0x062f, {0xd7, 0xd2}},
+       {0x0630, {0x15, 0x15}},
+       {0x0631, {0xa3, 0xa9}},
+       {0x0632, {0x1f, 0x1f}},
+       {0x0633, {0xf9, 0xd1}},
+       {0x0634, {0xc0, 0xc3}},
+       {0x0635, {0x4d, 0x8d}},
+       {0x0636, {0x21, 0x31}},
+       {0x0637, {0x83, 0x83}},
+       {0x0638, {0x08, 0x8c}},
+       {0x0639, {0x19, 0x19}},
+       {0x063a, {0x45, 0xa5}},
+       {0x063b, {0xef, 0xec}},
+       {0x063c, {0x8a, 0x8a}},
+       {0x063d, {0xf4, 0xf6}},
+       {0x063e, {0x8f, 0x8f}},
+       {0x063f, {0x44, 0x0c}},
+       {0x0640, {0xef, 0xf0}},
+       {0x0641, {0x66, 0x66}},
+       {0x0642, {0xcc, 0xd2}},
+       {0x0643, {0x41, 0x41}},
+       {0x0644, {0x63, 0x93}},
+       {0x0645, {0x8e, 0x8e}},
+       {0x0646, {0xa2, 0x42}},
+       {0x0647, {0x7b, 0x7b}},
+       {0x0648, {0x04, 0x04}},
+       {0x0649, {0x00, 0x00}},
+       {0x064a, {0x40, 0x40}},
+       {0x064b, {0x8c, 0x98}},
+       {0x064c, {0x00, 0x00}},
+       {0x064d, {0x63, 0xc3}},
+       {0x064e, {0x04, 0x04}},
+       {0x064f, {0x20, 0x20}},
+       {0x0650, {0x00, 0x00}},
+       {0x0651, {0x40 ,0x40}},
+       {0x0652, {0x01, 0x01}},
+};
+#define NUM_LPFILTER_COEF (sizeof (lpfilter_coef) / sizeof(struct au8522_register_config))
+
+static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct au8522_state, sd);
+}
+
+static void setup_vbi(struct au8522_state *state, int aud_input)
+{
+       int i;
+
+       /* These are set to zero regardless of what mode we're in */
+       au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,0x00);
+       au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,0x00);
+
+       /* Setup the VBI registers */
+       for (i = 0x30; i < 0x60; i++) {
+               au8522_writereg(state, i, 0x40);
+       }
+       /* For some reason, every register is 0x40 except register 0x44
+          (confirmed via the HVR-950q USB capture) */
+       au8522_writereg(state, 0x44, 0x60);
+
+       /* Enable VBI (we always do this regardless of whether the user is
+          viewing closed caption info) */
+       au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
+                       AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
+
+}
+
+static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
+{
+       int i;
+       int filter_coef_type;
+
+       /* Provide reasonable defaults for picture tuning values */
+       au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
+       au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
+       state->brightness = 0xed - 128;
+       au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
+       state->contrast = 0x79;
+       au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
+       au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
+       au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
+       au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
+
+       /* Other decoder registers */
+       au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
+
+       if (input_mode == 0x23) {
+               /* S-Video input mapping */
+               au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
+       } else {
+               /* All other modes (CVBS/ATVRF etc.) */
+               au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
+       }
+
+       au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
+                       AU8522_TVDEC_PGA_REG012H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
+                       AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
+       au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
+                       AU8522_TVDED_DBG_MODE_REG060H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+                       AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
+       au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+                       AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
+       au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
+                       AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
+                       AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
+                       AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
+                       AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
+                       AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
+                       AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
+                       AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
+                       AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
+                       AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
+                       AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
+                       AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
+                       AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
+                       AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
+                       AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
+       au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
+       au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
+                       AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
+       au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
+       au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
+                       AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
+                       AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
+                       AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
+                       AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
+                       AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
+       au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
+                       AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
+       au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
+                       AU8522_TOREGAAGC_REG0E5H_CVBS);
+       au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
+
+       setup_vbi(state, 0);
+
+       if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
+           input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+               /* Despite what the table says, for the HVR-950q we still need
+                  to be in CVBS mode for the S-Video input (reason uknown). */
+               /* filter_coef_type = 3; */
+               filter_coef_type = 5;
+       } else {
+               filter_coef_type = 5;
+       }
+
+       /* Load the Video Decoder Filter Coefficients */
+       for (i = 0; i < NUM_FILTER_COEF; i++) {
+               au8522_writereg(state, filter_coef[i].reg_name,
+                               filter_coef[i].reg_val[filter_coef_type]);
+       }
+
+       /* It's not clear what these registers are for, but they are always
+          set to the same value regardless of what mode we're in */
+       au8522_writereg(state, AU8522_REG42EH, 0x87);
+       au8522_writereg(state, AU8522_REG42FH, 0xa2);
+       au8522_writereg(state, AU8522_REG430H, 0xbf);
+       au8522_writereg(state, AU8522_REG431H, 0xcb);
+       au8522_writereg(state, AU8522_REG432H, 0xa1);
+       au8522_writereg(state, AU8522_REG433H, 0x41);
+       au8522_writereg(state, AU8522_REG434H, 0x88);
+       au8522_writereg(state, AU8522_REG435H, 0xc2);
+       au8522_writereg(state, AU8522_REG436H, 0x3c);
+}
+
+static void au8522_setup_cvbs_mode(struct au8522_state *state)
+{
+       /* here we're going to try the pre-programmed route */
+       au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+                       AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
+
+       au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+       au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
+       au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
+
+       au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+                       AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+
+       setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                       AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
+{
+       /* here we're going to try the pre-programmed route */
+       au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+                       AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
+
+       /* It's not clear why they turn off the PGA before enabling the clamp
+          control, but the Windows trace does it so we will too... */
+       au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+       /* Enable clamping control */
+       au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
+
+       /* Turn on the PGA */
+       au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
+
+       /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
+       au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+                       AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+
+       setup_decoder_defaults(state,
+                              AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                       AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+static void au8522_setup_svideo_mode(struct au8522_state *state)
+{
+       au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+                       AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
+
+       /* Set input to Y on Channe1, C on Channel 3 */
+       au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+                       AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+
+       /* Disable clamping control (required for S-video) */
+       au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
+
+       setup_decoder_defaults(state,
+                              AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                       AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void disable_audio_input(struct au8522_state *state)
+{
+       /* This can probably be optimized */
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
+       au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
+       au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
+
+       au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+       au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
+       au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
+
+       au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
+       msleep(5);
+       au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
+
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
+       au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
+       au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
+
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                       AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+/* 0=disable, 1=SIF */
+static void set_audio_input(struct au8522_state *state, int aud_input)
+{
+       int i;
+
+       /* Note that this function needs to be used in conjunction with setting
+          the input routing via register 0x81 */
+
+       if (aud_input == AU8522_AUDIO_NONE) {
+               disable_audio_input(state);
+               return;
+       }
+
+       if (aud_input != AU8522_AUDIO_SIF) {
+               /* The caller asked for a mode we don't currently support */
+               printk("Unsupported audio mode requested! mode=%d\n",
+                      aud_input);
+               return;
+       }
+
+       /* Load the Audio Decoder Filter Coefficients */
+       for (i = 0; i < NUM_LPFILTER_COEF; i++) {
+               au8522_writereg(state, lpfilter_coef[i].reg_name,
+                               lpfilter_coef[i].reg_val[0]);
+       }
+
+       /* Setup audio */
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
+       au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
+       au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
+       msleep(150);
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
+       msleep(1);
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
+       msleep(50);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
+       msleep(80);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+       au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+       au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
+       au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
+       msleep(70);
+       au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
+       au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
+       au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct au8522_state *state = to_state(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               state->brightness = ctrl->value;
+               au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
+                               ctrl->value - 128);
+               break;
+       case V4L2_CID_CONTRAST:
+               state->contrast = ctrl->value;
+               au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
+                               ctrl->value);
+               break;
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_HUE:
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_MUTE:
+               /* Not yet implemented */
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct au8522_state *state = to_state(sd);
+
+       /* Note that we are using values cached in the state structure instead
+          of reading the registers due to issues with i2c reads not working
+          properly/consistently yet on the HVR-950q */
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = state->brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = state->contrast;
+               break;
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_HUE:
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_MUTE:
+               /* Not yet supported */
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       switch (fmt->type) {
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       switch (fmt->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               /* Not yet implemented */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int au8522_g_register(struct v4l2_subdev *sd,
+                            struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct au8522_state *state = to_state(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       reg->val = au8522_readreg(state, reg->reg & 0xffff);
+       return 0;
+}
+
+static int au8522_s_register(struct v4l2_subdev *sd,
+                            struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct au8522_state *state = to_state(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       au8522_writereg(state, reg->reg, reg->val & 0xff);
+       return 0;
+}
+#endif
+
+static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct au8522_state *state = to_state(sd);
+
+       if (enable) {
+               au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                               0x01);
+               msleep(1);
+               au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                               AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+       } else {
+               /* This does not completely power down the device
+                  (it only reduces it from around 140ma to 80ma) */
+               au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+                               1 << 5);
+       }
+       return 0;
+}
+
+static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+       switch (qc->id) {
+       case V4L2_CID_CONTRAST:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1,
+                                           AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_HUE:
+               /* Not yet implemented */
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+{
+       struct au8522_state *state = to_state(sd);
+
+       au8522_writereg(state, 0xa4, 1 << 5);
+
+       return 0;
+}
+
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+                                 const struct v4l2_routing *route)
+{
+       struct au8522_state *state = to_state(sd);
+
+       au8522_reset(sd, 0);
+
+       /* Jam open the i2c gate to the tuner.  We do this here to handle the
+          case where the user went into digital mode (causing the gate to be
+          closed), and then came back to analog mode */
+       au8522_writereg(state, 0x106, 1);
+
+       if (route->input == AU8522_COMPOSITE_CH1) {
+               au8522_setup_cvbs_mode(state);
+       } else if (route->input == AU8522_SVIDEO_CH13) {
+               au8522_setup_svideo_mode(state);
+       } else if (route->input == AU8522_COMPOSITE_CH4_SIF) {
+               au8522_setup_cvbs_tuner_mode(state);
+       } else {
+               printk("au8522 mode not currently supported\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int au8522_s_audio_routing(struct v4l2_subdev *sd,
+                                 const struct v4l2_routing *route)
+{
+       struct au8522_state *state = to_state(sd);
+       set_audio_input(state, route->input);
+       return 0;
+}
+
+static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       int val = 0;
+       struct au8522_state *state = to_state(sd);
+       u8 lock_status;
+
+       /* Interrogate the decoder to see if we are getting a real signal */
+       lock_status = au8522_readreg(state, 0x00);
+       if (lock_status == 0xa2)
+               vt->signal = 0x01;
+       else
+               vt->signal = 0x00;
+
+       vt->capability |=
+               V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+               V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+       val = V4L2_TUNER_SUB_MONO;
+       vt->rxsubchans = val;
+       vt->audmode = V4L2_TUNER_MODE_STEREO;
+       return 0;
+}
+
+static int au8522_g_chip_ident(struct v4l2_subdev *sd,
+                              struct v4l2_dbg_chip_ident *chip)
+{
+       struct au8522_state *state = to_state(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
+}
+
+static int au8522_log_status(struct v4l2_subdev *sd)
+{
+       /* FIXME: Add some status info here */
+       return 0;
+}
+
+static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+       return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops au8522_core_ops = {
+       .log_status = au8522_log_status,
+       .g_chip_ident = au8522_g_chip_ident,
+       .g_ctrl = au8522_g_ctrl,
+       .s_ctrl = au8522_s_ctrl,
+       .queryctrl = au8522_queryctrl,
+       .reset = au8522_reset,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = au8522_g_register,
+       .s_register = au8522_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
+       .g_tuner = au8522_g_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
+       .s_routing = au8522_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops au8522_video_ops = {
+       .s_routing = au8522_s_video_routing,
+       .g_fmt = au8522_g_fmt,
+       .s_fmt = au8522_s_fmt,
+       .s_stream = au8522_s_stream,
+};
+
+static const struct v4l2_subdev_ops au8522_ops = {
+       .core = &au8522_core_ops,
+       .tuner = &au8522_tuner_ops,
+       .audio = &au8522_audio_ops,
+       .video = &au8522_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_probe(struct i2c_client *client,
+                       const struct i2c_device_id *did)
+{
+       struct au8522_state *state;
+       struct v4l2_subdev *sd;
+       int instance;
+       struct au8522_config *demod_config;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
+               return -EIO;
+       }
+
+       /* allocate memory for the internal state */
+       instance = au8522_get_state(&state, client->adapter, client->addr);
+       switch (instance) {
+       case 0:
+               printk("au8522_decoder allocation failed\n");
+               return -EIO;
+       case 1:
+               /* new demod instance */
+               printk("au8522_decoder creating new instance...\n");
+               break;
+       default:
+               /* existing demod instance */
+               printk("au8522_decoder attaching to existing instance...\n");
+               break;
+       }
+
+       demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
+       demod_config->demod_address = 0x8e >> 1;
+
+       state->config = demod_config;
+       state->i2c = client->adapter;
+
+       sd = &state->sd;
+       v4l2_i2c_subdev_init(sd, client, &au8522_ops);
+
+       state->c = client;
+       state->vid_input = AU8522_COMPOSITE_CH1;
+       state->aud_input = AU8522_AUDIO_NONE;
+       state->id = 8522;
+       state->rev = 0;
+
+       /* Jam open the i2c gate to the tuner */
+       au8522_writereg(state, 0x106, 1);
+
+       return 0;
+}
+
+static int au8522_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       v4l2_device_unregister_subdev(sd);
+       au8522_release_state(to_state(sd));
+       return 0;
+}
+
+static const struct i2c_device_id au8522_id[] = {
+       {"au8522", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, au8522_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "au8522",
+       .driverid = I2C_DRIVERID_AU8522,
+       .command = au8522_command,
+       .probe = au8522_probe,
+       .remove = au8522_remove,
+       .id_table = au8522_id,
+};
index 98b09ca..f328f2b 100644 (file)
@@ -35,6 +35,7 @@
 #include "tuner-i2c.h"
 
 struct au8522_state {
+       struct i2c_client *c;
        struct i2c_adapter *i2c;
 
        /* Used for sharing of the state between analog and digital mode */
@@ -51,6 +52,16 @@ struct au8522_state {
 
        u32 fe_status;
        unsigned int led_state;
+
+       /* Analog settings */
+       struct v4l2_subdev sd;
+       v4l2_std_id std;
+       int vid_input;
+       int aud_input;
+       u32 id;
+       u32 rev;
+       u8 brightness;
+       u8 contrast;
 };
 
 /* These are routines shared by both the VSB/QAM demodulator and the analog
@@ -63,3 +74,339 @@ int au8522_sleep(struct dvb_frontend *fe);
 int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
                     u8 client_address);
 void au8522_release_state(struct au8522_state *state);
+
+/* REGISTERS */
+#define AU8522_INPUT_CONTROL_REG081H                   0x081
+#define AU8522_PGA_CONTROL_REG082H                     0x082
+#define AU8522_CLAMPING_CONTROL_REG083H                        0x083
+
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H            0x0A3
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H         0x0A4
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H         0x0A5
+#define AU8522_AGC_CONTROL_RANGE_REG0A6H               0x0A6
+#define AU8522_SYSTEM_GAIN_CONTROL_REG0A7H             0x0A7
+#define AU8522_TUNER_AGC_RF_STOP_REG0A8H               0x0A8
+#define AU8522_TUNER_AGC_RF_START_REG0A9H              0x0A9
+#define AU8522_TUNER_RF_AGC_DEFAULT_REG0AAH            0x0AA
+#define AU8522_TUNER_AGC_IF_STOP_REG0ABH               0x0AB
+#define AU8522_TUNER_AGC_IF_START_REG0ACH              0x0AC
+#define AU8522_TUNER_AGC_IF_DEFAULT_REG0ADH            0x0AD
+#define AU8522_TUNER_AGC_STEP_REG0AEH                  0x0AE
+#define AU8522_TUNER_GAIN_STEP_REG0AFH                 0x0AF
+
+/* Receiver registers */
+#define AU8522_FRMREGTHRD1_REG0B0H                     0x0B0
+#define AU8522_FRMREGAGC1H_REG0B1H                     0x0B1
+#define AU8522_FRMREGSHIFT1_REG0B2H                    0x0B2
+#define AU8522_TOREGAGC1_REG0B3H                       0x0B3
+#define AU8522_TOREGASHIFT1_REG0B4H                    0x0B4
+#define AU8522_FRMREGBBH_REG0B5H                       0x0B5
+#define AU8522_FRMREGBBM_REG0B6H                       0x0B6
+#define AU8522_FRMREGBBL_REG0B7H                       0x0B7
+/* 0xB8 TO 0xD7 are the filter coefficients */
+#define AU8522_FRMREGTHRD2_REG0D8H                     0x0D8
+#define AU8522_FRMREGAGC2H_REG0D9H                     0x0D9
+#define AU8522_TOREGAGC2_REG0DAH                       0x0DA
+#define AU8522_TOREGSHIFT2_REG0DBH                     0x0DB
+#define AU8522_FRMREGPILOTH_REG0DCH                    0x0DC
+#define AU8522_FRMREGPILOTM_REG0DDH                    0x0DD
+#define AU8522_FRMREGPILOTL_REG0DEH                    0x0DE
+#define AU8522_TOREGFREQ_REG0DFH                       0x0DF
+
+#define AU8522_RX_PGA_RFOUT_REG0EBH                    0x0EB
+#define AU8522_RX_PGA_IFOUT_REG0ECH                    0x0EC
+#define AU8522_RX_PGA_PGAOUT_REG0EDH                   0x0ED
+
+#define AU8522_CHIP_MODE_REG0FEH                       0x0FE
+
+/* I2C bus control registers */
+#define AU8522_I2C_CONTROL_REG0_REG090H                0x090
+#define AU8522_I2C_CONTROL_REG1_REG091H                0x091
+#define AU8522_I2C_STATUS_REG092H                      0x092
+#define AU8522_I2C_WR_DATA0_REG093H                    0x093
+#define AU8522_I2C_WR_DATA1_REG094H                    0x094
+#define AU8522_I2C_WR_DATA2_REG095H                    0x095
+#define AU8522_I2C_WR_DATA3_REG096H                    0x096
+#define AU8522_I2C_WR_DATA4_REG097H                    0x097
+#define AU8522_I2C_WR_DATA5_REG098H                    0x098
+#define AU8522_I2C_WR_DATA6_REG099H                    0x099
+#define AU8522_I2C_WR_DATA7_REG09AH                    0x09A
+#define AU8522_I2C_RD_DATA0_REG09BH                    0x09B
+#define AU8522_I2C_RD_DATA1_REG09CH                    0x09C
+#define AU8522_I2C_RD_DATA2_REG09DH                    0x09D
+#define AU8522_I2C_RD_DATA3_REG09EH                    0x09E
+#define AU8522_I2C_RD_DATA4_REG09FH                    0x09F
+#define AU8522_I2C_RD_DATA5_REG0A0H                    0x0A0
+#define AU8522_I2C_RD_DATA6_REG0A1H                    0x0A1
+#define AU8522_I2C_RD_DATA7_REG0A2H                    0x0A2
+
+#define AU8522_ENA_USB_REG101H                         0x101
+
+#define AU8522_I2S_CTRL_0_REG110H                      0x110
+#define AU8522_I2S_CTRL_1_REG111H                      0x111
+#define AU8522_I2S_CTRL_2_REG112H                      0x112
+
+#define AU8522_FRMREGFFECONTROL_REG121H                0x121
+#define AU8522_FRMREGDFECONTROL_REG122H                0x122
+
+#define AU8522_CARRFREQOFFSET0_REG201H                         0x201
+#define AU8522_CARRFREQOFFSET1_REG202H                 0x202
+
+#define AU8522_DECIMATION_GAIN_REG21AH                 0x21A
+#define AU8522_FRMREGIFSLP_REG21BH                     0x21B
+#define AU8522_FRMREGTHRDL2_REG21CH                    0x21C
+#define AU8522_FRMREGSTEP3DB_REG21DH                   0x21D
+#define AU8522_DAGC_GAIN_ADJUSTMENT_REG21EH            0x21E
+#define AU8522_FRMREGPLLMODE_REG21FH                   0x21F
+#define AU8522_FRMREGCSTHRD_REG220H                    0x220
+#define AU8522_FRMREGCRLOCKDMAX_REG221H                0x221
+#define AU8522_FRMREGCRPERIODMASK_REG222H              0x222
+#define AU8522_FRMREGCRLOCK0THH_REG223H                0x223
+#define AU8522_FRMREGCRLOCK1THH_REG224H                0x224
+#define AU8522_FRMREGCRLOCK0THL_REG225H                0x225
+#define AU8522_FRMREGCRLOCK1THL_REG226H                0x226
+#define AU_FRMREGPLLACQPHASESCL_REG227H                        0x227
+#define AU8522_FRMREGFREQFBCTRL_REG228H                0x228
+
+/* Analog TV Decoder */
+#define AU8522_TVDEC_STATUS_REG000H                    0x000
+#define AU8522_TVDEC_INT_STATUS_REG001H                        0x001
+#define AU8522_TVDEC_MACROVISION_STATUS_REG002H        0x002
+#define AU8522_TVDEC_SHARPNESSREG009H                  0x009
+#define AU8522_TVDEC_BRIGHTNESS_REG00AH                        0x00A
+#define AU8522_TVDEC_CONTRAST_REG00BH                  0x00B
+#define AU8522_TVDEC_SATURATION_CB_REG00CH             0x00C
+#define AU8522_TVDEC_SATURATION_CR_REG00DH             0x00D
+#define AU8522_TVDEC_HUE_H_REG00EH                     0x00E
+#define AU8522_TVDEC_HUE_L_REG00FH                     0x00F
+#define AU8522_TVDEC_INT_MASK_REG010H                  0x010
+#define AU8522_VIDEO_MODE_REG011H                      0x011
+#define AU8522_TVDEC_PGA_REG012H                       0x012
+#define AU8522_TVDEC_COMB_MODE_REG015H                 0x015
+#define AU8522_REG016H                                 0x016
+#define AU8522_TVDED_DBG_MODE_REG060H                  0x060
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H              0x061
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H              0x062
+#define AU8522_TVDEC_VCR_DET_LLIM_REG063H              0x063
+#define AU8522_TVDEC_VCR_DET_HLIM_REG064H              0x064
+#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H            0x065
+#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H            0x066
+#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H            0x067
+#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H            0x068
+#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H            0x069
+#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH            0x06A
+#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH            0x06B
+#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH           0x06C
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH           0x06D
+#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH           0x06E
+#define AU8522_TVDEC_UV_SEP_THR_REG06FH                0x06F
+#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H         0x070
+#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H         0x073
+#define AU8522_TVDEC_DCAGC_CTRL_REG077H                        0x077
+#define AU8522_TVDEC_PIC_START_ADJ_REG078H             0x078
+#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H            0x079
+#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH      0x07A
+#define AU8522_TVDEC_INTRP_CTRL_REG07BH                        0x07B
+#define AU8522_TVDEC_PLL_STATUS_REG07EH                        0x07E
+#define AU8522_TVDEC_FSC_FREQ_REG07FH                  0x07F
+
+#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H             0x0E4
+#define AU8522_TOREGAAGC_REG0E5H                       0x0E5
+
+#define AU8522_TVDEC_CHROMA_AGC_REG401H                0x401
+#define AU8522_TVDEC_CHROMA_SFT_REG402H                0x402
+#define AU8522_FILTER_COEF_R410                0x410
+#define AU8522_FILTER_COEF_R411                0x411
+#define AU8522_FILTER_COEF_R412                0x412
+#define AU8522_FILTER_COEF_R413                0x413
+#define AU8522_FILTER_COEF_R414                0x414
+#define AU8522_FILTER_COEF_R415                0x415
+#define AU8522_FILTER_COEF_R416                0x416
+#define AU8522_FILTER_COEF_R417                0x417
+#define AU8522_FILTER_COEF_R418                0x418
+#define AU8522_FILTER_COEF_R419                0x419
+#define AU8522_FILTER_COEF_R41A                0x41A
+#define AU8522_FILTER_COEF_R41B                0x41B
+#define AU8522_FILTER_COEF_R41C                0x41C
+#define AU8522_FILTER_COEF_R41D                0x41D
+#define AU8522_FILTER_COEF_R41E                0x41E
+#define AU8522_FILTER_COEF_R41F                0x41F
+#define AU8522_FILTER_COEF_R420                0x420
+#define AU8522_FILTER_COEF_R421                0x421
+#define AU8522_FILTER_COEF_R422                0x422
+#define AU8522_FILTER_COEF_R423                0x423
+#define AU8522_FILTER_COEF_R424                0x424
+#define AU8522_FILTER_COEF_R425                0x425
+#define AU8522_FILTER_COEF_R426                0x426
+#define AU8522_FILTER_COEF_R427                0x427
+#define AU8522_FILTER_COEF_R428                0x428
+#define AU8522_FILTER_COEF_R429                0x429
+#define AU8522_FILTER_COEF_R42A                0x42A
+#define AU8522_FILTER_COEF_R42B                0x42B
+#define AU8522_FILTER_COEF_R42C                0x42C
+#define AU8522_FILTER_COEF_R42D                0x42D
+
+/* VBI Control Registers */
+#define AU8522_TVDEC_VBI_RX_FIFO_CONTAIN_REG004H       0x004
+#define AU8522_TVDEC_VBI_TX_FIFO_CONTAIN_REG005H       0x005
+#define AU8522_TVDEC_VBI_RX_FIFO_READ_REG006H          0x006
+#define AU8522_TVDEC_VBI_FIFO_STATUS_REG007H           0x007
+#define AU8522_TVDEC_VBI_CTRL_H_REG017H                        0x017
+#define AU8522_TVDEC_VBI_CTRL_L_REG018H                        0x018
+#define AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H       0x019
+#define AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH          0x01A
+#define AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH          0x01B
+#define AU8522_TVDEC_VBI_USER_THRESH1_REG01CH          0x01C
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH       0x01E
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH       0x01F
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H       0x020
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H      0x021
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H      0x022
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H      0x023
+
+#define AU8522_REG071H                                 0x071
+#define AU8522_REG072H                                 0x072
+#define AU8522_REG074H                                 0x074
+#define AU8522_REG075H                                 0x075
+
+/* Digital Demodulator Registers */
+#define AU8522_FRAME_COUNT0_REG084H                    0x084
+#define AU8522_RS_STATUS_G0_REG085H                    0x085
+#define AU8522_RS_STATUS_B0_REG086H                    0x086
+#define AU8522_RS_STATUS_E_REG087H                     0x087
+#define AU8522_DEMODULATION_STATUS_REG088H             0x088
+#define AU8522_TOREGTRESTATUS_REG0E6H                  0x0E6
+#define AU8522_TSPORT_CONTROL_REG10BH                  0x10B
+#define AU8522_TSTHES_REG10CH                          0x10C
+#define AU8522_FRMREGDFEKEEP_REG301H                   0x301
+#define AU8522_DFE_AVERAGE_REG302H                     0x302
+#define AU8522_FRMREGEQLERRWIN_REG303H                 0x303
+#define AU8522_FRMREGFFEKEEP_REG304H                   0x304
+#define AU8522_FRMREGDFECONTROL1_REG305H               0x305
+#define AU8522_FRMREGEQLERRLOW_REG306H                 0x306
+
+#define AU8522_REG42EH                         0x42E
+#define AU8522_REG42FH                         0x42F
+#define AU8522_REG430H                         0x430
+#define AU8522_REG431H                         0x431
+#define AU8522_REG432H                         0x432
+#define AU8522_REG433H                         0x433
+#define AU8522_REG434H                         0x434
+#define AU8522_REG435H                         0x435
+#define AU8522_REG436H                         0x436
+
+/* GPIO Registers */
+#define AU8522_GPIO_CONTROL_REG0E0H                    0x0E0
+#define AU8522_GPIO_STATUS_REG0E1H                     0x0E1
+#define AU8522_GPIO_DATA_REG0E2H                       0x0E2
+
+/* Audio Control Registers */
+#define AU8522_AUDIOAGC_REG0EEH                        0x0EE
+#define AU8522_AUDIO_STATUS_REG0F0H                    0x0F0
+#define AU8522_AUDIO_MODE_REG0F1H                      0x0F1
+#define AU8522_AUDIO_VOLUME_L_REG0F2H                  0x0F2
+#define AU8522_AUDIO_VOLUME_R_REG0F3H                  0x0F3
+#define AU8522_AUDIO_VOLUME_REG0F4H                    0x0F4
+#define AU8522_FRMREGAUPHASE_REG0F7H                   0x0F7
+#define AU8522_REG0F9H                                 0x0F9
+
+#define AU8522_AUDIOAGC2_REG605H                       0x605
+#define AU8522_AUDIOFREQ_REG606H                       0x606
+
+
+/**************************************************************/
+
+#define AU8522_INPUT_CONTROL_REG081H_ATSC                      0xC4
+#define AU8522_INPUT_CONTROL_REG081H_ATVRF                     0xC4
+#define AU8522_INPUT_CONTROL_REG081H_ATVRF13                   0xC4
+#define AU8522_INPUT_CONTROL_REG081H_J83B64                    0xC4
+#define AU8522_INPUT_CONTROL_REG081H_J83B256                   0xC4
+#define AU8522_INPUT_CONTROL_REG081H_CVBS                      0x20
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH1                  0xA2
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH2                  0xA0
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH3                  0x69
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4                  0x68
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF              0x28
+/* CH1 AS Y,CH3 AS C */
+#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13               0x23
+/* CH2 AS Y,CH4 AS C */
+#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24               0x20
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATSC               0x0C
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B64             0x09
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B256                    0x09
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS               0x12
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF              0x1A
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF13            0x1A
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO             0x02
+
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CLEAR           0x00
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO          0x9C
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS            0x9D
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATSC            0xE8
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B256                 0xCA
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B64                  0xCA
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF                   0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF13         0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_PAL             0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_FM              0xDD
+
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATSC            0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B256                 0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B64                  0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_ATSC     0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B256  0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B64   0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_CLEAR    0x00
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF           0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF13         0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_SVIDEO                  0x04
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_CVBS            0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PWM                     0x03
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_IIS             0x09
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PAL             0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_FM              0x01
+
+/* STILL NEED TO BE REFACTORED @@@@@@@@@@@@@@ */
+#define AU8522_TVDEC_CONTRAST_REG00BH_CVBS                     0x79
+#define AU8522_TVDEC_SATURATION_CB_REG00CH_CVBS                        0x80
+#define AU8522_TVDEC_SATURATION_CR_REG00DH_CVBS                        0x80
+#define AU8522_TVDEC_HUE_H_REG00EH_CVBS                                0x00
+#define AU8522_TVDEC_HUE_L_REG00FH_CVBS                                0x00
+#define AU8522_TVDEC_PGA_REG012H_CVBS                          0x0F
+#define AU8522_TVDEC_COMB_MODE_REG015H_CVBS                    0x00
+#define AU8522_REG016H_CVBS                                    0x00
+#define AU8522_TVDED_DBG_MODE_REG060H_CVBS                     0x00
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS                 0x0B
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13               0x03
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13               0x00
+#define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS                 0x19
+#define AU8522_REG0F9H_AUDIO                                   0x20
+#define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS                 0xA7
+#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS               0x0A
+#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS               0x32
+#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS               0x19
+#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS               0x23
+#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS               0x41
+#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS               0x0A
+#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS               0x32
+#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS              0x34
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS              0x05
+#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS              0x6E
+#define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS                   0x0F
+#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS            0x80
+#define AU8522_REG071H_CVBS                                    0x18
+#define AU8522_REG072H_CVBS                                    0x30
+#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS            0xF0
+#define AU8522_REG074H_CVBS                                    0x80
+#define AU8522_REG075H_CVBS                                    0xF0
+#define AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS                   0xFB
+#define AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS                        0x04
+#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS               0x00
+#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS         0x00
+#define AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS                   0xEE
+#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS                        0xFE
+#define AU8522_TOREGAAGC_REG0E5H_CVBS                          0x00
+#define AU8522_TVDEC_VBI6A_REG035H_CVBS                                0x40
+
+/* Enables Closed captioning */
+#define AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON                   0x21
index 1ffc23b..17d9af0 100644 (file)
@@ -71,6 +71,7 @@
 #define I2C_DRIVERID_VP27SMPX  93      /* Panasonic VP27s tuner internal MPX */
 #define I2C_DRIVERID_M52790    95      /* Mitsubishi M52790SP/FP AV switch */
 #define I2C_DRIVERID_CS5345    96      /* cs5345 audio processor       */
+#define I2C_DRIVERID_AU8522    97      /* Auvitek au8522       */
 
 #define I2C_DRIVERID_OV7670 1048       /* Omnivision 7670 camera */