20 #include <linux/kernel.h>
26 #define DEFAULT_HDELAY_NTSC (32 - 4)
27 #define DEFAULT_HACTIVE_NTSC (720 + 16)
28 #define DEFAULT_VDELAY_NTSC (7 - 2)
29 #define DEFAULT_VACTIVE_NTSC (240 + 4)
31 #define DEFAULT_HDELAY_PAL (32 + 4)
32 #define DEFAULT_HACTIVE_PAL (864-DEFAULT_HDELAY_PAL)
33 #define DEFAULT_VDELAY_PAL (6)
34 #define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL)
36 static u8 tbl_tw2864_template[] = {
37 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02,
38 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
39 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02,
40 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
41 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02,
42 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
43 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02,
44 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
53 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50,
54 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
55 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05,
56 0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
57 0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a,
58 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
59 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
63 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20,
64 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
65 0x10, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00,
66 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
67 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20,
68 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
71 static u8 tbl_tw2865_ntsc_template[] = {
72 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
73 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
74 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
75 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
76 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
77 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
78 0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02,
79 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
80 0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80,
81 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
86 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03,
87 0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
88 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50,
89 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
90 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05,
91 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
92 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A,
93 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
94 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF,
95 0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
96 0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
98 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31,
99 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
100 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00,
101 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
102 0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20,
103 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
106 static u8 tbl_tw2865_pal_template[] = {
107 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
108 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
109 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
110 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
111 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
112 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
113 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
114 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
115 0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80,
116 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
121 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03,
122 0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
123 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50,
124 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
125 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05,
126 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
127 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A,
128 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
129 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF,
130 0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
131 0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
133 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31,
134 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
135 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00,
136 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
137 0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20,
138 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
141 #define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
169 static void tw_write_and_verify(
struct solo_dev *solo_dev,
u8 addr,
u8 off,
174 for (i = 0; i < 5; i++) {
187 static int tw2865_setup(
struct solo_dev *solo_dev,
u8 dev_addr)
189 u8 tbl_tw2865_common[256];
193 memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
194 sizeof(tbl_tw2865_common));
196 memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
197 sizeof(tbl_tw2865_common));
201 tbl_tw2865_common[0xd2] = 0x01;
202 tbl_tw2865_common[0xcf] = 0x00;
203 }
else if (solo_dev->
nr_chans == 8) {
204 tbl_tw2865_common[0xd2] = 0x02;
206 tbl_tw2865_common[0xcf] = 0x80;
207 }
else if (solo_dev->
nr_chans == 16) {
208 tbl_tw2865_common[0xd2] = 0x03;
210 tbl_tw2865_common[0xcf] = 0x83;
212 tbl_tw2865_common[0xcf] = 0x83;
214 tbl_tw2865_common[0xcf] = 0x80;
217 for (i = 0; i < 0xff; i++) {
219 if (i >= 0xb8 && i <= 0xc1)
221 if ((i & ~0x30) == 0x00 ||
222 (i & ~0x30) == 0x0c ||
225 if (i >= 0xc4 && i <= 0xc7)
230 tw_write_and_verify(solo_dev, dev_addr, i,
231 tbl_tw2865_common[i]);
237 static int tw2864_setup(
struct solo_dev *solo_dev,
u8 dev_addr)
239 u8 tbl_tw2864_common[
sizeof(tbl_tw2864_template)];
242 memcpy(tbl_tw2864_common, tbl_tw2864_template,
243 sizeof(tbl_tw2864_common));
245 if (solo_dev->
tw2865 == 0) {
248 tbl_tw2864_common[0xd2] = 0x01;
249 tbl_tw2864_common[0xcf] = 0x00;
250 }
else if (solo_dev->
nr_chans == 8) {
251 tbl_tw2864_common[0xd2] = 0x02;
253 tbl_tw2864_common[0xcf] = 0x43;
255 tbl_tw2864_common[0xcf] = 0x40;
256 }
else if (solo_dev->
nr_chans == 16) {
257 tbl_tw2864_common[0xd2] = 0x03;
259 tbl_tw2864_common[0xcf] = 0x43;
261 tbl_tw2864_common[0xcf] = 0x43;
263 tbl_tw2864_common[0xcf] = 0x43;
265 tbl_tw2864_common[0xcf] = 0x40;
270 for (i = 0; i <= 4; i++)
271 tbl_tw2864_common[0x08 | i << 4] = 0x12;
274 tbl_tw2864_common[0xd2] = 0x02;
276 tbl_tw2864_common[0xcf] = 0x80;
277 }
else if (solo_dev->
nr_chans == 16) {
278 tbl_tw2864_common[0xd2] = 0x03;
280 tbl_tw2864_common[0xcf] = 0x83;
282 tbl_tw2864_common[0xcf] = 0x83;
284 tbl_tw2864_common[0xcf] = 0x80;
290 for (i = 0; i < 4; i++) {
291 tbl_tw2864_common[0x07 | (i << 4)] |= 0x10;
292 tbl_tw2864_common[0x08 | (i << 4)] |= 0x06;
293 tbl_tw2864_common[0x0a | (i << 4)] |= 0x08;
294 tbl_tw2864_common[0x0b | (i << 4)] |= 0x13;
295 tbl_tw2864_common[0x0e | (i << 4)] |= 0x01;
297 tbl_tw2864_common[0x9d] = 0x90;
298 tbl_tw2864_common[0xf3] = 0x00;
299 tbl_tw2864_common[0xf4] = 0xa0;
302 for (i = 0; i < 0xff; i++) {
304 if (i >= 0xb8 && i <= 0xc1)
306 if ((i & ~0x30) == 0x00 ||
307 (i & ~0x30) == 0x0c ||
310 if (i == 0x74 || i == 0x77 || i == 0x78 ||
311 i == 0x79 || i == 0x7a)
316 tw_write_and_verify(solo_dev, dev_addr, i,
317 tbl_tw2864_common[i]);
323 static int tw2815_setup(
struct solo_dev *solo_dev,
u8 dev_addr)
325 u8 tbl_ntsc_tw2815_common[] = {
326 0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
327 0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
330 u8 tbl_pal_tw2815_common[] = {
331 0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
332 0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
335 u8 tbl_tw2815_sfr[] = {
336 0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f,
337 0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
338 0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00,
339 0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
340 0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec,
341 0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
342 0x88, 0x11, 0x00, 0x88, 0x88, 0x00,
344 u8 *tbl_tw2815_common;
348 tbl_ntsc_tw2815_common[0x06] = 0;
356 tbl_ntsc_tw2815_common[0x06] |=
361 tbl_ntsc_tw2815_common[0x06] |=
366 tbl_ntsc_tw2815_common[0x06] |=
369 tbl_pal_tw2815_common[0x06] = 0;
377 tbl_pal_tw2815_common[0x06] |=
382 tbl_pal_tw2815_common[0x06] |=
387 tbl_pal_tw2815_common[0x06] |=
392 tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
395 tbl_tw2815_common[0x0d] |= 0x04;
398 tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
401 tbl_tw2815_sfr[0x63 - 0x40] |= 1;
402 tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
403 }
else if (solo_dev->
nr_chans == 8) {
404 tbl_tw2815_sfr[0x63 - 0x40] |= 2;
406 tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
408 tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
409 }
else if (solo_dev->
nr_chans == 16) {
410 tbl_tw2815_sfr[0x63 - 0x40] |= 3;
412 tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
414 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
416 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
418 tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
425 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
426 tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
429 tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
432 tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
435 tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
437 tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
438 tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
442 for (ch = 0; ch < 4; ch++) {
443 tbl_tw2815_common[0x0d] &= ~3;
446 tbl_tw2815_common[0x0d] |= 0x21;
449 tbl_tw2815_common[0x0d] |= 0x20;
452 tbl_tw2815_common[0x0d] |= 0x23;
455 tbl_tw2815_common[0x0d] |= 0x22;
459 for (i = 0; i < 0x0f; i++) {
463 dev_addr, (ch * 0x10) + i,
464 tbl_tw2815_common[i]);
468 for (i = 0x40; i < 0x76; i++) {
470 if (i == 0x40 || i == 0x59 || i == 0x5a ||
471 i == 0x5d || i == 0x5e || i == 0x5f)
475 tbl_tw2815_sfr[i - 0x40]);
481 #define FIRST_ACTIVE_LINE 0x0008
482 #define LAST_ACTIVE_LINE 0x0102
484 static void saa7128_setup(
struct solo_dev *solo_dev)
487 unsigned char regs[128] = {
488 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x1C, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
493 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, 0x00, 0x00,
494 0x1c, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00,
495 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
497 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
498 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
499 0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
500 0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
501 0x41, 0x88, 0x41, 0x12, 0xed, 0x10, 0x10, 0x00,
502 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
503 0x00, 0x00, 0x08, 0xff, 0x80, 0x00, 0xff, 0xff,
508 regs[0x7C] = ((1 << 7) |
527 regs[0x7A] = 0x06 + 12;
528 regs[0x7b] = 0x24 + 12;
529 regs[0x7c] |= 1 << 6;
533 for (i = 0x26; i < 128; i++) {
534 if (i == 0x60 || i == 0x7D)
552 switch (value >> 3) {
564 if ((value >> 3) == 0x04) {
574 saa7128_setup(solo_dev);
576 for (i = 0; i < solo_dev->
tw28_cnt; i++) {
577 if ((solo_dev->
tw2865 & (1 << i)))
579 else if ((solo_dev->
tw2864 & (1 << i)))
585 dev_info(&solo_dev->
pdev->dev,
"Initialized %d tw28xx chip%s:",
616 return val & (1 << ch) ? 1 : 0;
622 u16 tw28_get_audio_status(
struct solo_dev *solo_dev)
628 for (i = 0; i < solo_dev->
tw28_cnt; i++) {
631 status |= val << (i * 4);
647 if (val > 255 || val < 0)
653 if (val > 0x0f || val < 0)
734 *val = (
s32)((
char)rval) + 128;
739 *val = tw_readbyte(solo_dev, chip_num,
744 *val = tw_readbyte(solo_dev, chip_num,
749 rval = tw_readbyte(solo_dev, chip_num,
753 *val = (
s32)((
char)rval) + 128;
770 void tw2815_Set_AudioOutVol(
struct solo_dev *solo_dev,
unsigned int u_val)
773 unsigned int chip_num;
775 chip_num = (solo_dev->
nr_chans - 1) / 4;
780 u_val = (val & 0x0f) | (u_val << 4);
796 val = tw_readbyte(solo_dev, chip_num,
800 return (ch % 2) ? (val >> 4) : (val & 0x0f);
812 old_val = tw_readbyte(solo_dev, chip_num,
816 val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
817 ((ch % 2) ? (val << 4) : val);