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
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-device.h>
41 #include "au8522_priv.h"
43 MODULE_AUTHOR("Devin Heitmueller");
44 MODULE_LICENSE("GPL");
46 static int au8522_analog_debug;
49 module_param_named(analog_debug, au8522_analog_debug, int, 0644);
51 MODULE_PARM_DESC(analog_debug,
52 "Analog debugging messages [0=Off (default) 1=On]");
54 struct au8522_register_config {
60 /* Video Decoder Filter Coefficients
61 The values are as follows from left to right
62 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
64 static const struct au8522_register_config filter_coef[] = {
65 {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
66 {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
67 {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
68 {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
69 {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
70 {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
71 {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
72 {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
73 {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
74 {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
75 {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
76 {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
77 {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
78 {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
79 {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
80 {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
81 {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
82 {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
83 {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
84 {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
85 {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
86 {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
87 {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
88 {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
89 {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
90 {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
91 {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
92 {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
93 {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
94 {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
97 #define NUM_FILTER_COEF (sizeof(filter_coef)\
98 / sizeof(struct au8522_register_config))
101 /* Registers 0x060b through 0x0652 are the LP Filter coefficients
102 The values are as follows from left to right
103 0="SIF" 1="ATVRF/ATVRF13"
104 Note: the "ATVRF/ATVRF13" mode has never been tested
106 static const struct au8522_register_config lpfilter_coef[] = {
107 {0x060b, {0x21, 0x0b} },
108 {0x060c, {0xad, 0xad} },
109 {0x060d, {0x70, 0xf0} },
110 {0x060e, {0xea, 0xe9} },
111 {0x060f, {0xdd, 0xdd} },
112 {0x0610, {0x08, 0x64} },
113 {0x0611, {0x60, 0x60} },
114 {0x0612, {0xf8, 0xb2} },
115 {0x0613, {0x01, 0x02} },
116 {0x0614, {0xe4, 0xb4} },
117 {0x0615, {0x19, 0x02} },
118 {0x0616, {0xae, 0x2e} },
119 {0x0617, {0xee, 0xc5} },
120 {0x0618, {0x56, 0x56} },
121 {0x0619, {0x30, 0x58} },
122 {0x061a, {0xf9, 0xf8} },
123 {0x061b, {0x24, 0x64} },
124 {0x061c, {0x07, 0x07} },
125 {0x061d, {0x30, 0x30} },
126 {0x061e, {0xa9, 0xed} },
127 {0x061f, {0x09, 0x0b} },
128 {0x0620, {0x42, 0xc2} },
129 {0x0621, {0x1d, 0x2a} },
130 {0x0622, {0xd6, 0x56} },
131 {0x0623, {0x95, 0x8b} },
132 {0x0624, {0x2b, 0x2b} },
133 {0x0625, {0x30, 0x24} },
134 {0x0626, {0x3e, 0x3e} },
135 {0x0627, {0x62, 0xe2} },
136 {0x0628, {0xe9, 0xf5} },
137 {0x0629, {0x99, 0x19} },
138 {0x062a, {0xd4, 0x11} },
139 {0x062b, {0x03, 0x04} },
140 {0x062c, {0xb5, 0x85} },
141 {0x062d, {0x1e, 0x20} },
142 {0x062e, {0x2a, 0xea} },
143 {0x062f, {0xd7, 0xd2} },
144 {0x0630, {0x15, 0x15} },
145 {0x0631, {0xa3, 0xa9} },
146 {0x0632, {0x1f, 0x1f} },
147 {0x0633, {0xf9, 0xd1} },
148 {0x0634, {0xc0, 0xc3} },
149 {0x0635, {0x4d, 0x8d} },
150 {0x0636, {0x21, 0x31} },
151 {0x0637, {0x83, 0x83} },
152 {0x0638, {0x08, 0x8c} },
153 {0x0639, {0x19, 0x19} },
154 {0x063a, {0x45, 0xa5} },
155 {0x063b, {0xef, 0xec} },
156 {0x063c, {0x8a, 0x8a} },
157 {0x063d, {0xf4, 0xf6} },
158 {0x063e, {0x8f, 0x8f} },
159 {0x063f, {0x44, 0x0c} },
160 {0x0640, {0xef, 0xf0} },
161 {0x0641, {0x66, 0x66} },
162 {0x0642, {0xcc, 0xd2} },
163 {0x0643, {0x41, 0x41} },
164 {0x0644, {0x63, 0x93} },
165 {0x0645, {0x8e, 0x8e} },
166 {0x0646, {0xa2, 0x42} },
167 {0x0647, {0x7b, 0x7b} },
168 {0x0648, {0x04, 0x04} },
169 {0x0649, {0x00, 0x00} },
170 {0x064a, {0x40, 0x40} },
171 {0x064b, {0x8c, 0x98} },
172 {0x064c, {0x00, 0x00} },
173 {0x064d, {0x63, 0xc3} },
174 {0x064e, {0x04, 0x04} },
175 {0x064f, {0x20, 0x20} },
176 {0x0650, {0x00, 0x00} },
177 {0x0651, {0x40, 0x40} },
178 {0x0652, {0x01, 0x01} },
180 #define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
181 / sizeof(struct au8522_register_config))
183 static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
185 return container_of(sd, struct au8522_state, sd);
188 static void setup_vbi(struct au8522_state *state, int aud_input)
192 /* These are set to zero regardless of what mode we're in */
193 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
194 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
195 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
196 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
197 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
198 au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
199 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
200 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
201 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
202 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,
204 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
206 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
209 /* Setup the VBI registers */
210 for (i = 0x30; i < 0x60; i++)
211 au8522_writereg(state, i, 0x40);
213 /* For some reason, every register is 0x40 except register 0x44
214 (confirmed via the HVR-950q USB capture) */
215 au8522_writereg(state, 0x44, 0x60);
217 /* Enable VBI (we always do this regardless of whether the user is
218 viewing closed caption info) */
219 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
220 AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
224 static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
227 int filter_coef_type;
229 /* Provide reasonable defaults for picture tuning values */
230 au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
231 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
232 state->brightness = 0xed - 128;
233 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
234 state->contrast = 0x79;
235 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
236 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
237 state->saturation = 0x80;
238 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
239 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
242 /* Other decoder registers */
243 au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
245 if (input_mode == 0x23) {
246 /* S-Video input mapping */
247 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
249 /* All other modes (CVBS/ATVRF etc.) */
250 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
253 au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
254 AU8522_TVDEC_PGA_REG012H_CVBS);
255 au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
256 AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
257 au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
258 AU8522_TVDED_DBG_MODE_REG060H_CVBS);
259 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
260 AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
261 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
262 AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
263 au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
264 AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
265 au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
266 AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
267 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
268 AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
269 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
270 AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
271 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
272 AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
273 au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
274 AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
275 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
276 AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
277 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
278 AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
279 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
280 AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
281 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
282 AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
283 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
284 AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
285 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
286 AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
287 au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
288 AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
289 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
290 AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
291 au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
292 au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
293 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
294 AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
295 au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
296 au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
297 au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
298 AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
299 au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
300 AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
301 au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
302 AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
303 au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
304 AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
305 au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
306 AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
307 au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
308 AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
309 au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
310 AU8522_TOREGAAGC_REG0E5H_CVBS);
311 au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
315 if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
316 input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
317 /* Despite what the table says, for the HVR-950q we still need
318 to be in CVBS mode for the S-Video input (reason unknown). */
319 /* filter_coef_type = 3; */
320 filter_coef_type = 5;
322 filter_coef_type = 5;
325 /* Load the Video Decoder Filter Coefficients */
326 for (i = 0; i < NUM_FILTER_COEF; i++) {
327 au8522_writereg(state, filter_coef[i].reg_name,
328 filter_coef[i].reg_val[filter_coef_type]);
331 /* It's not clear what these registers are for, but they are always
332 set to the same value regardless of what mode we're in */
333 au8522_writereg(state, AU8522_REG42EH, 0x87);
334 au8522_writereg(state, AU8522_REG42FH, 0xa2);
335 au8522_writereg(state, AU8522_REG430H, 0xbf);
336 au8522_writereg(state, AU8522_REG431H, 0xcb);
337 au8522_writereg(state, AU8522_REG432H, 0xa1);
338 au8522_writereg(state, AU8522_REG433H, 0x41);
339 au8522_writereg(state, AU8522_REG434H, 0x88);
340 au8522_writereg(state, AU8522_REG435H, 0xc2);
341 au8522_writereg(state, AU8522_REG436H, 0x3c);
344 static void au8522_setup_cvbs_mode(struct au8522_state *state)
346 /* here we're going to try the pre-programmed route */
347 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
348 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
350 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
351 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
352 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
354 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
355 AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
357 setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
359 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
360 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
363 static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
365 /* here we're going to try the pre-programmed route */
366 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
367 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
369 /* It's not clear why they turn off the PGA before enabling the clamp
370 control, but the Windows trace does it so we will too... */
371 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
373 /* Enable clamping control */
374 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
376 /* Turn on the PGA */
377 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
379 /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
380 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
381 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
383 setup_decoder_defaults(state,
384 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
386 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
387 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
390 static void au8522_setup_svideo_mode(struct au8522_state *state)
392 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
393 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
395 /* Set input to Y on Channe1, C on Channel 3 */
396 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
397 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
399 /* Disable clamping control (required for S-video) */
400 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
402 setup_decoder_defaults(state,
403 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
405 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
406 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
409 /* ----------------------------------------------------------------------- */
411 static void disable_audio_input(struct au8522_state *state)
413 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
414 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
415 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
417 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
418 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
420 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
421 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
424 /* 0=disable, 1=SIF */
425 static void set_audio_input(struct au8522_state *state, int aud_input)
429 /* Note that this function needs to be used in conjunction with setting
430 the input routing via register 0x81 */
432 if (aud_input == AU8522_AUDIO_NONE) {
433 disable_audio_input(state);
437 if (aud_input != AU8522_AUDIO_SIF) {
438 /* The caller asked for a mode we don't currently support */
439 printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
444 /* Load the Audio Decoder Filter Coefficients */
445 for (i = 0; i < NUM_LPFILTER_COEF; i++) {
446 au8522_writereg(state, lpfilter_coef[i].reg_name,
447 lpfilter_coef[i].reg_val[0]);
451 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
452 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
453 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
454 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
455 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
457 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
459 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
461 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
462 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
463 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
465 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
466 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
467 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
468 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
470 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
471 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
472 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
475 /* ----------------------------------------------------------------------- */
477 static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
479 struct au8522_state *state = to_state(sd);
482 case V4L2_CID_BRIGHTNESS:
483 state->brightness = ctrl->value;
484 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
487 case V4L2_CID_CONTRAST:
488 state->contrast = ctrl->value;
489 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
492 case V4L2_CID_SATURATION:
493 state->saturation = ctrl->value;
494 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
496 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
500 state->hue = ctrl->value;
501 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
503 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
506 case V4L2_CID_AUDIO_VOLUME:
507 case V4L2_CID_AUDIO_BASS:
508 case V4L2_CID_AUDIO_TREBLE:
509 case V4L2_CID_AUDIO_BALANCE:
510 case V4L2_CID_AUDIO_MUTE:
511 /* Not yet implemented */
519 static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
521 struct au8522_state *state = to_state(sd);
523 /* Note that we are using values cached in the state structure instead
524 of reading the registers due to issues with i2c reads not working
525 properly/consistently yet on the HVR-950q */
528 case V4L2_CID_BRIGHTNESS:
529 ctrl->value = state->brightness;
531 case V4L2_CID_CONTRAST:
532 ctrl->value = state->contrast;
534 case V4L2_CID_SATURATION:
535 ctrl->value = state->saturation;
538 ctrl->value = state->hue;
540 case V4L2_CID_AUDIO_VOLUME:
541 case V4L2_CID_AUDIO_BASS:
542 case V4L2_CID_AUDIO_TREBLE:
543 case V4L2_CID_AUDIO_BALANCE:
544 case V4L2_CID_AUDIO_MUTE:
545 /* Not yet supported */
553 /* ----------------------------------------------------------------------- */
555 #ifdef CONFIG_VIDEO_ADV_DEBUG
556 static int au8522_g_register(struct v4l2_subdev *sd,
557 struct v4l2_dbg_register *reg)
559 struct i2c_client *client = v4l2_get_subdevdata(sd);
560 struct au8522_state *state = to_state(sd);
562 if (!v4l2_chip_match_i2c_client(client, ®->match))
564 if (!capable(CAP_SYS_ADMIN))
566 reg->val = au8522_readreg(state, reg->reg & 0xffff);
570 static int au8522_s_register(struct v4l2_subdev *sd,
571 struct v4l2_dbg_register *reg)
573 struct i2c_client *client = v4l2_get_subdevdata(sd);
574 struct au8522_state *state = to_state(sd);
576 if (!v4l2_chip_match_i2c_client(client, ®->match))
578 if (!capable(CAP_SYS_ADMIN))
580 au8522_writereg(state, reg->reg, reg->val & 0xff);
585 static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
587 struct au8522_state *state = to_state(sd);
590 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
593 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
594 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
596 /* This does not completely power down the device
597 (it only reduces it from around 140ma to 80ma) */
598 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
604 static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
607 case V4L2_CID_CONTRAST:
608 return v4l2_ctrl_query_fill(qc, 0, 255, 1,
609 AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
610 case V4L2_CID_BRIGHTNESS:
611 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
612 case V4L2_CID_SATURATION:
613 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
615 return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
624 static int au8522_reset(struct v4l2_subdev *sd, u32 val)
626 struct au8522_state *state = to_state(sd);
628 state->operational_mode = AU8522_ANALOG_MODE;
630 /* Clear out any state associated with the digital side of the
631 chip, so that when it gets powered back up it won't think
632 that it is already tuned */
633 state->current_frequency = 0;
635 au8522_writereg(state, 0xa4, 1 << 5);
640 static int au8522_s_video_routing(struct v4l2_subdev *sd,
641 u32 input, u32 output, u32 config)
643 struct au8522_state *state = to_state(sd);
647 /* Jam open the i2c gate to the tuner. We do this here to handle the
648 case where the user went into digital mode (causing the gate to be
649 closed), and then came back to analog mode */
650 au8522_writereg(state, 0x106, 1);
652 if (input == AU8522_COMPOSITE_CH1) {
653 au8522_setup_cvbs_mode(state);
654 } else if (input == AU8522_SVIDEO_CH13) {
655 au8522_setup_svideo_mode(state);
656 } else if (input == AU8522_COMPOSITE_CH4_SIF) {
657 au8522_setup_cvbs_tuner_mode(state);
659 printk(KERN_ERR "au8522 mode not currently supported\n");
665 static int au8522_s_audio_routing(struct v4l2_subdev *sd,
666 u32 input, u32 output, u32 config)
668 struct au8522_state *state = to_state(sd);
669 set_audio_input(state, input);
673 static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
676 struct au8522_state *state = to_state(sd);
679 /* Interrogate the decoder to see if we are getting a real signal */
680 lock_status = au8522_readreg(state, 0x00);
681 if (lock_status == 0xa2)
687 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
688 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
690 val = V4L2_TUNER_SUB_MONO;
691 vt->rxsubchans = val;
692 vt->audmode = V4L2_TUNER_MODE_STEREO;
696 static int au8522_g_chip_ident(struct v4l2_subdev *sd,
697 struct v4l2_dbg_chip_ident *chip)
699 struct au8522_state *state = to_state(sd);
700 struct i2c_client *client = v4l2_get_subdevdata(sd);
702 return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
705 static int au8522_log_status(struct v4l2_subdev *sd)
707 /* FIXME: Add some status info here */
711 /* ----------------------------------------------------------------------- */
713 static const struct v4l2_subdev_core_ops au8522_core_ops = {
714 .log_status = au8522_log_status,
715 .g_chip_ident = au8522_g_chip_ident,
716 .g_ctrl = au8522_g_ctrl,
717 .s_ctrl = au8522_s_ctrl,
718 .queryctrl = au8522_queryctrl,
719 .reset = au8522_reset,
720 #ifdef CONFIG_VIDEO_ADV_DEBUG
721 .g_register = au8522_g_register,
722 .s_register = au8522_s_register,
726 static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
727 .g_tuner = au8522_g_tuner,
730 static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
731 .s_routing = au8522_s_audio_routing,
734 static const struct v4l2_subdev_video_ops au8522_video_ops = {
735 .s_routing = au8522_s_video_routing,
736 .s_stream = au8522_s_stream,
739 static const struct v4l2_subdev_ops au8522_ops = {
740 .core = &au8522_core_ops,
741 .tuner = &au8522_tuner_ops,
742 .audio = &au8522_audio_ops,
743 .video = &au8522_video_ops,
746 /* ----------------------------------------------------------------------- */
748 static int au8522_probe(struct i2c_client *client,
749 const struct i2c_device_id *did)
751 struct au8522_state *state;
752 struct v4l2_subdev *sd;
754 struct au8522_config *demod_config;
756 /* Check if the adapter supports the needed features */
757 if (!i2c_check_functionality(client->adapter,
758 I2C_FUNC_SMBUS_BYTE_DATA)) {
762 /* allocate memory for the internal state */
763 instance = au8522_get_state(&state, client->adapter, client->addr);
766 printk(KERN_ERR "au8522_decoder allocation failed\n");
769 /* new demod instance */
770 printk(KERN_INFO "au8522_decoder creating new instance...\n");
773 /* existing demod instance */
774 printk(KERN_INFO "au8522_decoder attach existing instance.\n");
778 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
779 if (demod_config == NULL) {
784 demod_config->demod_address = 0x8e >> 1;
786 state->config = demod_config;
787 state->i2c = client->adapter;
790 v4l2_i2c_subdev_init(sd, client, &au8522_ops);
793 state->vid_input = AU8522_COMPOSITE_CH1;
794 state->aud_input = AU8522_AUDIO_NONE;
798 /* Jam open the i2c gate to the tuner */
799 au8522_writereg(state, 0x106, 1);
804 static int au8522_remove(struct i2c_client *client)
806 struct v4l2_subdev *sd = i2c_get_clientdata(client);
807 v4l2_device_unregister_subdev(sd);
808 au8522_release_state(to_state(sd));
812 static const struct i2c_device_id au8522_id[] = {
817 MODULE_DEVICE_TABLE(i2c, au8522_id);
819 static struct i2c_driver au8522_driver = {
821 .owner = THIS_MODULE,
824 .probe = au8522_probe,
825 .remove = au8522_remove,
826 .id_table = au8522_id,
829 static __init int init_au8522(void)
831 return i2c_add_driver(&au8522_driver);
834 static __exit void exit_au8522(void)
836 i2c_del_driver(&au8522_driver);
839 module_init(init_au8522);
840 module_exit(exit_au8522);