This source file includes following definitions.
- to_state
- saa7127_read
- saa7127_write
- saa7127_write_inittab
- saa7127_set_vps
- saa7127_set_cc
- saa7127_set_xds
- saa7127_set_wss
- saa7127_set_video_enable
- saa7127_set_std
- saa7127_set_output_type
- saa7127_set_input_type
- saa7127_s_std_output
- saa7127_s_routing
- saa7127_s_stream
- saa7127_g_sliced_fmt
- saa7127_s_vbi_data
- saa7127_g_register
- saa7127_s_register
- saa7127_log_status
- saa7127_probe
- saa7127_remove
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 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/slab.h>
41 #include <linux/i2c.h>
42 #include <linux/videodev2.h>
43 #include <media/v4l2-device.h>
44 #include <media/i2c/saa7127.h>
45
46 static int debug;
47 static int test_image;
48
49 MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
50 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
51 MODULE_LICENSE("GPL");
52 module_param(debug, int, 0644);
53 module_param(test_image, int, 0644);
54 MODULE_PARM_DESC(debug, "debug level (0-2)");
55 MODULE_PARM_DESC(test_image, "test_image (0-1)");
56
57
58
59
60
61
62 #define SAA7127_REG_STATUS 0x00
63 #define SAA7127_REG_WIDESCREEN_CONFIG 0x26
64 #define SAA7127_REG_WIDESCREEN_ENABLE 0x27
65 #define SAA7127_REG_BURST_START 0x28
66 #define SAA7127_REG_BURST_END 0x29
67 #define SAA7127_REG_COPYGEN_0 0x2a
68 #define SAA7127_REG_COPYGEN_1 0x2b
69 #define SAA7127_REG_COPYGEN_2 0x2c
70 #define SAA7127_REG_OUTPUT_PORT_CONTROL 0x2d
71 #define SAA7127_REG_GAIN_LUMINANCE_RGB 0x38
72 #define SAA7127_REG_GAIN_COLORDIFF_RGB 0x39
73 #define SAA7127_REG_INPUT_PORT_CONTROL_1 0x3a
74 #define SAA7129_REG_FADE_KEY_COL2 0x4f
75 #define SAA7127_REG_CHROMA_PHASE 0x5a
76 #define SAA7127_REG_GAINU 0x5b
77 #define SAA7127_REG_GAINV 0x5c
78 #define SAA7127_REG_BLACK_LEVEL 0x5d
79 #define SAA7127_REG_BLANKING_LEVEL 0x5e
80 #define SAA7127_REG_VBI_BLANKING 0x5f
81 #define SAA7127_REG_DAC_CONTROL 0x61
82 #define SAA7127_REG_BURST_AMP 0x62
83 #define SAA7127_REG_SUBC3 0x63
84 #define SAA7127_REG_SUBC2 0x64
85 #define SAA7127_REG_SUBC1 0x65
86 #define SAA7127_REG_SUBC0 0x66
87 #define SAA7127_REG_LINE_21_ODD_0 0x67
88 #define SAA7127_REG_LINE_21_ODD_1 0x68
89 #define SAA7127_REG_LINE_21_EVEN_0 0x69
90 #define SAA7127_REG_LINE_21_EVEN_1 0x6a
91 #define SAA7127_REG_RCV_PORT_CONTROL 0x6b
92 #define SAA7127_REG_VTRIG 0x6c
93 #define SAA7127_REG_HTRIG_HI 0x6d
94 #define SAA7127_REG_MULTI 0x6e
95 #define SAA7127_REG_CLOSED_CAPTION 0x6f
96 #define SAA7127_REG_RCV2_OUTPUT_START 0x70
97 #define SAA7127_REG_RCV2_OUTPUT_END 0x71
98 #define SAA7127_REG_RCV2_OUTPUT_MSBS 0x72
99 #define SAA7127_REG_TTX_REQUEST_H_START 0x73
100 #define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH 0x74
101 #define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT 0x75
102 #define SAA7127_REG_TTX_ODD_REQ_VERT_START 0x76
103 #define SAA7127_REG_TTX_ODD_REQ_VERT_END 0x77
104 #define SAA7127_REG_TTX_EVEN_REQ_VERT_START 0x78
105 #define SAA7127_REG_TTX_EVEN_REQ_VERT_END 0x79
106 #define SAA7127_REG_FIRST_ACTIVE 0x7a
107 #define SAA7127_REG_LAST_ACTIVE 0x7b
108 #define SAA7127_REG_MSB_VERTICAL 0x7c
109 #define SAA7127_REG_DISABLE_TTX_LINE_LO_0 0x7e
110 #define SAA7127_REG_DISABLE_TTX_LINE_LO_1 0x7f
111
112
113
114
115
116
117
118
119
120 struct i2c_reg_value {
121 unsigned char reg;
122 unsigned char value;
123 };
124
125 static const struct i2c_reg_value saa7129_init_config_extra[] = {
126 { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 },
127 { SAA7127_REG_VTRIG, 0xfa },
128 { 0, 0 }
129 };
130
131 static const struct i2c_reg_value saa7127_init_config_common[] = {
132 { SAA7127_REG_WIDESCREEN_CONFIG, 0x0d },
133 { SAA7127_REG_WIDESCREEN_ENABLE, 0x00 },
134 { SAA7127_REG_COPYGEN_0, 0x77 },
135 { SAA7127_REG_COPYGEN_1, 0x41 },
136 { SAA7127_REG_COPYGEN_2, 0x00 },
137 { SAA7127_REG_OUTPUT_PORT_CONTROL, 0xbf },
138 { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 },
139 { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 },
140 { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 },
141 { SAA7127_REG_LINE_21_ODD_0, 0x77 },
142 { SAA7127_REG_LINE_21_ODD_1, 0x41 },
143 { SAA7127_REG_LINE_21_EVEN_0, 0x88 },
144 { SAA7127_REG_LINE_21_EVEN_1, 0x41 },
145 { SAA7127_REG_RCV_PORT_CONTROL, 0x12 },
146 { SAA7127_REG_VTRIG, 0xf9 },
147 { SAA7127_REG_HTRIG_HI, 0x00 },
148 { SAA7127_REG_RCV2_OUTPUT_START, 0x41 },
149 { SAA7127_REG_RCV2_OUTPUT_END, 0xc3 },
150 { SAA7127_REG_RCV2_OUTPUT_MSBS, 0x00 },
151 { SAA7127_REG_TTX_REQUEST_H_START, 0x3e },
152 { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 0xb8 },
153 { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT, 0x03 },
154 { SAA7127_REG_TTX_ODD_REQ_VERT_START, 0x15 },
155 { SAA7127_REG_TTX_ODD_REQ_VERT_END, 0x16 },
156 { SAA7127_REG_TTX_EVEN_REQ_VERT_START, 0x15 },
157 { SAA7127_REG_TTX_EVEN_REQ_VERT_END, 0x16 },
158 { SAA7127_REG_FIRST_ACTIVE, 0x1a },
159 { SAA7127_REG_LAST_ACTIVE, 0x01 },
160 { SAA7127_REG_MSB_VERTICAL, 0xc0 },
161 { SAA7127_REG_DISABLE_TTX_LINE_LO_0, 0x00 },
162 { SAA7127_REG_DISABLE_TTX_LINE_LO_1, 0x00 },
163 { 0, 0 }
164 };
165
166 #define SAA7127_60HZ_DAC_CONTROL 0x15
167 static const struct i2c_reg_value saa7127_init_config_60hz[] = {
168 { SAA7127_REG_BURST_START, 0x19 },
169
170 { SAA7127_REG_BURST_END, 0x1d },
171 { SAA7127_REG_CHROMA_PHASE, 0xa3 },
172 { SAA7127_REG_GAINU, 0x98 },
173 { SAA7127_REG_GAINV, 0xd3 },
174 { SAA7127_REG_BLACK_LEVEL, 0x39 },
175 { SAA7127_REG_BLANKING_LEVEL, 0x2e },
176 { SAA7127_REG_VBI_BLANKING, 0x2e },
177 { SAA7127_REG_DAC_CONTROL, 0x15 },
178 { SAA7127_REG_BURST_AMP, 0x4d },
179 { SAA7127_REG_SUBC3, 0x1f },
180 { SAA7127_REG_SUBC2, 0x7c },
181 { SAA7127_REG_SUBC1, 0xf0 },
182 { SAA7127_REG_SUBC0, 0x21 },
183 { SAA7127_REG_MULTI, 0x90 },
184 { SAA7127_REG_CLOSED_CAPTION, 0x11 },
185 { 0, 0 }
186 };
187
188 #define SAA7127_50HZ_PAL_DAC_CONTROL 0x02
189 static struct i2c_reg_value saa7127_init_config_50hz_pal[] = {
190 { SAA7127_REG_BURST_START, 0x21 },
191
192 { SAA7127_REG_BURST_END, 0x1d },
193 { SAA7127_REG_CHROMA_PHASE, 0x3f },
194 { SAA7127_REG_GAINU, 0x7d },
195 { SAA7127_REG_GAINV, 0xaf },
196 { SAA7127_REG_BLACK_LEVEL, 0x33 },
197 { SAA7127_REG_BLANKING_LEVEL, 0x35 },
198 { SAA7127_REG_VBI_BLANKING, 0x35 },
199 { SAA7127_REG_DAC_CONTROL, 0x02 },
200 { SAA7127_REG_BURST_AMP, 0x2f },
201 { SAA7127_REG_SUBC3, 0xcb },
202 { SAA7127_REG_SUBC2, 0x8a },
203 { SAA7127_REG_SUBC1, 0x09 },
204 { SAA7127_REG_SUBC0, 0x2a },
205 { SAA7127_REG_MULTI, 0xa0 },
206 { SAA7127_REG_CLOSED_CAPTION, 0x00 },
207 { 0, 0 }
208 };
209
210 #define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08
211 static struct i2c_reg_value saa7127_init_config_50hz_secam[] = {
212 { SAA7127_REG_BURST_START, 0x21 },
213
214 { SAA7127_REG_BURST_END, 0x1d },
215 { SAA7127_REG_CHROMA_PHASE, 0x3f },
216 { SAA7127_REG_GAINU, 0x6a },
217 { SAA7127_REG_GAINV, 0x81 },
218 { SAA7127_REG_BLACK_LEVEL, 0x33 },
219 { SAA7127_REG_BLANKING_LEVEL, 0x35 },
220 { SAA7127_REG_VBI_BLANKING, 0x35 },
221 { SAA7127_REG_DAC_CONTROL, 0x08 },
222 { SAA7127_REG_BURST_AMP, 0x2f },
223 { SAA7127_REG_SUBC3, 0xb2 },
224 { SAA7127_REG_SUBC2, 0x3b },
225 { SAA7127_REG_SUBC1, 0xa3 },
226 { SAA7127_REG_SUBC0, 0x28 },
227 { SAA7127_REG_MULTI, 0x90 },
228 { SAA7127_REG_CLOSED_CAPTION, 0x00 },
229 { 0, 0 }
230 };
231
232
233
234
235
236
237
238
239
240 enum saa712x_model {
241 SAA7127,
242 SAA7129,
243 };
244
245 struct saa7127_state {
246 struct v4l2_subdev sd;
247 v4l2_std_id std;
248 enum saa712x_model ident;
249 enum saa7127_input_type input_type;
250 enum saa7127_output_type output_type;
251 int video_enable;
252 int wss_enable;
253 u16 wss_mode;
254 int cc_enable;
255 u16 cc_data;
256 int xds_enable;
257 u16 xds_data;
258 int vps_enable;
259 u8 vps_data[5];
260 u8 reg_2d;
261 u8 reg_3a;
262 u8 reg_3a_cb;
263 u8 reg_61;
264 };
265
266 static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
267 {
268 return container_of(sd, struct saa7127_state, sd);
269 }
270
271 static const char * const output_strs[] =
272 {
273 "S-Video + Composite",
274 "Composite",
275 "S-Video",
276 "RGB",
277 "YUV C",
278 "YUV V"
279 };
280
281 static const char * const wss_strs[] = {
282 "invalid",
283 "letterbox 14:9 center",
284 "letterbox 14:9 top",
285 "invalid",
286 "letterbox 16:9 top",
287 "invalid",
288 "invalid",
289 "16:9 full format anamorphic",
290 "4:3 full format",
291 "invalid",
292 "invalid",
293 "letterbox 16:9 center",
294 "invalid",
295 "letterbox >16:9 center",
296 "14:9 full format center",
297 "invalid",
298 };
299
300
301
302 static int saa7127_read(struct v4l2_subdev *sd, u8 reg)
303 {
304 struct i2c_client *client = v4l2_get_subdevdata(sd);
305
306 return i2c_smbus_read_byte_data(client, reg);
307 }
308
309
310
311 static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
312 {
313 struct i2c_client *client = v4l2_get_subdevdata(sd);
314 int i;
315
316 for (i = 0; i < 3; i++) {
317 if (i2c_smbus_write_byte_data(client, reg, val) == 0)
318 return 0;
319 }
320 v4l2_err(sd, "I2C Write Problem\n");
321 return -1;
322 }
323
324
325
326 static int saa7127_write_inittab(struct v4l2_subdev *sd,
327 const struct i2c_reg_value *regs)
328 {
329 while (regs->reg != 0) {
330 saa7127_write(sd, regs->reg, regs->value);
331 regs++;
332 }
333 return 0;
334 }
335
336
337
338 static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
339 {
340 struct saa7127_state *state = to_state(sd);
341 int enable = (data->line != 0);
342
343 if (enable && (data->field != 0 || data->line != 16))
344 return -EINVAL;
345 if (state->vps_enable != enable) {
346 v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
347 saa7127_write(sd, 0x54, enable << 7);
348 state->vps_enable = enable;
349 }
350 if (!enable)
351 return 0;
352
353 state->vps_data[0] = data->data[2];
354 state->vps_data[1] = data->data[8];
355 state->vps_data[2] = data->data[9];
356 state->vps_data[3] = data->data[10];
357 state->vps_data[4] = data->data[11];
358 v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
359 saa7127_write(sd, 0x55, state->vps_data[0]);
360 saa7127_write(sd, 0x56, state->vps_data[1]);
361 saa7127_write(sd, 0x57, state->vps_data[2]);
362 saa7127_write(sd, 0x58, state->vps_data[3]);
363 saa7127_write(sd, 0x59, state->vps_data[4]);
364 return 0;
365 }
366
367
368
369 static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
370 {
371 struct saa7127_state *state = to_state(sd);
372 u16 cc = data->data[1] << 8 | data->data[0];
373 int enable = (data->line != 0);
374
375 if (enable && (data->field != 0 || data->line != 21))
376 return -EINVAL;
377 if (state->cc_enable != enable) {
378 v4l2_dbg(1, debug, sd,
379 "Turn CC %s\n", enable ? "on" : "off");
380 saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
381 (state->xds_enable << 7) | (enable << 6) | 0x11);
382 state->cc_enable = enable;
383 }
384 if (!enable)
385 return 0;
386
387 v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
388 saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
389 saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
390 state->cc_data = cc;
391 return 0;
392 }
393
394
395
396 static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
397 {
398 struct saa7127_state *state = to_state(sd);
399 u16 xds = data->data[1] << 8 | data->data[0];
400 int enable = (data->line != 0);
401
402 if (enable && (data->field != 1 || data->line != 21))
403 return -EINVAL;
404 if (state->xds_enable != enable) {
405 v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
406 saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
407 (enable << 7) | (state->cc_enable << 6) | 0x11);
408 state->xds_enable = enable;
409 }
410 if (!enable)
411 return 0;
412
413 v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
414 saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
415 saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
416 state->xds_data = xds;
417 return 0;
418 }
419
420
421
422 static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
423 {
424 struct saa7127_state *state = to_state(sd);
425 int enable = (data->line != 0);
426
427 if (enable && (data->field != 0 || data->line != 23))
428 return -EINVAL;
429 if (state->wss_enable != enable) {
430 v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
431 saa7127_write(sd, 0x27, enable << 7);
432 state->wss_enable = enable;
433 }
434 if (!enable)
435 return 0;
436
437 saa7127_write(sd, 0x26, data->data[0]);
438 saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
439 v4l2_dbg(1, debug, sd,
440 "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
441 state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
442 return 0;
443 }
444
445
446
447 static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
448 {
449 struct saa7127_state *state = to_state(sd);
450
451 if (enable) {
452 v4l2_dbg(1, debug, sd, "Enable Video Output\n");
453 saa7127_write(sd, 0x2d, state->reg_2d);
454 saa7127_write(sd, 0x61, state->reg_61);
455 } else {
456 v4l2_dbg(1, debug, sd, "Disable Video Output\n");
457 saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
458 saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
459 }
460 state->video_enable = enable;
461 return 0;
462 }
463
464
465
466 static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
467 {
468 struct saa7127_state *state = to_state(sd);
469 const struct i2c_reg_value *inittab;
470
471 if (std & V4L2_STD_525_60) {
472 v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
473 inittab = saa7127_init_config_60hz;
474 state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
475
476 } else if (state->ident == SAA7129 &&
477 (std & V4L2_STD_SECAM) &&
478 !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) {
479
480
481 v4l2_dbg(1, debug, sd,
482 "Selecting 50 Hz SECAM video Standard\n");
483 inittab = saa7127_init_config_50hz_secam;
484 state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL;
485
486 } else {
487 v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n");
488 inittab = saa7127_init_config_50hz_pal;
489 state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL;
490 }
491
492
493 saa7127_write_inittab(sd, inittab);
494 state->std = std;
495 return 0;
496 }
497
498
499
500 static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
501 {
502 struct saa7127_state *state = to_state(sd);
503
504 switch (output) {
505 case SAA7127_OUTPUT_TYPE_RGB:
506 state->reg_2d = 0x0f;
507 state->reg_3a = 0x13;
508 break;
509
510 case SAA7127_OUTPUT_TYPE_COMPOSITE:
511 if (state->ident == SAA7129)
512 state->reg_2d = 0x20;
513 else
514 state->reg_2d = 0x08;
515 state->reg_3a = 0x13;
516 break;
517
518 case SAA7127_OUTPUT_TYPE_SVIDEO:
519 if (state->ident == SAA7129)
520 state->reg_2d = 0x18;
521 else
522 state->reg_2d = 0xff;
523 state->reg_3a = 0x13;
524 break;
525
526 case SAA7127_OUTPUT_TYPE_YUV_V:
527 state->reg_2d = 0x4f;
528 state->reg_3a = 0x0b;
529 break;
530
531 case SAA7127_OUTPUT_TYPE_YUV_C:
532 state->reg_2d = 0x0f;
533 state->reg_3a = 0x0b;
534 break;
535
536 case SAA7127_OUTPUT_TYPE_BOTH:
537 if (state->ident == SAA7129)
538 state->reg_2d = 0x38;
539 else
540 state->reg_2d = 0xbf;
541 state->reg_3a = 0x13;
542 break;
543
544 default:
545 return -EINVAL;
546 }
547 v4l2_dbg(1, debug, sd,
548 "Selecting %s output type\n", output_strs[output]);
549
550
551 saa7127_write(sd, 0x2d, state->reg_2d);
552 saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
553 state->output_type = output;
554 return 0;
555 }
556
557
558
559 static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
560 {
561 struct saa7127_state *state = to_state(sd);
562
563 switch (input) {
564 case SAA7127_INPUT_TYPE_NORMAL:
565 v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
566 state->reg_3a_cb = 0;
567 break;
568
569 case SAA7127_INPUT_TYPE_TEST_IMAGE:
570 v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
571 state->reg_3a_cb = 0x80;
572 break;
573
574 default:
575 return -EINVAL;
576 }
577 saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
578 state->input_type = input;
579 return 0;
580 }
581
582
583
584 static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
585 {
586 struct saa7127_state *state = to_state(sd);
587
588 if (state->std == std)
589 return 0;
590 return saa7127_set_std(sd, std);
591 }
592
593 static int saa7127_s_routing(struct v4l2_subdev *sd,
594 u32 input, u32 output, u32 config)
595 {
596 struct saa7127_state *state = to_state(sd);
597 int rc = 0;
598
599 if (state->input_type != input)
600 rc = saa7127_set_input_type(sd, input);
601 if (rc == 0 && state->output_type != output)
602 rc = saa7127_set_output_type(sd, output);
603 return rc;
604 }
605
606 static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
607 {
608 struct saa7127_state *state = to_state(sd);
609
610 if (state->video_enable == enable)
611 return 0;
612 return saa7127_set_video_enable(sd, enable);
613 }
614
615 static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
616 {
617 struct saa7127_state *state = to_state(sd);
618
619 memset(fmt->service_lines, 0, sizeof(fmt->service_lines));
620 if (state->vps_enable)
621 fmt->service_lines[0][16] = V4L2_SLICED_VPS;
622 if (state->wss_enable)
623 fmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
624 if (state->cc_enable) {
625 fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
626 fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
627 }
628 fmt->service_set =
629 (state->vps_enable ? V4L2_SLICED_VPS : 0) |
630 (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
631 (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
632 return 0;
633 }
634
635 static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
636 {
637 switch (data->id) {
638 case V4L2_SLICED_WSS_625:
639 return saa7127_set_wss(sd, data);
640 case V4L2_SLICED_VPS:
641 return saa7127_set_vps(sd, data);
642 case V4L2_SLICED_CAPTION_525:
643 if (data->field == 0)
644 return saa7127_set_cc(sd, data);
645 return saa7127_set_xds(sd, data);
646 default:
647 return -EINVAL;
648 }
649 return 0;
650 }
651
652 #ifdef CONFIG_VIDEO_ADV_DEBUG
653 static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
654 {
655 reg->val = saa7127_read(sd, reg->reg & 0xff);
656 reg->size = 1;
657 return 0;
658 }
659
660 static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
661 {
662 saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
663 return 0;
664 }
665 #endif
666
667 static int saa7127_log_status(struct v4l2_subdev *sd)
668 {
669 struct saa7127_state *state = to_state(sd);
670
671 v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
672 v4l2_info(sd, "Input: %s\n", state->input_type ? "color bars" : "normal");
673 v4l2_info(sd, "Output: %s\n", state->video_enable ?
674 output_strs[state->output_type] : "disabled");
675 v4l2_info(sd, "WSS: %s\n", state->wss_enable ?
676 wss_strs[state->wss_mode] : "disabled");
677 v4l2_info(sd, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
678 v4l2_info(sd, "CC: %s\n", state->cc_enable ? "enabled" : "disabled");
679 return 0;
680 }
681
682
683
684 static const struct v4l2_subdev_core_ops saa7127_core_ops = {
685 .log_status = saa7127_log_status,
686 #ifdef CONFIG_VIDEO_ADV_DEBUG
687 .g_register = saa7127_g_register,
688 .s_register = saa7127_s_register,
689 #endif
690 };
691
692 static const struct v4l2_subdev_video_ops saa7127_video_ops = {
693 .s_std_output = saa7127_s_std_output,
694 .s_routing = saa7127_s_routing,
695 .s_stream = saa7127_s_stream,
696 };
697
698 static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
699 .s_vbi_data = saa7127_s_vbi_data,
700 .g_sliced_fmt = saa7127_g_sliced_fmt,
701 };
702
703 static const struct v4l2_subdev_ops saa7127_ops = {
704 .core = &saa7127_core_ops,
705 .video = &saa7127_video_ops,
706 .vbi = &saa7127_vbi_ops,
707 };
708
709
710
711 static int saa7127_probe(struct i2c_client *client,
712 const struct i2c_device_id *id)
713 {
714 struct saa7127_state *state;
715 struct v4l2_subdev *sd;
716 struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };
717
718
719 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
720 return -EIO;
721
722 v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
723 client->addr << 1);
724
725 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
726 if (state == NULL)
727 return -ENOMEM;
728
729 sd = &state->sd;
730 v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
731
732
733
734
735
736
737 if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
738 (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
739 v4l2_dbg(1, debug, sd, "saa7127 not found\n");
740 return -ENODEV;
741 }
742
743 if (id->driver_data) {
744 state->ident = id->driver_data;
745 } else {
746 int read_result;
747
748
749 read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
750 saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
751 if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
752 saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
753 read_result);
754 state->ident = SAA7129;
755 strscpy(client->name, "saa7129", I2C_NAME_SIZE);
756 } else {
757 state->ident = SAA7127;
758 strscpy(client->name, "saa7127", I2C_NAME_SIZE);
759 }
760 }
761
762 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
763 client->addr << 1, client->adapter->name);
764
765 v4l2_dbg(1, debug, sd, "Configuring encoder\n");
766 saa7127_write_inittab(sd, saa7127_init_config_common);
767 saa7127_set_std(sd, V4L2_STD_NTSC);
768 saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
769 saa7127_set_vps(sd, &vbi);
770 saa7127_set_wss(sd, &vbi);
771 saa7127_set_cc(sd, &vbi);
772 saa7127_set_xds(sd, &vbi);
773 if (test_image == 1)
774
775
776 saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
777 else
778 saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
779 saa7127_set_video_enable(sd, 1);
780
781 if (state->ident == SAA7129)
782 saa7127_write_inittab(sd, saa7129_init_config_extra);
783 return 0;
784 }
785
786
787
788 static int saa7127_remove(struct i2c_client *client)
789 {
790 struct v4l2_subdev *sd = i2c_get_clientdata(client);
791
792 v4l2_device_unregister_subdev(sd);
793
794 saa7127_set_video_enable(sd, 0);
795 return 0;
796 }
797
798
799
800 static const struct i2c_device_id saa7127_id[] = {
801 { "saa7127_auto", 0 },
802 { "saa7126", SAA7127 },
803 { "saa7127", SAA7127 },
804 { "saa7128", SAA7129 },
805 { "saa7129", SAA7129 },
806 { }
807 };
808 MODULE_DEVICE_TABLE(i2c, saa7127_id);
809
810 static struct i2c_driver saa7127_driver = {
811 .driver = {
812 .name = "saa7127",
813 },
814 .probe = saa7127_probe,
815 .remove = saa7127_remove,
816 .id_table = saa7127_id,
817 };
818
819 module_i2c_driver(saa7127_driver);