Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/frontends/au8522_decoder.c
15112 views
1
/*
2
* Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
3
*
4
* Copyright (C) 2009 Devin Heitmueller <[email protected]>
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
43
MODULE_AUTHOR("Devin Heitmueller");
44
MODULE_LICENSE("GPL");
45
46
static int au8522_analog_debug;
47
48
49
module_param_named(analog_debug, au8522_analog_debug, int, 0644);
50
51
MODULE_PARM_DESC(analog_debug,
52
"Analog debugging messages [0=Off (default) 1=On]");
53
54
struct 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
*/
64
static const struct au8522_register_config filter_coef[] = {
65
{AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
66
{AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
67
{AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
68
{AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
69
{AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
70
{AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
71
{AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
72
{AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
73
{AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
74
{AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
75
{AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
76
{AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
77
{AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
78
{AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
79
{AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
80
{AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
81
{AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
82
{AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
83
{AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
84
{AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
85
{AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
86
{AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
87
{AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
88
{AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
89
{AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
90
{AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
91
{AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
92
{AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
93
{AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
94
{AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
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
*/
106
static const struct au8522_register_config lpfilter_coef[] = {
107
{0x060b, {0x21, 0x0b} },
108
{0x060c, {0xad, 0xad} },
109
{0x060d, {0x70, 0xf0} },
110
{0x060e, {0xea, 0xe9} },
111
{0x060f, {0xdd, 0xdd} },
112
{0x0610, {0x08, 0x64} },
113
{0x0611, {0x60, 0x60} },
114
{0x0612, {0xf8, 0xb2} },
115
{0x0613, {0x01, 0x02} },
116
{0x0614, {0xe4, 0xb4} },
117
{0x0615, {0x19, 0x02} },
118
{0x0616, {0xae, 0x2e} },
119
{0x0617, {0xee, 0xc5} },
120
{0x0618, {0x56, 0x56} },
121
{0x0619, {0x30, 0x58} },
122
{0x061a, {0xf9, 0xf8} },
123
{0x061b, {0x24, 0x64} },
124
{0x061c, {0x07, 0x07} },
125
{0x061d, {0x30, 0x30} },
126
{0x061e, {0xa9, 0xed} },
127
{0x061f, {0x09, 0x0b} },
128
{0x0620, {0x42, 0xc2} },
129
{0x0621, {0x1d, 0x2a} },
130
{0x0622, {0xd6, 0x56} },
131
{0x0623, {0x95, 0x8b} },
132
{0x0624, {0x2b, 0x2b} },
133
{0x0625, {0x30, 0x24} },
134
{0x0626, {0x3e, 0x3e} },
135
{0x0627, {0x62, 0xe2} },
136
{0x0628, {0xe9, 0xf5} },
137
{0x0629, {0x99, 0x19} },
138
{0x062a, {0xd4, 0x11} },
139
{0x062b, {0x03, 0x04} },
140
{0x062c, {0xb5, 0x85} },
141
{0x062d, {0x1e, 0x20} },
142
{0x062e, {0x2a, 0xea} },
143
{0x062f, {0xd7, 0xd2} },
144
{0x0630, {0x15, 0x15} },
145
{0x0631, {0xa3, 0xa9} },
146
{0x0632, {0x1f, 0x1f} },
147
{0x0633, {0xf9, 0xd1} },
148
{0x0634, {0xc0, 0xc3} },
149
{0x0635, {0x4d, 0x8d} },
150
{0x0636, {0x21, 0x31} },
151
{0x0637, {0x83, 0x83} },
152
{0x0638, {0x08, 0x8c} },
153
{0x0639, {0x19, 0x19} },
154
{0x063a, {0x45, 0xa5} },
155
{0x063b, {0xef, 0xec} },
156
{0x063c, {0x8a, 0x8a} },
157
{0x063d, {0xf4, 0xf6} },
158
{0x063e, {0x8f, 0x8f} },
159
{0x063f, {0x44, 0x0c} },
160
{0x0640, {0xef, 0xf0} },
161
{0x0641, {0x66, 0x66} },
162
{0x0642, {0xcc, 0xd2} },
163
{0x0643, {0x41, 0x41} },
164
{0x0644, {0x63, 0x93} },
165
{0x0645, {0x8e, 0x8e} },
166
{0x0646, {0xa2, 0x42} },
167
{0x0647, {0x7b, 0x7b} },
168
{0x0648, {0x04, 0x04} },
169
{0x0649, {0x00, 0x00} },
170
{0x064a, {0x40, 0x40} },
171
{0x064b, {0x8c, 0x98} },
172
{0x064c, {0x00, 0x00} },
173
{0x064d, {0x63, 0xc3} },
174
{0x064e, {0x04, 0x04} },
175
{0x064f, {0x20, 0x20} },
176
{0x0650, {0x00, 0x00} },
177
{0x0651, {0x40, 0x40} },
178
{0x0652, {0x01, 0x01} },
179
};
180
#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
181
/ sizeof(struct au8522_register_config))
182
183
static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
184
{
185
return container_of(sd, struct au8522_state, sd);
186
}
187
188
static 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
224
static 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
352
static 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
373
static 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
400
static 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
424
static 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 */
438
static 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
490
static 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
532
static 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
569
static 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
583
static 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
598
static 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
617
static 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
637
static 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
653
static 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
678
static 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
686
static 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 = 0x01;
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
709
static 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
718
static int au8522_log_status(struct v4l2_subdev *sd)
719
{
720
/* FIXME: Add some status info here */
721
return 0;
722
}
723
724
/* ----------------------------------------------------------------------- */
725
726
static 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
739
static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
740
.g_tuner = au8522_g_tuner,
741
};
742
743
static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
744
.s_routing = au8522_s_audio_routing,
745
};
746
747
static const struct v4l2_subdev_video_ops au8522_video_ops = {
748
.s_routing = au8522_s_video_routing,
749
.s_stream = au8522_s_stream,
750
};
751
752
static 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
761
static 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
817
static 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
825
static const struct i2c_device_id au8522_id[] = {
826
{"au8522", 0},
827
{}
828
};
829
830
MODULE_DEVICE_TABLE(i2c, au8522_id);
831
832
static 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
842
static __init int init_au8522(void)
843
{
844
return i2c_add_driver(&au8522_driver);
845
}
846
847
static __exit void exit_au8522(void)
848
{
849
i2c_del_driver(&au8522_driver);
850
}
851
852
module_init(init_au8522);
853
module_exit(exit_au8522);
854
855