Linux 2.6.34-rc3
[pohmelfs.git] / drivers / media / dvb / frontends / au8522_decoder.c
blob24268ef2753d7b33ed1069d7bfa9d81bf8d59cc7
1 /*
2 * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
4 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
5 * Copyright (C) 2005-2008 Auvitek International, Ltd.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * As published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
23 /* Developer notes:
25 * VBI support is not yet working
26 * Enough is implemented here for CVBS and S-Video inputs, but the actual
27 * analog demodulator code isn't implemented (not needed for xc5000 since it
28 * has its own demodulator and outputs CVBS)
32 #include <linux/kernel.h>
33 #include <linux/slab.h>
34 #include <linux/videodev2.h>
35 #include <linux/i2c.h>
36 #include <linux/delay.h>
37 #include <media/v4l2-common.h>
38 #include <media/v4l2-chip-ident.h>
39 #include <media/v4l2-i2c-drv.h>
40 #include <media/v4l2-device.h>
41 #include "au8522.h"
42 #include "au8522_priv.h"
44 MODULE_AUTHOR("Devin Heitmueller");
45 MODULE_LICENSE("GPL");
47 static int au8522_analog_debug;
50 module_param_named(analog_debug, au8522_analog_debug, int, 0644);
52 MODULE_PARM_DESC(analog_debug,
53 "Analog debugging messages [0=Off (default) 1=On]");
55 struct au8522_register_config {
56 u16 reg_name;
57 u8 reg_val[8];
61 /* Video Decoder Filter Coefficients
62 The values are as follows from left to right
63 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
65 static const struct au8522_register_config filter_coef[] = {
66 {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
67 {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
68 {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
69 {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
70 {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
71 {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
72 {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
73 {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
74 {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
75 {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
76 {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
77 {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
78 {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
79 {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
80 {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
81 {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
82 {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
83 {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
84 {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
85 {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
86 {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
87 {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
88 {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
89 {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
90 {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
91 {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
92 {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
93 {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
94 {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
95 {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
98 #define NUM_FILTER_COEF (sizeof(filter_coef)\
99 / sizeof(struct au8522_register_config))
102 /* Registers 0x060b through 0x0652 are the LP Filter coefficients
103 The values are as follows from left to right
104 0="SIF" 1="ATVRF/ATVRF13"
105 Note: the "ATVRF/ATVRF13" mode has never been tested
107 static const struct au8522_register_config lpfilter_coef[] = {
108 {0x060b, {0x21, 0x0b} },
109 {0x060c, {0xad, 0xad} },
110 {0x060d, {0x70, 0xf0} },
111 {0x060e, {0xea, 0xe9} },
112 {0x060f, {0xdd, 0xdd} },
113 {0x0610, {0x08, 0x64} },
114 {0x0611, {0x60, 0x60} },
115 {0x0612, {0xf8, 0xb2} },
116 {0x0613, {0x01, 0x02} },
117 {0x0614, {0xe4, 0xb4} },
118 {0x0615, {0x19, 0x02} },
119 {0x0616, {0xae, 0x2e} },
120 {0x0617, {0xee, 0xc5} },
121 {0x0618, {0x56, 0x56} },
122 {0x0619, {0x30, 0x58} },
123 {0x061a, {0xf9, 0xf8} },
124 {0x061b, {0x24, 0x64} },
125 {0x061c, {0x07, 0x07} },
126 {0x061d, {0x30, 0x30} },
127 {0x061e, {0xa9, 0xed} },
128 {0x061f, {0x09, 0x0b} },
129 {0x0620, {0x42, 0xc2} },
130 {0x0621, {0x1d, 0x2a} },
131 {0x0622, {0xd6, 0x56} },
132 {0x0623, {0x95, 0x8b} },
133 {0x0624, {0x2b, 0x2b} },
134 {0x0625, {0x30, 0x24} },
135 {0x0626, {0x3e, 0x3e} },
136 {0x0627, {0x62, 0xe2} },
137 {0x0628, {0xe9, 0xf5} },
138 {0x0629, {0x99, 0x19} },
139 {0x062a, {0xd4, 0x11} },
140 {0x062b, {0x03, 0x04} },
141 {0x062c, {0xb5, 0x85} },
142 {0x062d, {0x1e, 0x20} },
143 {0x062e, {0x2a, 0xea} },
144 {0x062f, {0xd7, 0xd2} },
145 {0x0630, {0x15, 0x15} },
146 {0x0631, {0xa3, 0xa9} },
147 {0x0632, {0x1f, 0x1f} },
148 {0x0633, {0xf9, 0xd1} },
149 {0x0634, {0xc0, 0xc3} },
150 {0x0635, {0x4d, 0x8d} },
151 {0x0636, {0x21, 0x31} },
152 {0x0637, {0x83, 0x83} },
153 {0x0638, {0x08, 0x8c} },
154 {0x0639, {0x19, 0x19} },
155 {0x063a, {0x45, 0xa5} },
156 {0x063b, {0xef, 0xec} },
157 {0x063c, {0x8a, 0x8a} },
158 {0x063d, {0xf4, 0xf6} },
159 {0x063e, {0x8f, 0x8f} },
160 {0x063f, {0x44, 0x0c} },
161 {0x0640, {0xef, 0xf0} },
162 {0x0641, {0x66, 0x66} },
163 {0x0642, {0xcc, 0xd2} },
164 {0x0643, {0x41, 0x41} },
165 {0x0644, {0x63, 0x93} },
166 {0x0645, {0x8e, 0x8e} },
167 {0x0646, {0xa2, 0x42} },
168 {0x0647, {0x7b, 0x7b} },
169 {0x0648, {0x04, 0x04} },
170 {0x0649, {0x00, 0x00} },
171 {0x064a, {0x40, 0x40} },
172 {0x064b, {0x8c, 0x98} },
173 {0x064c, {0x00, 0x00} },
174 {0x064d, {0x63, 0xc3} },
175 {0x064e, {0x04, 0x04} },
176 {0x064f, {0x20, 0x20} },
177 {0x0650, {0x00, 0x00} },
178 {0x0651, {0x40, 0x40} },
179 {0x0652, {0x01, 0x01} },
181 #define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
182 / sizeof(struct au8522_register_config))
184 static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
186 return container_of(sd, struct au8522_state, sd);
189 static void setup_vbi(struct au8522_state *state, int aud_input)
191 int i;
193 /* These are set to zero regardless of what mode we're in */
194 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
195 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
196 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
197 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
198 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
199 au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
200 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
201 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
202 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
203 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,
204 0x00);
205 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
206 0x00);
207 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
208 0x00);
210 /* Setup the VBI registers */
211 for (i = 0x30; i < 0x60; i++)
212 au8522_writereg(state, i, 0x40);
214 /* For some reason, every register is 0x40 except register 0x44
215 (confirmed via the HVR-950q USB capture) */
216 au8522_writereg(state, 0x44, 0x60);
218 /* Enable VBI (we always do this regardless of whether the user is
219 viewing closed caption info) */
220 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
221 AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
225 static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
227 int i;
228 int filter_coef_type;
230 /* Provide reasonable defaults for picture tuning values */
231 au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
232 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
233 state->brightness = 0xed - 128;
234 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
235 state->contrast = 0x79;
236 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
237 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
238 state->saturation = 0x80;
239 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
240 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
241 state->hue = 0x00;
243 /* Other decoder registers */
244 au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
246 if (input_mode == 0x23) {
247 /* S-Video input mapping */
248 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
249 } else {
250 /* All other modes (CVBS/ATVRF etc.) */
251 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
254 au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
255 AU8522_TVDEC_PGA_REG012H_CVBS);
256 au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
257 AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
258 au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
259 AU8522_TVDED_DBG_MODE_REG060H_CVBS);
260 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
261 AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
262 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
263 AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
264 au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
265 AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
266 au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
267 AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
268 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
269 AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
270 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
271 AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
272 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
273 AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
274 au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
275 AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
276 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
277 AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
278 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
279 AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
280 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
281 AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
282 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
283 AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
284 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
285 AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
286 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
287 AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
288 au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
289 AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
290 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
291 AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
292 au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
293 au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
294 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
295 AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
296 au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
297 au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
298 au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
299 AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
300 au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
301 AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
302 au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
303 AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
304 au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
305 AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
306 au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
307 AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
308 au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
309 AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
310 au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
311 AU8522_TOREGAAGC_REG0E5H_CVBS);
312 au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
314 setup_vbi(state, 0);
316 if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
317 input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
318 /* Despite what the table says, for the HVR-950q we still need
319 to be in CVBS mode for the S-Video input (reason unknown). */
320 /* filter_coef_type = 3; */
321 filter_coef_type = 5;
322 } else {
323 filter_coef_type = 5;
326 /* Load the Video Decoder Filter Coefficients */
327 for (i = 0; i < NUM_FILTER_COEF; i++) {
328 au8522_writereg(state, filter_coef[i].reg_name,
329 filter_coef[i].reg_val[filter_coef_type]);
332 /* It's not clear what these registers are for, but they are always
333 set to the same value regardless of what mode we're in */
334 au8522_writereg(state, AU8522_REG42EH, 0x87);
335 au8522_writereg(state, AU8522_REG42FH, 0xa2);
336 au8522_writereg(state, AU8522_REG430H, 0xbf);
337 au8522_writereg(state, AU8522_REG431H, 0xcb);
338 au8522_writereg(state, AU8522_REG432H, 0xa1);
339 au8522_writereg(state, AU8522_REG433H, 0x41);
340 au8522_writereg(state, AU8522_REG434H, 0x88);
341 au8522_writereg(state, AU8522_REG435H, 0xc2);
342 au8522_writereg(state, AU8522_REG436H, 0x3c);
345 static void au8522_setup_cvbs_mode(struct au8522_state *state)
347 /* here we're going to try the pre-programmed route */
348 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
349 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
351 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
352 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
353 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
355 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
356 AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
358 setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
360 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
361 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
364 static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
366 /* here we're going to try the pre-programmed route */
367 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
368 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
370 /* It's not clear why they turn off the PGA before enabling the clamp
371 control, but the Windows trace does it so we will too... */
372 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
374 /* Enable clamping control */
375 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
377 /* Turn on the PGA */
378 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
380 /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
381 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
382 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
384 setup_decoder_defaults(state,
385 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
387 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
388 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
391 static void au8522_setup_svideo_mode(struct au8522_state *state)
393 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
394 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
396 /* Set input to Y on Channe1, C on Channel 3 */
397 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
398 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
400 /* Disable clamping control (required for S-video) */
401 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
403 setup_decoder_defaults(state,
404 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
406 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
407 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
410 /* ----------------------------------------------------------------------- */
412 static void disable_audio_input(struct au8522_state *state)
414 /* This can probably be optimized */
415 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
416 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
417 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
418 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
419 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
421 au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
422 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
423 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
424 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
425 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
427 au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
428 msleep(5);
429 au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
431 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
432 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
433 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
435 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
436 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
439 /* 0=disable, 1=SIF */
440 static void set_audio_input(struct au8522_state *state, int aud_input)
442 int i;
444 /* Note that this function needs to be used in conjunction with setting
445 the input routing via register 0x81 */
447 if (aud_input == AU8522_AUDIO_NONE) {
448 disable_audio_input(state);
449 return;
452 if (aud_input != AU8522_AUDIO_SIF) {
453 /* The caller asked for a mode we don't currently support */
454 printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
455 aud_input);
456 return;
459 /* Load the Audio Decoder Filter Coefficients */
460 for (i = 0; i < NUM_LPFILTER_COEF; i++) {
461 au8522_writereg(state, lpfilter_coef[i].reg_name,
462 lpfilter_coef[i].reg_val[0]);
465 /* Setup audio */
466 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
467 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
468 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
469 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
470 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
471 msleep(150);
472 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
473 msleep(1);
474 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
475 msleep(50);
476 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
477 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
478 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
479 msleep(80);
480 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
481 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
482 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
483 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
484 msleep(70);
485 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
486 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
487 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
490 /* ----------------------------------------------------------------------- */
492 static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
494 struct au8522_state *state = to_state(sd);
496 switch (ctrl->id) {
497 case V4L2_CID_BRIGHTNESS:
498 state->brightness = ctrl->value;
499 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
500 ctrl->value - 128);
501 break;
502 case V4L2_CID_CONTRAST:
503 state->contrast = ctrl->value;
504 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
505 ctrl->value);
506 break;
507 case V4L2_CID_SATURATION:
508 state->saturation = ctrl->value;
509 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
510 ctrl->value);
511 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
512 ctrl->value);
513 break;
514 case V4L2_CID_HUE:
515 state->hue = ctrl->value;
516 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
517 ctrl->value >> 8);
518 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
519 ctrl->value & 0xFF);
520 break;
521 case V4L2_CID_AUDIO_VOLUME:
522 case V4L2_CID_AUDIO_BASS:
523 case V4L2_CID_AUDIO_TREBLE:
524 case V4L2_CID_AUDIO_BALANCE:
525 case V4L2_CID_AUDIO_MUTE:
526 /* Not yet implemented */
527 default:
528 return -EINVAL;
531 return 0;
534 static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
536 struct au8522_state *state = to_state(sd);
538 /* Note that we are using values cached in the state structure instead
539 of reading the registers due to issues with i2c reads not working
540 properly/consistently yet on the HVR-950q */
542 switch (ctrl->id) {
543 case V4L2_CID_BRIGHTNESS:
544 ctrl->value = state->brightness;
545 break;
546 case V4L2_CID_CONTRAST:
547 ctrl->value = state->contrast;
548 break;
549 case V4L2_CID_SATURATION:
550 ctrl->value = state->saturation;
551 break;
552 case V4L2_CID_HUE:
553 ctrl->value = state->hue;
554 break;
555 case V4L2_CID_AUDIO_VOLUME:
556 case V4L2_CID_AUDIO_BASS:
557 case V4L2_CID_AUDIO_TREBLE:
558 case V4L2_CID_AUDIO_BALANCE:
559 case V4L2_CID_AUDIO_MUTE:
560 /* Not yet supported */
561 default:
562 return -EINVAL;
565 return 0;
568 /* ----------------------------------------------------------------------- */
570 static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
572 switch (fmt->type) {
573 default:
574 return -EINVAL;
576 return 0;
579 static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
581 switch (fmt->type) {
582 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
583 /* Not yet implemented */
584 break;
585 default:
586 return -EINVAL;
589 return 0;
592 /* ----------------------------------------------------------------------- */
594 #ifdef CONFIG_VIDEO_ADV_DEBUG
595 static int au8522_g_register(struct v4l2_subdev *sd,
596 struct v4l2_dbg_register *reg)
598 struct i2c_client *client = v4l2_get_subdevdata(sd);
599 struct au8522_state *state = to_state(sd);
601 if (!v4l2_chip_match_i2c_client(client, &reg->match))
602 return -EINVAL;
603 if (!capable(CAP_SYS_ADMIN))
604 return -EPERM;
605 reg->val = au8522_readreg(state, reg->reg & 0xffff);
606 return 0;
609 static int au8522_s_register(struct v4l2_subdev *sd,
610 struct v4l2_dbg_register *reg)
612 struct i2c_client *client = v4l2_get_subdevdata(sd);
613 struct au8522_state *state = to_state(sd);
615 if (!v4l2_chip_match_i2c_client(client, &reg->match))
616 return -EINVAL;
617 if (!capable(CAP_SYS_ADMIN))
618 return -EPERM;
619 au8522_writereg(state, reg->reg, reg->val & 0xff);
620 return 0;
622 #endif
624 static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
626 struct au8522_state *state = to_state(sd);
628 if (enable) {
629 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
630 0x01);
631 msleep(1);
632 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
633 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
634 } else {
635 /* This does not completely power down the device
636 (it only reduces it from around 140ma to 80ma) */
637 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
638 1 << 5);
640 return 0;
643 static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
645 switch (qc->id) {
646 case V4L2_CID_CONTRAST:
647 return v4l2_ctrl_query_fill(qc, 0, 255, 1,
648 AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
649 case V4L2_CID_BRIGHTNESS:
650 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
651 case V4L2_CID_SATURATION:
652 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
653 case V4L2_CID_HUE:
654 return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
655 default:
656 break;
659 qc->type = 0;
660 return -EINVAL;
663 static int au8522_reset(struct v4l2_subdev *sd, u32 val)
665 struct au8522_state *state = to_state(sd);
667 au8522_writereg(state, 0xa4, 1 << 5);
669 return 0;
672 static int au8522_s_video_routing(struct v4l2_subdev *sd,
673 u32 input, u32 output, u32 config)
675 struct au8522_state *state = to_state(sd);
677 au8522_reset(sd, 0);
679 /* Jam open the i2c gate to the tuner. We do this here to handle the
680 case where the user went into digital mode (causing the gate to be
681 closed), and then came back to analog mode */
682 au8522_writereg(state, 0x106, 1);
684 if (input == AU8522_COMPOSITE_CH1) {
685 au8522_setup_cvbs_mode(state);
686 } else if (input == AU8522_SVIDEO_CH13) {
687 au8522_setup_svideo_mode(state);
688 } else if (input == AU8522_COMPOSITE_CH4_SIF) {
689 au8522_setup_cvbs_tuner_mode(state);
690 } else {
691 printk(KERN_ERR "au8522 mode not currently supported\n");
692 return -EINVAL;
694 return 0;
697 static int au8522_s_audio_routing(struct v4l2_subdev *sd,
698 u32 input, u32 output, u32 config)
700 struct au8522_state *state = to_state(sd);
701 set_audio_input(state, input);
702 return 0;
705 static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
707 int val = 0;
708 struct au8522_state *state = to_state(sd);
709 u8 lock_status;
711 /* Interrogate the decoder to see if we are getting a real signal */
712 lock_status = au8522_readreg(state, 0x00);
713 if (lock_status == 0xa2)
714 vt->signal = 0x01;
715 else
716 vt->signal = 0x00;
718 vt->capability |=
719 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
720 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
722 val = V4L2_TUNER_SUB_MONO;
723 vt->rxsubchans = val;
724 vt->audmode = V4L2_TUNER_MODE_STEREO;
725 return 0;
728 static int au8522_g_chip_ident(struct v4l2_subdev *sd,
729 struct v4l2_dbg_chip_ident *chip)
731 struct au8522_state *state = to_state(sd);
732 struct i2c_client *client = v4l2_get_subdevdata(sd);
734 return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
737 static int au8522_log_status(struct v4l2_subdev *sd)
739 /* FIXME: Add some status info here */
740 return 0;
743 /* ----------------------------------------------------------------------- */
745 static const struct v4l2_subdev_core_ops au8522_core_ops = {
746 .log_status = au8522_log_status,
747 .g_chip_ident = au8522_g_chip_ident,
748 .g_ctrl = au8522_g_ctrl,
749 .s_ctrl = au8522_s_ctrl,
750 .queryctrl = au8522_queryctrl,
751 .reset = au8522_reset,
752 #ifdef CONFIG_VIDEO_ADV_DEBUG
753 .g_register = au8522_g_register,
754 .s_register = au8522_s_register,
755 #endif
758 static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
759 .g_tuner = au8522_g_tuner,
762 static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
763 .s_routing = au8522_s_audio_routing,
766 static const struct v4l2_subdev_video_ops au8522_video_ops = {
767 .s_routing = au8522_s_video_routing,
768 .g_fmt = au8522_g_fmt,
769 .s_fmt = au8522_s_fmt,
770 .s_stream = au8522_s_stream,
773 static const struct v4l2_subdev_ops au8522_ops = {
774 .core = &au8522_core_ops,
775 .tuner = &au8522_tuner_ops,
776 .audio = &au8522_audio_ops,
777 .video = &au8522_video_ops,
780 /* ----------------------------------------------------------------------- */
782 static int au8522_probe(struct i2c_client *client,
783 const struct i2c_device_id *did)
785 struct au8522_state *state;
786 struct v4l2_subdev *sd;
787 int instance;
788 struct au8522_config *demod_config;
790 /* Check if the adapter supports the needed features */
791 if (!i2c_check_functionality(client->adapter,
792 I2C_FUNC_SMBUS_BYTE_DATA)) {
793 return -EIO;
796 /* allocate memory for the internal state */
797 instance = au8522_get_state(&state, client->adapter, client->addr);
798 switch (instance) {
799 case 0:
800 printk(KERN_ERR "au8522_decoder allocation failed\n");
801 return -EIO;
802 case 1:
803 /* new demod instance */
804 printk(KERN_INFO "au8522_decoder creating new instance...\n");
805 break;
806 default:
807 /* existing demod instance */
808 printk(KERN_INFO "au8522_decoder attach existing instance.\n");
809 break;
812 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
813 if (demod_config == NULL) {
814 if (instance == 1)
815 kfree(state);
816 return -ENOMEM;
818 demod_config->demod_address = 0x8e >> 1;
820 state->config = demod_config;
821 state->i2c = client->adapter;
823 sd = &state->sd;
824 v4l2_i2c_subdev_init(sd, client, &au8522_ops);
826 state->c = client;
827 state->vid_input = AU8522_COMPOSITE_CH1;
828 state->aud_input = AU8522_AUDIO_NONE;
829 state->id = 8522;
830 state->rev = 0;
832 /* Jam open the i2c gate to the tuner */
833 au8522_writereg(state, 0x106, 1);
835 return 0;
838 static int au8522_remove(struct i2c_client *client)
840 struct v4l2_subdev *sd = i2c_get_clientdata(client);
841 v4l2_device_unregister_subdev(sd);
842 au8522_release_state(to_state(sd));
843 return 0;
846 static const struct i2c_device_id au8522_id[] = {
847 {"au8522", 0},
851 MODULE_DEVICE_TABLE(i2c, au8522_id);
853 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
854 .name = "au8522",
855 .probe = au8522_probe,
856 .remove = au8522_remove,
857 .id_table = au8522_id,