aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/au8522_decoder.c
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@linuxtv.org>2009-03-11 02:00:38 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:25 -0400
commit968cf78285ef03672ae514e9ad7a60919eb97551 (patch)
treec26377d32cdff87748b38c82c436c97806763dfb /drivers/media/dvb/frontends/au8522_decoder.c
parent209fdf66b8699a6b2998b58e572d67230dae507f (diff)
V4L/DVB (11065): au8522: add support for analog side of demodulator
Add support for the analog functionality in the au8522 analog/digital demodulator Thanks to Michael Krufky <mkrufky@linuxtv.org> and Steven Toth <stoth@linuxtv.org> for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> [mchehab: renamed drivers/media/video/au8522_decoder.c as drivers/media/dvb/frontends/au8522_decoder.c to avoid breaking bisect] Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends/au8522_decoder.c')
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c839
1 files changed, 839 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 000000000000..e2927c145cd8
--- /dev/null
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -0,0 +1,839 @@
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 * 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[] = {
70 {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}},
100
101};
102#define NUM_FILTER_COEF (sizeof (filter_coef) / sizeof(struct au8522_register_config))
103
104
105/* Registers 0x060b through 0x0652 are the LP Filter coefficients
106 The values are as follows from left to right
107 0="SIF" 1="ATVRF/ATVRF13"
108 Note: the "ATVRF/ATVRF13" mode has never been tested
109*/
110struct au8522_register_config lpfilter_coef[] = {
111 {0x060b, {0x21, 0x0b}},
112 {0x060c, {0xad, 0xad}},
113 {0x060d, {0x70, 0xf0}},
114 {0x060e, {0xea, 0xe9}},
115 {0x060f, {0xdd, 0xdd}},
116 {0x0610, {0x08, 0x64}},
117 {0x0611, {0x60, 0x60}},
118 {0x0612, {0xf8, 0xb2}},
119 {0x0613, {0x01, 0x02}},
120 {0x0614, {0xe4, 0xb4}},
121 {0x0615, {0x19, 0x02}},
122 {0x0616, {0xae, 0x2e}},
123 {0x0617, {0xee, 0xc5}},
124 {0x0618, {0x56, 0x56}},
125 {0x0619, {0x30, 0x58}},
126 {0x061a, {0xf9, 0xf8}},
127 {0x061b, {0x24, 0x64}},
128 {0x061c, {0x07, 0x07}},
129 {0x061d, {0x30, 0x30}},
130 {0x061e, {0xa9, 0xed}},
131 {0x061f, {0x09, 0x0b}},
132 {0x0620, {0x42, 0xc2}},
133 {0x0621, {0x1d, 0x2a}},
134 {0x0622, {0xd6, 0x56}},
135 {0x0623, {0x95, 0x8b}},
136 {0x0624, {0x2b, 0x2b}},
137 {0x0625, {0x30, 0x24}},
138 {0x0626, {0x3e, 0x3e}},
139 {0x0627, {0x62, 0xe2}},
140 {0x0628, {0xe9, 0xf5}},
141 {0x0629, {0x99, 0x19}},
142 {0x062a, {0xd4, 0x11}},
143 {0x062b, {0x03, 0x04}},
144 {0x062c, {0xb5, 0x85}},
145 {0x062d, {0x1e, 0x20}},
146 {0x062e, {0x2a, 0xea}},
147 {0x062f, {0xd7, 0xd2}},
148 {0x0630, {0x15, 0x15}},
149 {0x0631, {0xa3, 0xa9}},
150 {0x0632, {0x1f, 0x1f}},
151 {0x0633, {0xf9, 0xd1}},
152 {0x0634, {0xc0, 0xc3}},
153 {0x0635, {0x4d, 0x8d}},
154 {0x0636, {0x21, 0x31}},
155 {0x0637, {0x83, 0x83}},
156 {0x0638, {0x08, 0x8c}},
157 {0x0639, {0x19, 0x19}},
158 {0x063a, {0x45, 0xa5}},
159 {0x063b, {0xef, 0xec}},
160 {0x063c, {0x8a, 0x8a}},
161 {0x063d, {0xf4, 0xf6}},
162 {0x063e, {0x8f, 0x8f}},
163 {0x063f, {0x44, 0x0c}},
164 {0x0640, {0xef, 0xf0}},
165 {0x0641, {0x66, 0x66}},
166 {0x0642, {0xcc, 0xd2}},
167 {0x0643, {0x41, 0x41}},
168 {0x0644, {0x63, 0x93}},
169 {0x0645, {0x8e, 0x8e}},
170 {0x0646, {0xa2, 0x42}},
171 {0x0647, {0x7b, 0x7b}},
172 {0x0648, {0x04, 0x04}},
173 {0x0649, {0x00, 0x00}},
174 {0x064a, {0x40, 0x40}},
175 {0x064b, {0x8c, 0x98}},
176 {0x064c, {0x00, 0x00}},
177 {0x064d, {0x63, 0xc3}},
178 {0x064e, {0x04, 0x04}},
179 {0x064f, {0x20, 0x20}},
180 {0x0650, {0x00, 0x00}},
181 {0x0651, {0x40 ,0x40}},
182 {0x0652, {0x01, 0x01}},
183};
184#define NUM_LPFILTER_COEF (sizeof (lpfilter_coef) / sizeof(struct au8522_register_config))
185
186static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
187{
188 return container_of(sd, struct au8522_state, sd);
189}
190
191static void setup_vbi(struct au8522_state *state, int aud_input)
192{
193 int i;
194
195 /* These are set to zero regardless of what mode we're in */
196 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
197 au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
198 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
199 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
200 au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
201 au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
202 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
203 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
204 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
205 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,0x00);
206 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,0x00);
207 au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,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 au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
238 au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
239
240 /* Other decoder registers */
241 au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
242
243 if (input_mode == 0x23) {
244 /* S-Video input mapping */
245 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
246 } else {
247 /* All other modes (CVBS/ATVRF etc.) */
248 au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
249 }
250
251 au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
252 AU8522_TVDEC_PGA_REG012H_CVBS);
253 au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
254 AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
255 au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
256 AU8522_TVDED_DBG_MODE_REG060H_CVBS);
257 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
258 AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
259 au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
260 AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
261 au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
262 AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
263 au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
264 AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
265 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
266 AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
267 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
268 AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
269 au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
270 AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
271 au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
272 AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
273 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
274 AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
275 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
276 AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
277 au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
278 AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
279 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
280 AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
281 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
282 AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
283 au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
284 AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
285 au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
286 AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
287 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
288 AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
289 au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
290 au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
291 au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
292 AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
293 au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
294 au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
295 au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
296 AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
297 au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
298 AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
299 au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
300 AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
301 au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
302 AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
303 au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
304 AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
305 au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
306 AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
307 au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
308 AU8522_TOREGAAGC_REG0E5H_CVBS);
309 au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
310
311 setup_vbi(state, 0);
312
313 if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
314 input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
315 /* Despite what the table says, for the HVR-950q we still need
316 to be in CVBS mode for the S-Video input (reason uknown). */
317 /* filter_coef_type = 3; */
318 filter_coef_type = 5;
319 } else {
320 filter_coef_type = 5;
321 }
322
323 /* Load the Video Decoder Filter Coefficients */
324 for (i = 0; i < NUM_FILTER_COEF; i++) {
325 au8522_writereg(state, filter_coef[i].reg_name,
326 filter_coef[i].reg_val[filter_coef_type]);
327 }
328
329 /* It's not clear what these registers are for, but they are always
330 set to the same value regardless of what mode we're in */
331 au8522_writereg(state, AU8522_REG42EH, 0x87);
332 au8522_writereg(state, AU8522_REG42FH, 0xa2);
333 au8522_writereg(state, AU8522_REG430H, 0xbf);
334 au8522_writereg(state, AU8522_REG431H, 0xcb);
335 au8522_writereg(state, AU8522_REG432H, 0xa1);
336 au8522_writereg(state, AU8522_REG433H, 0x41);
337 au8522_writereg(state, AU8522_REG434H, 0x88);
338 au8522_writereg(state, AU8522_REG435H, 0xc2);
339 au8522_writereg(state, AU8522_REG436H, 0x3c);
340}
341
342static void au8522_setup_cvbs_mode(struct au8522_state *state)
343{
344 /* here we're going to try the pre-programmed route */
345 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
346 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
347
348 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
349 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
350 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
351
352 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
353 AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
354
355 setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
356
357 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
358 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
359}
360
361static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
362{
363 /* here we're going to try the pre-programmed route */
364 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
365 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
366
367 /* It's not clear why they turn off the PGA before enabling the clamp
368 control, but the Windows trace does it so we will too... */
369 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
370
371 /* Enable clamping control */
372 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
373
374 /* Turn on the PGA */
375 au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
376
377 /* Set input mode to CVBS on channel 4 with SIF audio input enabled */
378 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
379 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
380
381 setup_decoder_defaults(state,
382 AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
383
384 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
385 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
386}
387
388static void au8522_setup_svideo_mode(struct au8522_state *state)
389{
390 au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
391 AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
392
393 /* Set input to Y on Channe1, C on Channel 3 */
394 au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
395 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
396
397 /* Disable clamping control (required for S-video) */
398 au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
399
400 setup_decoder_defaults(state,
401 AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
402
403 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
404 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
405}
406
407/* ----------------------------------------------------------------------- */
408
409static void disable_audio_input(struct au8522_state *state)
410{
411 /* This can probably be optimized */
412 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
413 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
414 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
415 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
416 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
417
418 au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
419 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
420 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
421 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
422 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
423
424 au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
425 msleep(5);
426 au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
427
428 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
429 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
430 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
431
432 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
433 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
434}
435
436/* 0=disable, 1=SIF */
437static void set_audio_input(struct au8522_state *state, int aud_input)
438{
439 int i;
440
441 /* Note that this function needs to be used in conjunction with setting
442 the input routing via register 0x81 */
443
444 if (aud_input == AU8522_AUDIO_NONE) {
445 disable_audio_input(state);
446 return;
447 }
448
449 if (aud_input != AU8522_AUDIO_SIF) {
450 /* The caller asked for a mode we don't currently support */
451 printk("Unsupported audio mode requested! mode=%d\n",
452 aud_input);
453 return;
454 }
455
456 /* Load the Audio Decoder Filter Coefficients */
457 for (i = 0; i < NUM_LPFILTER_COEF; i++) {
458 au8522_writereg(state, lpfilter_coef[i].reg_name,
459 lpfilter_coef[i].reg_val[0]);
460 }
461
462 /* Setup audio */
463 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
464 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
465 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
466 au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
467 au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
468 msleep(150);
469 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
470 msleep(1);
471 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
472 msleep(50);
473 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
474 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
475 au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
476 msleep(80);
477 au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
478 au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
479 au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
480 au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
481 msleep(70);
482 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
483 au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
484 au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
485}
486
487/* ----------------------------------------------------------------------- */
488
489static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
490{
491 struct au8522_state *state = to_state(sd);
492
493 switch (ctrl->id) {
494 case V4L2_CID_BRIGHTNESS:
495 state->brightness = ctrl->value;
496 au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
497 ctrl->value - 128);
498 break;
499 case V4L2_CID_CONTRAST:
500 state->contrast = ctrl->value;
501 au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
502 ctrl->value);
503 break;
504 case V4L2_CID_SATURATION:
505 case V4L2_CID_HUE:
506 case V4L2_CID_AUDIO_VOLUME:
507 case V4L2_CID_AUDIO_BASS:
508 case V4L2_CID_AUDIO_TREBLE:
509 case V4L2_CID_AUDIO_BALANCE:
510 case V4L2_CID_AUDIO_MUTE:
511 /* Not yet implemented */
512 default:
513 return -EINVAL;
514 }
515
516 return 0;
517}
518
519static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
520{
521 struct au8522_state *state = to_state(sd);
522
523 /* Note that we are using values cached in the state structure instead
524 of reading the registers due to issues with i2c reads not working
525 properly/consistently yet on the HVR-950q */
526
527 switch (ctrl->id) {
528 case V4L2_CID_BRIGHTNESS:
529 ctrl->value = state->brightness;
530 break;
531 case V4L2_CID_CONTRAST:
532 ctrl->value = state->contrast;
533 break;
534 case V4L2_CID_SATURATION:
535 case V4L2_CID_HUE:
536 case V4L2_CID_AUDIO_VOLUME:
537 case V4L2_CID_AUDIO_BASS:
538 case V4L2_CID_AUDIO_TREBLE:
539 case V4L2_CID_AUDIO_BALANCE:
540 case V4L2_CID_AUDIO_MUTE:
541 /* Not yet supported */
542 default:
543 return -EINVAL;
544 }
545
546 return 0;
547}
548
549/* ----------------------------------------------------------------------- */
550
551static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
552{
553 switch (fmt->type) {
554 default:
555 return -EINVAL;
556 }
557 return 0;
558}
559
560static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
561{
562 switch (fmt->type) {
563 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
564 /* Not yet implemented */
565 break;
566 default:
567 return -EINVAL;
568 }
569
570 return 0;
571}
572
573/* ----------------------------------------------------------------------- */
574
575#ifdef CONFIG_VIDEO_ADV_DEBUG
576static int au8522_g_register(struct v4l2_subdev *sd,
577 struct v4l2_dbg_register *reg)
578{
579 struct i2c_client *client = v4l2_get_subdevdata(sd);
580 struct au8522_state *state = to_state(sd);
581
582 if (!v4l2_chip_match_i2c_client(client, &reg->match))
583 return -EINVAL;
584 if (!capable(CAP_SYS_ADMIN))
585 return -EPERM;
586 reg->val = au8522_readreg(state, reg->reg & 0xffff);
587 return 0;
588}
589
590static int au8522_s_register(struct v4l2_subdev *sd,
591 struct v4l2_dbg_register *reg)
592{
593 struct i2c_client *client = v4l2_get_subdevdata(sd);
594 struct au8522_state *state = to_state(sd);
595
596 if (!v4l2_chip_match_i2c_client(client, &reg->match))
597 return -EINVAL;
598 if (!capable(CAP_SYS_ADMIN))
599 return -EPERM;
600 au8522_writereg(state, reg->reg, reg->val & 0xff);
601 return 0;
602}
603#endif
604
605static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
606{
607 struct au8522_state *state = to_state(sd);
608
609 if (enable) {
610 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
611 0x01);
612 msleep(1);
613 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
614 AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
615 } else {
616 /* This does not completely power down the device
617 (it only reduces it from around 140ma to 80ma) */
618 au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
619 1 << 5);
620 }
621 return 0;
622}
623
624static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
625{
626 switch (qc->id) {
627 case V4L2_CID_CONTRAST:
628 return v4l2_ctrl_query_fill(qc, 0, 255, 1,
629 AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
630 case V4L2_CID_BRIGHTNESS:
631 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
632 case V4L2_CID_SATURATION:
633 case V4L2_CID_HUE:
634 /* Not yet implemented */
635 default:
636 break;
637 }
638
639 return -EINVAL;
640}
641
642static int au8522_reset(struct v4l2_subdev *sd, u32 val)
643{
644 struct au8522_state *state = to_state(sd);
645
646 au8522_writereg(state, 0xa4, 1 << 5);
647
648 return 0;
649}
650
651static int au8522_s_video_routing(struct v4l2_subdev *sd,
652 const struct v4l2_routing *route)
653{
654 struct au8522_state *state = to_state(sd);
655
656 au8522_reset(sd, 0);
657
658 /* Jam open the i2c gate to the tuner. We do this here to handle the
659 case where the user went into digital mode (causing the gate to be
660 closed), and then came back to analog mode */
661 au8522_writereg(state, 0x106, 1);
662
663 if (route->input == AU8522_COMPOSITE_CH1) {
664 au8522_setup_cvbs_mode(state);
665 } else if (route->input == AU8522_SVIDEO_CH13) {
666 au8522_setup_svideo_mode(state);
667 } else if (route->input == AU8522_COMPOSITE_CH4_SIF) {
668 au8522_setup_cvbs_tuner_mode(state);
669 } else {
670 printk("au8522 mode not currently supported\n");
671 return -EINVAL;
672 }
673 return 0;
674}
675
676static int au8522_s_audio_routing(struct v4l2_subdev *sd,
677 const struct v4l2_routing *route)
678{
679 struct au8522_state *state = to_state(sd);
680 set_audio_input(state, route->input);
681 return 0;
682}
683
684static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
685{
686 int val = 0;
687 struct au8522_state *state = to_state(sd);
688 u8 lock_status;
689
690 /* Interrogate the decoder to see if we are getting a real signal */
691 lock_status = au8522_readreg(state, 0x00);
692 if (lock_status == 0xa2)
693 vt->signal = 0x01;
694 else
695 vt->signal = 0x00;
696
697 vt->capability |=
698 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
699 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
700
701 val = V4L2_TUNER_SUB_MONO;
702 vt->rxsubchans = val;
703 vt->audmode = V4L2_TUNER_MODE_STEREO;
704 return 0;
705}
706
707static int au8522_g_chip_ident(struct v4l2_subdev *sd,
708 struct v4l2_dbg_chip_ident *chip)
709{
710 struct au8522_state *state = to_state(sd);
711 struct i2c_client *client = v4l2_get_subdevdata(sd);
712
713 return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
714}
715
716static int au8522_log_status(struct v4l2_subdev *sd)
717{
718 /* FIXME: Add some status info here */
719 return 0;
720}
721
722static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg)
723{
724 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
725}
726
727/* ----------------------------------------------------------------------- */
728
729static const struct v4l2_subdev_core_ops au8522_core_ops = {
730 .log_status = au8522_log_status,
731 .g_chip_ident = au8522_g_chip_ident,
732 .g_ctrl = au8522_g_ctrl,
733 .s_ctrl = au8522_s_ctrl,
734 .queryctrl = au8522_queryctrl,
735 .reset = au8522_reset,
736#ifdef CONFIG_VIDEO_ADV_DEBUG
737 .g_register = au8522_g_register,
738 .s_register = au8522_s_register,
739#endif
740};
741
742static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
743 .g_tuner = au8522_g_tuner,
744};
745
746static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
747 .s_routing = au8522_s_audio_routing,
748};
749
750static const struct v4l2_subdev_video_ops au8522_video_ops = {
751 .s_routing = au8522_s_video_routing,
752 .g_fmt = au8522_g_fmt,
753 .s_fmt = au8522_s_fmt,
754 .s_stream = au8522_s_stream,
755};
756
757static const struct v4l2_subdev_ops au8522_ops = {
758 .core = &au8522_core_ops,
759 .tuner = &au8522_tuner_ops,
760 .audio = &au8522_audio_ops,
761 .video = &au8522_video_ops,
762};
763
764/* ----------------------------------------------------------------------- */
765
766static int au8522_probe(struct i2c_client *client,
767 const struct i2c_device_id *did)
768{
769 struct au8522_state *state;
770 struct v4l2_subdev *sd;
771 int instance;
772 struct au8522_config *demod_config;
773
774 /* Check if the adapter supports the needed features */
775 if (!i2c_check_functionality(client->adapter,
776 I2C_FUNC_SMBUS_BYTE_DATA)) {
777 return -EIO;
778 }
779
780 /* allocate memory for the internal state */
781 instance = au8522_get_state(&state, client->adapter, client->addr);
782 switch (instance) {
783 case 0:
784 printk("au8522_decoder allocation failed\n");
785 return -EIO;
786 case 1:
787 /* new demod instance */
788 printk("au8522_decoder creating new instance...\n");
789 break;
790 default:
791 /* existing demod instance */
792 printk("au8522_decoder attaching to existing instance...\n");
793 break;
794 }
795
796 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
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 v4l2_i2c_driver_data v4l2_i2c_data = {
833 .name = "au8522",
834 .driverid = I2C_DRIVERID_AU8522,
835 .command = au8522_command,
836 .probe = au8522_probe,
837 .remove = au8522_remove,
838 .id_table = au8522_id,
839};