OMAP3 SRF: Generic shared resource f/w
[linux-ginger.git] / drivers / media / video / saa717x.c
blobb15c40908e8423556ed4ca6dae8590af520395c4
1 /*
2 * saa717x - Philips SAA717xHL video decoder driver
4 * Based on the saa7115 driver
6 * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
7 * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
9 * Changes by T.Adachi (tadachi@tadachi-net.com)
10 * - support audio, video scaler etc, and checked the initialize sequence.
12 * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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.
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.
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/sched.h>
37 #include <linux/videodev2.h>
38 #include <linux/i2c.h>
39 #include <media/v4l2-device.h>
40 #include <media/v4l2-i2c-drv.h>
42 MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
43 MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
44 MODULE_LICENSE("GPL");
46 static int debug;
47 module_param(debug, int, 0644);
48 MODULE_PARM_DESC(debug, "Debug level (0-1)");
51 * Generic i2c probe
52 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
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;
78 static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
80 return container_of(sd, struct saa717x_state, sd);
83 /* ----------------------------------------------------------------------- */
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 */
91 #define SAA717X_NTSC_WIDTH (704)
92 #define SAA717X_NTSC_HEIGHT (480)
94 /* ----------------------------------------------------------------------- */
96 static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
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;
104 msg.flags = 0;
105 msg.addr = client->addr;
106 mm1[0] = (reg >> 8) & 0xff;
107 mm1[1] = reg & 0xff;
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;
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;
122 static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
124 while (data[0] || data[1]) {
125 saa717x_write(sd, data[0], data[1]);
126 data += 2;
130 static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
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;
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);
151 if (fw_addr)
152 value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
153 else
154 value = mm2[0] & 0xff;
156 v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value);
157 return value;
160 /* ----------------------------------------------------------------------- */
162 static u32 reg_init_initialize[] =
164 /* from linux driver */
165 0x101, 0x008, /* Increment delay */
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 */
174 0x10f, 0x02a, /* Chroma gain control */
175 0x110, 0x000, /* Chroma control 2 */
177 0x114, 0x045, /* analog/ADC */
179 0x118, 0x040, /* RAW data gain */
180 0x119, 0x080, /* RAW data offset */
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 */
187 0x049, 0x000, /* VBI vertical input window start (H) TASK A */
189 0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
190 0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
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 */
200 0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
201 0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
203 0x072, 0x000, /* Vertical filter mode TASK A */
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 */
210 0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
212 0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
213 0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
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 */
223 0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
224 0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
226 0x0b2, 0x000, /* Vertical filter mode TASK B */
228 0x00c, 0x000, /* Start point GREEN path */
229 0x00d, 0x000, /* Start point BLUE path */
230 0x00e, 0x000, /* Start point RED path */
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 */
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 */
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 */
283 0x109, 0x085, /* Luminance control */
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 */
299 0x595, 0x000, /* ?? */
300 0x596, 0x000, /* ?? */
301 0x597, 0x000, /* ?? */
303 0x464, 0x00, /* Digital input crossbar1 */
305 0x46c, 0xbbbb10, /* Digital output selection1-3 */
306 0x470, 0x101010, /* Digital output selection4-6 */
308 0x478, 0x00, /* Sound feature control */
310 0x474, 0x18, /* Softmute control */
312 0x454, 0x0425b9, /* Sound Easy programming(reset) */
313 0x454, 0x042539, /* Sound Easy programming(reset) */
316 /**** common setting( of DVD play, including scaler commands) ****/
317 0x042, 0x003, /* Data path configuration for VBI (TASK A) */
319 0x082, 0x003, /* Data path configuration for VBI (TASK B) */
321 0x108, 0x0f8, /* Sync control */
322 0x2a9, 0x0fd, /* ??? */
323 0x102, 0x089, /* select video input "mode 9" */
324 0x111, 0x000, /* Mode/delay control */
326 0x10e, 0x00a, /* Chroma control 1 */
328 0x594, 0x002, /* SIF, analog I/O select */
330 0x454, 0x0425b9, /* Sound */
331 0x454, 0x042539,
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,
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,
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,
630 0, 0
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
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
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
657 static u32 reg_set_audio_template[4][2] =
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,
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,
677 { /* for STEREO */
678 0xbbbb10, 0x101010,
680 { /* for LANG1 */
681 0xbbbb00, 0x00,
683 { /* for LANG2/SAP */
684 0xbbbb11, 0x111111,
689 /* Get detected audio flags (from saa7134 driver) */
690 static void get_inf_dev_status(struct v4l2_subdev *sd,
691 int *dual_flag, int *stereo_flag)
693 u32 reg_data3;
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)",
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",
710 [0x0c] = "M Korea",
711 [0x0d] = "M BTSC ",
712 [0x0e] = "M EIAJ",
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",
719 [0x13 ... 0x1e] = "unknown",
720 [0x1f] = "??? [in progress]",
724 *dual_flag = *stereo_flag = 0;
726 /* (demdec status: 0x528) */
728 /* read current status */
729 reg_data3 = saa717x_read(sd, 0x0528);
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 " : "",
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 " : "",
748 (reg_data3 & 0x010000) ? " NICST " : "",
749 (reg_data3 & 0x020000) ? " NICDU " : "",
750 (reg_data3 & 0x040000) ? " NICAM muted " : "",
751 (reg_data3 & 0x080000) ? " NICAM reserve sound " : "",
753 (reg_data3 & 0x100000) ? " init done " : "");
755 if (reg_data3 & 0x000220) {
756 v4l2_dbg(1, debug, sd, "ST!!!\n");
757 *stereo_flag = 1;
760 if (reg_data3 & 0x000140) {
761 v4l2_dbg(1, debug, sd, "DUAL!!!\n");
762 *dual_flag = 1;
766 /* regs write to set audio mode */
767 static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
769 v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
770 audio_mode);
772 saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
773 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
776 /* write regs to video output level (bright,contrast,hue,sat) */
777 static void set_video_output_level_regs(struct v4l2_subdev *sd,
778 struct saa717x_state *decoder)
780 /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
781 saa717x_write(sd, 0x10a, decoder->bright);
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);
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);
794 /* color hue (phase) control
795 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
796 saa717x_write(sd, 0x10d, decoder->hue);
799 /* write regs to set audio volume, bass and treble */
800 static int set_audio_regs(struct v4l2_subdev *sd,
801 struct saa717x_state *decoder)
803 u8 mute = 0xac; /* -84 dB */
804 u32 val;
805 unsigned int work_l, work_r;
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);
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;
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);
829 saa717x_write(sd, 0x480, val);
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;
838 /********** scaling staff ***********/
839 static void set_h_prescale(struct v4l2_subdev *sd,
840 int task, int prescale)
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 },
861 static const int count = ARRAY_SIZE(vals);
862 int i, task_shift;
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;
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);
883 /********** scaling staff ***********/
884 static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
886 int task_shift;
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);
895 static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
897 struct saa717x_state *state = to_state(sd);
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;
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;
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;
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;
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;
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;
933 case V4L2_CID_HUE:
934 if (ctrl->value < -128 || ctrl->value > 127) {
935 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
936 return -ERANGE;
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;
944 case V4L2_CID_AUDIO_MUTE:
945 state->audio_main_mute = ctrl->value;
946 set_audio_regs(sd, state);
947 break;
949 case V4L2_CID_AUDIO_VOLUME:
950 state->audio_main_volume = ctrl->value;
951 set_audio_regs(sd, state);
952 break;
954 case V4L2_CID_AUDIO_BALANCE:
955 state->audio_main_balance = ctrl->value;
956 set_audio_regs(sd, state);
957 break;
959 case V4L2_CID_AUDIO_TREBLE:
960 state->audio_main_treble = ctrl->value;
961 set_audio_regs(sd, state);
962 break;
964 case V4L2_CID_AUDIO_BASS:
965 state->audio_main_bass = ctrl->value;
966 set_audio_regs(sd, state);
967 break;
969 default:
970 return -EINVAL;
973 return 0;
976 static int saa717x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
978 struct saa717x_state *state = to_state(sd);
980 switch (ctrl->id) {
981 case V4L2_CID_BRIGHTNESS:
982 ctrl->value = state->bright;
983 break;
985 case V4L2_CID_CONTRAST:
986 ctrl->value = state->contrast;
987 break;
989 case V4L2_CID_SATURATION:
990 ctrl->value = state->sat;
991 break;
993 case V4L2_CID_HUE:
994 ctrl->value = state->hue;
995 break;
997 case V4L2_CID_AUDIO_MUTE:
998 ctrl->value = state->audio_main_mute;
999 break;
1001 case V4L2_CID_AUDIO_VOLUME:
1002 ctrl->value = state->audio_main_volume;
1003 break;
1005 case V4L2_CID_AUDIO_BALANCE:
1006 ctrl->value = state->audio_main_balance;
1007 break;
1009 case V4L2_CID_AUDIO_TREBLE:
1010 ctrl->value = state->audio_main_treble;
1011 break;
1013 case V4L2_CID_AUDIO_BASS:
1014 ctrl->value = state->audio_main_bass;
1015 break;
1017 default:
1018 return -EINVAL;
1021 return 0;
1024 static struct v4l2_queryctrl saa717x_qctrl[] = {
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,
1107 static int saa717x_s_video_routing(struct v4l2_subdev *sd,
1108 u32 input, u32 output, u32 config)
1110 struct saa717x_state *decoder = to_state(sd);
1111 int is_tuner = input & 0x80; /* tuner input flag */
1113 input &= 0x7f;
1115 v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
1116 /* inputs from 0-9 are available*/
1117 /* saa717x have mode0-mode9 but mode5 is reserved. */
1118 if (input < 0 || input > 9 || input == 5)
1119 return -EINVAL;
1121 if (decoder->input != input) {
1122 int input_line = input;
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);
1129 /* select mode */
1130 saa717x_write(sd, 0x102,
1131 (saa717x_read(sd, 0x102) & 0xf0) |
1132 input_line);
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));
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);
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);
1157 return 0;
1160 static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1162 int i;
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;
1169 return -EINVAL;
1172 #ifdef CONFIG_VIDEO_ADV_DEBUG
1173 static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1175 struct i2c_client *client = v4l2_get_subdevdata(sd);
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;
1186 static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1188 struct i2c_client *client = v4l2_get_subdevdata(sd);
1189 u16 addr = reg->reg & 0xffff;
1190 u8 val = reg->val & 0xff;
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;
1199 #endif
1201 static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1203 struct v4l2_pix_format *pix;
1204 int prescale, h_scale, v_scale;
1206 pix = &fmt->fmt.pix;
1207 v4l2_dbg(1, debug, sd, "decoder set size\n");
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;
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;
1224 /* Horizontal prescaling etc */
1225 set_h_prescale(sd, 0, prescale);
1226 set_h_prescale(sd, 1, prescale);
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));
1236 /* Vertical prescaling etc */
1237 set_v_scale(sd, 0, v_scale);
1238 set_v_scale(sd, 1, v_scale);
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));
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;
1259 static int saa717x_s_radio(struct v4l2_subdev *sd)
1261 struct saa717x_state *decoder = to_state(sd);
1263 decoder->radio = 1;
1264 return 0;
1267 static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1269 struct saa717x_state *decoder = to_state(sd);
1271 v4l2_dbg(1, debug, sd, "decoder set norm ");
1272 v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
1274 decoder->radio = 0;
1275 decoder->std = std;
1276 return 0;
1279 static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1280 u32 input, u32 output, u32 config)
1282 struct saa717x_state *decoder = to_state(sd);
1284 if (input < 3) { /* FIXME! --tadachi */
1285 decoder->audio_input = input;
1286 v4l2_dbg(1, debug, sd,
1287 "set decoder audio input to %d\n",
1288 decoder->audio_input);
1289 set_audio_regs(sd, decoder);
1290 return 0;
1292 return -ERANGE;
1295 static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1297 struct saa717x_state *decoder = to_state(sd);
1299 v4l2_dbg(1, debug, sd, "decoder %s output\n",
1300 enable ? "enable" : "disable");
1301 decoder->enable = enable;
1302 saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1303 return 0;
1306 /* change audio mode */
1307 static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1309 struct saa717x_state *decoder = to_state(sd);
1310 int audio_mode;
1311 char *mes[4] = {
1312 "MONO", "STEREO", "LANG1", "LANG2/SAP"
1315 audio_mode = V4L2_TUNER_MODE_STEREO;
1317 switch (vt->audmode) {
1318 case V4L2_TUNER_MODE_MONO:
1319 audio_mode = TUNER_AUDIO_MONO;
1320 break;
1321 case V4L2_TUNER_MODE_STEREO:
1322 audio_mode = TUNER_AUDIO_STEREO;
1323 break;
1324 case V4L2_TUNER_MODE_LANG2:
1325 audio_mode = TUNER_AUDIO_LANG2;
1326 break;
1327 case V4L2_TUNER_MODE_LANG1:
1328 audio_mode = TUNER_AUDIO_LANG1;
1329 break;
1332 v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1333 mes[audio_mode]);
1334 decoder->tuner_audio_mode = audio_mode;
1335 /* The registers are not changed here. */
1336 /* See DECODER_ENABLE_OUTPUT section. */
1337 set_audio_mode(sd, decoder->tuner_audio_mode);
1338 return 0;
1341 static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1343 struct saa717x_state *decoder = to_state(sd);
1344 int dual_f, stereo_f;
1346 if (decoder->radio)
1347 return 0;
1348 get_inf_dev_status(sd, &dual_f, &stereo_f);
1350 v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1351 stereo_f, dual_f);
1353 /* mono */
1354 if ((dual_f == 0) && (stereo_f == 0)) {
1355 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1356 v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1359 /* stereo */
1360 if (stereo_f == 1) {
1361 if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1362 vt->audmode == V4L2_TUNER_MODE_LANG1) {
1363 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1364 v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1365 } else {
1366 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1367 v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
1371 /* dual */
1372 if (dual_f == 1) {
1373 if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1374 vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1375 v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1376 } else {
1377 vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1378 v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1381 return 0;
1384 /* ----------------------------------------------------------------------- */
1386 static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1387 #ifdef CONFIG_VIDEO_ADV_DEBUG
1388 .g_register = saa717x_g_register,
1389 .s_register = saa717x_s_register,
1390 #endif
1391 .queryctrl = saa717x_queryctrl,
1392 .g_ctrl = saa717x_g_ctrl,
1393 .s_ctrl = saa717x_s_ctrl,
1394 .s_std = saa717x_s_std,
1397 static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1398 .g_tuner = saa717x_g_tuner,
1399 .s_tuner = saa717x_s_tuner,
1400 .s_radio = saa717x_s_radio,
1403 static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1404 .s_routing = saa717x_s_video_routing,
1405 .s_fmt = saa717x_s_fmt,
1406 .s_stream = saa717x_s_stream,
1409 static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1410 .s_routing = saa717x_s_audio_routing,
1413 static const struct v4l2_subdev_ops saa717x_ops = {
1414 .core = &saa717x_core_ops,
1415 .tuner = &saa717x_tuner_ops,
1416 .audio = &saa717x_audio_ops,
1417 .video = &saa717x_video_ops,
1420 /* ----------------------------------------------------------------------- */
1423 /* i2c implementation */
1425 /* ----------------------------------------------------------------------- */
1426 static int saa717x_probe(struct i2c_client *client,
1427 const struct i2c_device_id *did)
1429 struct saa717x_state *decoder;
1430 struct v4l2_subdev *sd;
1431 u8 id = 0;
1432 char *p = "";
1434 /* Check if the adapter supports the needed features */
1435 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1436 return -EIO;
1438 decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
1439 if (decoder == NULL)
1440 return -ENOMEM;
1442 sd = &decoder->sd;
1443 v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1445 if (saa717x_write(sd, 0x5a4, 0xfe) &&
1446 saa717x_write(sd, 0x5a5, 0x0f) &&
1447 saa717x_write(sd, 0x5a6, 0x00) &&
1448 saa717x_write(sd, 0x5a7, 0x01))
1449 id = saa717x_read(sd, 0x5a0);
1450 if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1451 v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1452 kfree(decoder);
1453 return -ENODEV;
1455 if (id == 0xc2)
1456 p = "saa7173";
1457 else if (id == 0x32)
1458 p = "saa7174A";
1459 else if (id == 0x6c)
1460 p = "saa7174HL";
1461 else
1462 p = "saa7171";
1463 v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
1464 client->addr << 1, client->adapter->name);
1465 decoder->std = V4L2_STD_NTSC;
1466 decoder->input = -1;
1467 decoder->enable = 1;
1469 /* tune these parameters */
1470 decoder->bright = 0x80;
1471 decoder->contrast = 0x44;
1472 decoder->sat = 0x40;
1473 decoder->hue = 0x00;
1475 /* FIXME!! */
1476 decoder->playback = 0; /* initially capture mode used */
1477 decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1479 decoder->audio_input = 2; /* FIXME!! */
1481 decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1482 /* set volume, bass and treble */
1483 decoder->audio_main_vol_l = 6;
1484 decoder->audio_main_vol_r = 6;
1485 decoder->audio_main_bass = 0;
1486 decoder->audio_main_treble = 0;
1487 decoder->audio_main_mute = 0;
1488 decoder->audio_main_balance = 32768;
1489 /* normalize (24 to -40 (not -84) -> 65535 to 0) */
1490 decoder->audio_main_volume =
1491 (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
1493 v4l2_dbg(1, debug, sd, "writing init values\n");
1495 /* FIXME!! */
1496 saa717x_write_regs(sd, reg_init_initialize);
1497 set_video_output_level_regs(sd, decoder);
1498 /* set bass,treble to 0db 20041101 K.Ohta */
1499 decoder->audio_main_bass = 0;
1500 decoder->audio_main_treble = 0;
1501 set_audio_regs(sd, decoder);
1503 set_current_state(TASK_INTERRUPTIBLE);
1504 schedule_timeout(2*HZ);
1505 return 0;
1508 static int saa717x_remove(struct i2c_client *client)
1510 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1512 v4l2_device_unregister_subdev(sd);
1513 kfree(to_state(sd));
1514 return 0;
1517 /* ----------------------------------------------------------------------- */
1519 static const struct i2c_device_id saa717x_id[] = {
1520 { "saa717x", 0 },
1523 MODULE_DEVICE_TABLE(i2c, saa717x_id);
1525 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1526 .name = "saa717x",
1527 .probe = saa717x_probe,
1528 .remove = saa717x_remove,
1529 .id_table = saa717x_id,