include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / saa717x.c
CommitLineData
fb7b37cf
HV
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
fb7b37cf
HV
33#include <linux/module.h>
34#include <linux/kernel.h>
5a0e3ad6 35#include <linux/slab.h>
fb7b37cf
HV
36#include <linux/sched.h>
37
fb7b37cf
HV
38#include <linux/videodev2.h>
39#include <linux/i2c.h>
27760fc4 40#include <media/v4l2-device.h>
fb7b37cf
HV
41#include <media/v4l2-i2c-drv.h>
42
43MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
44MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
45MODULE_LICENSE("GPL");
46
47static int debug;
48module_param(debug, int, 0644);
49MODULE_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
56struct saa717x_state {
27760fc4 57 struct v4l2_subdev sd;
fb7b37cf
HV
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
27760fc4
HV
79static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
80{
81 return container_of(sd, struct saa717x_state, sd);
82}
83
fb7b37cf
HV
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
27760fc4 97static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
fb7b37cf 98{
27760fc4 99 struct i2c_client *client = v4l2_get_subdevdata(sd);
fb7b37cf
HV
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;
27760fc4 119 v4l2_dbg(2, debug, sd, "wrote: reg 0x%03x=%08x\n", reg, value);
fb7b37cf
HV
120 return i2c_transfer(adap, &msg, 1) == 1;
121}
122
27760fc4 123static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
fb7b37cf
HV
124{
125 while (data[0] || data[1]) {
27760fc4 126 saa717x_write(sd, data[0], data[1]);
fb7b37cf
HV
127 data += 2;
128 }
129}
130
27760fc4 131static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
fb7b37cf 132{
27760fc4 133 struct i2c_client *client = v4l2_get_subdevdata(sd);
fb7b37cf
HV
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
27760fc4 157 v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value);
fb7b37cf
HV
158 return value;
159}
160
161/* ----------------------------------------------------------------------- */
162
163static 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 */
635static 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 */
643static 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 */
651static 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
658static 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) */
27760fc4 691static void get_inf_dev_status(struct v4l2_subdev *sd,
fb7b37cf
HV
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 */
27760fc4 730 reg_data3 = saa717x_read(sd, 0x0528);
fb7b37cf 731
27760fc4 732 v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
fb7b37cf
HV
733 reg_data3, stdres[reg_data3 & 0x1f],
734 (reg_data3 & 0x000020) ? ",stereo" : "",
735 (reg_data3 & 0x000040) ? ",dual" : "");
27760fc4 736 v4l2_dbg(1, debug, sd, "detailed status: "
fb7b37cf
HV
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) {
27760fc4 757 v4l2_dbg(1, debug, sd, "ST!!!\n");
fb7b37cf
HV
758 *stereo_flag = 1;
759 }
760
761 if (reg_data3 & 0x000140) {
27760fc4 762 v4l2_dbg(1, debug, sd, "DUAL!!!\n");
fb7b37cf
HV
763 *dual_flag = 1;
764 }
765}
766
767/* regs write to set audio mode */
27760fc4 768static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
fb7b37cf 769{
27760fc4 770 v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
fb7b37cf
HV
771 audio_mode);
772
27760fc4
HV
773 saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
774 saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
fb7b37cf
HV
775}
776
777/* write regs to video output level (bright,contrast,hue,sat) */
27760fc4 778static void set_video_output_level_regs(struct v4l2_subdev *sd,
fb7b37cf
HV
779 struct saa717x_state *decoder)
780{
781 /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
27760fc4 782 saa717x_write(sd, 0x10a, decoder->bright);
fb7b37cf
HV
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) */
27760fc4 788 saa717x_write(sd, 0x10b, decoder->contrast);
fb7b37cf
HV
789
790 /* saturation? 7fh(max)-40h(ITU)-0h(color off)
791 c0h (-1.0 inverse chrominance)
792 80h (-2.0 inverse chrominance) */
27760fc4 793 saa717x_write(sd, 0x10c, decoder->sat);
fb7b37cf
HV
794
795 /* color hue (phase) control
796 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
27760fc4 797 saa717x_write(sd, 0x10d, decoder->hue);
fb7b37cf
HV
798}
799
800/* write regs to set audio volume, bass and treble */
27760fc4 801static int set_audio_regs(struct v4l2_subdev *sd,
fb7b37cf
HV
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 */
27760fc4
HV
809 saa717x_write(sd, 0x0594, decoder->audio_input);
810 v4l2_dbg(1, debug, sd, "set audio input %d\n",
fb7b37cf
HV
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
27760fc4 830 saa717x_write(sd, 0x480, val);
fb7b37cf
HV
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);
27760fc4 835 saa717x_write(sd, 0x488, val);
fb7b37cf
HV
836 return 0;
837}
838
839/********** scaling staff ***********/
27760fc4 840static void set_h_prescale(struct v4l2_subdev *sd,
fb7b37cf
HV
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 */
27760fc4 873 saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
fb7b37cf 874 /* accumulation length */
27760fc4 875 saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
fb7b37cf 876 /* level control */
27760fc4 877 saa717x_write(sd, 0x62 + task_shift,
fb7b37cf
HV
878 (vals[i].xc2_1 << 3) | vals[i].xdcg);
879 /*FIR prefilter control */
27760fc4 880 saa717x_write(sd, 0x63 + task_shift,
fb7b37cf
HV
881 (vals[i].vpfy << 2) | vals[i].vpfy);
882}
883
884/********** scaling staff ***********/
27760fc4 885static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
fb7b37cf
HV
886{
887 int task_shift;
888
889 task_shift = task * 0x40;
890 /* Vertical scaling ratio (LOW) */
27760fc4 891 saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
fb7b37cf 892 /* Vertical scaling ratio (HI) */
27760fc4 893 saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
fb7b37cf
HV
894}
895
27760fc4 896static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
fb7b37cf 897{
27760fc4 898 struct saa717x_state *state = to_state(sd);
fb7b37cf
HV
899
900 switch (ctrl->id) {
901 case V4L2_CID_BRIGHTNESS:
902 if (ctrl->value < 0 || ctrl->value > 255) {
27760fc4 903 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
fb7b37cf
HV
904 return -ERANGE;
905 }
906
907 state->bright = ctrl->value;
27760fc4
HV
908 v4l2_dbg(1, debug, sd, "bright:%d\n", state->bright);
909 saa717x_write(sd, 0x10a, state->bright);
fb7b37cf
HV
910 break;
911
912 case V4L2_CID_CONTRAST:
913 if (ctrl->value < 0 || ctrl->value > 127) {
27760fc4 914 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
fb7b37cf
HV
915 return -ERANGE;
916 }
917
918 state->contrast = ctrl->value;
27760fc4
HV
919 v4l2_dbg(1, debug, sd, "contrast:%d\n", state->contrast);
920 saa717x_write(sd, 0x10b, state->contrast);
fb7b37cf
HV
921 break;
922
923 case V4L2_CID_SATURATION:
924 if (ctrl->value < 0 || ctrl->value > 127) {
27760fc4 925 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
fb7b37cf
HV
926 return -ERANGE;
927 }
928
929 state->sat = ctrl->value;
27760fc4
HV
930 v4l2_dbg(1, debug, sd, "sat:%d\n", state->sat);
931 saa717x_write(sd, 0x10c, state->sat);
fb7b37cf
HV
932 break;
933
934 case V4L2_CID_HUE:
de6476f5 935 if (ctrl->value < -128 || ctrl->value > 127) {
27760fc4 936 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
fb7b37cf
HV
937 return -ERANGE;
938 }
939
940 state->hue = ctrl->value;
27760fc4
HV
941 v4l2_dbg(1, debug, sd, "hue:%d\n", state->hue);
942 saa717x_write(sd, 0x10d, state->hue);
fb7b37cf
HV
943 break;
944
945 case V4L2_CID_AUDIO_MUTE:
946 state->audio_main_mute = ctrl->value;
27760fc4 947 set_audio_regs(sd, state);
fb7b37cf
HV
948 break;
949
950 case V4L2_CID_AUDIO_VOLUME:
951 state->audio_main_volume = ctrl->value;
27760fc4 952 set_audio_regs(sd, state);
fb7b37cf
HV
953 break;
954
955 case V4L2_CID_AUDIO_BALANCE:
956 state->audio_main_balance = ctrl->value;
27760fc4 957 set_audio_regs(sd, state);
fb7b37cf
HV
958 break;
959
960 case V4L2_CID_AUDIO_TREBLE:
961 state->audio_main_treble = ctrl->value;
27760fc4 962 set_audio_regs(sd, state);
fb7b37cf
HV
963 break;
964
965 case V4L2_CID_AUDIO_BASS:
966 state->audio_main_bass = ctrl->value;
27760fc4 967 set_audio_regs(sd, state);
fb7b37cf
HV
968 break;
969
970 default:
971 return -EINVAL;
972 }
973
974 return 0;
975}
976
27760fc4 977static int saa717x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
fb7b37cf 978{
27760fc4 979 struct saa717x_state *state = to_state(sd);
fb7b37cf
HV
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
1025static 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
5325b427
HV
1108static int saa717x_s_video_routing(struct v4l2_subdev *sd,
1109 u32 input, u32 output, u32 config)
fb7b37cf 1110{
27760fc4 1111 struct saa717x_state *decoder = to_state(sd);
5325b427 1112 int is_tuner = input & 0x80; /* tuner input flag */
fb7b37cf 1113
5325b427 1114 input &= 0x7f;
fb7b37cf 1115
5325b427 1116 v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
fb7b37cf
HV
1117 /* inputs from 0-9 are available*/
1118 /* saa717x have mode0-mode9 but mode5 is reserved. */
f14a2972 1119 if (input > 9 || input == 5)
fb7b37cf
HV
1120 return -EINVAL;
1121
5325b427
HV
1122 if (decoder->input != input) {
1123 int input_line = input;
fb7b37cf
HV
1124
1125 decoder->input = input_line;
27760fc4 1126 v4l2_dbg(1, debug, sd, "now setting %s input %d\n",
fb7b37cf
HV
1127 input_line >= 6 ? "S-Video" : "Composite",
1128 input_line);
1129
1130 /* select mode */
27760fc4
HV
1131 saa717x_write(sd, 0x102,
1132 (saa717x_read(sd, 0x102) & 0xf0) |
fb7b37cf
HV
1133 input_line);
1134
1135 /* bypass chrominance trap for modes 6..9 */
27760fc4
HV
1136 saa717x_write(sd, 0x109,
1137 (saa717x_read(sd, 0x109) & 0x7f) |
fb7b37cf
HV
1138 (input_line < 6 ? 0x0 : 0x80));
1139
1140 /* change audio_mode */
1141 if (is_tuner) {
1142 /* tuner */
27760fc4 1143 set_audio_mode(sd, decoder->tuner_audio_mode);
fb7b37cf
HV
1144 } else {
1145 /* Force to STEREO mode if Composite or
1146 * S-Video were chosen */
27760fc4 1147 set_audio_mode(sd, TUNER_AUDIO_STEREO);
fb7b37cf
HV
1148 }
1149 /* change initialize procedure (Composite/S-Video) */
1150 if (is_tuner)
27760fc4 1151 saa717x_write_regs(sd, reg_init_tuner_input);
fb7b37cf 1152 else if (input_line >= 6)
27760fc4 1153 saa717x_write_regs(sd, reg_init_svideo_input);
fb7b37cf 1154 else
27760fc4 1155 saa717x_write_regs(sd, reg_init_composite_input);
fb7b37cf
HV
1156 }
1157
1158 return 0;
1159}
1160
27760fc4 1161static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
fb7b37cf 1162{
27760fc4 1163 int i;
fb7b37cf 1164
27760fc4
HV
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}
fb7b37cf 1172
27760fc4 1173#ifdef CONFIG_VIDEO_ADV_DEBUG
aecde8b5 1174static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
27760fc4
HV
1175{
1176 struct i2c_client *client = v4l2_get_subdevdata(sd);
fb7b37cf 1177
aecde8b5 1178 if (!v4l2_chip_match_i2c_client(client, &reg->match))
27760fc4
HV
1179 return -EINVAL;
1180 if (!capable(CAP_SYS_ADMIN))
1181 return -EPERM;
1182 reg->val = saa717x_read(sd, reg->reg);
aecde8b5 1183 reg->size = 1;
27760fc4
HV
1184 return 0;
1185}
fb7b37cf 1186
aecde8b5 1187static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
27760fc4
HV
1188{
1189 struct i2c_client *client = v4l2_get_subdevdata(sd);
1190 u16 addr = reg->reg & 0xffff;
1191 u8 val = reg->val & 0xff;
fb7b37cf 1192
aecde8b5 1193 if (!v4l2_chip_match_i2c_client(client, &reg->match))
fb7b37cf 1194 return -EINVAL;
27760fc4
HV
1195 if (!capable(CAP_SYS_ADMIN))
1196 return -EPERM;
1197 saa717x_write(sd, addr, val);
1198 return 0;
1199}
1200#endif
fb7b37cf 1201
27760fc4
HV
1202static 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;
fb7b37cf 1206
27760fc4
HV
1207 pix = &fmt->fmt.pix;
1208 v4l2_dbg(1, debug, sd, "decoder set size\n");
fb7b37cf 1209
27760fc4
HV
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;
fb7b37cf 1215
27760fc4
HV
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}
fb7b37cf 1259
27760fc4
HV
1260static int saa717x_s_radio(struct v4l2_subdev *sd)
1261{
1262 struct saa717x_state *decoder = to_state(sd);
fb7b37cf 1263
27760fc4
HV
1264 decoder->radio = 1;
1265 return 0;
1266}
fb7b37cf 1267
27760fc4
HV
1268static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1269{
1270 struct saa717x_state *decoder = to_state(sd);
fb7b37cf 1271
27760fc4
HV
1272 v4l2_dbg(1, debug, sd, "decoder set norm ");
1273 v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
fb7b37cf 1274
27760fc4
HV
1275 decoder->radio = 0;
1276 decoder->std = std;
1277 return 0;
1278}
fb7b37cf 1279
5325b427
HV
1280static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
1281 u32 input, u32 output, u32 config)
27760fc4
HV
1282{
1283 struct saa717x_state *decoder = to_state(sd);
fb7b37cf 1284
5325b427
HV
1285 if (input < 3) { /* FIXME! --tadachi */
1286 decoder->audio_input = input;
27760fc4 1287 v4l2_dbg(1, debug, sd,
fb7b37cf
HV
1288 "set decoder audio input to %d\n",
1289 decoder->audio_input);
27760fc4
HV
1290 set_audio_regs(sd, decoder);
1291 return 0;
fb7b37cf 1292 }
27760fc4
HV
1293 return -ERANGE;
1294}
fb7b37cf 1295
27760fc4
HV
1296static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
1297{
1298 struct saa717x_state *decoder = to_state(sd);
fb7b37cf 1299
27760fc4
HV
1300 v4l2_dbg(1, debug, sd, "decoder %s output\n",
1301 enable ? "enable" : "disable");
1302 decoder->enable = enable;
1303 saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
1304 return 0;
1305}
fb7b37cf 1306
27760fc4
HV
1307/* change audio mode */
1308static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1309{
1310 struct saa717x_state *decoder = to_state(sd);
1311 int audio_mode;
1312 char *mes[4] = {
1313 "MONO", "STEREO", "LANG1", "LANG2/SAP"
1314 };
fb7b37cf 1315
b921d929 1316 audio_mode = TUNER_AUDIO_STEREO;
fb7b37cf 1317
27760fc4 1318 switch (vt->audmode) {
fb7b37cf
HV
1319 case V4L2_TUNER_MODE_MONO:
1320 audio_mode = TUNER_AUDIO_MONO;
1321 break;
1322 case V4L2_TUNER_MODE_STEREO:
1323 audio_mode = TUNER_AUDIO_STEREO;
1324 break;
1325 case V4L2_TUNER_MODE_LANG2:
1326 audio_mode = TUNER_AUDIO_LANG2;
1327 break;
1328 case V4L2_TUNER_MODE_LANG1:
1329 audio_mode = TUNER_AUDIO_LANG1;
1330 break;
fb7b37cf
HV
1331 }
1332
27760fc4
HV
1333 v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
1334 mes[audio_mode]);
1335 decoder->tuner_audio_mode = audio_mode;
1336 /* The registers are not changed here. */
1337 /* See DECODER_ENABLE_OUTPUT section. */
1338 set_audio_mode(sd, decoder->tuner_audio_mode);
1339 return 0;
1340}
fb7b37cf 1341
27760fc4
HV
1342static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1343{
1344 struct saa717x_state *decoder = to_state(sd);
1345 int dual_f, stereo_f;
fb7b37cf 1346
27760fc4
HV
1347 if (decoder->radio)
1348 return 0;
1349 get_inf_dev_status(sd, &dual_f, &stereo_f);
fb7b37cf 1350
27760fc4
HV
1351 v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
1352 stereo_f, dual_f);
fb7b37cf 1353
27760fc4
HV
1354 /* mono */
1355 if ((dual_f == 0) && (stereo_f == 0)) {
1356 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1357 v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
1358 }
fb7b37cf 1359
27760fc4
HV
1360 /* stereo */
1361 if (stereo_f == 1) {
1362 if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1363 vt->audmode == V4L2_TUNER_MODE_LANG1) {
1364 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1365 v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
1366 } else {
1367 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1368 v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
fb7b37cf 1369 }
fb7b37cf
HV
1370 }
1371
27760fc4
HV
1372 /* dual */
1373 if (dual_f == 1) {
1374 if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1375 vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1376 v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
1377 } else {
1378 vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1379 v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
1380 }
fb7b37cf 1381 }
fb7b37cf
HV
1382 return 0;
1383}
1384
27760fc4
HV
1385/* ----------------------------------------------------------------------- */
1386
1387static const struct v4l2_subdev_core_ops saa717x_core_ops = {
1388#ifdef CONFIG_VIDEO_ADV_DEBUG
1389 .g_register = saa717x_g_register,
1390 .s_register = saa717x_s_register,
1391#endif
1392 .queryctrl = saa717x_queryctrl,
1393 .g_ctrl = saa717x_g_ctrl,
1394 .s_ctrl = saa717x_s_ctrl,
f41737ec 1395 .s_std = saa717x_s_std,
27760fc4
HV
1396};
1397
1398static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1399 .g_tuner = saa717x_g_tuner,
1400 .s_tuner = saa717x_s_tuner,
27760fc4
HV
1401 .s_radio = saa717x_s_radio,
1402};
1403
1404static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1405 .s_routing = saa717x_s_video_routing,
1406 .s_fmt = saa717x_s_fmt,
1407 .s_stream = saa717x_s_stream,
1408};
1409
1410static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
1411 .s_routing = saa717x_s_audio_routing,
1412};
1413
1414static const struct v4l2_subdev_ops saa717x_ops = {
1415 .core = &saa717x_core_ops,
1416 .tuner = &saa717x_tuner_ops,
1417 .audio = &saa717x_audio_ops,
1418 .video = &saa717x_video_ops,
1419};
1420
fb7b37cf
HV
1421/* ----------------------------------------------------------------------- */
1422
1423
1424/* i2c implementation */
1425
1426/* ----------------------------------------------------------------------- */
d2653e92
JD
1427static int saa717x_probe(struct i2c_client *client,
1428 const struct i2c_device_id *did)
fb7b37cf
HV
1429{
1430 struct saa717x_state *decoder;
27760fc4 1431 struct v4l2_subdev *sd;
fb7b37cf
HV
1432 u8 id = 0;
1433 char *p = "";
1434
1435 /* Check if the adapter supports the needed features */
1436 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1437 return -EIO;
1438
27760fc4
HV
1439 decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
1440 if (decoder == NULL)
1441 return -ENOMEM;
1442
1443 sd = &decoder->sd;
1444 v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
1445
1446 if (saa717x_write(sd, 0x5a4, 0xfe) &&
1447 saa717x_write(sd, 0x5a5, 0x0f) &&
1448 saa717x_write(sd, 0x5a6, 0x00) &&
1449 saa717x_write(sd, 0x5a7, 0x01))
1450 id = saa717x_read(sd, 0x5a0);
fb7b37cf 1451 if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
27760fc4
HV
1452 v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
1453 kfree(decoder);
fb7b37cf
HV
1454 return -ENODEV;
1455 }
1456 if (id == 0xc2)
1457 p = "saa7173";
1458 else if (id == 0x32)
1459 p = "saa7174A";
1460 else if (id == 0x6c)
1461 p = "saa7174HL";
1462 else
1463 p = "saa7171";
27760fc4 1464 v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
fb7b37cf 1465 client->addr << 1, client->adapter->name);
fb7b37cf
HV
1466 decoder->std = V4L2_STD_NTSC;
1467 decoder->input = -1;
1468 decoder->enable = 1;
1469
1470 /* tune these parameters */
1471 decoder->bright = 0x80;
1472 decoder->contrast = 0x44;
1473 decoder->sat = 0x40;
1474 decoder->hue = 0x00;
1475
1476 /* FIXME!! */
1477 decoder->playback = 0; /* initially capture mode used */
1478 decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1479
1480 decoder->audio_input = 2; /* FIXME!! */
1481
1482 decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1483 /* set volume, bass and treble */
1484 decoder->audio_main_vol_l = 6;
1485 decoder->audio_main_vol_r = 6;
1486 decoder->audio_main_bass = 0;
1487 decoder->audio_main_treble = 0;
1488 decoder->audio_main_mute = 0;
1489 decoder->audio_main_balance = 32768;
1490 /* normalize (24 to -40 (not -84) -> 65535 to 0) */
1491 decoder->audio_main_volume =
1492 (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
1493
27760fc4 1494 v4l2_dbg(1, debug, sd, "writing init values\n");
fb7b37cf
HV
1495
1496 /* FIXME!! */
27760fc4
HV
1497 saa717x_write_regs(sd, reg_init_initialize);
1498 set_video_output_level_regs(sd, decoder);
fb7b37cf
HV
1499 /* set bass,treble to 0db 20041101 K.Ohta */
1500 decoder->audio_main_bass = 0;
1501 decoder->audio_main_treble = 0;
27760fc4 1502 set_audio_regs(sd, decoder);
fb7b37cf
HV
1503
1504 set_current_state(TASK_INTERRUPTIBLE);
1505 schedule_timeout(2*HZ);
1506 return 0;
1507}
1508
1509static int saa717x_remove(struct i2c_client *client)
1510{
27760fc4
HV
1511 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1512
1513 v4l2_device_unregister_subdev(sd);
1514 kfree(to_state(sd));
fb7b37cf
HV
1515 return 0;
1516}
1517
1518/* ----------------------------------------------------------------------- */
1519
af294867
JD
1520static const struct i2c_device_id saa717x_id[] = {
1521 { "saa717x", 0 },
1522 { }
1523};
1524MODULE_DEVICE_TABLE(i2c, saa717x_id);
1525
fb7b37cf
HV
1526static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1527 .name = "saa717x",
fb7b37cf
HV
1528 .probe = saa717x_probe,
1529 .remove = saa717x_remove,
af294867 1530 .id_table = saa717x_id,
fb7b37cf 1531};