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