1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#include "saa711x_regs.h"
41
42#include <linux/kernel.h>
43#include <linux/module.h>
44#include <linux/slab.h>
45#include <linux/i2c.h>
46#include <linux/videodev2.h>
47#include <media/v4l2-device.h>
48#include <media/v4l2-chip-ident.h>
49#include <media/v4l2-i2c-drv.h>
50#include <media/saa7115.h>
51#include <asm/div64.h>
52
53#define VRES_60HZ (480+16)
54
55MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
56MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
57 "Hans Verkuil, Mauro Carvalho Chehab");
58MODULE_LICENSE("GPL");
59
60static int debug;
61module_param(debug, bool, 0644);
62
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
65
66struct saa711x_state {
67 struct v4l2_subdev sd;
68 v4l2_std_id std;
69 int input;
70 int output;
71 int enable;
72 int radio;
73 int bright;
74 int contrast;
75 int hue;
76 int sat;
77 int width;
78 int height;
79 u32 ident;
80 u32 audclk_freq;
81 u32 crystal_freq;
82 u8 ucgc;
83 u8 cgcdiv;
84 u8 apll;
85};
86
87static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
88{
89 return container_of(sd, struct saa711x_state, sd);
90}
91
92
93
94static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
95{
96 struct i2c_client *client = v4l2_get_subdevdata(sd);
97
98 return i2c_smbus_write_byte_data(client, reg, value);
99}
100
101
102static int saa711x_has_reg(const int id, const u8 reg)
103{
104 if (id == V4L2_IDENT_SAA7111)
105 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
106 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
107
108
109 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
110 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
111 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
112 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
113 return 0;
114
115 switch (id) {
116 case V4L2_IDENT_SAA7113:
117 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
118 reg != 0x5d && reg < 0x63;
119 case V4L2_IDENT_SAA7114:
120 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
121 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
122 reg != 0x81 && reg < 0xf0;
123 case V4L2_IDENT_SAA7115:
124 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
125 case V4L2_IDENT_SAA7118:
126 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
127 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
128 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
129 }
130 return 1;
131}
132
133static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
134{
135 struct saa711x_state *state = to_state(sd);
136 unsigned char reg, data;
137
138 while (*regs != 0x00) {
139 reg = *(regs++);
140 data = *(regs++);
141
142
143
144 if (saa711x_has_reg(state->ident, reg)) {
145 if (saa711x_write(sd, reg, data) < 0)
146 return -1;
147 } else {
148 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
149 }
150 }
151 return 0;
152}
153
154static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
155{
156 struct i2c_client *client = v4l2_get_subdevdata(sd);
157
158 return i2c_smbus_read_byte_data(client, reg);
159}
160
161
162
163
164static const unsigned char saa7111_init[] = {
165 R_01_INC_DELAY, 0x00,
166
167
168 R_02_INPUT_CNTL_1, 0xd0,
169 R_03_INPUT_CNTL_2, 0x23,
170
171 R_04_INPUT_CNTL_3, 0x00,
172 R_05_INPUT_CNTL_4, 0x00,
173
174
175 R_06_H_SYNC_START, 0xf3,
176
177 R_07_H_SYNC_STOP, 0xe8,
178
179 R_08_SYNC_CNTL, 0xc8,
180
181 R_09_LUMA_CNTL, 0x01,
182
183 R_0A_LUMA_BRIGHT_CNTL, 0x80,
184 R_0B_LUMA_CONTRAST_CNTL, 0x47,
185 R_0C_CHROMA_SAT_CNTL, 0x40,
186 R_0D_CHROMA_HUE_CNTL, 0x00,
187 R_0E_CHROMA_CNTL_1, 0x01,
188
189 R_0F_CHROMA_GAIN_CNTL, 0x00,
190 R_10_CHROMA_CNTL_2, 0x48,
191 R_11_MODE_DELAY_CNTL, 0x1c,
192
193 R_12_RT_SIGNAL_CNTL, 0x00,
194 R_13_RT_X_PORT_OUT_CNTL, 0x00,
195 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
196 R_15_VGATE_START_FID_CHG, 0x00,
197 R_16_VGATE_STOP, 0x00,
198 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
199
200 0x00, 0x00
201};
202
203
204static const unsigned char saa7113_init[] = {
205 R_01_INC_DELAY, 0x08,
206 R_02_INPUT_CNTL_1, 0xc2,
207 R_03_INPUT_CNTL_2, 0x30,
208 R_04_INPUT_CNTL_3, 0x00,
209 R_05_INPUT_CNTL_4, 0x00,
210 R_06_H_SYNC_START, 0x89,
211 R_07_H_SYNC_STOP, 0x0d,
212 R_08_SYNC_CNTL, 0x88,
213 R_09_LUMA_CNTL, 0x01,
214 R_0A_LUMA_BRIGHT_CNTL, 0x80,
215 R_0B_LUMA_CONTRAST_CNTL, 0x47,
216 R_0C_CHROMA_SAT_CNTL, 0x40,
217 R_0D_CHROMA_HUE_CNTL, 0x00,
218 R_0E_CHROMA_CNTL_1, 0x01,
219 R_0F_CHROMA_GAIN_CNTL, 0x2a,
220 R_10_CHROMA_CNTL_2, 0x08,
221 R_11_MODE_DELAY_CNTL, 0x0c,
222 R_12_RT_SIGNAL_CNTL, 0x07,
223 R_13_RT_X_PORT_OUT_CNTL, 0x00,
224 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
225 R_15_VGATE_START_FID_CHG, 0x00,
226 R_16_VGATE_STOP, 0x00,
227 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
228
229 0x00, 0x00
230};
231
232
233
234
235
236
237static const unsigned char saa7115_init_auto_input[] = {
238
239 R_01_INC_DELAY, 0x48,
240 R_03_INPUT_CNTL_2, 0x20,
241 R_04_INPUT_CNTL_3, 0x90,
242 R_05_INPUT_CNTL_4, 0x90,
243
244 R_06_H_SYNC_START, 0xeb,
245 R_07_H_SYNC_STOP, 0xe0,
246 R_09_LUMA_CNTL, 0x53,
247 R_0A_LUMA_BRIGHT_CNTL, 0x80,
248 R_0B_LUMA_CONTRAST_CNTL, 0x44,
249 R_0C_CHROMA_SAT_CNTL, 0x40,
250 R_0D_CHROMA_HUE_CNTL, 0x00,
251 R_0F_CHROMA_GAIN_CNTL, 0x00,
252 R_10_CHROMA_CNTL_2, 0x06,
253 R_11_MODE_DELAY_CNTL, 0x00,
254 R_12_RT_SIGNAL_CNTL, 0x9d,
255 R_13_RT_X_PORT_OUT_CNTL, 0x80,
256 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
257 R_18_RAW_DATA_GAIN_CNTL, 0x40,
258 R_19_RAW_DATA_OFF_CNTL, 0x80,
259 R_1A_COLOR_KILL_LVL_CNTL, 0x77,
260 R_1B_MISC_TVVCRDET, 0x42,
261 R_1C_ENHAN_COMB_CTRL1, 0xa9,
262 R_1D_ENHAN_COMB_CTRL2, 0x01,
263
264
265 R_80_GLOBAL_CNTL_1, 0x0,
266
267
268 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
269 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
270 0x00, 0x00
271};
272
273
274static const unsigned char saa7115_cfg_reset_scaler[] = {
275 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00,
276 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
277 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
278 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
279 0x00, 0x00
280};
281
282
283
284static const unsigned char saa7115_cfg_60hz_video[] = {
285 R_80_GLOBAL_CNTL_1, 0x00,
286 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
287
288 R_15_VGATE_START_FID_CHG, 0x03,
289 R_16_VGATE_STOP, 0x11,
290 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
291
292 R_08_SYNC_CNTL, 0x68,
293 R_0E_CHROMA_CNTL_1, 0x07,
294
295 R_5A_V_OFF_FOR_SLICER, 0x06,
296
297
298 R_90_A_TASK_HANDLING_CNTL, 0x80,
299 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
300 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
301 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
302
303
304 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
305 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
306
307
308 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
309 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
310
311 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
312 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
313
314 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
315 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
316
317 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
318 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
319
320 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
321 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
322
323
324 R_C0_B_TASK_HANDLING_CNTL, 0x00,
325 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
326 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
327 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
328
329
330 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
331 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
332
333
334 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
335 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
336
337
338 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
339 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
340
341
342 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
343 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
344
345
346 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
347 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
348
349 R_F0_LFCO_PER_LINE, 0xad,
350 R_F1_P_I_PARAM_SELECT, 0x05,
351 R_F5_PULSGEN_LINE_LENGTH, 0xad,
352 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
353
354 0x00, 0x00
355};
356
357static const unsigned char saa7115_cfg_50hz_video[] = {
358 R_80_GLOBAL_CNTL_1, 0x00,
359 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
360
361 R_15_VGATE_START_FID_CHG, 0x37,
362 R_16_VGATE_STOP, 0x16,
363 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
364
365 R_08_SYNC_CNTL, 0x28,
366 R_0E_CHROMA_CNTL_1, 0x07,
367
368 R_5A_V_OFF_FOR_SLICER, 0x03,
369
370
371 R_90_A_TASK_HANDLING_CNTL, 0x81,
372 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
373 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
374 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
375
376
377
378
379 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
380 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
381
382
383 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
384 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
385
386 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
387 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
388
389
390 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
391 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
392
393
394 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
395 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
396 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12,
397 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
398
399
400 R_C0_B_TASK_HANDLING_CNTL, 0x00,
401 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
402 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
403 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
404
405
406
407
408 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
409 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
410
411
412 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
413 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
414
415
416 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
417 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
418
419
420 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
421 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
422
423
424 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
425 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
426
427 R_F0_LFCO_PER_LINE, 0xb0,
428 R_F1_P_I_PARAM_SELECT, 0x05,
429 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
430 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
431
432 0x00, 0x00
433};
434
435
436
437static const unsigned char saa7115_cfg_vbi_on[] = {
438 R_80_GLOBAL_CNTL_1, 0x00,
439 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
440 R_80_GLOBAL_CNTL_1, 0x30,
441 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
442 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
443
444 0x00, 0x00
445};
446
447static const unsigned char saa7115_cfg_vbi_off[] = {
448 R_80_GLOBAL_CNTL_1, 0x00,
449 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
450 R_80_GLOBAL_CNTL_1, 0x20,
451 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
452 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
453
454 0x00, 0x00
455};
456
457
458static const unsigned char saa7115_init_misc[] = {
459 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
460 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
461 R_84_I_PORT_SIGNAL_DEF, 0x20,
462 R_85_I_PORT_SIGNAL_POLAR, 0x21,
463 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
464 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
465
466
467 R_A0_A_HORIZ_PRESCALING, 0x01,
468 R_A1_A_ACCUMULATION_LENGTH, 0x00,
469 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
470
471
472 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
473 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
474 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
475
476
477 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
478 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
479
480 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
481
482
483 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
484 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
485
486
487 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
488
489 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
490 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
491
492 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
493 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
494
495 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
496
497 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
498 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
499 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
500 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
501
502 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
503 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
504 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
505 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
506
507
508 R_D0_B_HORIZ_PRESCALING, 0x01,
509 R_D1_B_ACCUMULATION_LENGTH, 0x00,
510 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
511
512
513 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
514 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
515 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
516
517
518 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
519 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
520
521 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
522
523
524 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
525 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
526
527
528 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
529
530 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
531 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
532
533 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
534 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
535
536 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
537
538 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
539 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
540 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
541 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
542
543 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
544 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
545 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
546 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
547
548 R_F2_NOMINAL_PLL2_DTO, 0x50,
549 R_F3_PLL_INCREMENT, 0x46,
550 R_F4_PLL2_STATUS, 0x00,
551 R_F7_PULSE_A_POS_MSB, 0x4b,
552 R_F8_PULSE_B_POS, 0x00,
553 R_F9_PULSE_B_POS_MSB, 0x4b,
554 R_FA_PULSE_C_POS, 0x00,
555 R_FB_PULSE_C_POS_MSB, 0x4b,
556
557
558 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
559
560
561 R_40_SLICER_CNTL_1, 0x20,
562 R_41_LCR_BASE, 0xff,
563 R_41_LCR_BASE+1, 0xff,
564 R_41_LCR_BASE+2, 0xff,
565 R_41_LCR_BASE+3, 0xff,
566 R_41_LCR_BASE+4, 0xff,
567 R_41_LCR_BASE+5, 0xff,
568 R_41_LCR_BASE+6, 0xff,
569 R_41_LCR_BASE+7, 0xff,
570 R_41_LCR_BASE+8, 0xff,
571 R_41_LCR_BASE+9, 0xff,
572 R_41_LCR_BASE+10, 0xff,
573 R_41_LCR_BASE+11, 0xff,
574 R_41_LCR_BASE+12, 0xff,
575 R_41_LCR_BASE+13, 0xff,
576 R_41_LCR_BASE+14, 0xff,
577 R_41_LCR_BASE+15, 0xff,
578 R_41_LCR_BASE+16, 0xff,
579 R_41_LCR_BASE+17, 0xff,
580 R_41_LCR_BASE+18, 0xff,
581 R_41_LCR_BASE+19, 0xff,
582 R_41_LCR_BASE+20, 0xff,
583 R_41_LCR_BASE+21, 0xff,
584 R_41_LCR_BASE+22, 0xff,
585 R_58_PROGRAM_FRAMING_CODE, 0x40,
586 R_59_H_OFF_FOR_SLICER, 0x47,
587 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
588 R_5D_DID, 0xbd,
589 R_5E_SDID, 0x35,
590
591 R_02_INPUT_CNTL_1, 0x84,
592
593 R_80_GLOBAL_CNTL_1, 0x20,
594 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
595 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
596 0x00, 0x00
597};
598
599static int saa711x_odd_parity(u8 c)
600{
601 c ^= (c >> 4);
602 c ^= (c >> 2);
603 c ^= (c >> 1);
604
605 return c & 1;
606}
607
608static int saa711x_decode_vps(u8 *dst, u8 *p)
609{
610 static const u8 biphase_tbl[] = {
611 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
612 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
613 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
614 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
615 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
616 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
617 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
618 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
619 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
620 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
621 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
622 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
623 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
624 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
625 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
626 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
627 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
628 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
629 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
630 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
631 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
632 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
633 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
634 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
635 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
636 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
637 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
638 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
639 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
640 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
641 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
642 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
643 };
644 int i;
645 u8 c, err = 0;
646
647 for (i = 0; i < 2 * 13; i += 2) {
648 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
649 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
650 dst[i / 2] = c;
651 }
652 return err & 0xf0;
653}
654
655static int saa711x_decode_wss(u8 *p)
656{
657 static const int wss_bits[8] = {
658 0, 0, 0, 1, 0, 1, 1, 1
659 };
660 unsigned char parity;
661 int wss = 0;
662 int i;
663
664 for (i = 0; i < 16; i++) {
665 int b1 = wss_bits[p[i] & 7];
666 int b2 = wss_bits[(p[i] >> 3) & 7];
667
668 if (b1 == b2)
669 return -1;
670 wss |= b2 << i;
671 }
672 parity = wss & 15;
673 parity ^= parity >> 2;
674 parity ^= parity >> 1;
675
676 if (!(parity & 1))
677 return -1;
678
679 return wss;
680}
681
682static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
683{
684 struct saa711x_state *state = to_state(sd);
685 u32 acpf;
686 u32 acni;
687 u32 hz;
688 u64 f;
689 u8 acc = 0;
690
691
692 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
693 return 0;
694
695 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
696
697
698 if (freq < 32000 || freq > 48000)
699 return -EINVAL;
700
701
702 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
703
704 acpf = (25600 * freq) / hz;
705
706
707
708 f = freq;
709 f = f << 31;
710 do_div(f, state->crystal_freq);
711 acni = f;
712 if (state->ucgc) {
713 acpf = acpf * state->cgcdiv / 16;
714 acni = acni * state->cgcdiv / 16;
715 acc = 0x80;
716 if (state->cgcdiv == 3)
717 acc |= 0x40;
718 }
719 if (state->apll)
720 acc |= 0x08;
721
722 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
723 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
724 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
725
726 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
727 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
728 (acpf >> 8) & 0xff);
729 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
730 (acpf >> 16) & 0x03);
731
732 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
733 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
734 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
735 state->audclk_freq = freq;
736 return 0;
737}
738
739static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
740{
741 struct saa711x_state *state = to_state(sd);
742
743 switch (ctrl->id) {
744 case V4L2_CID_BRIGHTNESS:
745 if (ctrl->value < 0 || ctrl->value > 255) {
746 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
747 return -ERANGE;
748 }
749
750 state->bright = ctrl->value;
751 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright);
752 break;
753
754 case V4L2_CID_CONTRAST:
755 if (ctrl->value < 0 || ctrl->value > 127) {
756 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
757 return -ERANGE;
758 }
759
760 state->contrast = ctrl->value;
761 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
762 break;
763
764 case V4L2_CID_SATURATION:
765 if (ctrl->value < 0 || ctrl->value > 127) {
766 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
767 return -ERANGE;
768 }
769
770 state->sat = ctrl->value;
771 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat);
772 break;
773
774 case V4L2_CID_HUE:
775 if (ctrl->value < -128 || ctrl->value > 127) {
776 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
777 return -ERANGE;
778 }
779
780 state->hue = ctrl->value;
781 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue);
782 break;
783
784 default:
785 return -EINVAL;
786 }
787
788 return 0;
789}
790
791static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
792{
793 struct saa711x_state *state = to_state(sd);
794
795 switch (ctrl->id) {
796 case V4L2_CID_BRIGHTNESS:
797 ctrl->value = state->bright;
798 break;
799 case V4L2_CID_CONTRAST:
800 ctrl->value = state->contrast;
801 break;
802 case V4L2_CID_SATURATION:
803 ctrl->value = state->sat;
804 break;
805 case V4L2_CID_HUE:
806 ctrl->value = state->hue;
807 break;
808 default:
809 return -EINVAL;
810 }
811
812 return 0;
813}
814
815static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
816{
817 struct saa711x_state *state = to_state(sd);
818 int HPSC, HFSC;
819 int VSCY;
820 int res;
821 int is_50hz = state->std & V4L2_STD_625_50;
822 int Vsrc = is_50hz ? 576 : 480;
823
824 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
825
826
827 if ((width < 1) || (width > 1440))
828 return -EINVAL;
829 if ((height < 1) || (height > Vsrc))
830 return -EINVAL;
831
832 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
833
834 if (width != 720)
835 return -EINVAL;
836 if (height != Vsrc)
837 return -EINVAL;
838 }
839
840 state->width = width;
841 state->height = height;
842
843 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
844 return 0;
845
846
847
848
849
850 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
851 (u8) (width & 0xff));
852 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
853 (u8) ((width >> 8) & 0xff));
854
855
856 res = height / 2;
857
858
859 if (!is_50hz)
860 res += (VRES_60HZ - 480) >> 1;
861
862
863 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
864 (u8) (res & 0xff));
865 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
866 (u8) ((res >> 8) & 0xff));
867
868
869
870 HPSC = (int)(720 / width);
871
872 HPSC = HPSC ? HPSC : 1;
873 HFSC = (int)((1024 * 720) / (HPSC * width));
874
875
876 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
877 (u8) (HPSC & 0x3f));
878
879 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
880
881 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
882 (u8) (HFSC & 0xff));
883 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
884 (u8) ((HFSC >> 8) & 0xff));
885
886
887 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
888 (u8) ((HFSC >> 1) & 0xff));
889 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
890 (u8) ((HFSC >> 9) & 0xff));
891
892 VSCY = (int)((1024 * Vsrc) / height);
893 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
894
895
896 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
897 (u8) (64 * 1024 / VSCY));
898 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
899 (u8) (64 * 1024 / VSCY));
900
901
902 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
903 (u8) (VSCY & 0xff));
904 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
905 (u8) ((VSCY >> 8) & 0xff));
906
907 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
908 (u8) (VSCY & 0xff));
909 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
910 (u8) ((VSCY >> 8) & 0xff));
911
912 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
913
914
915 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
916 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
917
918 return 0;
919}
920
921static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
922{
923 struct saa711x_state *state = to_state(sd);
924
925
926
927
928
929
930
931
932 if (std == state->std)
933 return;
934
935 state->std = std;
936
937
938 if (std & V4L2_STD_525_60) {
939 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
940 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
941 saa711x_set_size(sd, 720, 480);
942 } else {
943 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
944 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
945 saa711x_set_size(sd, 720, 576);
946 }
947
948
949
950
951
952
953
954
955
956
957 if (state->ident == V4L2_IDENT_SAA7111 ||
958 state->ident == V4L2_IDENT_SAA7113) {
959 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
960
961 if (std == V4L2_STD_PAL_M) {
962 reg |= 0x30;
963 } else if (std == V4L2_STD_PAL_Nc) {
964 reg |= 0x20;
965 } else if (std == V4L2_STD_PAL_60) {
966 reg |= 0x10;
967 } else if (std == V4L2_STD_NTSC_M_JP) {
968 reg |= 0x40;
969 } else if (std & V4L2_STD_SECAM) {
970 reg |= 0x50;
971 }
972 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
973 } else {
974
975 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
976
977 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
978 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
979 }
980
981
982 saa711x_s_clock_freq(sd, state->audclk_freq);
983 }
984}
985
986
987static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
988{
989 struct saa711x_state *state = to_state(sd);
990 int is_50hz = (state->std & V4L2_STD_625_50);
991 u8 lcr[24];
992 int i, x;
993
994#if 1
995
996 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
997 return;
998
999#else
1000
1001 if (state->ident != V4L2_IDENT_SAA7115)
1002 return;
1003#endif
1004
1005 for (i = 0; i <= 23; i++)
1006 lcr[i] = 0xff;
1007
1008 if (fmt == NULL) {
1009
1010 if (is_50hz)
1011 for (i = 6; i <= 23; i++)
1012 lcr[i] = 0xdd;
1013 else
1014 for (i = 10; i <= 21; i++)
1015 lcr[i] = 0xdd;
1016 } else {
1017
1018
1019 if (is_50hz) {
1020 for (i = 0; i <= 5; i++)
1021 fmt->service_lines[0][i] =
1022 fmt->service_lines[1][i] = 0;
1023 }
1024 else {
1025 for (i = 0; i <= 9; i++)
1026 fmt->service_lines[0][i] =
1027 fmt->service_lines[1][i] = 0;
1028 for (i = 22; i <= 23; i++)
1029 fmt->service_lines[0][i] =
1030 fmt->service_lines[1][i] = 0;
1031 }
1032
1033
1034 for (i = 6; i <= 23; i++) {
1035 lcr[i] = 0;
1036 for (x = 0; x <= 1; x++) {
1037 switch (fmt->service_lines[1-x][i]) {
1038 case 0:
1039 lcr[i] |= 0xf << (4 * x);
1040 break;
1041 case V4L2_SLICED_TELETEXT_B:
1042 lcr[i] |= 1 << (4 * x);
1043 break;
1044 case V4L2_SLICED_CAPTION_525:
1045 lcr[i] |= 4 << (4 * x);
1046 break;
1047 case V4L2_SLICED_WSS_625:
1048 lcr[i] |= 5 << (4 * x);
1049 break;
1050 case V4L2_SLICED_VPS:
1051 lcr[i] |= 7 << (4 * x);
1052 break;
1053 }
1054 }
1055 }
1056 }
1057
1058
1059 for (i = 2; i <= 23; i++) {
1060 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
1061 }
1062
1063
1064 saa711x_writeregs(sd, fmt == NULL ?
1065 saa7115_cfg_vbi_on :
1066 saa7115_cfg_vbi_off);
1067}
1068
1069static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1070{
1071 static u16 lcr2vbi[] = {
1072 0, V4L2_SLICED_TELETEXT_B, 0,
1073 0, V4L2_SLICED_CAPTION_525,
1074 V4L2_SLICED_WSS_625, 0,
1075 V4L2_SLICED_VPS, 0, 0, 0, 0,
1076 0, 0, 0, 0
1077 };
1078 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
1079 int i;
1080
1081 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1082 return -EINVAL;
1083 memset(sliced, 0, sizeof(*sliced));
1084
1085 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
1086 return 0;
1087 for (i = 2; i <= 23; i++) {
1088 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
1089
1090 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1091 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1092 sliced->service_set |=
1093 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1094 }
1095 return 0;
1096}
1097
1098static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1099{
1100 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1101 saa711x_set_lcr(sd, &fmt->fmt.sliced);
1102 return 0;
1103 }
1104 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1105 saa711x_set_lcr(sd, NULL);
1106 return 0;
1107 }
1108 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1109 return -EINVAL;
1110
1111 return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
1112}
1113
1114
1115
1116
1117
1118
1119
1120static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
1121{
1122 struct saa711x_state *state = to_state(sd);
1123 static const char vbi_no_data_pattern[] = {
1124 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1125 };
1126 u8 *p = vbi->p;
1127 u32 wss;
1128 int id1, id2;
1129
1130 vbi->type = 0;
1131 id1 = p[2];
1132 id2 = p[3];
1133
1134 if (state->std & V4L2_STD_525_60)
1135 id1 ^= 0x40;
1136
1137
1138 p += 4;
1139 vbi->p = p;
1140
1141
1142 vbi->is_second_field = ((id1 & 0x40) != 0);
1143 vbi->line = (id1 & 0x3f) << 3;
1144 vbi->line |= (id2 & 0x70) >> 4;
1145
1146
1147 id2 &= 0xf;
1148
1149
1150
1151 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
1152 return 0;
1153
1154
1155 switch (id2) {
1156 case 1:
1157 vbi->type = V4L2_SLICED_TELETEXT_B;
1158 break;
1159 case 4:
1160 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
1161 return 0;
1162 vbi->type = V4L2_SLICED_CAPTION_525;
1163 break;
1164 case 5:
1165 wss = saa711x_decode_wss(p);
1166 if (wss == -1)
1167 return 0;
1168 p[0] = wss & 0xff;
1169 p[1] = wss >> 8;
1170 vbi->type = V4L2_SLICED_WSS_625;
1171 break;
1172 case 7:
1173 if (saa711x_decode_vps(p, p) != 0)
1174 return 0;
1175 vbi->type = V4L2_SLICED_VPS;
1176 break;
1177 default:
1178 break;
1179 }
1180 return 0;
1181}
1182
1183
1184
1185static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1186{
1187 struct saa711x_state *state = to_state(sd);
1188 int status;
1189
1190 if (state->radio)
1191 return 0;
1192 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1193
1194 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1195 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1196 return 0;
1197}
1198
1199static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1200{
1201 switch (qc->id) {
1202 case V4L2_CID_BRIGHTNESS:
1203 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1204 case V4L2_CID_CONTRAST:
1205 case V4L2_CID_SATURATION:
1206 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
1207 case V4L2_CID_HUE:
1208 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
1209 default:
1210 return -EINVAL;
1211 }
1212}
1213
1214static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1215{
1216 struct saa711x_state *state = to_state(sd);
1217
1218 state->radio = 0;
1219 saa711x_set_v4lstd(sd, std);
1220 return 0;
1221}
1222
1223static int saa711x_s_radio(struct v4l2_subdev *sd)
1224{
1225 struct saa711x_state *state = to_state(sd);
1226
1227 state->radio = 1;
1228 return 0;
1229}
1230
1231static int saa711x_s_routing(struct v4l2_subdev *sd,
1232 u32 input, u32 output, u32 config)
1233{
1234 struct saa711x_state *state = to_state(sd);
1235 u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;
1236
1237 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1238 input, output);
1239
1240
1241 if ((state->ident == V4L2_IDENT_SAA7113 ||
1242 state->ident == V4L2_IDENT_SAA7111) &&
1243 (input == SAA7115_COMPOSITE4 ||
1244 input == SAA7115_COMPOSITE5)) {
1245 return -EINVAL;
1246 }
1247 if (input > SAA7115_SVIDEO3)
1248 return -EINVAL;
1249 if (output > SAA7115_IPORT_ON)
1250 return -EINVAL;
1251 if (state->input == input && state->output == output)
1252 return 0;
1253 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
1254 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1255 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1256 state->input = input;
1257
1258
1259 if (state->ident == V4L2_IDENT_SAA7111) {
1260 if (input >= SAA7115_COMPOSITE4)
1261 input -= 2;
1262
1263 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1264 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
1265 ((output & 0xc0) ^ 0x40));
1266 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1267 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
1268 ((output & 2) ? 0x0a : 0));
1269 }
1270
1271
1272 saa711x_write(sd, R_02_INPUT_CNTL_1,
1273 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1274 input);
1275
1276
1277 saa711x_write(sd, R_09_LUMA_CNTL,
1278 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1279 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1280
1281 state->output = output;
1282 if (state->ident == V4L2_IDENT_SAA7114 ||
1283 state->ident == V4L2_IDENT_SAA7115) {
1284 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1285 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1286 (state->output & 0x01));
1287 }
1288 return 0;
1289}
1290
1291static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1292{
1293 struct saa711x_state *state = to_state(sd);
1294
1295 if (state->ident != V4L2_IDENT_SAA7111)
1296 return -EINVAL;
1297 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1298 (val ? 0x80 : 0));
1299 return 0;
1300}
1301
1302static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1303{
1304 struct saa711x_state *state = to_state(sd);
1305
1306 v4l2_dbg(1, debug, sd, "%s output\n",
1307 enable ? "enable" : "disable");
1308
1309 if (state->enable == enable)
1310 return 0;
1311 state->enable = enable;
1312 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1313 return 0;
1314 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
1315 return 0;
1316}
1317
1318static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
1319{
1320 struct saa711x_state *state = to_state(sd);
1321
1322 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
1323 return -EINVAL;
1324 state->crystal_freq = freq;
1325 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1326 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1327 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
1328 saa711x_s_clock_freq(sd, state->audclk_freq);
1329 return 0;
1330}
1331
1332static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1333{
1334 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1335 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1336 return 0;
1337}
1338
1339static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1340{
1341
1342
1343
1344 switch (data->id) {
1345 case V4L2_SLICED_WSS_625:
1346 if (saa711x_read(sd, 0x6b) & 0xc0)
1347 return -EIO;
1348 data->data[0] = saa711x_read(sd, 0x6c);
1349 data->data[1] = saa711x_read(sd, 0x6d);
1350 return 0;
1351 case V4L2_SLICED_CAPTION_525:
1352 if (data->field == 0) {
1353
1354 if (saa711x_read(sd, 0x66) & 0x30)
1355 return -EIO;
1356 data->data[0] = saa711x_read(sd, 0x69);
1357 data->data[1] = saa711x_read(sd, 0x6a);
1358 return 0;
1359 }
1360
1361 if (saa711x_read(sd, 0x66) & 0xc0)
1362 return -EIO;
1363 data->data[0] = saa711x_read(sd, 0x67);
1364 data->data[1] = saa711x_read(sd, 0x68);
1365 return 0;
1366 default:
1367 return -EINVAL;
1368 }
1369}
1370
1371static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1372{
1373 struct saa711x_state *state = to_state(sd);
1374 int reg1e;
1375
1376 *std = V4L2_STD_ALL;
1377 if (state->ident != V4L2_IDENT_SAA7115)
1378 return 0;
1379 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1380
1381 switch (reg1e & 0x03) {
1382 case 1:
1383 *std = V4L2_STD_NTSC;
1384 break;
1385 case 2:
1386 *std = V4L2_STD_PAL;
1387 break;
1388 case 3:
1389 *std = V4L2_STD_SECAM;
1390 break;
1391 default:
1392 break;
1393 }
1394 return 0;
1395}
1396
1397static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1398{
1399 struct saa711x_state *state = to_state(sd);
1400 int reg1e = 0x80;
1401 int reg1f;
1402
1403 *status = V4L2_IN_ST_NO_SIGNAL;
1404 if (state->ident == V4L2_IDENT_SAA7115)
1405 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1406 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1407 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1408 *status = 0;
1409 return 0;
1410}
1411
1412#ifdef CONFIG_VIDEO_ADV_DEBUG
1413static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1414{
1415 struct i2c_client *client = v4l2_get_subdevdata(sd);
1416
1417 if (!v4l2_chip_match_i2c_client(client, ®->match))
1418 return -EINVAL;
1419 if (!capable(CAP_SYS_ADMIN))
1420 return -EPERM;
1421 reg->val = saa711x_read(sd, reg->reg & 0xff);
1422 reg->size = 1;
1423 return 0;
1424}
1425
1426static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1427{
1428 struct i2c_client *client = v4l2_get_subdevdata(sd);
1429
1430 if (!v4l2_chip_match_i2c_client(client, ®->match))
1431 return -EINVAL;
1432 if (!capable(CAP_SYS_ADMIN))
1433 return -EPERM;
1434 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1435 return 0;
1436}
1437#endif
1438
1439static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
1440{
1441 struct saa711x_state *state = to_state(sd);
1442 struct i2c_client *client = v4l2_get_subdevdata(sd);
1443
1444 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1445}
1446
1447static int saa711x_log_status(struct v4l2_subdev *sd)
1448{
1449 struct saa711x_state *state = to_state(sd);
1450 int reg1e, reg1f;
1451 int signalOk;
1452 int vcr;
1453
1454 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1455 if (state->ident != V4L2_IDENT_SAA7115) {
1456
1457 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1458 signalOk = (reg1f & 0xc1) == 0x81;
1459 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1460 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1461 return 0;
1462 }
1463
1464
1465 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1466 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1467
1468 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1469 vcr = !(reg1f & 0x10);
1470
1471 if (state->input >= 6)
1472 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1473 else
1474 v4l2_info(sd, "Input: Composite %d\n", state->input);
1475 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1476 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1477
1478 switch (reg1e & 0x03) {
1479 case 1:
1480 v4l2_info(sd, "Detected format: NTSC\n");
1481 break;
1482 case 2:
1483 v4l2_info(sd, "Detected format: PAL\n");
1484 break;
1485 case 3:
1486 v4l2_info(sd, "Detected format: SECAM\n");
1487 break;
1488 default:
1489 v4l2_info(sd, "Detected format: BW/No color\n");
1490 break;
1491 }
1492 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1493 return 0;
1494}
1495
1496
1497
1498static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1499 .log_status = saa711x_log_status,
1500 .g_chip_ident = saa711x_g_chip_ident,
1501 .g_ctrl = saa711x_g_ctrl,
1502 .s_ctrl = saa711x_s_ctrl,
1503 .queryctrl = saa711x_queryctrl,
1504 .s_std = saa711x_s_std,
1505 .reset = saa711x_reset,
1506 .s_gpio = saa711x_s_gpio,
1507#ifdef CONFIG_VIDEO_ADV_DEBUG
1508 .g_register = saa711x_g_register,
1509 .s_register = saa711x_s_register,
1510#endif
1511};
1512
1513static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
1514 .s_radio = saa711x_s_radio,
1515 .g_tuner = saa711x_g_tuner,
1516};
1517
1518static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1519 .s_clock_freq = saa711x_s_clock_freq,
1520};
1521
1522static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1523 .s_routing = saa711x_s_routing,
1524 .s_crystal_freq = saa711x_s_crystal_freq,
1525 .g_fmt = saa711x_g_fmt,
1526 .s_fmt = saa711x_s_fmt,
1527 .g_vbi_data = saa711x_g_vbi_data,
1528 .decode_vbi_line = saa711x_decode_vbi_line,
1529 .s_stream = saa711x_s_stream,
1530 .querystd = saa711x_querystd,
1531 .g_input_status = saa711x_g_input_status,
1532};
1533
1534static const struct v4l2_subdev_ops saa711x_ops = {
1535 .core = &saa711x_core_ops,
1536 .tuner = &saa711x_tuner_ops,
1537 .audio = &saa711x_audio_ops,
1538 .video = &saa711x_video_ops,
1539};
1540
1541
1542
1543static int saa711x_probe(struct i2c_client *client,
1544 const struct i2c_device_id *id)
1545{
1546 struct saa711x_state *state;
1547 struct v4l2_subdev *sd;
1548 int i;
1549 char name[17];
1550 char chip_id;
1551 int autodetect = !id || id->driver_data == 1;
1552
1553
1554 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1555 return -EIO;
1556
1557 for (i = 0; i < 0x0f; i++) {
1558 i2c_smbus_write_byte_data(client, 0, i);
1559 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
1560 if (name[i] > '9')
1561 name[i] += 'a' - '9' - 1;
1562 }
1563 name[i] = '\0';
1564
1565 chip_id = name[5];
1566
1567
1568 if (memcmp(name, "1f711", 5)) {
1569 v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
1570 client->addr << 1, name);
1571 return -ENODEV;
1572 }
1573
1574
1575 if (!autodetect && id->name[6] != chip_id) {
1576 v4l_warn(client, "found saa711%c while %s was expected\n",
1577 chip_id, id->name);
1578 }
1579 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1580 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1581 client->addr << 1, client->adapter->name);
1582
1583 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
1584 if (state == NULL)
1585 return -ENOMEM;
1586 sd = &state->sd;
1587 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
1588 state->input = -1;
1589 state->output = SAA7115_IPORT_ON;
1590 state->enable = 1;
1591 state->radio = 0;
1592 state->bright = 128;
1593 state->contrast = 64;
1594 state->hue = 0;
1595 state->sat = 64;
1596 switch (chip_id) {
1597 case '1':
1598 state->ident = V4L2_IDENT_SAA7111;
1599 break;
1600 case '3':
1601 state->ident = V4L2_IDENT_SAA7113;
1602 break;
1603 case '4':
1604 state->ident = V4L2_IDENT_SAA7114;
1605 break;
1606 case '5':
1607 state->ident = V4L2_IDENT_SAA7115;
1608 break;
1609 case '8':
1610 state->ident = V4L2_IDENT_SAA7118;
1611 break;
1612 default:
1613 state->ident = V4L2_IDENT_SAA7111;
1614 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
1615
1616 }
1617
1618 state->audclk_freq = 48000;
1619
1620 v4l2_dbg(1, debug, sd, "writing init values\n");
1621
1622
1623 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1624 switch (state->ident) {
1625 case V4L2_IDENT_SAA7111:
1626 saa711x_writeregs(sd, saa7111_init);
1627 break;
1628 case V4L2_IDENT_SAA7113:
1629 saa711x_writeregs(sd, saa7113_init);
1630 break;
1631 default:
1632 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
1633 saa711x_writeregs(sd, saa7115_init_auto_input);
1634 }
1635 if (state->ident != V4L2_IDENT_SAA7111)
1636 saa711x_writeregs(sd, saa7115_init_misc);
1637 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
1638
1639 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1640 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1641 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
1642 return 0;
1643}
1644
1645
1646
1647static int saa711x_remove(struct i2c_client *client)
1648{
1649 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1650
1651 v4l2_device_unregister_subdev(sd);
1652 kfree(to_state(sd));
1653 return 0;
1654}
1655
1656static const struct i2c_device_id saa7115_id[] = {
1657 { "saa7115_auto", 1 },
1658 { "saa7111", 0 },
1659 { "saa7113", 0 },
1660 { "saa7114", 0 },
1661 { "saa7115", 0 },
1662 { "saa7118", 0 },
1663 { }
1664};
1665MODULE_DEVICE_TABLE(i2c, saa7115_id);
1666
1667static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1668 .name = "saa7115",
1669 .probe = saa711x_probe,
1670 .remove = saa711x_remove,
1671 .id_table = saa7115_id,
1672};
1673