xref: /linux/drivers/media/i2c/saa717x.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * saa717x - Philips SAA717xHL video decoder driver
4  *
5  * Based on the saa7115 driver
6  *
7  * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
8  *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
9  *
10  * Changes by T.Adachi (tadachi@tadachi-net.com)
11  *    - support audio, video scaler etc, and checked the initialize sequence.
12  *
13  * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
14  *
15  * Note: this is a reversed engineered driver based on captures from
16  * the I2C bus under Windows. This chip is very similar to the saa7134,
17  * though. Unfortunately, this driver is currently only working for NTSC.
18  */
19 
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/slab.h>
23 #include <linux/sched.h>
24 
25 #include <linux/videodev2.h>
26 #include <linux/i2c.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-ctrls.h>
29 
30 MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
31 MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
32 MODULE_LICENSE("GPL");
33 
34 static int debug;
35 module_param(debug, int, 0644);
36 MODULE_PARM_DESC(debug, "Debug level (0-1)");
37 
38 /*
39  * Generic i2c probe
40  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
41  */
42 
43 struct saa717x_state {
44 	struct v4l2_subdev sd;
45 	struct v4l2_ctrl_handler hdl;
46 	v4l2_std_id std;
47 	int input;
48 	int enable;
49 	int radio;
50 	int playback;
51 	int audio;
52 	int tuner_audio_mode;
53 	int audio_main_mute;
54 	int audio_main_vol_r;
55 	int audio_main_vol_l;
56 	u16 audio_main_bass;
57 	u16 audio_main_treble;
58 	u16 audio_main_volume;
59 	u16 audio_main_balance;
60 	int audio_input;
61 };
62 
to_state(struct v4l2_subdev * sd)63 static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
64 {
65 	return container_of(sd, struct saa717x_state, sd);
66 }
67 
to_sd(struct v4l2_ctrl * ctrl)68 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
69 {
70 	return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
71 }
72 
73 /* ----------------------------------------------------------------------- */
74 
75 /* for audio mode */
76 #define TUNER_AUDIO_MONO	0  /* LL */
77 #define TUNER_AUDIO_STEREO	1  /* LR */
78 #define TUNER_AUDIO_LANG1	2  /* LL */
79 #define TUNER_AUDIO_LANG2	3  /* RR */
80 
81 #define SAA717X_NTSC_WIDTH	(704)
82 #define SAA717X_NTSC_HEIGHT	(480)
83 
84 /* ----------------------------------------------------------------------- */
85 
saa717x_write(struct v4l2_subdev * sd,u32 reg,u32 value)86 static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
87 {
88 	struct i2c_client *client = v4l2_get_subdevdata(sd);
89 	struct i2c_adapter *adap = client->adapter;
90 	int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
91 	unsigned char mm1[6];
92 	struct i2c_msg msg;
93 
94 	msg.flags = 0;
95 	msg.addr = client->addr;
96 	mm1[0] = (reg >> 8) & 0xff;
97 	mm1[1] = reg & 0xff;
98 
99 	if (fw_addr) {
100 		mm1[4] = (value >> 16) & 0xff;
101 		mm1[3] = (value >> 8) & 0xff;
102 		mm1[2] = value & 0xff;
103 	} else {
104 		mm1[2] = value & 0xff;
105 	}
106 	msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
107 	msg.buf = mm1;
108 	v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
109 	return i2c_transfer(adap, &msg, 1) == 1;
110 }
111 
saa717x_write_regs(struct v4l2_subdev * sd,u32 * data)112 static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
113 {
114 	while (data[0] || data[1]) {
115 		saa717x_write(sd, data[0], data[1]);
116 		data += 2;
117 	}
118 }
119 
saa717x_read(struct v4l2_subdev * sd,u32 reg)120 static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
121 {
122 	struct i2c_client *client = v4l2_get_subdevdata(sd);
123 	struct i2c_adapter *adap = client->adapter;
124 	int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
125 	unsigned char mm1[2];
126 	unsigned char mm2[4] = { 0, 0, 0, 0 };
127 	struct i2c_msg msgs[2];
128 	u32 value;
129 
130 	msgs[0].flags = 0;
131 	msgs[1].flags = I2C_M_RD;
132 	msgs[0].addr = msgs[1].addr = client->addr;
133 	mm1[0] = (reg >> 8) & 0xff;
134 	mm1[1] = reg & 0xff;
135 	msgs[0].len = 2;
136 	msgs[0].buf = mm1;
137 	msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
138 	msgs[1].buf = mm2;
139 	i2c_transfer(adap, msgs, 2);
140 
141 	if (fw_addr)
142 		value = (mm2[2] << 16)  | (mm2[1] << 8) | mm2[0];
143 	else
144 		value = mm2[0];
145 
146 	v4l2_dbg(2, debug, sd, "read:  reg 0x%03x=0x%08x\n", reg, value);
147 	return value;
148 }
149 
150 /* ----------------------------------------------------------------------- */
151 
152 static u32 reg_init_initialize[] =
153 {
154 	/* from linux driver */
155 	0x101, 0x008, /* Increment delay */
156 
157 	0x103, 0x000, /* Analog input control 2 */
158 	0x104, 0x090, /* Analog input control 3 */
159 	0x105, 0x090, /* Analog input control 4 */
160 	0x106, 0x0eb, /* Horizontal sync start */
161 	0x107, 0x0e0, /* Horizontal sync stop */
162 	0x109, 0x055, /* Luminance control */
163 
164 	0x10f, 0x02a, /* Chroma gain control */
165 	0x110, 0x000, /* Chroma control 2 */
166 
167 	0x114, 0x045, /* analog/ADC */
168 
169 	0x118, 0x040, /* RAW data gain */
170 	0x119, 0x080, /* RAW data offset */
171 
172 	0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
173 	0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
174 	0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
175 	0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
176 
177 	0x049, 0x000, /* VBI vertical input window start (H) TASK A */
178 
179 	0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
180 	0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
181 
182 	0x064, 0x080, /* Lumina brightness TASK A */
183 	0x065, 0x040, /* Luminance contrast TASK A */
184 	0x066, 0x040, /* Chroma saturation TASK A */
185 	/* 067H: Reserved */
186 	0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
187 	0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
188 	0x06a, 0x000, /* VBI phase offset TASK A */
189 
190 	0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
191 	0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
192 
193 	0x072, 0x000, /* Vertical filter mode TASK A */
194 
195 	0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
196 	0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
197 	0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
198 	0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
199 
200 	0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
201 
202 	0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
203 	0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
204 
205 	0x0a4, 0x080, /* Lumina brightness TASK B */
206 	0x0a5, 0x040, /* Luminance contrast TASK B */
207 	0x0a6, 0x040, /* Chroma saturation TASK B */
208 	/* 0A7H reserved */
209 	0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
210 	0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
211 	0x0aa, 0x000, /* VBI phase offset TASK B */
212 
213 	0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
214 	0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
215 
216 	0x0b2, 0x000, /* Vertical filter mode TASK B */
217 
218 	0x00c, 0x000, /* Start point GREEN path */
219 	0x00d, 0x000, /* Start point BLUE path */
220 	0x00e, 0x000, /* Start point RED path */
221 
222 	0x010, 0x010, /* GREEN path gamma curve --- */
223 	0x011, 0x020,
224 	0x012, 0x030,
225 	0x013, 0x040,
226 	0x014, 0x050,
227 	0x015, 0x060,
228 	0x016, 0x070,
229 	0x017, 0x080,
230 	0x018, 0x090,
231 	0x019, 0x0a0,
232 	0x01a, 0x0b0,
233 	0x01b, 0x0c0,
234 	0x01c, 0x0d0,
235 	0x01d, 0x0e0,
236 	0x01e, 0x0f0,
237 	0x01f, 0x0ff, /* --- GREEN path gamma curve */
238 
239 	0x020, 0x010, /* BLUE path gamma curve --- */
240 	0x021, 0x020,
241 	0x022, 0x030,
242 	0x023, 0x040,
243 	0x024, 0x050,
244 	0x025, 0x060,
245 	0x026, 0x070,
246 	0x027, 0x080,
247 	0x028, 0x090,
248 	0x029, 0x0a0,
249 	0x02a, 0x0b0,
250 	0x02b, 0x0c0,
251 	0x02c, 0x0d0,
252 	0x02d, 0x0e0,
253 	0x02e, 0x0f0,
254 	0x02f, 0x0ff, /* --- BLUE path gamma curve */
255 
256 	0x030, 0x010, /* RED path gamma curve --- */
257 	0x031, 0x020,
258 	0x032, 0x030,
259 	0x033, 0x040,
260 	0x034, 0x050,
261 	0x035, 0x060,
262 	0x036, 0x070,
263 	0x037, 0x080,
264 	0x038, 0x090,
265 	0x039, 0x0a0,
266 	0x03a, 0x0b0,
267 	0x03b, 0x0c0,
268 	0x03c, 0x0d0,
269 	0x03d, 0x0e0,
270 	0x03e, 0x0f0,
271 	0x03f, 0x0ff, /* --- RED path gamma curve */
272 
273 	0x109, 0x085, /* Luminance control  */
274 
275 	/**** from app start ****/
276 	0x584, 0x000, /* AGC gain control */
277 	0x585, 0x000, /* Program count */
278 	0x586, 0x003, /* Status reset */
279 	0x588, 0x0ff, /* Number of audio samples (L) */
280 	0x589, 0x00f, /* Number of audio samples (M) */
281 	0x58a, 0x000, /* Number of audio samples (H) */
282 	0x58b, 0x000, /* Audio select */
283 	0x58c, 0x010, /* Audio channel assign1 */
284 	0x58d, 0x032, /* Audio channel assign2 */
285 	0x58e, 0x054, /* Audio channel assign3 */
286 	0x58f, 0x023, /* Audio format */
287 	0x590, 0x000, /* SIF control */
288 
289 	0x595, 0x000, /* ?? */
290 	0x596, 0x000, /* ?? */
291 	0x597, 0x000, /* ?? */
292 
293 	0x464, 0x00, /* Digital input crossbar1 */
294 
295 	0x46c, 0xbbbb10, /* Digital output selection1-3 */
296 	0x470, 0x101010, /* Digital output selection4-6 */
297 
298 	0x478, 0x00, /* Sound feature control */
299 
300 	0x474, 0x18, /* Softmute control */
301 
302 	0x454, 0x0425b9, /* Sound Easy programming(reset) */
303 	0x454, 0x042539, /* Sound Easy programming(reset) */
304 
305 
306 	/**** common setting( of DVD play, including scaler commands) ****/
307 	0x042, 0x003, /* Data path configuration for VBI (TASK A) */
308 
309 	0x082, 0x003, /* Data path configuration for VBI (TASK B) */
310 
311 	0x108, 0x0f8, /* Sync control */
312 	0x2a9, 0x0fd, /* ??? */
313 	0x102, 0x089, /* select video input "mode 9" */
314 	0x111, 0x000, /* Mode/delay control */
315 
316 	0x10e, 0x00a, /* Chroma control 1 */
317 
318 	0x594, 0x002, /* SIF, analog I/O select */
319 
320 	0x454, 0x0425b9, /* Sound  */
321 	0x454, 0x042539,
322 
323 	0x111, 0x000,
324 	0x10e, 0x00a,
325 	0x464, 0x000,
326 	0x300, 0x000,
327 	0x301, 0x006,
328 	0x302, 0x000,
329 	0x303, 0x006,
330 	0x308, 0x040,
331 	0x309, 0x000,
332 	0x30a, 0x000,
333 	0x30b, 0x000,
334 	0x000, 0x002,
335 	0x001, 0x000,
336 	0x002, 0x000,
337 	0x003, 0x000,
338 	0x004, 0x033,
339 	0x040, 0x01d,
340 	0x041, 0x001,
341 	0x042, 0x004,
342 	0x043, 0x000,
343 	0x080, 0x01e,
344 	0x081, 0x001,
345 	0x082, 0x004,
346 	0x083, 0x000,
347 	0x190, 0x018,
348 	0x115, 0x000,
349 	0x116, 0x012,
350 	0x117, 0x018,
351 	0x04a, 0x011,
352 	0x08a, 0x011,
353 	0x04b, 0x000,
354 	0x08b, 0x000,
355 	0x048, 0x000,
356 	0x088, 0x000,
357 	0x04e, 0x012,
358 	0x08e, 0x012,
359 	0x058, 0x012,
360 	0x098, 0x012,
361 	0x059, 0x000,
362 	0x099, 0x000,
363 	0x05a, 0x003,
364 	0x09a, 0x003,
365 	0x05b, 0x001,
366 	0x09b, 0x001,
367 	0x054, 0x008,
368 	0x094, 0x008,
369 	0x055, 0x000,
370 	0x095, 0x000,
371 	0x056, 0x0c7,
372 	0x096, 0x0c7,
373 	0x057, 0x002,
374 	0x097, 0x002,
375 	0x0ff, 0x0ff,
376 	0x060, 0x001,
377 	0x0a0, 0x001,
378 	0x061, 0x000,
379 	0x0a1, 0x000,
380 	0x062, 0x000,
381 	0x0a2, 0x000,
382 	0x063, 0x000,
383 	0x0a3, 0x000,
384 	0x070, 0x000,
385 	0x0b0, 0x000,
386 	0x071, 0x004,
387 	0x0b1, 0x004,
388 	0x06c, 0x0e9,
389 	0x0ac, 0x0e9,
390 	0x06d, 0x003,
391 	0x0ad, 0x003,
392 	0x05c, 0x0d0,
393 	0x09c, 0x0d0,
394 	0x05d, 0x002,
395 	0x09d, 0x002,
396 	0x05e, 0x0f2,
397 	0x09e, 0x0f2,
398 	0x05f, 0x000,
399 	0x09f, 0x000,
400 	0x074, 0x000,
401 	0x0b4, 0x000,
402 	0x075, 0x000,
403 	0x0b5, 0x000,
404 	0x076, 0x000,
405 	0x0b6, 0x000,
406 	0x077, 0x000,
407 	0x0b7, 0x000,
408 	0x195, 0x008,
409 	0x0ff, 0x0ff,
410 	0x108, 0x0f8,
411 	0x111, 0x000,
412 	0x10e, 0x00a,
413 	0x2a9, 0x0fd,
414 	0x464, 0x001,
415 	0x454, 0x042135,
416 	0x598, 0x0e7,
417 	0x599, 0x07d,
418 	0x59a, 0x018,
419 	0x59c, 0x066,
420 	0x59d, 0x090,
421 	0x59e, 0x001,
422 	0x584, 0x000,
423 	0x585, 0x000,
424 	0x586, 0x003,
425 	0x588, 0x0ff,
426 	0x589, 0x00f,
427 	0x58a, 0x000,
428 	0x58b, 0x000,
429 	0x58c, 0x010,
430 	0x58d, 0x032,
431 	0x58e, 0x054,
432 	0x58f, 0x023,
433 	0x590, 0x000,
434 	0x595, 0x000,
435 	0x596, 0x000,
436 	0x597, 0x000,
437 	0x464, 0x000,
438 	0x46c, 0xbbbb10,
439 	0x470, 0x101010,
440 
441 
442 	0x478, 0x000,
443 	0x474, 0x018,
444 	0x454, 0x042135,
445 	0x598, 0x0e7,
446 	0x599, 0x07d,
447 	0x59a, 0x018,
448 	0x59c, 0x066,
449 	0x59d, 0x090,
450 	0x59e, 0x001,
451 	0x584, 0x000,
452 	0x585, 0x000,
453 	0x586, 0x003,
454 	0x588, 0x0ff,
455 	0x589, 0x00f,
456 	0x58a, 0x000,
457 	0x58b, 0x000,
458 	0x58c, 0x010,
459 	0x58d, 0x032,
460 	0x58e, 0x054,
461 	0x58f, 0x023,
462 	0x590, 0x000,
463 	0x595, 0x000,
464 	0x596, 0x000,
465 	0x597, 0x000,
466 	0x464, 0x000,
467 	0x46c, 0xbbbb10,
468 	0x470, 0x101010,
469 
470 	0x478, 0x000,
471 	0x474, 0x018,
472 	0x454, 0x042135,
473 	0x598, 0x0e7,
474 	0x599, 0x07d,
475 	0x59a, 0x018,
476 	0x59c, 0x066,
477 	0x59d, 0x090,
478 	0x59e, 0x001,
479 	0x584, 0x000,
480 	0x585, 0x000,
481 	0x586, 0x003,
482 	0x588, 0x0ff,
483 	0x589, 0x00f,
484 	0x58a, 0x000,
485 	0x58b, 0x000,
486 	0x58c, 0x010,
487 	0x58d, 0x032,
488 	0x58e, 0x054,
489 	0x58f, 0x023,
490 	0x590, 0x000,
491 	0x595, 0x000,
492 	0x596, 0x000,
493 	0x597, 0x000,
494 	0x464, 0x000,
495 	0x46c, 0xbbbb10,
496 	0x470, 0x101010,
497 	0x478, 0x000,
498 	0x474, 0x018,
499 	0x454, 0x042135,
500 	0x193, 0x000,
501 	0x300, 0x000,
502 	0x301, 0x006,
503 	0x302, 0x000,
504 	0x303, 0x006,
505 	0x308, 0x040,
506 	0x309, 0x000,
507 	0x30a, 0x000,
508 	0x30b, 0x000,
509 	0x000, 0x002,
510 	0x001, 0x000,
511 	0x002, 0x000,
512 	0x003, 0x000,
513 	0x004, 0x033,
514 	0x040, 0x01d,
515 	0x041, 0x001,
516 	0x042, 0x004,
517 	0x043, 0x000,
518 	0x080, 0x01e,
519 	0x081, 0x001,
520 	0x082, 0x004,
521 	0x083, 0x000,
522 	0x190, 0x018,
523 	0x115, 0x000,
524 	0x116, 0x012,
525 	0x117, 0x018,
526 	0x04a, 0x011,
527 	0x08a, 0x011,
528 	0x04b, 0x000,
529 	0x08b, 0x000,
530 	0x048, 0x000,
531 	0x088, 0x000,
532 	0x04e, 0x012,
533 	0x08e, 0x012,
534 	0x058, 0x012,
535 	0x098, 0x012,
536 	0x059, 0x000,
537 	0x099, 0x000,
538 	0x05a, 0x003,
539 	0x09a, 0x003,
540 	0x05b, 0x001,
541 	0x09b, 0x001,
542 	0x054, 0x008,
543 	0x094, 0x008,
544 	0x055, 0x000,
545 	0x095, 0x000,
546 	0x056, 0x0c7,
547 	0x096, 0x0c7,
548 	0x057, 0x002,
549 	0x097, 0x002,
550 	0x060, 0x001,
551 	0x0a0, 0x001,
552 	0x061, 0x000,
553 	0x0a1, 0x000,
554 	0x062, 0x000,
555 	0x0a2, 0x000,
556 	0x063, 0x000,
557 	0x0a3, 0x000,
558 	0x070, 0x000,
559 	0x0b0, 0x000,
560 	0x071, 0x004,
561 	0x0b1, 0x004,
562 	0x06c, 0x0e9,
563 	0x0ac, 0x0e9,
564 	0x06d, 0x003,
565 	0x0ad, 0x003,
566 	0x05c, 0x0d0,
567 	0x09c, 0x0d0,
568 	0x05d, 0x002,
569 	0x09d, 0x002,
570 	0x05e, 0x0f2,
571 	0x09e, 0x0f2,
572 	0x05f, 0x000,
573 	0x09f, 0x000,
574 	0x074, 0x000,
575 	0x0b4, 0x000,
576 	0x075, 0x000,
577 	0x0b5, 0x000,
578 	0x076, 0x000,
579 	0x0b6, 0x000,
580 	0x077, 0x000,
581 	0x0b7, 0x000,
582 	0x195, 0x008,
583 	0x598, 0x0e7,
584 	0x599, 0x07d,
585 	0x59a, 0x018,
586 	0x59c, 0x066,
587 	0x59d, 0x090,
588 	0x59e, 0x001,
589 	0x584, 0x000,
590 	0x585, 0x000,
591 	0x586, 0x003,
592 	0x588, 0x0ff,
593 	0x589, 0x00f,
594 	0x58a, 0x000,
595 	0x58b, 0x000,
596 	0x58c, 0x010,
597 	0x58d, 0x032,
598 	0x58e, 0x054,
599 	0x58f, 0x023,
600 	0x590, 0x000,
601 	0x595, 0x000,
602 	0x596, 0x000,
603 	0x597, 0x000,
604 	0x464, 0x000,
605 	0x46c, 0xbbbb10,
606 	0x470, 0x101010,
607 	0x478, 0x000,
608 	0x474, 0x018,
609 	0x454, 0x042135,
610 	0x193, 0x0a6,
611 	0x108, 0x0f8,
612 	0x042, 0x003,
613 	0x082, 0x003,
614 	0x454, 0x0425b9,
615 	0x454, 0x042539,
616 	0x193, 0x000,
617 	0x193, 0x0a6,
618 	0x464, 0x000,
619 
620 	0, 0
621 };
622 
623 /* Tuner */
624 static u32 reg_init_tuner_input[] = {
625 	0x108, 0x0f8, /* Sync control */
626 	0x111, 0x000, /* Mode/delay control */
627 	0x10e, 0x00a, /* Chroma control 1 */
628 	0, 0
629 };
630 
631 /* Composite */
632 static u32 reg_init_composite_input[] = {
633 	0x108, 0x0e8, /* Sync control */
634 	0x111, 0x000, /* Mode/delay control */
635 	0x10e, 0x04a, /* Chroma control 1 */
636 	0, 0
637 };
638 
639 /* S-Video */
640 static u32 reg_init_svideo_input[] = {
641 	0x108, 0x0e8, /* Sync control */
642 	0x111, 0x000, /* Mode/delay control */
643 	0x10e, 0x04a, /* Chroma control 1 */
644 	0, 0
645 };
646 
647 static u32 reg_set_audio_template[4][2] =
648 {
649 	{ /* for MONO
650 		tadachi 6/29 DMA audio output select?
651 		Register 0x46c
652 		7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
653 		0: MAIN left,  1: MAIN right
654 		2: AUX1 left,  3: AUX1 right
655 		4: AUX2 left,  5: AUX2 right
656 		6: DPL left,   7: DPL  right
657 		8: DPL center, 9: DPL surround
658 		A: monitor output, B: digital sense */
659 		0xbbbb00,
660 
661 		/* tadachi 6/29 DAC and I2S output select?
662 		   Register 0x470
663 		   7-4:DAC right ch. 3-0:DAC left ch.
664 		   I2S1 right,left  I2S2 right,left */
665 		0x00,
666 	},
667 	{ /* for STEREO */
668 		0xbbbb10, 0x101010,
669 	},
670 	{ /* for LANG1 */
671 		0xbbbb00, 0x00,
672 	},
673 	{ /* for LANG2/SAP */
674 		0xbbbb11, 0x111111,
675 	}
676 };
677 
678 
679 /* Get detected audio flags (from saa7134 driver) */
get_inf_dev_status(struct v4l2_subdev * sd,int * dual_flag,int * stereo_flag)680 static void get_inf_dev_status(struct v4l2_subdev *sd,
681 		int *dual_flag, int *stereo_flag)
682 {
683 	u32 reg_data3;
684 
685 	static char *stdres[0x20] = {
686 		[0x00] = "no standard detected",
687 		[0x01] = "B/G (in progress)",
688 		[0x02] = "D/K (in progress)",
689 		[0x03] = "M (in progress)",
690 
691 		[0x04] = "B/G A2",
692 		[0x05] = "B/G NICAM",
693 		[0x06] = "D/K A2 (1)",
694 		[0x07] = "D/K A2 (2)",
695 		[0x08] = "D/K A2 (3)",
696 		[0x09] = "D/K NICAM",
697 		[0x0a] = "L NICAM",
698 		[0x0b] = "I NICAM",
699 
700 		[0x0c] = "M Korea",
701 		[0x0d] = "M BTSC ",
702 		[0x0e] = "M EIAJ",
703 
704 		[0x0f] = "FM radio / IF 10.7 / 50 deemp",
705 		[0x10] = "FM radio / IF 10.7 / 75 deemp",
706 		[0x11] = "FM radio / IF sel / 50 deemp",
707 		[0x12] = "FM radio / IF sel / 75 deemp",
708 
709 		[0x13 ... 0x1e] = "unknown",
710 		[0x1f] = "??? [in progress]",
711 	};
712 
713 
714 	*dual_flag = *stereo_flag = 0;
715 
716 	/* (demdec status: 0x528) */
717 
718 	/* read current status */
719 	reg_data3 = saa717x_read(sd, 0x0528);
720 
721 	v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
722 		reg_data3, stdres[reg_data3 & 0x1f],
723 		(reg_data3 & 0x000020) ? ",stereo" : "",
724 		(reg_data3 & 0x000040) ? ",dual"   : "");
725 	v4l2_dbg(1, debug, sd, "detailed status: "
726 		"%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
727 		(reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
728 		(reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
729 		(reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
730 		(reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
731 
732 		(reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
733 		(reg_data3 & 0x001000) ? " SAP carrier "            : "",
734 		(reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
735 		(reg_data3 & 0x004000) ? " SAP noise mute "         : "",
736 		(reg_data3 & 0x008000) ? " VDSP "                   : "",
737 
738 		(reg_data3 & 0x010000) ? " NICST "                  : "",
739 		(reg_data3 & 0x020000) ? " NICDU "                  : "",
740 		(reg_data3 & 0x040000) ? " NICAM muted "            : "",
741 		(reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
742 
743 		(reg_data3 & 0x100000) ? " init done "              : "");
744 
745 	if (reg_data3 & 0x000220) {
746 		v4l2_dbg(1, debug, sd, "ST!!!\n");
747 		*stereo_flag = 1;
748 	}
749 
750 	if (reg_data3 & 0x000140) {
751 		v4l2_dbg(1, debug, sd, "DUAL!!!\n");
752 		*dual_flag = 1;
753 	}
754 }
755 
756 /* regs write to set audio mode */
set_audio_mode(struct v4l2_subdev * sd,int audio_mode)757 static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
758 {
759 	v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
760 			audio_mode);
761 
762 	saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
763 	saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
764 }
765 
766 /* write regs to set audio volume, bass and treble */
set_audio_regs(struct v4l2_subdev * sd,struct saa717x_state * decoder)767 static int set_audio_regs(struct v4l2_subdev *sd,
768 		struct saa717x_state *decoder)
769 {
770 	u8 mute = 0xac; /* -84 dB */
771 	u32 val;
772 	unsigned int work_l, work_r;
773 
774 	/* set SIF analog I/O select */
775 	saa717x_write(sd, 0x0594, decoder->audio_input);
776 	v4l2_dbg(1, debug, sd, "set audio input %d\n",
777 			decoder->audio_input);
778 
779 	/* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
780 	work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
781 	work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
782 	decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
783 	decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
784 
785 	/* set main volume */
786 	/* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
787 	/*    def:0dB->6dB(MPG600GR) */
788 	/* if mute is on, set mute */
789 	if (decoder->audio_main_mute) {
790 		val = mute | (mute << 8);
791 	} else {
792 		val = (u8)decoder->audio_main_vol_l |
793 			((u8)decoder->audio_main_vol_r << 8);
794 	}
795 
796 	saa717x_write(sd, 0x480, val);
797 
798 	/* set bass and treble */
799 	val = decoder->audio_main_bass & 0x1f;
800 	val |= (decoder->audio_main_treble & 0x1f) << 5;
801 	saa717x_write(sd, 0x488, val);
802 	return 0;
803 }
804 
805 /********** scaling staff ***********/
set_h_prescale(struct v4l2_subdev * sd,int task,int prescale)806 static void set_h_prescale(struct v4l2_subdev *sd,
807 		int task, int prescale)
808 {
809 	static const struct {
810 		int xpsc;
811 		int xacl;
812 		int xc2_1;
813 		int xdcg;
814 		int vpfy;
815 	} vals[] = {
816 		/* XPSC XACL XC2_1 XDCG VPFY */
817 		{    1,   0,    0,    0,   0 },
818 		{    2,   2,    1,    2,   2 },
819 		{    3,   4,    1,    3,   2 },
820 		{    4,   8,    1,    4,   2 },
821 		{    5,   8,    1,    4,   2 },
822 		{    6,   8,    1,    4,   3 },
823 		{    7,   8,    1,    4,   3 },
824 		{    8,  15,    0,    4,   3 },
825 		{    9,  15,    0,    4,   3 },
826 		{   10,  16,    1,    5,   3 },
827 	};
828 	static const int count = ARRAY_SIZE(vals);
829 	int i, task_shift;
830 
831 	task_shift = task * 0x40;
832 	for (i = 0; i < count; i++)
833 		if (vals[i].xpsc == prescale)
834 			break;
835 	if (i == count)
836 		return;
837 
838 	/* horizontal prescaling */
839 	saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
840 	/* accumulation length */
841 	saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
842 	/* level control */
843 	saa717x_write(sd, 0x62 + task_shift,
844 			(vals[i].xc2_1 << 3) | vals[i].xdcg);
845 	/*FIR prefilter control */
846 	saa717x_write(sd, 0x63 + task_shift,
847 			(vals[i].vpfy << 2) | vals[i].vpfy);
848 }
849 
850 /********** scaling staff ***********/
set_v_scale(struct v4l2_subdev * sd,int task,int yscale)851 static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
852 {
853 	int task_shift;
854 
855 	task_shift = task * 0x40;
856 	/* Vertical scaling ratio (LOW) */
857 	saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
858 	/* Vertical scaling ratio (HI) */
859 	saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
860 }
861 
saa717x_s_ctrl(struct v4l2_ctrl * ctrl)862 static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
863 {
864 	struct v4l2_subdev *sd = to_sd(ctrl);
865 	struct saa717x_state *state = to_state(sd);
866 
867 	switch (ctrl->id) {
868 	case V4L2_CID_BRIGHTNESS:
869 		saa717x_write(sd, 0x10a, ctrl->val);
870 		return 0;
871 
872 	case V4L2_CID_CONTRAST:
873 		saa717x_write(sd, 0x10b, ctrl->val);
874 		return 0;
875 
876 	case V4L2_CID_SATURATION:
877 		saa717x_write(sd, 0x10c, ctrl->val);
878 		return 0;
879 
880 	case V4L2_CID_HUE:
881 		saa717x_write(sd, 0x10d, ctrl->val);
882 		return 0;
883 
884 	case V4L2_CID_AUDIO_MUTE:
885 		state->audio_main_mute = ctrl->val;
886 		break;
887 
888 	case V4L2_CID_AUDIO_VOLUME:
889 		state->audio_main_volume = ctrl->val;
890 		break;
891 
892 	case V4L2_CID_AUDIO_BALANCE:
893 		state->audio_main_balance = ctrl->val;
894 		break;
895 
896 	case V4L2_CID_AUDIO_TREBLE:
897 		state->audio_main_treble = ctrl->val;
898 		break;
899 
900 	case V4L2_CID_AUDIO_BASS:
901 		state->audio_main_bass = ctrl->val;
902 		break;
903 
904 	default:
905 		return 0;
906 	}
907 	set_audio_regs(sd, state);
908 	return 0;
909 }
910 
saa717x_s_video_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)911 static int saa717x_s_video_routing(struct v4l2_subdev *sd,
912 				   u32 input, u32 output, u32 config)
913 {
914 	struct saa717x_state *decoder = to_state(sd);
915 	int is_tuner = input & 0x80;  /* tuner input flag */
916 
917 	input &= 0x7f;
918 
919 	v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
920 	/* inputs from 0-9 are available*/
921 	/* saa717x have mode0-mode9 but mode5 is reserved. */
922 	if (input > 9 || input == 5)
923 		return -EINVAL;
924 
925 	if (decoder->input != input) {
926 		int input_line = input;
927 
928 		decoder->input = input_line;
929 		v4l2_dbg(1, debug, sd,  "now setting %s input %d\n",
930 				input_line >= 6 ? "S-Video" : "Composite",
931 				input_line);
932 
933 		/* select mode */
934 		saa717x_write(sd, 0x102,
935 				(saa717x_read(sd, 0x102) & 0xf0) |
936 				input_line);
937 
938 		/* bypass chrominance trap for modes 6..9 */
939 		saa717x_write(sd, 0x109,
940 				(saa717x_read(sd, 0x109) & 0x7f) |
941 				(input_line < 6 ? 0x0 : 0x80));
942 
943 		/* change audio_mode */
944 		if (is_tuner) {
945 			/* tuner */
946 			set_audio_mode(sd, decoder->tuner_audio_mode);
947 		} else {
948 			/* Force to STEREO mode if Composite or
949 			 * S-Video were chosen */
950 			set_audio_mode(sd, TUNER_AUDIO_STEREO);
951 		}
952 		/* change initialize procedure (Composite/S-Video) */
953 		if (is_tuner)
954 			saa717x_write_regs(sd, reg_init_tuner_input);
955 		else if (input_line >= 6)
956 			saa717x_write_regs(sd, reg_init_svideo_input);
957 		else
958 			saa717x_write_regs(sd, reg_init_composite_input);
959 	}
960 
961 	return 0;
962 }
963 
964 #ifdef CONFIG_VIDEO_ADV_DEBUG
saa717x_g_register(struct v4l2_subdev * sd,struct v4l2_dbg_register * reg)965 static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
966 {
967 	reg->val = saa717x_read(sd, reg->reg);
968 	reg->size = 1;
969 	return 0;
970 }
971 
saa717x_s_register(struct v4l2_subdev * sd,const struct v4l2_dbg_register * reg)972 static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
973 {
974 	u16 addr = reg->reg & 0xffff;
975 	u8 val = reg->val & 0xff;
976 
977 	saa717x_write(sd, addr, val);
978 	return 0;
979 }
980 #endif
981 
saa717x_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)982 static int saa717x_set_fmt(struct v4l2_subdev *sd,
983 		struct v4l2_subdev_state *sd_state,
984 		struct v4l2_subdev_format *format)
985 {
986 	struct v4l2_mbus_framefmt *fmt = &format->format;
987 	int prescale, h_scale, v_scale;
988 
989 	v4l2_dbg(1, debug, sd, "decoder set size\n");
990 
991 	if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
992 		return -EINVAL;
993 
994 	/* FIXME need better bounds checking here */
995 	if (fmt->width < 1 || fmt->width > 1440)
996 		return -EINVAL;
997 	if (fmt->height < 1 || fmt->height > 960)
998 		return -EINVAL;
999 
1000 	fmt->field = V4L2_FIELD_INTERLACED;
1001 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1002 
1003 	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
1004 		return 0;
1005 
1006 	/* scaling setting */
1007 	/* NTSC and interlace only */
1008 	prescale = SAA717X_NTSC_WIDTH / fmt->width;
1009 	if (prescale == 0)
1010 		prescale = 1;
1011 	h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
1012 	/* interlace */
1013 	v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1014 
1015 	/* Horizontal prescaling etc */
1016 	set_h_prescale(sd, 0, prescale);
1017 	set_h_prescale(sd, 1, prescale);
1018 
1019 	/* Horizontal scaling increment */
1020 	/* TASK A */
1021 	saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
1022 	saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1023 	/* TASK B */
1024 	saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
1025 	saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1026 
1027 	/* Vertical prescaling etc */
1028 	set_v_scale(sd, 0, v_scale);
1029 	set_v_scale(sd, 1, v_scale);
1030 
1031 	/* set video output size */
1032 	/* video number of pixels at output */
1033 	/* TASK A */
1034 	saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1035 	saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1036 	/* TASK B */
1037 	saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1038 	saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1039 
1040 	/* video number of lines at output */
1041 	/* TASK A */
1042 	saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1043 	saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1044 	/* TASK B */
1045 	saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
1046 	saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
1047 	return 0;
1048 }
1049 
saa717x_s_radio(struct v4l2_subdev * sd)1050 static int saa717x_s_radio(struct v4l2_subdev *sd)
1051 {
1052 	struct saa717x_state *decoder = to_state(sd);
1053 
1054 	decoder->radio = 1;
1055 	return 0;
1056 }
1057 
saa717x_s_std(struct v4l2_subdev * sd,v4l2_std_id std)1058 static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1059 {
1060 	struct saa717x_state *decoder = to_state(sd);
1061 
1062 	v4l2_dbg(1, debug, sd, "decoder set norm ");
1063 	v4l2_dbg(1, debug, sd, "(not yet implemented)\n");
1064 
1065 	decoder->radio = 0;
1066 	decoder->std = std;
1067 	return 0;
1068 }
1069 
saa717x_s_audio_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)1070 static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1071 				   u32 input, u32 output, u32 config)
1072 {
1073 	struct saa717x_state *decoder = to_state(sd);
1074 
1075 	if (input < 3) { /* FIXME! --tadachi */
1076 		decoder->audio_input = input;
1077 		v4l2_dbg(1, debug, sd,
1078 				"set decoder audio input to %d\n",
1079 				decoder->audio_input);
1080 		set_audio_regs(sd, decoder);
1081 		return 0;
1082 	}
1083 	return -ERANGE;
1084 }
1085 
saa717x_s_stream(struct v4l2_subdev * sd,int enable)1086 static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1087 {
1088 	struct saa717x_state *decoder = to_state(sd);
1089 
1090 	v4l2_dbg(1, debug, sd, "decoder %s output\n",
1091 			enable ? "enable" : "disable");
1092 	decoder->enable = enable;
1093 	saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1094 	return 0;
1095 }
1096 
1097 /* change audio mode */
saa717x_s_tuner(struct v4l2_subdev * sd,const struct v4l2_tuner * vt)1098 static int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
1099 {
1100 	struct saa717x_state *decoder = to_state(sd);
1101 	int audio_mode;
1102 	char *mes[4] = {
1103 		"MONO", "STEREO", "LANG1", "LANG2/SAP"
1104 	};
1105 
1106 	audio_mode = TUNER_AUDIO_STEREO;
1107 
1108 	switch (vt->audmode) {
1109 		case V4L2_TUNER_MODE_MONO:
1110 			audio_mode = TUNER_AUDIO_MONO;
1111 			break;
1112 		case V4L2_TUNER_MODE_STEREO:
1113 			audio_mode = TUNER_AUDIO_STEREO;
1114 			break;
1115 		case V4L2_TUNER_MODE_LANG2:
1116 			audio_mode = TUNER_AUDIO_LANG2;
1117 			break;
1118 		case V4L2_TUNER_MODE_LANG1:
1119 			audio_mode = TUNER_AUDIO_LANG1;
1120 			break;
1121 	}
1122 
1123 	v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1124 			mes[audio_mode]);
1125 	decoder->tuner_audio_mode = audio_mode;
1126 	/* The registers are not changed here. */
1127 	/* See DECODER_ENABLE_OUTPUT section. */
1128 	set_audio_mode(sd, decoder->tuner_audio_mode);
1129 	return 0;
1130 }
1131 
saa717x_g_tuner(struct v4l2_subdev * sd,struct v4l2_tuner * vt)1132 static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1133 {
1134 	struct saa717x_state *decoder = to_state(sd);
1135 	int dual_f, stereo_f;
1136 
1137 	if (decoder->radio)
1138 		return 0;
1139 	get_inf_dev_status(sd, &dual_f, &stereo_f);
1140 
1141 	v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1142 			stereo_f, dual_f);
1143 
1144 	/* mono */
1145 	if ((dual_f == 0) && (stereo_f == 0)) {
1146 		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1147 		v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1148 	}
1149 
1150 	/* stereo */
1151 	if (stereo_f == 1) {
1152 		if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1153 				vt->audmode == V4L2_TUNER_MODE_LANG1) {
1154 			vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1155 			v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1156 		} else {
1157 			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1158 			v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
1159 		}
1160 	}
1161 
1162 	/* dual */
1163 	if (dual_f == 1) {
1164 		if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1165 			vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1166 			v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1167 		} else {
1168 			vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1169 			v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1170 		}
1171 	}
1172 	return 0;
1173 }
1174 
saa717x_log_status(struct v4l2_subdev * sd)1175 static int saa717x_log_status(struct v4l2_subdev *sd)
1176 {
1177 	struct saa717x_state *state = to_state(sd);
1178 
1179 	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1180 	return 0;
1181 }
1182 
1183 /* ----------------------------------------------------------------------- */
1184 
1185 static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1186 	.s_ctrl = saa717x_s_ctrl,
1187 };
1188 
1189 static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1190 #ifdef CONFIG_VIDEO_ADV_DEBUG
1191 	.g_register = saa717x_g_register,
1192 	.s_register = saa717x_s_register,
1193 #endif
1194 	.log_status = saa717x_log_status,
1195 };
1196 
1197 static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1198 	.g_tuner = saa717x_g_tuner,
1199 	.s_tuner = saa717x_s_tuner,
1200 	.s_radio = saa717x_s_radio,
1201 };
1202 
1203 static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1204 	.s_std = saa717x_s_std,
1205 	.s_routing = saa717x_s_video_routing,
1206 	.s_stream = saa717x_s_stream,
1207 };
1208 
1209 static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1210 	.s_routing = saa717x_s_audio_routing,
1211 };
1212 
1213 static const struct v4l2_subdev_pad_ops saa717x_pad_ops = {
1214 	.set_fmt = saa717x_set_fmt,
1215 };
1216 
1217 static const struct v4l2_subdev_ops saa717x_ops = {
1218 	.core = &saa717x_core_ops,
1219 	.tuner = &saa717x_tuner_ops,
1220 	.audio = &saa717x_audio_ops,
1221 	.video = &saa717x_video_ops,
1222 	.pad = &saa717x_pad_ops,
1223 };
1224 
1225 /* ----------------------------------------------------------------------- */
1226 
1227 
1228 /* i2c implementation */
1229 
1230 /* ----------------------------------------------------------------------- */
saa717x_probe(struct i2c_client * client)1231 static int saa717x_probe(struct i2c_client *client)
1232 {
1233 	struct saa717x_state *decoder;
1234 	struct v4l2_ctrl_handler *hdl;
1235 	struct v4l2_subdev *sd;
1236 	u8 id = 0;
1237 	char *p = "";
1238 
1239 	/* Check if the adapter supports the needed features */
1240 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1241 		return -EIO;
1242 
1243 	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
1244 	if (decoder == NULL)
1245 		return -ENOMEM;
1246 
1247 	sd = &decoder->sd;
1248 	v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1249 
1250 	if (saa717x_write(sd, 0x5a4, 0xfe) &&
1251 			saa717x_write(sd, 0x5a5, 0x0f) &&
1252 			saa717x_write(sd, 0x5a6, 0x00) &&
1253 			saa717x_write(sd, 0x5a7, 0x01))
1254 		id = saa717x_read(sd, 0x5a0);
1255 	if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1256 		v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1257 		return -ENODEV;
1258 	}
1259 	if (id == 0xc2)
1260 		p = "saa7173";
1261 	else if (id == 0x32)
1262 		p = "saa7174A";
1263 	else if (id == 0x6c)
1264 		p = "saa7174HL";
1265 	else
1266 		p = "saa7171";
1267 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1268 			client->addr << 1, client->adapter->name);
1269 
1270 	hdl = &decoder->hdl;
1271 	v4l2_ctrl_handler_init(hdl, 9);
1272 	/* add in ascending ID order */
1273 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1274 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1275 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1276 			V4L2_CID_CONTRAST, 0, 255, 1, 68);
1277 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1278 			V4L2_CID_SATURATION, 0, 255, 1, 64);
1279 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1280 			V4L2_CID_HUE, -128, 127, 1, 0);
1281 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1282 			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
1283 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1284 			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
1285 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1286 			V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
1287 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1288 			V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
1289 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1290 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1291 	sd->ctrl_handler = hdl;
1292 	if (hdl->error) {
1293 		int err = hdl->error;
1294 
1295 		v4l2_ctrl_handler_free(hdl);
1296 		return err;
1297 	}
1298 
1299 	decoder->std = V4L2_STD_NTSC;
1300 	decoder->input = -1;
1301 	decoder->enable = 1;
1302 
1303 	/* FIXME!! */
1304 	decoder->playback = 0;	/* initially capture mode used */
1305 	decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1306 
1307 	decoder->audio_input = 2; /* FIXME!! */
1308 
1309 	decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1310 	/* set volume, bass and treble */
1311 	decoder->audio_main_vol_l = 6;
1312 	decoder->audio_main_vol_r = 6;
1313 
1314 	v4l2_dbg(1, debug, sd, "writing init values\n");
1315 
1316 	/* FIXME!! */
1317 	saa717x_write_regs(sd, reg_init_initialize);
1318 
1319 	v4l2_ctrl_handler_setup(hdl);
1320 
1321 	set_current_state(TASK_INTERRUPTIBLE);
1322 	schedule_timeout(2*HZ);
1323 	return 0;
1324 }
1325 
saa717x_remove(struct i2c_client * client)1326 static void saa717x_remove(struct i2c_client *client)
1327 {
1328 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1329 
1330 	v4l2_device_unregister_subdev(sd);
1331 	v4l2_ctrl_handler_free(sd->ctrl_handler);
1332 }
1333 
1334 /* ----------------------------------------------------------------------- */
1335 
1336 static const struct i2c_device_id saa717x_id[] = {
1337 	{ "saa717x" },
1338 	{ }
1339 };
1340 MODULE_DEVICE_TABLE(i2c, saa717x_id);
1341 
1342 static struct i2c_driver saa717x_driver = {
1343 	.driver = {
1344 		.name	= "saa717x",
1345 	},
1346 	.probe		= saa717x_probe,
1347 	.remove		= saa717x_remove,
1348 	.id_table	= saa717x_id,
1349 };
1350 
1351 module_i2c_driver(saa717x_driver);
1352