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