xref: /linux/drivers/media/i2c/saa717x.c (revision 4949009eb8d40a441dcddcd96e101e77d31cf1b2)
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] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
156 	else
157 		value = mm2[0] & 0xff;
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_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
996 {
997 	int prescale, h_scale, v_scale;
998 
999 	v4l2_dbg(1, debug, sd, "decoder set size\n");
1000 
1001 	if (fmt->code != MEDIA_BUS_FMT_FIXED)
1002 		return -EINVAL;
1003 
1004 	/* FIXME need better bounds checking here */
1005 	if (fmt->width < 1 || fmt->width > 1440)
1006 		return -EINVAL;
1007 	if (fmt->height < 1 || fmt->height > 960)
1008 		return -EINVAL;
1009 
1010 	fmt->field = V4L2_FIELD_INTERLACED;
1011 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1012 
1013 	/* scaling setting */
1014 	/* NTSC and interlace only */
1015 	prescale = SAA717X_NTSC_WIDTH / fmt->width;
1016 	if (prescale == 0)
1017 		prescale = 1;
1018 	h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
1019 	/* interlace */
1020 	v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1021 
1022 	/* Horizontal prescaling etc */
1023 	set_h_prescale(sd, 0, prescale);
1024 	set_h_prescale(sd, 1, prescale);
1025 
1026 	/* Horizontal scaling increment */
1027 	/* TASK A */
1028 	saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
1029 	saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1030 	/* TASK B */
1031 	saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
1032 	saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1033 
1034 	/* Vertical prescaling etc */
1035 	set_v_scale(sd, 0, v_scale);
1036 	set_v_scale(sd, 1, v_scale);
1037 
1038 	/* set video output size */
1039 	/* video number of pixels at output */
1040 	/* TASK A */
1041 	saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1042 	saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1043 	/* TASK B */
1044 	saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1045 	saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1046 
1047 	/* video number of lines at output */
1048 	/* TASK A */
1049 	saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1050 	saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1051 	/* TASK B */
1052 	saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
1053 	saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
1054 	return 0;
1055 }
1056 
1057 static int saa717x_s_radio(struct v4l2_subdev *sd)
1058 {
1059 	struct saa717x_state *decoder = to_state(sd);
1060 
1061 	decoder->radio = 1;
1062 	return 0;
1063 }
1064 
1065 static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1066 {
1067 	struct saa717x_state *decoder = to_state(sd);
1068 
1069 	v4l2_dbg(1, debug, sd, "decoder set norm ");
1070 	v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
1071 
1072 	decoder->radio = 0;
1073 	decoder->std = std;
1074 	return 0;
1075 }
1076 
1077 static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1078 				   u32 input, u32 output, u32 config)
1079 {
1080 	struct saa717x_state *decoder = to_state(sd);
1081 
1082 	if (input < 3) { /* FIXME! --tadachi */
1083 		decoder->audio_input = input;
1084 		v4l2_dbg(1, debug, sd,
1085 				"set decoder audio input to %d\n",
1086 				decoder->audio_input);
1087 		set_audio_regs(sd, decoder);
1088 		return 0;
1089 	}
1090 	return -ERANGE;
1091 }
1092 
1093 static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1094 {
1095 	struct saa717x_state *decoder = to_state(sd);
1096 
1097 	v4l2_dbg(1, debug, sd, "decoder %s output\n",
1098 			enable ? "enable" : "disable");
1099 	decoder->enable = enable;
1100 	saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1101 	return 0;
1102 }
1103 
1104 /* change audio mode */
1105 static int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
1106 {
1107 	struct saa717x_state *decoder = to_state(sd);
1108 	int audio_mode;
1109 	char *mes[4] = {
1110 		"MONO", "STEREO", "LANG1", "LANG2/SAP"
1111 	};
1112 
1113 	audio_mode = TUNER_AUDIO_STEREO;
1114 
1115 	switch (vt->audmode) {
1116 		case V4L2_TUNER_MODE_MONO:
1117 			audio_mode = TUNER_AUDIO_MONO;
1118 			break;
1119 		case V4L2_TUNER_MODE_STEREO:
1120 			audio_mode = TUNER_AUDIO_STEREO;
1121 			break;
1122 		case V4L2_TUNER_MODE_LANG2:
1123 			audio_mode = TUNER_AUDIO_LANG2;
1124 			break;
1125 		case V4L2_TUNER_MODE_LANG1:
1126 			audio_mode = TUNER_AUDIO_LANG1;
1127 			break;
1128 	}
1129 
1130 	v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1131 			mes[audio_mode]);
1132 	decoder->tuner_audio_mode = audio_mode;
1133 	/* The registers are not changed here. */
1134 	/* See DECODER_ENABLE_OUTPUT section. */
1135 	set_audio_mode(sd, decoder->tuner_audio_mode);
1136 	return 0;
1137 }
1138 
1139 static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1140 {
1141 	struct saa717x_state *decoder = to_state(sd);
1142 	int dual_f, stereo_f;
1143 
1144 	if (decoder->radio)
1145 		return 0;
1146 	get_inf_dev_status(sd, &dual_f, &stereo_f);
1147 
1148 	v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1149 			stereo_f, dual_f);
1150 
1151 	/* mono */
1152 	if ((dual_f == 0) && (stereo_f == 0)) {
1153 		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1154 		v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1155 	}
1156 
1157 	/* stereo */
1158 	if (stereo_f == 1) {
1159 		if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1160 				vt->audmode == V4L2_TUNER_MODE_LANG1) {
1161 			vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1162 			v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1163 		} else {
1164 			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1165 			v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
1166 		}
1167 	}
1168 
1169 	/* dual */
1170 	if (dual_f == 1) {
1171 		if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1172 			vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1173 			v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1174 		} else {
1175 			vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1176 			v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1177 		}
1178 	}
1179 	return 0;
1180 }
1181 
1182 static int saa717x_log_status(struct v4l2_subdev *sd)
1183 {
1184 	struct saa717x_state *state = to_state(sd);
1185 
1186 	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
1187 	return 0;
1188 }
1189 
1190 /* ----------------------------------------------------------------------- */
1191 
1192 static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
1193 	.s_ctrl = saa717x_s_ctrl,
1194 };
1195 
1196 static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1197 #ifdef CONFIG_VIDEO_ADV_DEBUG
1198 	.g_register = saa717x_g_register,
1199 	.s_register = saa717x_s_register,
1200 #endif
1201 	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1202 	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1203 	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1204 	.g_ctrl = v4l2_subdev_g_ctrl,
1205 	.s_ctrl = v4l2_subdev_s_ctrl,
1206 	.queryctrl = v4l2_subdev_queryctrl,
1207 	.querymenu = v4l2_subdev_querymenu,
1208 	.log_status = saa717x_log_status,
1209 };
1210 
1211 static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1212 	.g_tuner = saa717x_g_tuner,
1213 	.s_tuner = saa717x_s_tuner,
1214 	.s_radio = saa717x_s_radio,
1215 };
1216 
1217 static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1218 	.s_std = saa717x_s_std,
1219 	.s_routing = saa717x_s_video_routing,
1220 	.s_mbus_fmt = saa717x_s_mbus_fmt,
1221 	.s_stream = saa717x_s_stream,
1222 };
1223 
1224 static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1225 	.s_routing = saa717x_s_audio_routing,
1226 };
1227 
1228 static const struct v4l2_subdev_ops saa717x_ops = {
1229 	.core = &saa717x_core_ops,
1230 	.tuner = &saa717x_tuner_ops,
1231 	.audio = &saa717x_audio_ops,
1232 	.video = &saa717x_video_ops,
1233 };
1234 
1235 /* ----------------------------------------------------------------------- */
1236 
1237 
1238 /* i2c implementation */
1239 
1240 /* ----------------------------------------------------------------------- */
1241 static int saa717x_probe(struct i2c_client *client,
1242 			 const struct i2c_device_id *did)
1243 {
1244 	struct saa717x_state *decoder;
1245 	struct v4l2_ctrl_handler *hdl;
1246 	struct v4l2_subdev *sd;
1247 	u8 id = 0;
1248 	char *p = "";
1249 
1250 	/* Check if the adapter supports the needed features */
1251 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1252 		return -EIO;
1253 
1254 	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
1255 	if (decoder == NULL)
1256 		return -ENOMEM;
1257 
1258 	sd = &decoder->sd;
1259 	v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1260 
1261 	if (saa717x_write(sd, 0x5a4, 0xfe) &&
1262 			saa717x_write(sd, 0x5a5, 0x0f) &&
1263 			saa717x_write(sd, 0x5a6, 0x00) &&
1264 			saa717x_write(sd, 0x5a7, 0x01))
1265 		id = saa717x_read(sd, 0x5a0);
1266 	if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1267 		v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1268 		return -ENODEV;
1269 	}
1270 	if (id == 0xc2)
1271 		p = "saa7173";
1272 	else if (id == 0x32)
1273 		p = "saa7174A";
1274 	else if (id == 0x6c)
1275 		p = "saa7174HL";
1276 	else
1277 		p = "saa7171";
1278 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1279 			client->addr << 1, client->adapter->name);
1280 
1281 	hdl = &decoder->hdl;
1282 	v4l2_ctrl_handler_init(hdl, 9);
1283 	/* add in ascending ID order */
1284 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1285 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1286 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1287 			V4L2_CID_CONTRAST, 0, 255, 1, 68);
1288 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1289 			V4L2_CID_SATURATION, 0, 255, 1, 64);
1290 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1291 			V4L2_CID_HUE, -128, 127, 1, 0);
1292 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1293 			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
1294 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1295 			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
1296 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1297 			V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
1298 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1299 			V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
1300 	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
1301 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1302 	sd->ctrl_handler = hdl;
1303 	if (hdl->error) {
1304 		int err = hdl->error;
1305 
1306 		v4l2_ctrl_handler_free(hdl);
1307 		return err;
1308 	}
1309 
1310 	decoder->std = V4L2_STD_NTSC;
1311 	decoder->input = -1;
1312 	decoder->enable = 1;
1313 
1314 	/* FIXME!! */
1315 	decoder->playback = 0;	/* initially capture mode used */
1316 	decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1317 
1318 	decoder->audio_input = 2; /* FIXME!! */
1319 
1320 	decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1321 	/* set volume, bass and treble */
1322 	decoder->audio_main_vol_l = 6;
1323 	decoder->audio_main_vol_r = 6;
1324 
1325 	v4l2_dbg(1, debug, sd, "writing init values\n");
1326 
1327 	/* FIXME!! */
1328 	saa717x_write_regs(sd, reg_init_initialize);
1329 
1330 	v4l2_ctrl_handler_setup(hdl);
1331 
1332 	set_current_state(TASK_INTERRUPTIBLE);
1333 	schedule_timeout(2*HZ);
1334 	return 0;
1335 }
1336 
1337 static int saa717x_remove(struct i2c_client *client)
1338 {
1339 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1340 
1341 	v4l2_device_unregister_subdev(sd);
1342 	v4l2_ctrl_handler_free(sd->ctrl_handler);
1343 	return 0;
1344 }
1345 
1346 /* ----------------------------------------------------------------------- */
1347 
1348 static const struct i2c_device_id saa717x_id[] = {
1349 	{ "saa717x", 0 },
1350 	{ }
1351 };
1352 MODULE_DEVICE_TABLE(i2c, saa717x_id);
1353 
1354 static struct i2c_driver saa717x_driver = {
1355 	.driver = {
1356 		.owner	= THIS_MODULE,
1357 		.name	= "saa717x",
1358 	},
1359 	.probe		= saa717x_probe,
1360 	.remove		= saa717x_remove,
1361 	.id_table	= saa717x_id,
1362 };
1363 
1364 module_i2c_driver(saa717x_driver);
1365