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