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