1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/kernel.h>
22#include <linux/delay.h>
23
24#include "solo6x10.h"
25#include "solo6x10-tw28.h"
26
27#define DEFAULT_HDELAY_NTSC (32 - 8)
28#define DEFAULT_HACTIVE_NTSC (720 + 16)
29#define DEFAULT_VDELAY_NTSC (7 - 2)
30#define DEFAULT_VACTIVE_NTSC (240 + 4)
31
32#define DEFAULT_HDELAY_PAL (32 + 4)
33#define DEFAULT_HACTIVE_PAL (864-DEFAULT_HDELAY_PAL)
34#define DEFAULT_VDELAY_PAL (6)
35#define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL)
36
37
38static const u8 tbl_tw2864_ntsc_template[] = {
39 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
40 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
41 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
42 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
43 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
44 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
45 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
46 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
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, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
55 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50,
56 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
57 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05,
58 0x00, 0x28, 0x44, 0x44, 0xa0, 0x88, 0x5a, 0x01,
59 0x08, 0x08, 0x08, 0x08, 0x1a, 0x1a, 0x1a, 0x1a,
60 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
61 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
65 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20,
66 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
67 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00,
68 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
69 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20,
70 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
71};
72
73static const u8 tbl_tw2864_pal_template[] = {
74 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
75 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
76 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
77 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
78 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
79 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
80 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
81 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
90 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50,
91 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
92 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05,
93 0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01,
94 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a,
95 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
96 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
100 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20,
101 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
102 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00,
103 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
104 0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20,
105 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
106};
107
108static const u8 tbl_tw2865_ntsc_template[] = {
109 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
110 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
111 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
112 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
113 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02,
114 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
115 0x00, 0xf0, 0x70, 0x48, 0x80, 0x80, 0x00, 0x02,
116 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
117 0x00, 0x00, 0x90, 0x68, 0x00, 0x38, 0x80, 0x80,
118 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
123 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03,
124 0xE9, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
125 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50,
126 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
127 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05,
128 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
129 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1B, 0x1A,
130 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
131 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF,
132 0xFF, 0xE7, 0xE9, 0xE9, 0xEB, 0xFF, 0xD6, 0xD8,
133 0xD8, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
135 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31,
136 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
137 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00,
138 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
139 0x83, 0xB5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20,
140 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
141};
142
143static const u8 tbl_tw2865_pal_template[] = {
144 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
145 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
146 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
147 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
148 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
149 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
150 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12,
151 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
152 0x00, 0x94, 0x90, 0x48, 0x00, 0x38, 0x7F, 0x80,
153 0x80, 0x80, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x43,
158 0x08, 0x00, 0x00, 0x01, 0xf1, 0x03, 0xEF, 0x03,
159 0xEA, 0x03, 0xD9, 0x15, 0x15, 0xE4, 0xA3, 0x80,
160 0x00, 0x02, 0x00, 0xCC, 0x00, 0x80, 0x44, 0x50,
161 0x22, 0x01, 0xD8, 0xBC, 0xB8, 0x44, 0x38, 0x00,
162 0x00, 0x78, 0x44, 0x3D, 0x14, 0xA5, 0xE0, 0x05,
163 0x00, 0x28, 0x44, 0x44, 0xA0, 0x90, 0x52, 0x13,
164 0x08, 0x08, 0x08, 0x08, 0x1A, 0x1A, 0x1A, 0x1A,
165 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x44,
166 0x44, 0x4A, 0x00, 0xFF, 0xEF, 0xEF, 0xEF, 0xEF,
167 0xFF, 0xE7, 0xE9, 0xE9, 0xE9, 0xFF, 0xD7, 0xD8,
168 0xD9, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x55, 0x00, 0xE4, 0x39, 0x00, 0x80,
170 0x77, 0x77, 0x03, 0x20, 0x57, 0x9b, 0xdf, 0x31,
171 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81,
172 0x10, 0xC0, 0xAA, 0xAA, 0x00, 0x11, 0x00, 0x00,
173 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
174 0x83, 0xB5, 0x09, 0x00, 0xA0, 0x00, 0x01, 0x20,
175 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
176};
177
178#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id)))
179
180static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off,
181 u8 tw_off)
182{
183 if (is_tw286x(solo_dev, chip_id))
184 return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
185 TW_CHIP_OFFSET_ADDR(chip_id),
186 tw6x_off);
187 else
188 return solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
189 TW_CHIP_OFFSET_ADDR(chip_id),
190 tw_off);
191}
192
193static void tw_writebyte(struct solo_dev *solo_dev, int chip_id,
194 u8 tw6x_off, u8 tw_off, u8 val)
195{
196 if (is_tw286x(solo_dev, chip_id))
197 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
198 TW_CHIP_OFFSET_ADDR(chip_id),
199 tw6x_off, val);
200 else
201 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
202 TW_CHIP_OFFSET_ADDR(chip_id),
203 tw_off, val);
204}
205
206static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
207 u8 val)
208{
209 int i;
210
211 for (i = 0; i < 5; i++) {
212 u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
213
214 if (rval == val)
215 return;
216
217 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, addr, off, val);
218 msleep_interruptible(1);
219 }
220
221
222
223}
224
225static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
226{
227 u8 tbl_tw2865_common[256];
228 int i;
229
230 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
231 memcpy(tbl_tw2865_common, tbl_tw2865_pal_template,
232 sizeof(tbl_tw2865_common));
233 else
234 memcpy(tbl_tw2865_common, tbl_tw2865_ntsc_template,
235 sizeof(tbl_tw2865_common));
236
237
238 if (solo_dev->nr_chans == 4) {
239 tbl_tw2865_common[0xd2] = 0x01;
240 tbl_tw2865_common[0xcf] = 0x00;
241 } else if (solo_dev->nr_chans == 8) {
242 tbl_tw2865_common[0xd2] = 0x02;
243 if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
244 tbl_tw2865_common[0xcf] = 0x80;
245 } else if (solo_dev->nr_chans == 16) {
246 tbl_tw2865_common[0xd2] = 0x03;
247 if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
248 tbl_tw2865_common[0xcf] = 0x83;
249 else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
250 tbl_tw2865_common[0xcf] = 0x83;
251 else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
252 tbl_tw2865_common[0xcf] = 0x80;
253 }
254
255 for (i = 0; i < 0xff; i++) {
256
257 switch (i) {
258 case 0xb8 ... 0xc1:
259 case 0xc4 ... 0xc7:
260 case 0xfd:
261 continue;
262 }
263 switch (i & ~0x30) {
264 case 0x00:
265 case 0x0c ... 0x0d:
266 continue;
267 }
268
269 tw_write_and_verify(solo_dev, dev_addr, i,
270 tbl_tw2865_common[i]);
271 }
272
273 return 0;
274}
275
276static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
277{
278 u8 tbl_tw2864_common[256];
279 int i;
280
281 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
282 memcpy(tbl_tw2864_common, tbl_tw2864_pal_template,
283 sizeof(tbl_tw2864_common));
284 else
285 memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template,
286 sizeof(tbl_tw2864_common));
287
288 if (solo_dev->tw2865 == 0) {
289
290 if (solo_dev->nr_chans == 4) {
291 tbl_tw2864_common[0xd2] = 0x01;
292 tbl_tw2864_common[0xcf] = 0x00;
293 } else if (solo_dev->nr_chans == 8) {
294 tbl_tw2864_common[0xd2] = 0x02;
295 if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
296 tbl_tw2864_common[0xcf] = 0x43;
297 else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
298 tbl_tw2864_common[0xcf] = 0x40;
299 } else if (solo_dev->nr_chans == 16) {
300 tbl_tw2864_common[0xd2] = 0x03;
301 if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
302 tbl_tw2864_common[0xcf] = 0x43;
303 else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
304 tbl_tw2864_common[0xcf] = 0x43;
305 else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
306 tbl_tw2864_common[0xcf] = 0x43;
307 else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
308 tbl_tw2864_common[0xcf] = 0x40;
309 }
310 } else {
311
312
313 for (i = 0; i <= 4; i++)
314 tbl_tw2864_common[0x08 | i << 4] = 0x12;
315
316 if (solo_dev->nr_chans == 8) {
317 tbl_tw2864_common[0xd2] = 0x02;
318 if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
319 tbl_tw2864_common[0xcf] = 0x80;
320 } else if (solo_dev->nr_chans == 16) {
321 tbl_tw2864_common[0xd2] = 0x03;
322 if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
323 tbl_tw2864_common[0xcf] = 0x83;
324 else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
325 tbl_tw2864_common[0xcf] = 0x83;
326 else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
327 tbl_tw2864_common[0xcf] = 0x80;
328 }
329 }
330
331 for (i = 0; i < 0xff; i++) {
332
333 switch (i) {
334 case 0xb8 ... 0xc1:
335 case 0xfd:
336 continue;
337 }
338 switch (i & ~0x30) {
339 case 0x00:
340 case 0x0c:
341 case 0x0d:
342 continue;
343 }
344
345 tw_write_and_verify(solo_dev, dev_addr, i,
346 tbl_tw2864_common[i]);
347 }
348
349 return 0;
350}
351
352static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr)
353{
354 u8 tbl_ntsc_tw2815_common[] = {
355 0x00, 0xc8, 0x20, 0xd0, 0x06, 0xf0, 0x08, 0x80,
356 0x80, 0x80, 0x80, 0x02, 0x06, 0x00, 0x11,
357 };
358
359 u8 tbl_pal_tw2815_common[] = {
360 0x00, 0x88, 0x20, 0xd0, 0x05, 0x20, 0x28, 0x80,
361 0x80, 0x80, 0x80, 0x82, 0x06, 0x00, 0x11,
362 };
363
364 u8 tbl_tw2815_sfr[] = {
365 0x00, 0x00, 0x00, 0xc0, 0x45, 0xa0, 0xd0, 0x2f,
366 0x64, 0x80, 0x80, 0x82, 0x82, 0x00, 0x00, 0x00,
367 0x00, 0x0f, 0x05, 0x00, 0x00, 0x80, 0x06, 0x00,
368 0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00,
369 0x88, 0x88, 0xc0, 0x00, 0x20, 0x64, 0xa8, 0xec,
370 0x31, 0x75, 0xb9, 0xfd, 0x00, 0x00, 0x88, 0x88,
371 0x88, 0x11, 0x00, 0x88, 0x88, 0x00,
372 };
373 u8 *tbl_tw2815_common;
374 int i;
375 int ch;
376
377 tbl_ntsc_tw2815_common[0x06] = 0;
378
379
380 tbl_ntsc_tw2815_common[0x02] = DEFAULT_HDELAY_NTSC & 0xff;
381 tbl_ntsc_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_NTSC >> 8);
382
383
384 tbl_ntsc_tw2815_common[0x03] = DEFAULT_HACTIVE_NTSC & 0xff;
385 tbl_ntsc_tw2815_common[0x06] |=
386 ((0x03 & (DEFAULT_HACTIVE_NTSC >> 8)) << 2);
387
388
389 tbl_ntsc_tw2815_common[0x04] = DEFAULT_VDELAY_NTSC & 0xff;
390 tbl_ntsc_tw2815_common[0x06] |=
391 ((0x01 & (DEFAULT_VDELAY_NTSC >> 8)) << 4);
392
393
394 tbl_ntsc_tw2815_common[0x05] = DEFAULT_VACTIVE_NTSC & 0xff;
395 tbl_ntsc_tw2815_common[0x06] |=
396 ((0x01 & (DEFAULT_VACTIVE_NTSC >> 8)) << 5);
397
398 tbl_pal_tw2815_common[0x06] = 0;
399
400
401 tbl_pal_tw2815_common[0x02] = DEFAULT_HDELAY_PAL & 0xff;
402 tbl_pal_tw2815_common[0x06] |= 0x03 & (DEFAULT_HDELAY_PAL >> 8);
403
404
405 tbl_pal_tw2815_common[0x03] = DEFAULT_HACTIVE_PAL & 0xff;
406 tbl_pal_tw2815_common[0x06] |=
407 ((0x03 & (DEFAULT_HACTIVE_PAL >> 8)) << 2);
408
409
410 tbl_pal_tw2815_common[0x04] = DEFAULT_VDELAY_PAL & 0xff;
411 tbl_pal_tw2815_common[0x06] |=
412 ((0x01 & (DEFAULT_VDELAY_PAL >> 8)) << 4);
413
414
415 tbl_pal_tw2815_common[0x05] = DEFAULT_VACTIVE_PAL & 0xff;
416 tbl_pal_tw2815_common[0x06] |=
417 ((0x01 & (DEFAULT_VACTIVE_PAL >> 8)) << 5);
418
419 tbl_tw2815_common =
420 (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) ?
421 tbl_ntsc_tw2815_common : tbl_pal_tw2815_common;
422
423
424 tbl_tw2815_common[0x0d] |= 0x04;
425
426
427 tbl_tw2815_sfr[0x62 - 0x40] &= ~(3 << 6);
428
429 if (solo_dev->nr_chans == 4) {
430 tbl_tw2815_sfr[0x63 - 0x40] |= 1;
431 tbl_tw2815_sfr[0x62 - 0x40] |= 3 << 6;
432 } else if (solo_dev->nr_chans == 8) {
433 tbl_tw2815_sfr[0x63 - 0x40] |= 2;
434 if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
435 tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
436 else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
437 tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
438 } else if (solo_dev->nr_chans == 16) {
439 tbl_tw2815_sfr[0x63 - 0x40] |= 3;
440 if (dev_addr == TW_CHIP_OFFSET_ADDR(0))
441 tbl_tw2815_sfr[0x62 - 0x40] |= 1 << 6;
442 else if (dev_addr == TW_CHIP_OFFSET_ADDR(1))
443 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
444 else if (dev_addr == TW_CHIP_OFFSET_ADDR(2))
445 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 6;
446 else if (dev_addr == TW_CHIP_OFFSET_ADDR(3))
447 tbl_tw2815_sfr[0x62 - 0x40] |= 2 << 6;
448 }
449
450
451
452
453
454 tbl_tw2815_sfr[0x62 - 0x40] |= 0 << 2;
455 tbl_tw2815_sfr[0x6c - 0x40] |= 0 << 2;
456
457
458 tbl_tw2815_sfr[0x6c - 0x40] |= 1 << 5;
459
460
461 tbl_tw2815_sfr[0x5c - 0x40] |= 1 << 5;
462
463
464 tbl_tw2815_sfr[0x70 - 0x40] |= 0xff;
465
466 tbl_tw2815_sfr[0x71 - 0x40] |= 0x10;
467 tbl_tw2815_sfr[0x6d - 0x40] |= 0x0f;
468
469
470
471 for (ch = 0; ch < 4; ch++) {
472 tbl_tw2815_common[0x0d] &= ~3;
473 switch (ch) {
474 case 0:
475 tbl_tw2815_common[0x0d] |= 0x21;
476 break;
477 case 1:
478 tbl_tw2815_common[0x0d] |= 0x20;
479 break;
480 case 2:
481 tbl_tw2815_common[0x0d] |= 0x23;
482 break;
483 case 3:
484 tbl_tw2815_common[0x0d] |= 0x22;
485 break;
486 }
487
488 for (i = 0; i < 0x0f; i++) {
489 if (i == 0x00)
490 continue;
491 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
492 dev_addr, (ch * 0x10) + i,
493 tbl_tw2815_common[i]);
494 }
495 }
496
497 for (i = 0x40; i < 0x76; i++) {
498
499 if (i == 0x40 || i == 0x59 || i == 0x5a ||
500 i == 0x5d || i == 0x5e || i == 0x5f)
501 continue;
502
503 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, dev_addr, i,
504 tbl_tw2815_sfr[i - 0x40]);
505 }
506
507 return 0;
508}
509
510#define FIRST_ACTIVE_LINE 0x0008
511#define LAST_ACTIVE_LINE 0x0102
512
513static void saa712x_write_regs(struct solo_dev *dev, const u8 *vals,
514 int start, int n)
515{
516 for (; start < n; start++, vals++) {
517
518 switch (start) {
519
520 case 0x2e ... 0x37:
521 case 0x60:
522 case 0x7d:
523 continue;
524 }
525 solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals);
526 }
527}
528
529#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \
530 | ((FIRST_ACTIVE_LINE & 0x100) >> 4))
531
532static void saa712x_setup(struct solo_dev *dev)
533{
534 const int reg_start = 0x26;
535 const u8 saa7128_regs_ntsc[] = {
536
537 0x0d, 0x00,
538
539 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
540
541 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543
544 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
545
546 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
547 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
548
549 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
550 0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e,
551
552 0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77,
553 0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00,
554
555 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
556 0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff,
557 SAA712x_reg7c, 0x00, 0xff, 0xff,
558 }, saa7128_regs_pal[] = {
559
560 0x0d, 0x00,
561
562 0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f,
563
564 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566
567 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
568
569 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18,
570 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f,
571
572 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06,
573 0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e,
574
575 0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77,
576 0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00,
577
578 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00,
579 0x00, 0x00, 0x12, 0x30,
580 SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff,
581 };
582
583 if (dev->video_type == SOLO_VO_FMT_TYPE_PAL)
584 saa712x_write_regs(dev, saa7128_regs_pal, reg_start,
585 sizeof(saa7128_regs_pal));
586 else
587 saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start,
588 sizeof(saa7128_regs_ntsc));
589}
590
591int solo_tw28_init(struct solo_dev *solo_dev)
592{
593 int i;
594 u8 value;
595
596 solo_dev->tw28_cnt = 0;
597
598
599 for (i = 0; i < solo_dev->nr_chans / 4; i++) {
600 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
601 TW_CHIP_OFFSET_ADDR(i), 0xFF);
602
603 switch (value >> 3) {
604 case 0x18:
605 solo_dev->tw2865 |= 1 << i;
606 solo_dev->tw28_cnt++;
607 break;
608 case 0x0c:
609 solo_dev->tw2864 |= 1 << i;
610 solo_dev->tw28_cnt++;
611 break;
612 default:
613 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
614 TW_CHIP_OFFSET_ADDR(i),
615 0x59);
616 if ((value >> 3) == 0x04) {
617 solo_dev->tw2815 |= 1 << i;
618 solo_dev->tw28_cnt++;
619 }
620 }
621 }
622
623 if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) {
624 dev_err(&solo_dev->pdev->dev,
625 "Could not initialize any techwell chips\n");
626 return -EINVAL;
627 }
628
629 saa712x_setup(solo_dev);
630
631 for (i = 0; i < solo_dev->tw28_cnt; i++) {
632 if ((solo_dev->tw2865 & (1 << i)))
633 tw2865_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
634 else if ((solo_dev->tw2864 & (1 << i)))
635 tw2864_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
636 else
637 tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
638 }
639
640 return 0;
641}
642
643
644
645
646
647
648
649int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
650{
651 u8 val, chip_num;
652
653
654 chip_num = ch / 4;
655 ch %= 4;
656
657 val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR,
658 TW_AV_STAT_ADDR) & 0x0f;
659
660 return val & (1 << ch) ? 1 : 0;
661}
662
663#if 0
664
665
666u16 tw28_get_audio_status(struct solo_dev *solo_dev)
667{
668 u8 val;
669 u16 status = 0;
670 int i;
671
672 for (i = 0; i < solo_dev->tw28_cnt; i++) {
673 val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR,
674 TW_AV_STAT_ADDR) & 0xf0) >> 4;
675 status |= val << (i * 4);
676 }
677
678 return status;
679}
680#endif
681
682bool tw28_has_sharpness(struct solo_dev *solo_dev, u8 ch)
683{
684 return is_tw286x(solo_dev, ch / 4);
685}
686
687int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
688 s32 val)
689{
690 char sval;
691 u8 chip_num;
692
693
694 chip_num = ch / 4;
695 ch %= 4;
696
697 if (val > 255 || val < 0)
698 return -ERANGE;
699
700 switch (ctrl) {
701 case V4L2_CID_SHARPNESS:
702
703 if (is_tw286x(solo_dev, chip_num)) {
704 u8 v = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
705 TW_CHIP_OFFSET_ADDR(chip_num),
706 TW286x_SHARPNESS(chip_num));
707 v &= 0xf0;
708 v |= val;
709 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
710 TW_CHIP_OFFSET_ADDR(chip_num),
711 TW286x_SHARPNESS(chip_num), v);
712 } else {
713 return -EINVAL;
714 }
715 break;
716
717 case V4L2_CID_HUE:
718 if (is_tw286x(solo_dev, chip_num))
719 sval = val - 128;
720 else
721 sval = (char)val;
722 tw_writebyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
723 TW_HUE_ADDR(ch), sval);
724
725 break;
726
727 case V4L2_CID_SATURATION:
728
729 if (is_tw286x(solo_dev, chip_num)) {
730 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
731 TW_CHIP_OFFSET_ADDR(chip_num),
732 TW286x_SATURATIONU_ADDR(ch), val);
733 }
734 tw_writebyte(solo_dev, chip_num, TW286x_SATURATIONV_ADDR(ch),
735 TW_SATURATION_ADDR(ch), val);
736
737 break;
738
739 case V4L2_CID_CONTRAST:
740 tw_writebyte(solo_dev, chip_num, TW286x_CONTRAST_ADDR(ch),
741 TW_CONTRAST_ADDR(ch), val);
742 break;
743
744 case V4L2_CID_BRIGHTNESS:
745 if (is_tw286x(solo_dev, chip_num))
746 sval = val - 128;
747 else
748 sval = (char)val;
749 tw_writebyte(solo_dev, chip_num, TW286x_BRIGHTNESS_ADDR(ch),
750 TW_BRIGHTNESS_ADDR(ch), sval);
751
752 break;
753 default:
754 return -EINVAL;
755 }
756
757 return 0;
758}
759
760int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
761 s32 *val)
762{
763 u8 rval, chip_num;
764
765
766 chip_num = ch / 4;
767 ch %= 4;
768
769 switch (ctrl) {
770 case V4L2_CID_SHARPNESS:
771
772 if (is_tw286x(solo_dev, chip_num)) {
773 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
774 TW_CHIP_OFFSET_ADDR(chip_num),
775 TW286x_SHARPNESS(chip_num));
776 *val = rval & 0x0f;
777 } else
778 *val = 0;
779 break;
780 case V4L2_CID_HUE:
781 rval = tw_readbyte(solo_dev, chip_num, TW286x_HUE_ADDR(ch),
782 TW_HUE_ADDR(ch));
783 if (is_tw286x(solo_dev, chip_num))
784 *val = (s32)((char)rval) + 128;
785 else
786 *val = rval;
787 break;
788 case V4L2_CID_SATURATION:
789 *val = tw_readbyte(solo_dev, chip_num,
790 TW286x_SATURATIONU_ADDR(ch),
791 TW_SATURATION_ADDR(ch));
792 break;
793 case V4L2_CID_CONTRAST:
794 *val = tw_readbyte(solo_dev, chip_num,
795 TW286x_CONTRAST_ADDR(ch),
796 TW_CONTRAST_ADDR(ch));
797 break;
798 case V4L2_CID_BRIGHTNESS:
799 rval = tw_readbyte(solo_dev, chip_num,
800 TW286x_BRIGHTNESS_ADDR(ch),
801 TW_BRIGHTNESS_ADDR(ch));
802 if (is_tw286x(solo_dev, chip_num))
803 *val = (s32)((char)rval) + 128;
804 else
805 *val = rval;
806 break;
807 default:
808 return -EINVAL;
809 }
810
811 return 0;
812}
813
814#if 0
815
816
817
818
819
820void tw2815_Set_AudioOutVol(struct solo_dev *solo_dev, unsigned int u_val)
821{
822 unsigned int val;
823 unsigned int chip_num;
824
825 chip_num = (solo_dev->nr_chans - 1) / 4;
826
827 val = tw_readbyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
828 TW_AUDIO_OUTPUT_VOL_ADDR);
829
830 u_val = (val & 0x0f) | (u_val << 4);
831
832 tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_OUTPUT_VOL_ADDR,
833 TW_AUDIO_OUTPUT_VOL_ADDR, u_val);
834}
835#endif
836
837u8 tw28_get_audio_gain(struct solo_dev *solo_dev, u8 ch)
838{
839 u8 val;
840 u8 chip_num;
841
842
843 chip_num = ch / 4;
844 ch %= 4;
845
846 val = tw_readbyte(solo_dev, chip_num,
847 TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
848 TW_AUDIO_INPUT_GAIN_ADDR(ch));
849
850 return (ch % 2) ? (val >> 4) : (val & 0x0f);
851}
852
853void tw28_set_audio_gain(struct solo_dev *solo_dev, u8 ch, u8 val)
854{
855 u8 old_val;
856 u8 chip_num;
857
858
859 chip_num = ch / 4;
860 ch %= 4;
861
862 old_val = tw_readbyte(solo_dev, chip_num,
863 TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
864 TW_AUDIO_INPUT_GAIN_ADDR(ch));
865
866 val = (old_val & ((ch % 2) ? 0x0f : 0xf0)) |
867 ((ch % 2) ? (val << 4) : val);
868
869 tw_writebyte(solo_dev, chip_num, TW286x_AUDIO_INPUT_GAIN_ADDR(ch),
870 TW_AUDIO_INPUT_GAIN_ADDR(ch), val);
871}
872