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