aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/au8522_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/au8522_decoder.c')
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c853
1 files changed, 853 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
new file mode 100644
index 00000000000..2b248c12f40
--- /dev/null
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -0,0 +1,853 @@
1/*
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 * 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)
29 *
30 */
31
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>
40#include "au8522.h"
41#include "au8522_priv.h"
42
43MODULE_AUTHOR("Devin Heitmueller");
44MODULE_LICENSE("GPL");
45
46static int au8522_analog_debug;
47
48
49module_param_named(analog_debug, au8522_analog_debug, int, 0644);
50
51MODULE_PARM_DESC(analog_debug,
52 "Analog debugging messages [0=Off (default) 1=On]");
53
54struct au8522_register_config {
55 u16 reg_name;
56 u8 reg_val[8];
57};
58
59
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"
63*/
64static 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} },
95
96};
97#define NUM_FILTER_COEF (sizeof(filter_coef)\
98 / sizeof(struct au8522_register_config))
99
100
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
105*/
106static 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} },
179};
180#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
181 / sizeof(struct au8522_register_config))
182
183static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
184{
185 return container_of(sd, struct au8522_state, sd);
186}
187
188static void setup_vbi(struct au8522_state *state, int aud_input)
189{
190 int i;
191
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,
203 0x00);
204 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
205 0x00);
206 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
207 0x00);
208
209 /* Setup the VBI registers */
210 for (i = 0x30; i < 0x60; i++)
211 au8522_writereg(state, i, 0x40);
212
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);
216
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);
221
222}
223
224static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
225{
226 int i;
227 int filter_coef_type;
228
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);
240 state->hue = 0x00;
241
242 /* Other decoder registers */
243 au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
244
245 if (input_mode == 0x23) {
246 /* S-Video input mapping */
247 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
248 } else {
249 /* All other modes (CVBS/ATVRF etc.) */
250 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
251 }
252
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 if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
282 input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
283 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
284 AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
285 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
286 AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
287 } else {
288 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
289 AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
290 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
291 AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
292 }
293 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
294 AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
295 au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
296 AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
297 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
298 AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
299 au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
300 au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
301 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
302 AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
303 au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
304 au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
305 au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
306 AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
307 au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
308 AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
309 au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
310 AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
311 au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
312 AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
313 au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
314 AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
315 au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
316 AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
317 au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
318 AU8522_TOREGAAGC_REG0E5H_CVBS);
319 au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
320
321 setup_vbi(state, 0);
322
323 if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
324 input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
325 /* Despite what the table says, for the HVR-950q we still need
326 to be in CVBS mode for the S-Video input (reason unknown). */
327 /* filter_coef_type = 3; */
328 filter_coef_type = 5;
329 } else {
330 filter_coef_type = 5;
331 }
332
333 /* Load the Video Decoder Filter Coefficients */
334 for (i = 0; i < NUM_FILTER_COEF; i++) {
335 au8522_writereg(state, filter_coef[i].reg_name,
336 filter_coef[i].reg_val[filter_coef_type]);
337 }
338
339 /* It's not clear what these registers are for, but they are always
340 set to the same value regardless of what mode we're in */
341 au8522_writereg(state, AU8522_REG42EH, 0x87);
342 au8522_writereg(state, AU8522_REG42FH, 0xa2);
343 au8522_writereg(state, AU8522_REG430H, 0xbf);
344 au8522_writereg(state, AU8522_REG431H, 0xcb);
345 au8522_writereg(state, AU8522_REG432H, 0xa1);
346 au8522_writereg(state, AU8522_REG433H, 0x41);
347 au8522_writereg(state, AU8522_REG434H, 0x88);
348 au8522_writereg(state, AU8522_REG435H, 0xc2);
349 au8522_writereg(state, AU8522_REG436H, 0x3c);
350}
351
352static void au8522_setup_cvbs_mode(struct au8522_state *state)
353{
354 /* here we're going to try the pre-programmed route */
355 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
356 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
357
358 /* PGA in automatic mode */
359 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
360
361 /* Enable clamping control */
362 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
363
364 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
365 AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
366
367 setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
368
369 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
370 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
371}
372
373static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
374{
375 /* here we're going to try the pre-programmed route */
376 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
377 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
378
379 /* It's not clear why we have to have the PGA in automatic mode while
380 enabling clamp control, but it's what Windows does */
381 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
382
383 /* Enable clamping control */
384 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
385
386 /* Disable automatic PGA (since the CVBS is coming from the tuner) */
387 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
388
389 /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
390 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
391 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
392
393 setup_decoder_defaults(state,
394 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
395
396 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
397 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
398}
399
400static void au8522_setup_svideo_mode(struct au8522_state *state)
401{
402 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
403 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
404
405 /* Set input to Y on Channe1, C on Channel 3 */
406 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
407 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
408
409 /* PGA in automatic mode */
410 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
411
412 /* Enable clamping control */
413 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
414
415 setup_decoder_defaults(state,
416 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
417
418 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
419 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
420}
421
422/* ----------------------------------------------------------------------- */
423
424static void disable_audio_input(struct au8522_state *state)
425{
426 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
427 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
428 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
429
430 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
431 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
432
433 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
434 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
435}
436
437/* 0=disable, 1=SIF */
438static void set_audio_input(struct au8522_state *state, int aud_input)
439{
440 int i;
441
442 /* Note that this function needs to be used in conjunction with setting
443 the input routing via register 0x81 */
444
445 if (aud_input == AU8522_AUDIO_NONE) {
446 disable_audio_input(state);
447 return;
448 }
449
450 if (aud_input != AU8522_AUDIO_SIF) {
451 /* The caller asked for a mode we don't currently support */
452 printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
453 aud_input);
454 return;
455 }
456
457 /* Load the Audio Decoder Filter Coefficients */
458 for (i = 0; i < NUM_LPFILTER_COEF; i++) {
459 au8522_writereg(state, lpfilter_coef[i].reg_name,
460 lpfilter_coef[i].reg_val[0]);
461 }
462
463 /* Setup audio */
464 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
465 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
466 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
467 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
468 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
469 msleep(150);
470 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
471 msleep(1);
472 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
473 msleep(50);
474 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
475 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
476 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
477 msleep(80);
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_REG0F9H, AU8522_REG0F9H_AUDIO);
481 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
482 msleep(70);
483 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
484 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
485 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
486}
487
488/* ----------------------------------------------------------------------- */
489
490static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
491{
492 struct au8522_state *state = to_state(sd);
493
494 switch (ctrl->id) {
495 case V4L2_CID_BRIGHTNESS:
496 state->brightness = ctrl->value;
497 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
498 ctrl->value - 128);
499 break;
500 case V4L2_CID_CONTRAST:
501 state->contrast = ctrl->value;
502 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
503 ctrl->value);
504 break;
505 case V4L2_CID_SATURATION:
506 state->saturation = ctrl->value;
507 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
508 ctrl->value);
509 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
510 ctrl->value);
511 break;
512 case V4L2_CID_HUE:
513 state->hue = ctrl->value;
514 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
515 ctrl->value >> 8);
516 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
517 ctrl->value & 0xFF);
518 break;
519 case V4L2_CID_AUDIO_VOLUME:
520 case V4L2_CID_AUDIO_BASS:
521 case V4L2_CID_AUDIO_TREBLE:
522 case V4L2_CID_AUDIO_BALANCE:
523 case V4L2_CID_AUDIO_MUTE:
524 /* Not yet implemented */
525 default:
526 return -EINVAL;
527 }
528
529 return 0;
530}
531
532static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
533{
534 struct au8522_state *state = to_state(sd);
535
536 /* Note that we are using values cached in the state structure instead
537 of reading the registers due to issues with i2c reads not working
538 properly/consistently yet on the HVR-950q */
539
540 switch (ctrl->id) {
541 case V4L2_CID_BRIGHTNESS:
542 ctrl->value = state->brightness;
543 break;
544 case V4L2_CID_CONTRAST:
545 ctrl->value = state->contrast;
546 break;
547 case V4L2_CID_SATURATION:
548 ctrl->value = state->saturation;
549 break;
550 case V4L2_CID_HUE:
551 ctrl->value = state->hue;
552 break;
553 case V4L2_CID_AUDIO_VOLUME:
554 case V4L2_CID_AUDIO_BASS:
555 case V4L2_CID_AUDIO_TREBLE:
556 case V4L2_CID_AUDIO_BALANCE:
557 case V4L2_CID_AUDIO_MUTE:
558 /* Not yet supported */
559 default:
560 return -EINVAL;
561 }
562
563 return 0;
564}
565
566/* ----------------------------------------------------------------------- */
567
568#ifdef CONFIG_VIDEO_ADV_DEBUG
569static int au8522_g_register(struct v4l2_subdev *sd,
570 struct v4l2_dbg_register *reg)
571{
572 struct i2c_client *client = v4l2_get_subdevdata(sd);
573 struct au8522_state *state = to_state(sd);
574
575 if (!v4l2_chip_match_i2c_client(client, &reg->match))
576 return -EINVAL;
577 if (!capable(CAP_SYS_ADMIN))
578 return -EPERM;
579 reg->val = au8522_readreg(state, reg->reg & 0xffff);
580 return 0;
581}
582
583static int au8522_s_register(struct v4l2_subdev *sd,
584 struct v4l2_dbg_register *reg)
585{
586 struct i2c_client *client = v4l2_get_subdevdata(sd);
587 struct au8522_state *state = to_state(sd);
588
589 if (!v4l2_chip_match_i2c_client(client, &reg->match))
590 return -EINVAL;
591 if (!capable(CAP_SYS_ADMIN))
592 return -EPERM;
593 au8522_writereg(state, reg->reg, reg->val & 0xff);
594 return 0;
595}
596#endif
597
598static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
599{
600 struct au8522_state *state = to_state(sd);
601
602 if (enable) {
603 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
604 0x01);
605 msleep(1);
606 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
607 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
608 } else {
609 /* This does not completely power down the device
610 (it only reduces it from around 140ma to 80ma) */
611 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
612 1 << 5);
613 }
614 return 0;
615}
616
617static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
618{
619 switch (qc->id) {
620 case V4L2_CID_CONTRAST:
621 return v4l2_ctrl_query_fill(qc, 0, 255, 1,
622 AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
623 case V4L2_CID_BRIGHTNESS:
624 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
625 case V4L2_CID_SATURATION:
626 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
627 case V4L2_CID_HUE:
628 return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
629 default:
630 break;
631 }
632
633 qc->type = 0;
634 return -EINVAL;
635}
636
637static int au8522_reset(struct v4l2_subdev *sd, u32 val)
638{
639 struct au8522_state *state = to_state(sd);
640
641 state->operational_mode = AU8522_ANALOG_MODE;
642
643 /* Clear out any state associated with the digital side of the
644 chip, so that when it gets powered back up it won't think
645 that it is already tuned */
646 state->current_frequency = 0;
647
648 au8522_writereg(state, 0xa4, 1 << 5);
649
650 return 0;
651}
652
653static int au8522_s_video_routing(struct v4l2_subdev *sd,
654 u32 input, u32 output, u32 config)
655{
656 struct au8522_state *state = to_state(sd);
657
658 au8522_reset(sd, 0);
659
660 /* Jam open the i2c gate to the tuner. We do this here to handle the
661 case where the user went into digital mode (causing the gate to be
662 closed), and then came back to analog mode */
663 au8522_writereg(state, 0x106, 1);
664
665 if (input == AU8522_COMPOSITE_CH1) {
666 au8522_setup_cvbs_mode(state);
667 } else if (input == AU8522_SVIDEO_CH13) {
668 au8522_setup_svideo_mode(state);
669 } else if (input == AU8522_COMPOSITE_CH4_SIF) {
670 au8522_setup_cvbs_tuner_mode(state);
671 } else {
672 printk(KERN_ERR "au8522 mode not currently supported\n");
673 return -EINVAL;
674 }
675 return 0;
676}
677
678static int au8522_s_audio_routing(struct v4l2_subdev *sd,
679 u32 input, u32 output, u32 config)
680{
681 struct au8522_state *state = to_state(sd);
682 set_audio_input(state, input);
683 return 0;
684}
685
686static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
687{
688 int val = 0;
689 struct au8522_state *state = to_state(sd);
690 u8 lock_status;
691
692 /* Interrogate the decoder to see if we are getting a real signal */
693 lock_status = au8522_readreg(state, 0x00);
694 if (lock_status == 0xa2)
695 vt->signal = 0xffff;
696 else
697 vt->signal = 0x00;
698
699 vt->capability |=
700 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
701 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
702
703 val = V4L2_TUNER_SUB_MONO;
704 vt->rxsubchans = val;
705 vt->audmode = V4L2_TUNER_MODE_STEREO;
706 return 0;
707}
708
709static int au8522_g_chip_ident(struct v4l2_subdev *sd,
710 struct v4l2_dbg_chip_ident *chip)
711{
712 struct au8522_state *state = to_state(sd);
713 struct i2c_client *client = v4l2_get_subdevdata(sd);
714
715 return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
716}
717
718static int au8522_log_status(struct v4l2_subdev *sd)
719{
720 /* FIXME: Add some status info here */
721 return 0;
722}
723
724/* ----------------------------------------------------------------------- */
725
726static const struct v4l2_subdev_core_ops au8522_core_ops = {
727 .log_status = au8522_log_status,
728 .g_chip_ident = au8522_g_chip_ident,
729 .g_ctrl = au8522_g_ctrl,
730 .s_ctrl = au8522_s_ctrl,
731 .queryctrl = au8522_queryctrl,
732 .reset = au8522_reset,
733#ifdef CONFIG_VIDEO_ADV_DEBUG
734 .g_register = au8522_g_register,
735 .s_register = au8522_s_register,
736#endif
737};
738
739static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
740 .g_tuner = au8522_g_tuner,
741};
742
743static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
744 .s_routing = au8522_s_audio_routing,
745};
746
747static const struct v4l2_subdev_video_ops au8522_video_ops = {
748 .s_routing = au8522_s_video_routing,
749 .s_stream = au8522_s_stream,
750};
751
752static const struct v4l2_subdev_ops au8522_ops = {
753 .core = &au8522_core_ops,
754 .tuner = &au8522_tuner_ops,
755 .audio = &au8522_audio_ops,
756 .video = &au8522_video_ops,
757};
758
759/* ----------------------------------------------------------------------- */
760
761static int au8522_probe(struct i2c_client *client,
762 const struct i2c_device_id *did)
763{
764 struct au8522_state *state;
765 struct v4l2_subdev *sd;
766 int instance;
767 struct au8522_config *demod_config;
768
769 /* Check if the adapter supports the needed features */
770 if (!i2c_check_functionality(client->adapter,
771 I2C_FUNC_SMBUS_BYTE_DATA)) {
772 return -EIO;
773 }
774
775 /* allocate memory for the internal state */
776 instance = au8522_get_state(&state, client->adapter, client->addr);
777 switch (instance) {
778 case 0:
779 printk(KERN_ERR "au8522_decoder allocation failed\n");
780 return -EIO;
781 case 1:
782 /* new demod instance */
783 printk(KERN_INFO "au8522_decoder creating new instance...\n");
784 break;
785 default:
786 /* existing demod instance */
787 printk(KERN_INFO "au8522_decoder attach existing instance.\n");
788 break;
789 }
790
791 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
792 if (demod_config == NULL) {
793 if (instance == 1)
794 kfree(state);
795 return -ENOMEM;
796 }
797 demod_config->demod_address = 0x8e >> 1;
798
799 state->config = demod_config;
800 state->i2c = client->adapter;
801
802 sd = &state->sd;
803 v4l2_i2c_subdev_init(sd, client, &au8522_ops);
804
805 state->c = client;
806 state->vid_input = AU8522_COMPOSITE_CH1;
807 state->aud_input = AU8522_AUDIO_NONE;
808 state->id = 8522;
809 state->rev = 0;
810
811 /* Jam open the i2c gate to the tuner */
812 au8522_writereg(state, 0x106, 1);
813
814 return 0;
815}
816
817static int au8522_remove(struct i2c_client *client)
818{
819 struct v4l2_subdev *sd = i2c_get_clientdata(client);
820 v4l2_device_unregister_subdev(sd);
821 au8522_release_state(to_state(sd));
822 return 0;
823}
824
825static const struct i2c_device_id au8522_id[] = {
826 {"au8522", 0},
827 {}
828};
829
830MODULE_DEVICE_TABLE(i2c, au8522_id);
831
832static struct i2c_driver au8522_driver = {
833 .driver = {
834 .owner = THIS_MODULE,
835 .name = "au8522",
836 },
837 .probe = au8522_probe,
838 .remove = au8522_remove,
839 .id_table = au8522_id,
840};
841
842static __init int init_au8522(void)
843{
844 return i2c_add_driver(&au8522_driver);
845}
846
847static __exit void exit_au8522(void)
848{
849 i2c_del_driver(&au8522_driver);
850}
851
852module_init(init_au8522);
853module_exit(exit_au8522);