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