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