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