blob: 5ec8697064096838803a6024b28c80e8703d9793 [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
Devin Heitmueller968cf782009-03-11 03:00:38 -030026 * 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>
Devin Heitmueller968cf782009-03-11 03:00:38 -030039#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
Devin Heitmueller968cf782009-03-11 03:00:38 -030048
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
Devin Heitmueller968cf782009-03-11 03:00:38 -030054struct 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*/
Márton Némethc86a3c32009-12-13 17:19:37 -030064static const struct au8522_register_config filter_coef[] = {
Devin Heitmueller62899a22009-03-15 18:48:52 -030065 {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} },
Devin Heitmueller968cf782009-03-11 03:00:38 -030095
96};
Devin Heitmueller62899a22009-03-15 18:48:52 -030097#define NUM_FILTER_COEF (sizeof(filter_coef)\
98 / sizeof(struct au8522_register_config))
Devin Heitmueller968cf782009-03-11 03:00:38 -030099
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*/
Márton Némethc86a3c32009-12-13 17:19:37 -0300106static const struct au8522_register_config lpfilter_coef[] = {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300107 {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} },
Devin Heitmueller968cf782009-03-11 03:00:38 -0300179};
Devin Heitmueller62899a22009-03-15 18:48:52 -0300180#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
181 / sizeof(struct au8522_register_config))
Devin Heitmueller968cf782009-03-11 03:00:38 -0300182
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);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300202 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);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300208
209 /* Setup the VBI registers */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300210 for (i = 0x30; i < 0x60; i++)
Devin Heitmueller968cf782009-03-11 03:00:38 -0300211 au8522_writereg(state, i, 0x40);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300212
Devin Heitmueller968cf782009-03-11 03:00:38 -0300213 /* 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);
Devin Heitmueller36a91872009-10-13 23:32:29 -0300237 state->saturation = 0x80;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300238 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
239 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
Devin Heitmueller36a91872009-10-13 23:32:29 -0300240 state->hue = 0x00;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300241
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 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);
312
313 setup_vbi(state, 0);
314
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
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200318 to be in CVBS mode for the S-Video input (reason unknown). */
Devin Heitmueller968cf782009-03-11 03:00:38 -0300319 /* filter_coef_type = 3; */
320 filter_coef_type = 5;
321 } else {
322 filter_coef_type = 5;
323 }
324
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]);
329 }
330
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);
342}
343
344static void au8522_setup_cvbs_mode(struct au8522_state *state)
345{
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);
349
Devin Heitmuellerd2c194c2010-06-27 18:01:40 -0300350 /* PGA in automatic mode */
Devin Heitmueller968cf782009-03-11 03:00:38 -0300351 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
Devin Heitmuellerd2c194c2010-06-27 18:01:40 -0300352
353 /* Enable clamping control */
354 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300355
356 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
357 AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
358
359 setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
360
361 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
362 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
363}
364
365static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
366{
367 /* here we're going to try the pre-programmed route */
368 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
369 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
370
Devin Heitmuellerd2c194c2010-06-27 18:01:40 -0300371 /* It's not clear why we have to have the PGA in automatic mode while
372 enabling clamp control, but it's what Windows does */
Devin Heitmueller968cf782009-03-11 03:00:38 -0300373 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
374
375 /* Enable clamping control */
376 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
377
Devin Heitmuellerd2c194c2010-06-27 18:01:40 -0300378 /* Disable automatic PGA (since the CVBS is coming from the tuner) */
Devin Heitmueller968cf782009-03-11 03:00:38 -0300379 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
380
381 /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
382 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
383 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
384
385 setup_decoder_defaults(state,
386 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
387
388 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
389 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
390}
391
392static void au8522_setup_svideo_mode(struct au8522_state *state)
393{
394 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
395 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
396
397 /* Set input to Y on Channe1, C on Channel 3 */
398 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
399 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
400
Devin Heitmuellerd2c194c2010-06-27 18:01:40 -0300401 /* PGA in automatic mode */
402 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
403
404 /* Enable clamping control */
Devin Heitmueller968cf782009-03-11 03:00:38 -0300405 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
406
407 setup_decoder_defaults(state,
408 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
409
410 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
411 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
412}
413
414/* ----------------------------------------------------------------------- */
415
416static void disable_audio_input(struct au8522_state *state)
417{
Devin Heitmueller968cf782009-03-11 03:00:38 -0300418 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
419 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
420 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300421
422 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300423 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
424
425 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
Devin Heitmueller2428a2e2010-06-27 17:40:42 -0300426 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300427}
428
429/* 0=disable, 1=SIF */
430static void set_audio_input(struct au8522_state *state, int aud_input)
431{
432 int i;
433
434 /* Note that this function needs to be used in conjunction with setting
435 the input routing via register 0x81 */
436
437 if (aud_input == AU8522_AUDIO_NONE) {
438 disable_audio_input(state);
439 return;
440 }
441
442 if (aud_input != AU8522_AUDIO_SIF) {
443 /* The caller asked for a mode we don't currently support */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300444 printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
Devin Heitmueller968cf782009-03-11 03:00:38 -0300445 aud_input);
446 return;
447 }
448
449 /* Load the Audio Decoder Filter Coefficients */
450 for (i = 0; i < NUM_LPFILTER_COEF; i++) {
451 au8522_writereg(state, lpfilter_coef[i].reg_name,
452 lpfilter_coef[i].reg_val[0]);
453 }
454
455 /* Setup audio */
456 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
457 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
458 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
459 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
460 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
461 msleep(150);
462 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
463 msleep(1);
464 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
465 msleep(50);
466 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
467 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
468 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
469 msleep(80);
470 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
471 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
472 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
473 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
474 msleep(70);
475 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
476 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
477 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
478}
479
480/* ----------------------------------------------------------------------- */
481
482static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
483{
484 struct au8522_state *state = to_state(sd);
485
486 switch (ctrl->id) {
487 case V4L2_CID_BRIGHTNESS:
488 state->brightness = ctrl->value;
489 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
490 ctrl->value - 128);
491 break;
492 case V4L2_CID_CONTRAST:
493 state->contrast = ctrl->value;
494 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
495 ctrl->value);
496 break;
497 case V4L2_CID_SATURATION:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300498 state->saturation = ctrl->value;
499 au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
500 ctrl->value);
501 au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
502 ctrl->value);
503 break;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300504 case V4L2_CID_HUE:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300505 state->hue = ctrl->value;
506 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
507 ctrl->value >> 8);
508 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
509 ctrl->value & 0xFF);
510 break;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300511 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:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300540 ctrl->value = state->saturation;
541 break;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300542 case V4L2_CID_HUE:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300543 ctrl->value = state->hue;
544 break;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300545 case V4L2_CID_AUDIO_VOLUME:
546 case V4L2_CID_AUDIO_BASS:
547 case V4L2_CID_AUDIO_TREBLE:
548 case V4L2_CID_AUDIO_BALANCE:
549 case V4L2_CID_AUDIO_MUTE:
550 /* Not yet supported */
551 default:
552 return -EINVAL;
553 }
554
555 return 0;
556}
557
558/* ----------------------------------------------------------------------- */
559
Devin Heitmueller968cf782009-03-11 03:00:38 -0300560#ifdef CONFIG_VIDEO_ADV_DEBUG
561static int au8522_g_register(struct v4l2_subdev *sd,
562 struct v4l2_dbg_register *reg)
563{
564 struct i2c_client *client = v4l2_get_subdevdata(sd);
565 struct au8522_state *state = to_state(sd);
566
567 if (!v4l2_chip_match_i2c_client(client, &reg->match))
568 return -EINVAL;
569 if (!capable(CAP_SYS_ADMIN))
570 return -EPERM;
571 reg->val = au8522_readreg(state, reg->reg & 0xffff);
572 return 0;
573}
574
575static int au8522_s_register(struct v4l2_subdev *sd,
576 struct v4l2_dbg_register *reg)
577{
578 struct i2c_client *client = v4l2_get_subdevdata(sd);
579 struct au8522_state *state = to_state(sd);
580
581 if (!v4l2_chip_match_i2c_client(client, &reg->match))
582 return -EINVAL;
583 if (!capable(CAP_SYS_ADMIN))
584 return -EPERM;
585 au8522_writereg(state, reg->reg, reg->val & 0xff);
586 return 0;
587}
588#endif
589
590static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
591{
592 struct au8522_state *state = to_state(sd);
593
594 if (enable) {
595 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
596 0x01);
597 msleep(1);
598 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
599 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
600 } else {
601 /* This does not completely power down the device
602 (it only reduces it from around 140ma to 80ma) */
603 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
604 1 << 5);
605 }
606 return 0;
607}
608
609static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
610{
611 switch (qc->id) {
612 case V4L2_CID_CONTRAST:
613 return v4l2_ctrl_query_fill(qc, 0, 255, 1,
614 AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
615 case V4L2_CID_BRIGHTNESS:
Devin Heitmueller88464102010-06-13 17:31:22 -0300616 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300617 case V4L2_CID_SATURATION:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300618 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300619 case V4L2_CID_HUE:
Devin Heitmueller36a91872009-10-13 23:32:29 -0300620 return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300621 default:
622 break;
623 }
624
Devin Heitmuellerd9109be2009-03-11 03:00:58 -0300625 qc->type = 0;
Devin Heitmueller968cf782009-03-11 03:00:38 -0300626 return -EINVAL;
627}
628
629static int au8522_reset(struct v4l2_subdev *sd, u32 val)
630{
631 struct au8522_state *state = to_state(sd);
632
Devin Heitmueller7f2c9832010-02-17 22:47:55 -0300633 state->operational_mode = AU8522_ANALOG_MODE;
634
Devin Heitmuellerb628a2a2010-02-17 22:51:46 -0300635 /* Clear out any state associated with the digital side of the
636 chip, so that when it gets powered back up it won't think
637 that it is already tuned */
638 state->current_frequency = 0;
639
Devin Heitmueller968cf782009-03-11 03:00:38 -0300640 au8522_writereg(state, 0xa4, 1 << 5);
641
642 return 0;
643}
644
645static int au8522_s_video_routing(struct v4l2_subdev *sd,
Hans Verkuil5325b422009-04-02 11:26:22 -0300646 u32 input, u32 output, u32 config)
Devin Heitmueller968cf782009-03-11 03:00:38 -0300647{
648 struct au8522_state *state = to_state(sd);
649
650 au8522_reset(sd, 0);
651
652 /* Jam open the i2c gate to the tuner. We do this here to handle the
653 case where the user went into digital mode (causing the gate to be
654 closed), and then came back to analog mode */
655 au8522_writereg(state, 0x106, 1);
656
Hans Verkuil5325b422009-04-02 11:26:22 -0300657 if (input == AU8522_COMPOSITE_CH1) {
Devin Heitmueller968cf782009-03-11 03:00:38 -0300658 au8522_setup_cvbs_mode(state);
Hans Verkuil5325b422009-04-02 11:26:22 -0300659 } else if (input == AU8522_SVIDEO_CH13) {
Devin Heitmueller968cf782009-03-11 03:00:38 -0300660 au8522_setup_svideo_mode(state);
Hans Verkuil5325b422009-04-02 11:26:22 -0300661 } else if (input == AU8522_COMPOSITE_CH4_SIF) {
Devin Heitmueller968cf782009-03-11 03:00:38 -0300662 au8522_setup_cvbs_tuner_mode(state);
663 } else {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300664 printk(KERN_ERR "au8522 mode not currently supported\n");
Devin Heitmueller968cf782009-03-11 03:00:38 -0300665 return -EINVAL;
666 }
667 return 0;
668}
669
670static int au8522_s_audio_routing(struct v4l2_subdev *sd,
Hans Verkuil5325b422009-04-02 11:26:22 -0300671 u32 input, u32 output, u32 config)
Devin Heitmueller968cf782009-03-11 03:00:38 -0300672{
673 struct au8522_state *state = to_state(sd);
Hans Verkuil5325b422009-04-02 11:26:22 -0300674 set_audio_input(state, input);
Devin Heitmueller968cf782009-03-11 03:00:38 -0300675 return 0;
676}
677
678static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
679{
680 int val = 0;
681 struct au8522_state *state = to_state(sd);
682 u8 lock_status;
683
684 /* Interrogate the decoder to see if we are getting a real signal */
685 lock_status = au8522_readreg(state, 0x00);
686 if (lock_status == 0xa2)
687 vt->signal = 0x01;
688 else
689 vt->signal = 0x00;
690
691 vt->capability |=
692 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
693 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
694
695 val = V4L2_TUNER_SUB_MONO;
696 vt->rxsubchans = val;
697 vt->audmode = V4L2_TUNER_MODE_STEREO;
698 return 0;
699}
700
701static int au8522_g_chip_ident(struct v4l2_subdev *sd,
702 struct v4l2_dbg_chip_ident *chip)
703{
704 struct au8522_state *state = to_state(sd);
705 struct i2c_client *client = v4l2_get_subdevdata(sd);
706
707 return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
708}
709
710static int au8522_log_status(struct v4l2_subdev *sd)
711{
712 /* FIXME: Add some status info here */
713 return 0;
714}
715
Devin Heitmueller968cf782009-03-11 03:00:38 -0300716/* ----------------------------------------------------------------------- */
717
718static const struct v4l2_subdev_core_ops au8522_core_ops = {
719 .log_status = au8522_log_status,
720 .g_chip_ident = au8522_g_chip_ident,
721 .g_ctrl = au8522_g_ctrl,
722 .s_ctrl = au8522_s_ctrl,
723 .queryctrl = au8522_queryctrl,
724 .reset = au8522_reset,
725#ifdef CONFIG_VIDEO_ADV_DEBUG
726 .g_register = au8522_g_register,
727 .s_register = au8522_s_register,
728#endif
729};
730
731static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
732 .g_tuner = au8522_g_tuner,
733};
734
735static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
736 .s_routing = au8522_s_audio_routing,
737};
738
739static const struct v4l2_subdev_video_ops au8522_video_ops = {
740 .s_routing = au8522_s_video_routing,
Devin Heitmueller968cf782009-03-11 03:00:38 -0300741 .s_stream = au8522_s_stream,
742};
743
744static const struct v4l2_subdev_ops au8522_ops = {
745 .core = &au8522_core_ops,
746 .tuner = &au8522_tuner_ops,
747 .audio = &au8522_audio_ops,
748 .video = &au8522_video_ops,
749};
750
751/* ----------------------------------------------------------------------- */
752
753static int au8522_probe(struct i2c_client *client,
754 const struct i2c_device_id *did)
755{
756 struct au8522_state *state;
757 struct v4l2_subdev *sd;
758 int instance;
759 struct au8522_config *demod_config;
760
761 /* Check if the adapter supports the needed features */
762 if (!i2c_check_functionality(client->adapter,
763 I2C_FUNC_SMBUS_BYTE_DATA)) {
764 return -EIO;
765 }
766
767 /* allocate memory for the internal state */
768 instance = au8522_get_state(&state, client->adapter, client->addr);
769 switch (instance) {
770 case 0:
Devin Heitmueller62899a22009-03-15 18:48:52 -0300771 printk(KERN_ERR "au8522_decoder allocation failed\n");
Devin Heitmueller968cf782009-03-11 03:00:38 -0300772 return -EIO;
773 case 1:
774 /* new demod instance */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300775 printk(KERN_INFO "au8522_decoder creating new instance...\n");
Devin Heitmueller968cf782009-03-11 03:00:38 -0300776 break;
777 default:
778 /* existing demod instance */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300779 printk(KERN_INFO "au8522_decoder attach existing instance.\n");
Devin Heitmueller968cf782009-03-11 03:00:38 -0300780 break;
781 }
782
783 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
Roel Kluin40d29512009-09-18 21:03:34 -0300784 if (demod_config == NULL) {
785 if (instance == 1)
786 kfree(state);
787 return -ENOMEM;
788 }
Devin Heitmueller968cf782009-03-11 03:00:38 -0300789 demod_config->demod_address = 0x8e >> 1;
790
791 state->config = demod_config;
792 state->i2c = client->adapter;
793
794 sd = &state->sd;
795 v4l2_i2c_subdev_init(sd, client, &au8522_ops);
796
797 state->c = client;
798 state->vid_input = AU8522_COMPOSITE_CH1;
799 state->aud_input = AU8522_AUDIO_NONE;
800 state->id = 8522;
801 state->rev = 0;
802
803 /* Jam open the i2c gate to the tuner */
804 au8522_writereg(state, 0x106, 1);
805
806 return 0;
807}
808
809static int au8522_remove(struct i2c_client *client)
810{
811 struct v4l2_subdev *sd = i2c_get_clientdata(client);
812 v4l2_device_unregister_subdev(sd);
813 au8522_release_state(to_state(sd));
814 return 0;
815}
816
817static const struct i2c_device_id au8522_id[] = {
818 {"au8522", 0},
819 {}
820};
821
822MODULE_DEVICE_TABLE(i2c, au8522_id);
823
Hans Verkuil978cff62010-09-15 15:52:25 -0300824static struct i2c_driver au8522_driver = {
825 .driver = {
826 .owner = THIS_MODULE,
827 .name = "au8522",
828 },
829 .probe = au8522_probe,
830 .remove = au8522_remove,
831 .id_table = au8522_id,
Devin Heitmueller968cf782009-03-11 03:00:38 -0300832};
Hans Verkuil978cff62010-09-15 15:52:25 -0300833
834static __init int init_au8522(void)
835{
836 return i2c_add_driver(&au8522_driver);
837}
838
839static __exit void exit_au8522(void)
840{
841 i2c_del_driver(&au8522_driver);
842}
843
844module_init(init_au8522);
845module_exit(exit_au8522);