diff options
Diffstat (limited to 'drivers/media/video/stradis.c')
-rw-r--r-- | drivers/media/video/stradis.c | 2258 |
1 files changed, 2258 insertions, 0 deletions
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c new file mode 100644 index 000000000000..b57743571087 --- /dev/null +++ b/drivers/media/video/stradis.c | |||
@@ -0,0 +1,2258 @@ | |||
1 | /* | ||
2 | * stradis.c - stradis 4:2:2 mpeg decoder driver | ||
3 | * | ||
4 | * Stradis 4:2:2 MPEG-2 Decoder Driver | ||
5 | * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/poll.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/signal.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <asm/pgtable.h> | ||
37 | #include <asm/page.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <asm/types.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | #include <linux/vmalloc.h> | ||
44 | #include <linux/videodev.h> | ||
45 | |||
46 | #include "saa7146.h" | ||
47 | #include "saa7146reg.h" | ||
48 | #include "ibmmpeg2.h" | ||
49 | #include "saa7121.h" | ||
50 | #include "cs8420.h" | ||
51 | |||
52 | #define DEBUG(x) /* debug driver */ | ||
53 | #undef IDEBUG /* debug irq handler */ | ||
54 | #undef MDEBUG /* debug memory management */ | ||
55 | |||
56 | #define SAA7146_MAX 6 | ||
57 | |||
58 | static struct saa7146 saa7146s[SAA7146_MAX]; | ||
59 | |||
60 | static int saa_num = 0; /* number of SAA7146s in use */ | ||
61 | |||
62 | static int video_nr = -1; | ||
63 | module_param(video_nr, int, 0); | ||
64 | MODULE_LICENSE("GPL"); | ||
65 | |||
66 | |||
67 | #define nDebNormal 0x00480000 | ||
68 | #define nDebNoInc 0x00480000 | ||
69 | #define nDebVideo 0xd0480000 | ||
70 | #define nDebAudio 0xd0400000 | ||
71 | #define nDebDMA 0x02c80000 | ||
72 | |||
73 | #define oDebNormal 0x13c80000 | ||
74 | #define oDebNoInc 0x13c80000 | ||
75 | #define oDebVideo 0xd1080000 | ||
76 | #define oDebAudio 0xd1080000 | ||
77 | #define oDebDMA 0x03080000 | ||
78 | |||
79 | #define NewCard (saa->boardcfg[3]) | ||
80 | #define ChipControl (saa->boardcfg[1]) | ||
81 | #define NTSCFirstActive (saa->boardcfg[4]) | ||
82 | #define PALFirstActive (saa->boardcfg[5]) | ||
83 | #define NTSCLastActive (saa->boardcfg[54]) | ||
84 | #define PALLastActive (saa->boardcfg[55]) | ||
85 | #define Have2MB (saa->boardcfg[18] & 0x40) | ||
86 | #define HaveCS8420 (saa->boardcfg[18] & 0x04) | ||
87 | #define IBMMPEGCD20 (saa->boardcfg[18] & 0x20) | ||
88 | #define HaveCS3310 (saa->boardcfg[18] & 0x01) | ||
89 | #define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31]) | ||
90 | #define HaveCS4341 (saa->boardcfg[40] == 2) | ||
91 | #define SDIType (saa->boardcfg[27]) | ||
92 | #define CurrentMode (saa->boardcfg[2]) | ||
93 | |||
94 | #define debNormal (NewCard ? nDebNormal : oDebNormal) | ||
95 | #define debNoInc (NewCard ? nDebNoInc : oDebNoInc) | ||
96 | #define debVideo (NewCard ? nDebVideo : oDebVideo) | ||
97 | #define debAudio (NewCard ? nDebAudio : oDebAudio) | ||
98 | #define debDMA (NewCard ? nDebDMA : oDebDMA) | ||
99 | |||
100 | #ifdef USE_RESCUE_EEPROM_SDM275 | ||
101 | static unsigned char rescue_eeprom[64] = { | ||
102 | 0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
103 | }; | ||
104 | #endif | ||
105 | |||
106 | /* ----------------------------------------------------------------------- */ | ||
107 | /* Hardware I2C functions */ | ||
108 | static void I2CWipe(struct saa7146 *saa) | ||
109 | { | ||
110 | int i; | ||
111 | /* set i2c to ~=100kHz, abort transfer, clear busy */ | ||
112 | saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); | ||
113 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | | ||
114 | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); | ||
115 | /* wait for i2c registers to be programmed */ | ||
116 | for (i = 0; i < 1000 && | ||
117 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) | ||
118 | schedule(); | ||
119 | saawrite(0x600, SAA7146_I2C_STATUS); | ||
120 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | | ||
121 | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); | ||
122 | /* wait for i2c registers to be programmed */ | ||
123 | for (i = 0; i < 1000 && | ||
124 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) | ||
125 | schedule(); | ||
126 | saawrite(0x600, SAA7146_I2C_STATUS); | ||
127 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | | ||
128 | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); | ||
129 | /* wait for i2c registers to be programmed */ | ||
130 | for (i = 0; i < 1000 && | ||
131 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) | ||
132 | schedule(); | ||
133 | } | ||
134 | |||
135 | /* read I2C */ | ||
136 | static int I2CRead(struct saa7146 *saa, unsigned char addr, | ||
137 | unsigned char subaddr, int dosub) | ||
138 | { | ||
139 | int i; | ||
140 | |||
141 | if (saaread(SAA7146_I2C_STATUS) & 0x3c) | ||
142 | I2CWipe(saa); | ||
143 | for (i = 0; i < 1000 && | ||
144 | (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) | ||
145 | schedule(); | ||
146 | if (i == 1000) | ||
147 | I2CWipe(saa); | ||
148 | if (dosub) | ||
149 | saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) | | ||
150 | ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER); | ||
151 | else | ||
152 | saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | | ||
153 | 0xf1, SAA7146_I2C_TRANSFER); | ||
154 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | | ||
155 | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); | ||
156 | /* wait for i2c registers to be programmed */ | ||
157 | for (i = 0; i < 1000 && | ||
158 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) | ||
159 | schedule(); | ||
160 | /* wait for valid data */ | ||
161 | for (i = 0; i < 1000 && | ||
162 | (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) | ||
163 | schedule(); | ||
164 | if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) | ||
165 | return -1; | ||
166 | if (i == 1000) | ||
167 | printk("i2c setup read timeout\n"); | ||
168 | saawrite(0x41, SAA7146_I2C_TRANSFER); | ||
169 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | | ||
170 | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); | ||
171 | /* wait for i2c registers to be programmed */ | ||
172 | for (i = 0; i < 1000 && | ||
173 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) | ||
174 | schedule(); | ||
175 | /* wait for valid data */ | ||
176 | for (i = 0; i < 1000 && | ||
177 | (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) | ||
178 | schedule(); | ||
179 | if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) | ||
180 | return -1; | ||
181 | if (i == 1000) | ||
182 | printk("i2c read timeout\n"); | ||
183 | return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff); | ||
184 | } | ||
185 | |||
186 | /* set both to write both bytes, reset it to write only b1 */ | ||
187 | |||
188 | static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1, | ||
189 | unsigned char b2, int both) | ||
190 | { | ||
191 | int i; | ||
192 | u32 data; | ||
193 | |||
194 | if (saaread(SAA7146_I2C_STATUS) & 0x3c) | ||
195 | I2CWipe(saa); | ||
196 | for (i = 0; i < 1000 && | ||
197 | (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) | ||
198 | schedule(); | ||
199 | if (i == 1000) | ||
200 | I2CWipe(saa); | ||
201 | data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); | ||
202 | if (both) | ||
203 | data |= ((b2 & 0xff) << 8) | 0xe5; | ||
204 | else | ||
205 | data |= 0xd1; | ||
206 | saawrite(data, SAA7146_I2C_TRANSFER); | ||
207 | saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, | ||
208 | SAA7146_MC2); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void attach_inform(struct saa7146 *saa, int id) | ||
213 | { | ||
214 | int i; | ||
215 | |||
216 | DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id)); | ||
217 | if (id == 0xa0) { /* we have rev2 or later board, fill in info */ | ||
218 | for (i = 0; i < 64; i++) | ||
219 | saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1); | ||
220 | #ifdef USE_RESCUE_EEPROM_SDM275 | ||
221 | if (saa->boardcfg[0] != 0) { | ||
222 | printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr); | ||
223 | for (i = 0; i < 64; i++) | ||
224 | saa->boardcfg[i] = rescue_eeprom[i]; | ||
225 | } | ||
226 | #endif | ||
227 | printk("stradis%d: config =", saa->nr); | ||
228 | for (i = 0; i < 51; i++) { | ||
229 | printk(" %02x",saa->boardcfg[i]); | ||
230 | } | ||
231 | printk("\n"); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | static void I2CBusScan(struct saa7146 *saa) | ||
236 | { | ||
237 | int i; | ||
238 | for (i = 0; i < 0xff; i += 2) | ||
239 | if ((I2CRead(saa, i, 0, 0)) >= 0) | ||
240 | attach_inform(saa, i); | ||
241 | } | ||
242 | |||
243 | static int debiwait_maxwait = 0; | ||
244 | |||
245 | static int wait_for_debi_done(struct saa7146 *saa) | ||
246 | { | ||
247 | int i; | ||
248 | |||
249 | /* wait for registers to be programmed */ | ||
250 | for (i = 0; i < 100000 && | ||
251 | !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) | ||
252 | saaread(SAA7146_MC2); | ||
253 | /* wait for transfer to complete */ | ||
254 | for (i = 0; i < 500000 && | ||
255 | (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++) | ||
256 | saaread(SAA7146_MC2); | ||
257 | if (i > debiwait_maxwait) | ||
258 | printk("wait-for-debi-done maxwait: %d\n", | ||
259 | debiwait_maxwait = i); | ||
260 | |||
261 | if (i == 500000) | ||
262 | return -1; | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int debiwrite(struct saa7146 *saa, u32 config, int addr, | ||
267 | u32 val, int count) | ||
268 | { | ||
269 | u32 cmd; | ||
270 | if (count <= 0 || count > 32764) | ||
271 | return -1; | ||
272 | if (wait_for_debi_done(saa) < 0) | ||
273 | return -1; | ||
274 | saawrite(config, SAA7146_DEBI_CONFIG); | ||
275 | if (count <= 4) /* immediate transfer */ | ||
276 | saawrite(val, SAA7146_DEBI_AD); | ||
277 | else /* block transfer */ | ||
278 | saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); | ||
279 | saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); | ||
280 | saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, | ||
281 | SAA7146_MC2); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count) | ||
286 | { | ||
287 | u32 result = 0; | ||
288 | |||
289 | if (count > 32764 || count <= 0) | ||
290 | return 0; | ||
291 | if (wait_for_debi_done(saa) < 0) | ||
292 | return 0; | ||
293 | saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); | ||
294 | saawrite((count << 17) | 0x10000 | (addr & 0xffff), | ||
295 | SAA7146_DEBI_COMMAND); | ||
296 | saawrite(config, SAA7146_DEBI_CONFIG); | ||
297 | saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, | ||
298 | SAA7146_MC2); | ||
299 | if (count > 4) /* not an immediate transfer */ | ||
300 | return count; | ||
301 | wait_for_debi_done(saa); | ||
302 | result = saaread(SAA7146_DEBI_AD); | ||
303 | if (count == 1) | ||
304 | result &= 0xff; | ||
305 | if (count == 2) | ||
306 | result &= 0xffff; | ||
307 | if (count == 3) | ||
308 | result &= 0xffffff; | ||
309 | return result; | ||
310 | } | ||
311 | |||
312 | #if 0 /* unused */ | ||
313 | /* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */ | ||
314 | /* data copied into saa->dmadebi buffer, caller must re-enable interrupts */ | ||
315 | static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes) | ||
316 | { | ||
317 | int i, j; | ||
318 | u32 *buf; | ||
319 | buf = (u32 *) saa->dmadebi; | ||
320 | if (bytes > 0x7000) | ||
321 | bytes = 0x7000; | ||
322 | saawrite(0, SAA7146_IER); /* disable interrupts */ | ||
323 | for (i=0; i < 10000 && | ||
324 | (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) | ||
325 | & 0x8000); i++) | ||
326 | saaread(SAA7146_MC2); | ||
327 | if (i == 10000) | ||
328 | printk(KERN_ERR "stradis%d: dram_busy never cleared\n", | ||
329 | saa->nr); | ||
330 | debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) | | ||
331 | (address>>16), 4); | ||
332 | debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2); | ||
333 | debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2); | ||
334 | for (j = 0; j < bytes/4; j++) { | ||
335 | for (i = 0; i < 10000 && | ||
336 | (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) | ||
337 | & 0x4000)); i++) | ||
338 | saaread(SAA7146_MC2); | ||
339 | if (i == 10000) | ||
340 | printk(KERN_ERR "stradis%d: dram_ready never set\n", | ||
341 | saa->nr); | ||
342 | buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4); | ||
343 | } | ||
344 | } | ||
345 | #endif /* unused */ | ||
346 | |||
347 | static void do_irq_send_data(struct saa7146 *saa) | ||
348 | { | ||
349 | int split, audbytes, vidbytes; | ||
350 | |||
351 | saawrite(SAA7146_PSR_PIN1, SAA7146_IER); | ||
352 | /* if special feature mode in effect, disable audio sending */ | ||
353 | if (saa->playmode != VID_PLAY_NORMAL) | ||
354 | saa->audtail = saa->audhead = 0; | ||
355 | if (saa->audhead <= saa->audtail) | ||
356 | audbytes = saa->audtail - saa->audhead; | ||
357 | else | ||
358 | audbytes = 65536 - (saa->audhead - saa->audtail); | ||
359 | if (saa->vidhead <= saa->vidtail) | ||
360 | vidbytes = saa->vidtail - saa->vidhead; | ||
361 | else | ||
362 | vidbytes = 524288 - (saa->vidhead - saa->vidtail); | ||
363 | if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { | ||
364 | saawrite(0, SAA7146_IER); | ||
365 | return; | ||
366 | } | ||
367 | /* if at least 1 block audio waiting and audio fifo isn't full */ | ||
368 | if (audbytes >= 2048 && (debiread(saa, debNormal, | ||
369 | IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) { | ||
370 | if (saa->audhead > saa->audtail) | ||
371 | split = 65536 - saa->audhead; | ||
372 | else | ||
373 | split = 0; | ||
374 | audbytes = 2048; | ||
375 | if (split > 0 && split < 2048) { | ||
376 | memcpy(saa->dmadebi, saa->audbuf + saa->audhead, | ||
377 | split); | ||
378 | saa->audhead = 0; | ||
379 | audbytes -= split; | ||
380 | } else | ||
381 | split = 0; | ||
382 | memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, | ||
383 | audbytes); | ||
384 | saa->audhead += audbytes; | ||
385 | saa->audhead &= 0xffff; | ||
386 | debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO : | ||
387 | IBM_MP2_AUD_FIFOW), 0, 2048); | ||
388 | wake_up_interruptible(&saa->audq); | ||
389 | /* if at least 1 block video waiting and video fifo isn't full */ | ||
390 | } else if (vidbytes >= 30720 && (debiread(saa, debNormal, | ||
391 | IBM_MP2_FIFO, 2)) < 16384) { | ||
392 | if (saa->vidhead > saa->vidtail) | ||
393 | split = 524288 - saa->vidhead; | ||
394 | else | ||
395 | split = 0; | ||
396 | vidbytes = 30720; | ||
397 | if (split > 0 && split < 30720) { | ||
398 | memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, | ||
399 | split); | ||
400 | saa->vidhead = 0; | ||
401 | vidbytes -= split; | ||
402 | } else | ||
403 | split = 0; | ||
404 | memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead, | ||
405 | vidbytes); | ||
406 | saa->vidhead += vidbytes; | ||
407 | saa->vidhead &= 0x7ffff; | ||
408 | debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO : | ||
409 | IBM_MP2_FIFOW), 0, 30720); | ||
410 | wake_up_interruptible(&saa->vidq); | ||
411 | } | ||
412 | saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); | ||
413 | } | ||
414 | |||
415 | static void send_osd_data(struct saa7146 *saa) | ||
416 | { | ||
417 | int size = saa->osdtail - saa->osdhead; | ||
418 | if (size > 30720) | ||
419 | size = 30720; | ||
420 | /* ensure some multiple of 8 bytes is transferred */ | ||
421 | size = 8 * ((size + 8)>>3); | ||
422 | if (size) { | ||
423 | debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, | ||
424 | (saa->osdhead>>3), 2); | ||
425 | memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size); | ||
426 | saa->osdhead += size; | ||
427 | /* block transfer of next 8 bytes to ~32k bytes */ | ||
428 | debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size); | ||
429 | } | ||
430 | if (saa->osdhead >= saa->osdtail) { | ||
431 | saa->osdhead = saa->osdtail = 0; | ||
432 | debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
437 | { | ||
438 | struct saa7146 *saa = (struct saa7146 *) dev_id; | ||
439 | u32 stat, astat; | ||
440 | int count; | ||
441 | int handled = 0; | ||
442 | |||
443 | count = 0; | ||
444 | while (1) { | ||
445 | /* get/clear interrupt status bits */ | ||
446 | stat = saaread(SAA7146_ISR); | ||
447 | astat = stat & saaread(SAA7146_IER); | ||
448 | if (!astat) | ||
449 | break; | ||
450 | handled = 1; | ||
451 | saawrite(astat, SAA7146_ISR); | ||
452 | if (astat & SAA7146_PSR_DEBI_S) { | ||
453 | do_irq_send_data(saa); | ||
454 | } | ||
455 | if (astat & SAA7146_PSR_PIN1) { | ||
456 | int istat; | ||
457 | /* the following read will trigger DEBI_S */ | ||
458 | istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); | ||
459 | if (istat & 1) { | ||
460 | saawrite(0, SAA7146_IER); | ||
461 | send_osd_data(saa); | ||
462 | saawrite(SAA7146_PSR_DEBI_S | | ||
463 | SAA7146_PSR_PIN1, SAA7146_IER); | ||
464 | } | ||
465 | if (istat & 0x20) { /* Video Start */ | ||
466 | saa->vidinfo.frame_count++; | ||
467 | } | ||
468 | if (istat & 0x400) { /* Picture Start */ | ||
469 | /* update temporal reference */ | ||
470 | } | ||
471 | if (istat & 0x200) { /* Picture Resolution Change */ | ||
472 | /* read new resolution */ | ||
473 | } | ||
474 | if (istat & 0x100) { /* New User Data found */ | ||
475 | /* read new user data */ | ||
476 | } | ||
477 | if (istat & 0x1000) { /* new GOP/SMPTE */ | ||
478 | /* read new SMPTE */ | ||
479 | } | ||
480 | if (istat & 0x8000) { /* Sequence Start Code */ | ||
481 | /* reset frame counter, load sizes */ | ||
482 | saa->vidinfo.frame_count = 0; | ||
483 | saa->vidinfo.h_size = 704; | ||
484 | saa->vidinfo.v_size = 480; | ||
485 | #if 0 | ||
486 | if (saa->endmarkhead != saa->endmarktail) { | ||
487 | saa->audhead = | ||
488 | saa->endmark[saa->endmarkhead]; | ||
489 | saa->endmarkhead++; | ||
490 | if (saa->endmarkhead >= MAX_MARKS) | ||
491 | saa->endmarkhead = 0; | ||
492 | } | ||
493 | #endif | ||
494 | } | ||
495 | if (istat & 0x4000) { /* Sequence Error Code */ | ||
496 | if (saa->endmarkhead != saa->endmarktail) { | ||
497 | saa->audhead = | ||
498 | saa->endmark[saa->endmarkhead]; | ||
499 | saa->endmarkhead++; | ||
500 | if (saa->endmarkhead >= MAX_MARKS) | ||
501 | saa->endmarkhead = 0; | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | #ifdef IDEBUG | ||
506 | if (astat & SAA7146_PSR_PPEF) { | ||
507 | IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr)); | ||
508 | } | ||
509 | if (astat & SAA7146_PSR_PABO) { | ||
510 | IDEBUG(printk("stradis%d irq: PABO\n", saa->nr)); | ||
511 | } | ||
512 | if (astat & SAA7146_PSR_PPED) { | ||
513 | IDEBUG(printk("stradis%d irq: PPED\n", saa->nr)); | ||
514 | } | ||
515 | if (astat & SAA7146_PSR_RPS_I1) { | ||
516 | IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr)); | ||
517 | } | ||
518 | if (astat & SAA7146_PSR_RPS_I0) { | ||
519 | IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr)); | ||
520 | } | ||
521 | if (astat & SAA7146_PSR_RPS_LATE1) { | ||
522 | IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr)); | ||
523 | } | ||
524 | if (astat & SAA7146_PSR_RPS_LATE0) { | ||
525 | IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr)); | ||
526 | } | ||
527 | if (astat & SAA7146_PSR_RPS_E1) { | ||
528 | IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr)); | ||
529 | } | ||
530 | if (astat & SAA7146_PSR_RPS_E0) { | ||
531 | IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr)); | ||
532 | } | ||
533 | if (astat & SAA7146_PSR_RPS_TO1) { | ||
534 | IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr)); | ||
535 | } | ||
536 | if (astat & SAA7146_PSR_RPS_TO0) { | ||
537 | IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr)); | ||
538 | } | ||
539 | if (astat & SAA7146_PSR_UPLD) { | ||
540 | IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr)); | ||
541 | } | ||
542 | if (astat & SAA7146_PSR_DEBI_E) { | ||
543 | IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr)); | ||
544 | } | ||
545 | if (astat & SAA7146_PSR_I2C_S) { | ||
546 | IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr)); | ||
547 | } | ||
548 | if (astat & SAA7146_PSR_I2C_E) { | ||
549 | IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr)); | ||
550 | } | ||
551 | if (astat & SAA7146_PSR_A2_IN) { | ||
552 | IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr)); | ||
553 | } | ||
554 | if (astat & SAA7146_PSR_A2_OUT) { | ||
555 | IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr)); | ||
556 | } | ||
557 | if (astat & SAA7146_PSR_A1_IN) { | ||
558 | IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr)); | ||
559 | } | ||
560 | if (astat & SAA7146_PSR_A1_OUT) { | ||
561 | IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr)); | ||
562 | } | ||
563 | if (astat & SAA7146_PSR_AFOU) { | ||
564 | IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr)); | ||
565 | } | ||
566 | if (astat & SAA7146_PSR_V_PE) { | ||
567 | IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr)); | ||
568 | } | ||
569 | if (astat & SAA7146_PSR_VFOU) { | ||
570 | IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr)); | ||
571 | } | ||
572 | if (astat & SAA7146_PSR_FIDA) { | ||
573 | IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr)); | ||
574 | } | ||
575 | if (astat & SAA7146_PSR_FIDB) { | ||
576 | IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr)); | ||
577 | } | ||
578 | if (astat & SAA7146_PSR_PIN3) { | ||
579 | IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr)); | ||
580 | } | ||
581 | if (astat & SAA7146_PSR_PIN2) { | ||
582 | IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr)); | ||
583 | } | ||
584 | if (astat & SAA7146_PSR_PIN0) { | ||
585 | IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr)); | ||
586 | } | ||
587 | if (astat & SAA7146_PSR_ECS) { | ||
588 | IDEBUG(printk("stradis%d irq: ECS\n", saa->nr)); | ||
589 | } | ||
590 | if (astat & SAA7146_PSR_EC3S) { | ||
591 | IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr)); | ||
592 | } | ||
593 | if (astat & SAA7146_PSR_EC0S) { | ||
594 | IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr)); | ||
595 | } | ||
596 | #endif | ||
597 | count++; | ||
598 | if (count > 15) | ||
599 | printk(KERN_WARNING "stradis%d: irq loop %d\n", | ||
600 | saa->nr, count); | ||
601 | if (count > 20) { | ||
602 | saawrite(0, SAA7146_IER); | ||
603 | printk(KERN_ERR | ||
604 | "stradis%d: IRQ loop cleared\n", saa->nr); | ||
605 | } | ||
606 | } | ||
607 | return IRQ_RETVAL(handled); | ||
608 | } | ||
609 | |||
610 | static int ibm_send_command(struct saa7146 *saa, | ||
611 | int command, int data, int chain) | ||
612 | { | ||
613 | int i; | ||
614 | |||
615 | if (chain) | ||
616 | debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2); | ||
617 | else | ||
618 | debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2); | ||
619 | debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2); | ||
620 | debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2); | ||
621 | for (i = 0; i < 100 && | ||
622 | (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++) | ||
623 | schedule(); | ||
624 | if (i == 100) | ||
625 | return -1; | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static void cs4341_setlevel(struct saa7146 *saa, int left, int right) | ||
630 | { | ||
631 | I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2); | ||
632 | I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2); | ||
633 | } | ||
634 | |||
635 | static void initialize_cs4341(struct saa7146 *saa) | ||
636 | { | ||
637 | int i; | ||
638 | for (i = 0; i < 200; i++) { | ||
639 | /* auto mute off, power on, no de-emphasis */ | ||
640 | /* I2S data up to 24-bit 64xFs internal SCLK */ | ||
641 | I2CWrite(saa, 0x22, 0x01, 0x11, 2); | ||
642 | /* ATAPI mixer settings */ | ||
643 | I2CWrite(saa, 0x22, 0x02, 0x49, 2); | ||
644 | /* attenuation left 3db */ | ||
645 | I2CWrite(saa, 0x22, 0x03, 0x00, 2); | ||
646 | /* attenuation right 3db */ | ||
647 | I2CWrite(saa, 0x22, 0x04, 0x00, 2); | ||
648 | I2CWrite(saa, 0x22, 0x01, 0x10, 2); | ||
649 | if (I2CRead(saa, 0x22, 0x02, 1) == 0x49) | ||
650 | break; | ||
651 | schedule(); | ||
652 | } | ||
653 | printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i); | ||
654 | return; | ||
655 | } | ||
656 | |||
657 | static void initialize_cs8420(struct saa7146 *saa, int pro) | ||
658 | { | ||
659 | int i; | ||
660 | u8 *sequence; | ||
661 | if (pro) | ||
662 | sequence = mode8420pro; | ||
663 | else | ||
664 | sequence = mode8420con; | ||
665 | for (i = 0; i < INIT8420LEN; i++) | ||
666 | I2CWrite(saa, 0x20, init8420[i * 2], | ||
667 | init8420[i * 2 + 1], 2); | ||
668 | for (i = 0; i < MODE8420LEN; i++) | ||
669 | I2CWrite(saa, 0x20, sequence[i * 2], | ||
670 | sequence[i * 2 + 1], 2); | ||
671 | printk("stradis%d: CS8420 initialized\n", saa->nr); | ||
672 | } | ||
673 | |||
674 | static void initialize_saa7121(struct saa7146 *saa, int dopal) | ||
675 | { | ||
676 | int i, mod; | ||
677 | u8 *sequence; | ||
678 | if (dopal) | ||
679 | sequence = init7121pal; | ||
680 | else | ||
681 | sequence = init7121ntsc; | ||
682 | mod = saaread(SAA7146_PSR) & 0x08; | ||
683 | /* initialize PAL/NTSC video encoder */ | ||
684 | for (i = 0; i < INIT7121LEN; i++) { | ||
685 | if (NewCard) { /* handle new card encoder differences */ | ||
686 | if (sequence[i*2] == 0x3a) | ||
687 | I2CWrite(saa, 0x88, 0x3a, 0x13, 2); | ||
688 | else if (sequence[i*2] == 0x6b) | ||
689 | I2CWrite(saa, 0x88, 0x6b, 0x20, 2); | ||
690 | else if (sequence[i*2] == 0x6c) | ||
691 | I2CWrite(saa, 0x88, 0x6c, | ||
692 | dopal ? 0x09 : 0xf5, 2); | ||
693 | else if (sequence[i*2] == 0x6d) | ||
694 | I2CWrite(saa, 0x88, 0x6d, | ||
695 | dopal ? 0x20 : 0x00, 2); | ||
696 | else if (sequence[i*2] == 0x7a) | ||
697 | I2CWrite(saa, 0x88, 0x7a, | ||
698 | dopal ? (PALFirstActive - 1) : | ||
699 | (NTSCFirstActive - 4), 2); | ||
700 | else if (sequence[i*2] == 0x7b) | ||
701 | I2CWrite(saa, 0x88, 0x7b, | ||
702 | dopal ? PALLastActive : | ||
703 | NTSCLastActive, 2); | ||
704 | else I2CWrite(saa, 0x88, sequence[i * 2], | ||
705 | sequence[i * 2 + 1], 2); | ||
706 | } else { | ||
707 | if (sequence[i*2] == 0x6b && mod) | ||
708 | I2CWrite(saa, 0x88, 0x6b, | ||
709 | (sequence[i * 2 + 1] ^ 0x09), 2); | ||
710 | else if (sequence[i*2] == 0x7a) | ||
711 | I2CWrite(saa, 0x88, 0x7a, | ||
712 | dopal ? (PALFirstActive - 1) : | ||
713 | (NTSCFirstActive - 4), 2); | ||
714 | else if (sequence[i*2] == 0x7b) | ||
715 | I2CWrite(saa, 0x88, 0x7b, | ||
716 | dopal ? PALLastActive : | ||
717 | NTSCLastActive, 2); | ||
718 | else | ||
719 | I2CWrite(saa, 0x88, sequence[i * 2], | ||
720 | sequence[i * 2 + 1], 2); | ||
721 | } | ||
722 | } | ||
723 | } | ||
724 | |||
725 | static void set_genlock_offset(struct saa7146 *saa, int noffset) | ||
726 | { | ||
727 | int nCode; | ||
728 | int PixelsPerLine = 858; | ||
729 | if (CurrentMode == VIDEO_MODE_PAL) | ||
730 | PixelsPerLine = 864; | ||
731 | if (noffset > 500) | ||
732 | noffset = 500; | ||
733 | else if (noffset < -500) | ||
734 | noffset = -500; | ||
735 | nCode = noffset + 0x100; | ||
736 | if (nCode == 1) | ||
737 | nCode = 0x401; | ||
738 | else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode; | ||
739 | debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2); | ||
740 | } | ||
741 | |||
742 | static void set_out_format(struct saa7146 *saa, int mode) | ||
743 | { | ||
744 | initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1)); | ||
745 | saa->boardcfg[2] = mode; | ||
746 | /* do not adjust analog video parameters here, use saa7121 init */ | ||
747 | /* you will affect the SDI output on the new card */ | ||
748 | if (mode == VIDEO_MODE_PAL) { /* PAL */ | ||
749 | debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2); | ||
750 | mdelay(50); | ||
751 | saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1); | ||
752 | if (NewCard) { | ||
753 | debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, | ||
754 | 0xe100, 2); | ||
755 | mdelay(50); | ||
756 | } | ||
757 | debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, | ||
758 | NewCard ? 0xe500: 0x6500, 2); | ||
759 | debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, | ||
760 | (1 << 8) | | ||
761 | (NewCard ? PALFirstActive : PALFirstActive-6), 2); | ||
762 | } else { /* NTSC */ | ||
763 | debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2); | ||
764 | mdelay(50); | ||
765 | saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1); | ||
766 | debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, | ||
767 | NewCard ? 0xe100: 0x6100, 2); | ||
768 | debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, | ||
769 | (1 << 8) | | ||
770 | (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2); | ||
771 | } | ||
772 | } | ||
773 | |||
774 | |||
775 | /* Intialize bitmangler to map from a byte value to the mangled word that | ||
776 | * must be output to program the Xilinx part through the DEBI port. | ||
777 | * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0 | ||
778 | * transfer FPGA code, init IBM chip, transfer IBM microcode | ||
779 | * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0 | ||
780 | */ | ||
781 | static u16 bitmangler[256]; | ||
782 | |||
783 | static int initialize_fpga(struct video_code *bitdata) | ||
784 | { | ||
785 | int i, num, startindex, failure = 0, loadtwo, loadfile = 0; | ||
786 | u16 *dmabuf; | ||
787 | u8 *newdma; | ||
788 | struct saa7146 *saa; | ||
789 | |||
790 | /* verify fpga code */ | ||
791 | for (startindex = 0; startindex < bitdata->datasize; startindex++) | ||
792 | if (bitdata->data[startindex] == 255) | ||
793 | break; | ||
794 | if (startindex == bitdata->datasize) { | ||
795 | printk(KERN_INFO "stradis: bad fpga code\n"); | ||
796 | return -1; | ||
797 | } | ||
798 | /* initialize all detected cards */ | ||
799 | for (num = 0; num < saa_num; num++) { | ||
800 | saa = &saa7146s[num]; | ||
801 | if (saa->boardcfg[0] > 20) | ||
802 | continue; /* card was programmed */ | ||
803 | loadtwo = (saa->boardcfg[18] & 0x10); | ||
804 | if (!NewCard) /* we have an old board */ | ||
805 | for (i = 0; i < 256; i++) | ||
806 | bitmangler[i] = ((i & 0x01) << 15) | | ||
807 | ((i & 0x02) << 6) | ((i & 0x04) << 4) | | ||
808 | ((i & 0x08) << 9) | ((i & 0x10) << 7) | | ||
809 | ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | | ||
810 | ((i & 0x80) >> 7); | ||
811 | else /* else we have a new board */ | ||
812 | for (i = 0; i < 256; i++) | ||
813 | bitmangler[i] = ((i & 0x01) << 7) | | ||
814 | ((i & 0x02) << 5) | ((i & 0x04) << 3) | | ||
815 | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | | ||
816 | ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | | ||
817 | ((i & 0x80) >> 7); | ||
818 | |||
819 | dmabuf = (u16 *) saa->dmadebi; | ||
820 | newdma = (u8 *) saa->dmadebi; | ||
821 | if (NewCard) { /* SDM2xxx */ | ||
822 | if (!strncmp(bitdata->loadwhat, "decoder2", 8)) | ||
823 | continue; /* fpga not for this card */ | ||
824 | if (!strncmp(&saa->boardcfg[42], | ||
825 | bitdata->loadwhat, 8)) { | ||
826 | loadfile = 1; | ||
827 | } else if (loadtwo && !strncmp(&saa->boardcfg[19], | ||
828 | bitdata->loadwhat, 8)) { | ||
829 | loadfile = 2; | ||
830 | } else if (!saa->boardcfg[42] && /* special */ | ||
831 | !strncmp("decxl", bitdata->loadwhat, 8)) { | ||
832 | loadfile = 1; | ||
833 | } else | ||
834 | continue; /* fpga not for this card */ | ||
835 | if (loadfile != 1 && loadfile != 2) { | ||
836 | continue; /* skip to next card */ | ||
837 | } | ||
838 | if (saa->boardcfg[0] && loadfile == 1 ) | ||
839 | continue; /* skip to next card */ | ||
840 | if (saa->boardcfg[0] != 1 && loadfile == 2) | ||
841 | continue; /* skip to next card */ | ||
842 | saa->boardcfg[0]++; /* mark fpga handled */ | ||
843 | printk("stradis%d: loading %s\n", saa->nr, | ||
844 | bitdata->loadwhat); | ||
845 | if (loadtwo && loadfile == 2) | ||
846 | goto send_fpga_stuff; | ||
847 | /* turn on the Audio interface to set PROG low */ | ||
848 | saawrite(0x00400040, SAA7146_GPIO_CTRL); | ||
849 | saaread(SAA7146_PSR); /* ensure posted write */ | ||
850 | /* wait for everyone to reset */ | ||
851 | mdelay(10); | ||
852 | saawrite(0x00400000, SAA7146_GPIO_CTRL); | ||
853 | } else { /* original card */ | ||
854 | if (strncmp(bitdata->loadwhat, "decoder2", 8)) | ||
855 | continue; /* fpga not for this card */ | ||
856 | /* Pull the Xilinx PROG signal WS3 low */ | ||
857 | saawrite(0x02000200, SAA7146_MC1); | ||
858 | /* Turn on the Audio interface so can set PROG low */ | ||
859 | saawrite(0x000000c0, SAA7146_ACON1); | ||
860 | /* Pull the Xilinx INIT signal (GPIO2) low */ | ||
861 | saawrite(0x00400000, SAA7146_GPIO_CTRL); | ||
862 | /* Make sure everybody resets */ | ||
863 | saaread(SAA7146_PSR); /* ensure posted write */ | ||
864 | mdelay(10); | ||
865 | /* Release the Xilinx PROG signal */ | ||
866 | saawrite(0x00000000, SAA7146_ACON1); | ||
867 | /* Turn off the Audio interface */ | ||
868 | saawrite(0x02000000, SAA7146_MC1); | ||
869 | } | ||
870 | /* Release Xilinx INIT signal (WS2) */ | ||
871 | saawrite(0x00000000, SAA7146_GPIO_CTRL); | ||
872 | /* Wait for the INIT to go High */ | ||
873 | for (i = 0; i < 10000 && | ||
874 | !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) | ||
875 | schedule(); | ||
876 | if (i == 1000) { | ||
877 | printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr); | ||
878 | return -1; | ||
879 | } | ||
880 | send_fpga_stuff: | ||
881 | if (NewCard) { | ||
882 | for (i = startindex; i < bitdata->datasize; i++) | ||
883 | newdma[i - startindex] = | ||
884 | bitmangler[bitdata->data[i]]; | ||
885 | debiwrite(saa, 0x01420000, 0, 0, | ||
886 | ((bitdata->datasize - startindex) + 5)); | ||
887 | if (loadtwo) { | ||
888 | if (loadfile == 1) { | ||
889 | printk("stradis%d: " | ||
890 | "awaiting 2nd FPGA bitfile\n", | ||
891 | saa->nr); | ||
892 | continue; /* skip to next card */ | ||
893 | } | ||
894 | |||
895 | } | ||
896 | } else { | ||
897 | for (i = startindex; i < bitdata->datasize; i++) | ||
898 | dmabuf[i - startindex] = | ||
899 | bitmangler[bitdata->data[i]]; | ||
900 | debiwrite(saa, 0x014a0000, 0, 0, | ||
901 | ((bitdata->datasize - startindex) + 5) * 2); | ||
902 | } | ||
903 | for (i = 0; i < 1000 && | ||
904 | !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) | ||
905 | schedule(); | ||
906 | if (i == 1000) { | ||
907 | printk(KERN_INFO "stradis%d: FPGA load failed\n", | ||
908 | saa->nr); | ||
909 | failure++; | ||
910 | continue; | ||
911 | } | ||
912 | if (!NewCard) { | ||
913 | /* Pull the Xilinx INIT signal (GPIO2) low */ | ||
914 | saawrite(0x00400000, SAA7146_GPIO_CTRL); | ||
915 | saaread(SAA7146_PSR); /* ensure posted write */ | ||
916 | mdelay(2); | ||
917 | saawrite(0x00000000, SAA7146_GPIO_CTRL); | ||
918 | mdelay(2); | ||
919 | } | ||
920 | printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr); | ||
921 | saa->boardcfg[0] = 26; /* mark fpga programmed */ | ||
922 | /* set VXCO to its lowest frequency */ | ||
923 | debiwrite(saa, debNormal, XILINX_PWM, 0, 2); | ||
924 | if (NewCard) { | ||
925 | /* mute CS3310 */ | ||
926 | if (HaveCS3310) | ||
927 | debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, | ||
928 | 0, 2); | ||
929 | /* set VXCO to PWM mode, release reset, blank on */ | ||
930 | debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2); | ||
931 | mdelay(10); | ||
932 | /* unmute CS3310 */ | ||
933 | if (HaveCS3310) | ||
934 | debiwrite(saa, debNormal, XILINX_CTL0, | ||
935 | 0x2020, 2); | ||
936 | } | ||
937 | /* set source Black */ | ||
938 | debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); | ||
939 | saa->boardcfg[4] = 22; /* set NTSC First Active Line */ | ||
940 | saa->boardcfg[5] = 23; /* set PAL First Active Line */ | ||
941 | saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */ | ||
942 | saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */ | ||
943 | set_out_format(saa, VIDEO_MODE_NTSC); | ||
944 | mdelay(50); | ||
945 | /* begin IBM chip init */ | ||
946 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); | ||
947 | saaread(SAA7146_PSR); /* wait for reset */ | ||
948 | mdelay(5); | ||
949 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); | ||
950 | debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); | ||
951 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2); | ||
952 | debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2); | ||
953 | debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); | ||
954 | if (NewCard) { | ||
955 | mdelay(5); | ||
956 | /* set i2s rate converter to 48KHz */ | ||
957 | debiwrite(saa, debNormal, 0x80c0, 6, 2); | ||
958 | /* we must init CS8420 first since rev b pulls i2s */ | ||
959 | /* master clock low and CS4341 needs i2s master to */ | ||
960 | /* run the i2c port. */ | ||
961 | if (HaveCS8420) { | ||
962 | /* 0=consumer, 1=pro */ | ||
963 | initialize_cs8420(saa, 0); | ||
964 | } | ||
965 | mdelay(5); | ||
966 | if (HaveCS4341) | ||
967 | initialize_cs4341(saa); | ||
968 | } | ||
969 | debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); | ||
970 | debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); | ||
971 | debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); | ||
972 | debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); | ||
973 | if (NewCard) | ||
974 | set_genlock_offset(saa, 0); | ||
975 | debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); | ||
976 | #if 0 | ||
977 | /* enable genlock */ | ||
978 | debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2); | ||
979 | #else | ||
980 | /* disable genlock */ | ||
981 | debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2); | ||
982 | #endif | ||
983 | } | ||
984 | return failure; | ||
985 | } | ||
986 | |||
987 | static int do_ibm_reset(struct saa7146 *saa) | ||
988 | { | ||
989 | /* failure if decoder not previously programmed */ | ||
990 | if (saa->boardcfg[0] < 37) | ||
991 | return -EIO; | ||
992 | /* mute CS3310 */ | ||
993 | if (HaveCS3310) | ||
994 | debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2); | ||
995 | /* disable interrupts */ | ||
996 | saawrite(0, SAA7146_IER); | ||
997 | saa->audhead = saa->audtail = 0; | ||
998 | saa->vidhead = saa->vidtail = 0; | ||
999 | /* tristate debi bus, disable debi transfers */ | ||
1000 | saawrite(0x00880000, SAA7146_MC1); | ||
1001 | /* ensure posted write */ | ||
1002 | saaread(SAA7146_MC1); | ||
1003 | mdelay(50); | ||
1004 | /* re-enable debi transfers */ | ||
1005 | saawrite(0x00880088, SAA7146_MC1); | ||
1006 | /* set source Black */ | ||
1007 | debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); | ||
1008 | /* begin IBM chip init */ | ||
1009 | set_out_format(saa, CurrentMode); | ||
1010 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); | ||
1011 | saaread(SAA7146_PSR); /* wait for reset */ | ||
1012 | mdelay(5); | ||
1013 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); | ||
1014 | debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); | ||
1015 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); | ||
1016 | debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); | ||
1017 | if (NewCard) { | ||
1018 | mdelay(5); | ||
1019 | /* set i2s rate converter to 48KHz */ | ||
1020 | debiwrite(saa, debNormal, 0x80c0, 6, 2); | ||
1021 | /* we must init CS8420 first since rev b pulls i2s */ | ||
1022 | /* master clock low and CS4341 needs i2s master to */ | ||
1023 | /* run the i2c port. */ | ||
1024 | if (HaveCS8420) { | ||
1025 | /* 0=consumer, 1=pro */ | ||
1026 | initialize_cs8420(saa, 1); | ||
1027 | } | ||
1028 | mdelay(5); | ||
1029 | if (HaveCS4341) | ||
1030 | initialize_cs4341(saa); | ||
1031 | } | ||
1032 | debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); | ||
1033 | debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); | ||
1034 | debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); | ||
1035 | debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); | ||
1036 | if (NewCard) | ||
1037 | set_genlock_offset(saa, 0); | ||
1038 | debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); | ||
1039 | debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); | ||
1040 | debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); | ||
1041 | if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, | ||
1042 | (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) { | ||
1043 | printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr); | ||
1044 | } | ||
1045 | if (HaveCS3310) { | ||
1046 | int i = CS3310MaxLvl; | ||
1047 | debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2); | ||
1048 | } | ||
1049 | /* start video decoder */ | ||
1050 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); | ||
1051 | /* 256k vid, 3520 bytes aud */ | ||
1052 | debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2); | ||
1053 | debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); | ||
1054 | ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); | ||
1055 | /* enable buffer threshold irq */ | ||
1056 | debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); | ||
1057 | /* clear pending interrupts */ | ||
1058 | debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); | ||
1059 | debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); | ||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | /* load the decoder microcode */ | ||
1064 | static int initialize_ibmmpeg2(struct video_code *microcode) | ||
1065 | { | ||
1066 | int i, num; | ||
1067 | struct saa7146 *saa; | ||
1068 | |||
1069 | for (num = 0; num < saa_num; num++) { | ||
1070 | saa = &saa7146s[num]; | ||
1071 | /* check that FPGA is loaded */ | ||
1072 | debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2); | ||
1073 | if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) != | ||
1074 | 0xa55a) { | ||
1075 | printk(KERN_INFO "stradis%d: %04x != 0xa55a\n", | ||
1076 | saa->nr, i); | ||
1077 | #if 0 | ||
1078 | return -1; | ||
1079 | #endif | ||
1080 | } | ||
1081 | if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) { | ||
1082 | if (saa->boardcfg[0] > 27) | ||
1083 | continue; /* skip to next card */ | ||
1084 | /* load video control store */ | ||
1085 | saa->boardcfg[1] = 0x13; /* no-sync default */ | ||
1086 | debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); | ||
1087 | debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); | ||
1088 | for (i = 0; i < microcode->datasize / 2; i++) | ||
1089 | debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA, | ||
1090 | (microcode->data[i * 2] << 8) | | ||
1091 | microcode->data[i * 2 + 1], 2); | ||
1092 | debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); | ||
1093 | debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); | ||
1094 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, | ||
1095 | ChipControl, 2); | ||
1096 | saa->boardcfg[0] = 28; | ||
1097 | } | ||
1098 | if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) { | ||
1099 | if (saa->boardcfg[0] > 35) | ||
1100 | continue; /* skip to next card */ | ||
1101 | /* load audio control store */ | ||
1102 | debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); | ||
1103 | debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); | ||
1104 | for (i = 0; i < microcode->datasize; i++) | ||
1105 | debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA, | ||
1106 | microcode->data[i], 1); | ||
1107 | debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); | ||
1108 | debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); | ||
1109 | debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); | ||
1110 | debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); | ||
1111 | if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, | ||
1112 | 0xe000, 1)) { | ||
1113 | printk(KERN_ERR | ||
1114 | "stradis%d: IBM config failed\n", | ||
1115 | saa->nr); | ||
1116 | return -1; | ||
1117 | } | ||
1118 | /* set PWM to center value */ | ||
1119 | if (NewCard) { | ||
1120 | debiwrite(saa, debNormal, XILINX_PWM, | ||
1121 | saa->boardcfg[14] + | ||
1122 | (saa->boardcfg[13]<<8), 2); | ||
1123 | } else | ||
1124 | debiwrite(saa, debNormal, XILINX_PWM, | ||
1125 | 0x46, 2); | ||
1126 | if (HaveCS3310) { | ||
1127 | i = CS3310MaxLvl; | ||
1128 | debiwrite(saa, debNormal, | ||
1129 | XILINX_CS3310_CMPLT, ((i<<8)|i), 2); | ||
1130 | } | ||
1131 | printk(KERN_INFO | ||
1132 | "stradis%d: IBM MPEGCD%d Initialized\n", | ||
1133 | saa->nr, 18 + (debiread(saa, debNormal, | ||
1134 | IBM_MP2_CHIP_CONTROL, 2) >> 12)); | ||
1135 | /* start video decoder */ | ||
1136 | debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, | ||
1137 | ChipControl, 2); | ||
1138 | debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, | ||
1139 | 0x4037, 2); /* 256k vid, 3520 bytes aud */ | ||
1140 | debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); | ||
1141 | ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); | ||
1142 | /* enable buffer threshold irq */ | ||
1143 | debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); | ||
1144 | debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); | ||
1145 | /* enable gpio irq */ | ||
1146 | saawrite(0x00002000, SAA7146_GPIO_CTRL); | ||
1147 | /* enable decoder output to HPS */ | ||
1148 | debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); | ||
1149 | saa->boardcfg[0] = 37; | ||
1150 | } | ||
1151 | } | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | static u32 palette2fmt[] = | ||
1156 | { /* some of these YUV translations are wrong */ | ||
1157 | 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000, | ||
1158 | 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000, | ||
1159 | 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000 | ||
1160 | }; | ||
1161 | static int bpp2fmt[4] = | ||
1162 | { | ||
1163 | VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24, | ||
1164 | VIDEO_PALETTE_RGB32 | ||
1165 | }; | ||
1166 | |||
1167 | /* I wish I could find a formula to calculate these... */ | ||
1168 | static u32 h_prescale[64] = | ||
1169 | { | ||
1170 | 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808, | ||
1171 | 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460, | ||
1172 | 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f, | ||
1173 | 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000, | ||
1174 | 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000, | ||
1175 | 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000, | ||
1176 | 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000, | ||
1177 | 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000, | ||
1178 | 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000, | ||
1179 | 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000, | ||
1180 | 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000, | ||
1181 | }; | ||
1182 | static u32 v_gain[64] = | ||
1183 | { | ||
1184 | 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff, | ||
1185 | 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, | ||
1186 | 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1187 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1188 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1189 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1190 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1191 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1192 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1193 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1194 | 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, | ||
1195 | }; | ||
1196 | |||
1197 | |||
1198 | static void saa7146_set_winsize(struct saa7146 *saa) | ||
1199 | { | ||
1200 | u32 format; | ||
1201 | int offset, yacl, ysci; | ||
1202 | saa->win.color_fmt = format = | ||
1203 | (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] : | ||
1204 | palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]]; | ||
1205 | offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl; | ||
1206 | saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1); | ||
1207 | saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1); | ||
1208 | saawrite(saa->win.bpl * 2, SAA7146_PITCH1); | ||
1209 | saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight, | ||
1210 | SAA7146_PROT_ADDR1); | ||
1211 | saawrite(0, SAA7146_PAGE1); | ||
1212 | saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); | ||
1213 | offset = (704 / (saa->win.width - 1)) & 0x3f; | ||
1214 | saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE); | ||
1215 | offset = (720896 / saa->win.width) / (offset + 1); | ||
1216 | saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE); | ||
1217 | if (CurrentMode == VIDEO_MODE_NTSC) { | ||
1218 | yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0; | ||
1219 | ysci = 1024 - (saa->win.height * 1024 / 480); | ||
1220 | } else { | ||
1221 | yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0; | ||
1222 | ysci = 1024 - (saa->win.height * 1024 / 576); | ||
1223 | } | ||
1224 | saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE); | ||
1225 | saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN); | ||
1226 | saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V | | ||
1227 | SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 | | ||
1228 | SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), | ||
1229 | SAA7146_MC2); | ||
1230 | } | ||
1231 | |||
1232 | /* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area | ||
1233 | * bitmap is fixed width, 128 bytes (1024 pixels represented) | ||
1234 | * arranged most-sigificant-bit-left in 32-bit words | ||
1235 | * based on saa7146 clipping hardware, it swaps bytes if LE | ||
1236 | * much of this makes up for egcs brain damage -- so if you | ||
1237 | * are wondering "why did he do this?" it is because the C | ||
1238 | * was adjusted to generate the optimal asm output without | ||
1239 | * writing non-portable __asm__ directives. | ||
1240 | */ | ||
1241 | |||
1242 | static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h) | ||
1243 | { | ||
1244 | register int startword, endword; | ||
1245 | register u32 bitsleft, bitsright; | ||
1246 | u32 *temp; | ||
1247 | if (x < 0) { | ||
1248 | w += x; | ||
1249 | x = 0; | ||
1250 | } | ||
1251 | if (y < 0) { | ||
1252 | h += y; | ||
1253 | y = 0; | ||
1254 | } | ||
1255 | if (w <= 0 || h <= 0 || x > 1023 || y > 639) | ||
1256 | return; /* throw away bad clips */ | ||
1257 | if (x + w > 1024) | ||
1258 | w = 1024 - x; | ||
1259 | if (y + h > 640) | ||
1260 | h = 640 - y; | ||
1261 | startword = (x >> 5); | ||
1262 | endword = ((x + w) >> 5); | ||
1263 | bitsleft = (0xffffffff >> (x & 31)); | ||
1264 | bitsright = (0xffffffff << (~((x + w) - (endword<<5)))); | ||
1265 | temp = &clipmap[(y<<5) + startword]; | ||
1266 | w = endword - startword; | ||
1267 | if (!w) { | ||
1268 | bitsleft |= bitsright; | ||
1269 | for (y = 0; y < h; y++) { | ||
1270 | *temp |= bitsleft; | ||
1271 | temp += 32; | ||
1272 | } | ||
1273 | } else { | ||
1274 | for (y = 0; y < h; y++) { | ||
1275 | *temp++ |= bitsleft; | ||
1276 | for (x = 1; x < w; x++) | ||
1277 | *temp++ = 0xffffffff; | ||
1278 | *temp |= bitsright; | ||
1279 | temp += (32 - w); | ||
1280 | } | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1284 | static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) | ||
1285 | { | ||
1286 | int i, width, height; | ||
1287 | u32 *clipmap; | ||
1288 | |||
1289 | clipmap = saa->dmavid2; | ||
1290 | if((width=saa->win.width)>1023) | ||
1291 | width = 1023; /* sanity check */ | ||
1292 | if((height=saa->win.height)>640) | ||
1293 | height = 639; /* sanity check */ | ||
1294 | if (ncr > 0) { /* rectangles pased */ | ||
1295 | /* convert rectangular clips to a bitmap */ | ||
1296 | memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ | ||
1297 | for (i = 0; i < ncr; i++) | ||
1298 | clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, | ||
1299 | cr[i].width, cr[i].height); | ||
1300 | } | ||
1301 | /* clip against viewing window AND screen | ||
1302 | so we do not have to rely on the user program | ||
1303 | */ | ||
1304 | clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ? | ||
1305 | (saa->win.swidth-saa->win.x) : width, 0, 1024, 768); | ||
1306 | clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ? | ||
1307 | (saa->win.sheight-saa->win.y) : height,1024,768); | ||
1308 | if (saa->win.x<0) | ||
1309 | clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768); | ||
1310 | if (saa->win.y<0) | ||
1311 | clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y)); | ||
1312 | } | ||
1313 | |||
1314 | static int saa_ioctl(struct inode *inode, struct file *file, | ||
1315 | unsigned int cmd, unsigned long argl) | ||
1316 | { | ||
1317 | struct saa7146 *saa = file->private_data; | ||
1318 | void __user *arg = (void __user *)argl; | ||
1319 | |||
1320 | switch (cmd) { | ||
1321 | case VIDIOCGCAP: | ||
1322 | { | ||
1323 | struct video_capability b; | ||
1324 | strcpy(b.name, saa->video_dev.name); | ||
1325 | b.type = VID_TYPE_CAPTURE | | ||
1326 | VID_TYPE_OVERLAY | | ||
1327 | VID_TYPE_CLIPPING | | ||
1328 | VID_TYPE_FRAMERAM | | ||
1329 | VID_TYPE_SCALES; | ||
1330 | b.channels = 1; | ||
1331 | b.audios = 1; | ||
1332 | b.maxwidth = 768; | ||
1333 | b.maxheight = 576; | ||
1334 | b.minwidth = 32; | ||
1335 | b.minheight = 32; | ||
1336 | if (copy_to_user(arg, &b, sizeof(b))) | ||
1337 | return -EFAULT; | ||
1338 | return 0; | ||
1339 | } | ||
1340 | case VIDIOCGPICT: | ||
1341 | { | ||
1342 | struct video_picture p = saa->picture; | ||
1343 | if (saa->win.depth == 8) | ||
1344 | p.palette = VIDEO_PALETTE_HI240; | ||
1345 | if (saa->win.depth == 15) | ||
1346 | p.palette = VIDEO_PALETTE_RGB555; | ||
1347 | if (saa->win.depth == 16) | ||
1348 | p.palette = VIDEO_PALETTE_RGB565; | ||
1349 | if (saa->win.depth == 24) | ||
1350 | p.palette = VIDEO_PALETTE_RGB24; | ||
1351 | if (saa->win.depth == 32) | ||
1352 | p.palette = VIDEO_PALETTE_RGB32; | ||
1353 | if (copy_to_user(arg, &p, sizeof(p))) | ||
1354 | return -EFAULT; | ||
1355 | return 0; | ||
1356 | } | ||
1357 | case VIDIOCSPICT: | ||
1358 | { | ||
1359 | struct video_picture p; | ||
1360 | u32 format; | ||
1361 | if (copy_from_user(&p, arg, sizeof(p))) | ||
1362 | return -EFAULT; | ||
1363 | if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { | ||
1364 | format = palette2fmt[p.palette]; | ||
1365 | saa->win.color_fmt = format; | ||
1366 | saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); | ||
1367 | } | ||
1368 | saawrite(((p.brightness & 0xff00) << 16) | | ||
1369 | ((p.contrast & 0xfe00) << 7) | | ||
1370 | ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL); | ||
1371 | saa->picture = p; | ||
1372 | /* upload changed registers */ | ||
1373 | saawrite(((SAA7146_MC2_UPLD_HPS_H | | ||
1374 | SAA7146_MC2_UPLD_HPS_V) << 16) | | ||
1375 | SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V, | ||
1376 | SAA7146_MC2); | ||
1377 | return 0; | ||
1378 | } | ||
1379 | case VIDIOCSWIN: | ||
1380 | { | ||
1381 | struct video_window vw; | ||
1382 | struct video_clip *vcp = NULL; | ||
1383 | |||
1384 | if (copy_from_user(&vw, arg, sizeof(vw))) | ||
1385 | return -EFAULT; | ||
1386 | |||
1387 | if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */ | ||
1388 | saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); | ||
1389 | return -EINVAL; | ||
1390 | } | ||
1391 | if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */ | ||
1392 | int i = vw.x; | ||
1393 | vw.x = (vw.x + 3) & ~3; | ||
1394 | i = vw.x - i; | ||
1395 | vw.width -= i; | ||
1396 | } | ||
1397 | saa->win.x = vw.x; | ||
1398 | saa->win.y = vw.y; | ||
1399 | saa->win.width = vw.width; | ||
1400 | if (saa->win.width > 768) | ||
1401 | saa->win.width = 768; | ||
1402 | saa->win.height = vw.height; | ||
1403 | if (CurrentMode == VIDEO_MODE_NTSC) { | ||
1404 | if (saa->win.height > 480) | ||
1405 | saa->win.height = 480; | ||
1406 | } else { | ||
1407 | if (saa->win.height > 576) | ||
1408 | saa->win.height = 576; | ||
1409 | } | ||
1410 | |||
1411 | /* stop capture */ | ||
1412 | saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); | ||
1413 | saa7146_set_winsize(saa); | ||
1414 | |||
1415 | /* | ||
1416 | * Do any clips. | ||
1417 | */ | ||
1418 | if (vw.clipcount < 0) { | ||
1419 | if (copy_from_user(saa->dmavid2, vw.clips, | ||
1420 | VIDEO_CLIPMAP_SIZE)) | ||
1421 | return -EFAULT; | ||
1422 | } | ||
1423 | else if (vw.clipcount > 16384) { | ||
1424 | return -EINVAL; | ||
1425 | } else if (vw.clipcount > 0) { | ||
1426 | if ((vcp = vmalloc(sizeof(struct video_clip) * | ||
1427 | (vw.clipcount))) == NULL) | ||
1428 | return -ENOMEM; | ||
1429 | if (copy_from_user(vcp, vw.clips, | ||
1430 | sizeof(struct video_clip) * | ||
1431 | vw.clipcount)) { | ||
1432 | vfree(vcp); | ||
1433 | return -EFAULT; | ||
1434 | } | ||
1435 | } else /* nothing clipped */ | ||
1436 | memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE); | ||
1437 | make_clip_tab(saa, vcp, vw.clipcount); | ||
1438 | if (vw.clipcount > 0) | ||
1439 | vfree(vcp); | ||
1440 | |||
1441 | /* start capture & clip dma if we have an address */ | ||
1442 | if ((saa->cap & 3) && saa->win.vidadr != 0) | ||
1443 | saawrite(((SAA7146_MC1_TR_E_1 | | ||
1444 | SAA7146_MC1_TR_E_2) << 16) | 0xffff, | ||
1445 | SAA7146_MC1); | ||
1446 | return 0; | ||
1447 | } | ||
1448 | case VIDIOCGWIN: | ||
1449 | { | ||
1450 | struct video_window vw; | ||
1451 | vw.x = saa->win.x; | ||
1452 | vw.y = saa->win.y; | ||
1453 | vw.width = saa->win.width; | ||
1454 | vw.height = saa->win.height; | ||
1455 | vw.chromakey = 0; | ||
1456 | vw.flags = 0; | ||
1457 | if (copy_to_user(arg, &vw, sizeof(vw))) | ||
1458 | return -EFAULT; | ||
1459 | return 0; | ||
1460 | } | ||
1461 | case VIDIOCCAPTURE: | ||
1462 | { | ||
1463 | int v; | ||
1464 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1465 | return -EFAULT; | ||
1466 | if (v == 0) { | ||
1467 | saa->cap &= ~1; | ||
1468 | saawrite((SAA7146_MC1_TR_E_1 << 16), | ||
1469 | SAA7146_MC1); | ||
1470 | } else { | ||
1471 | if (saa->win.vidadr == 0 || saa->win.width == 0 | ||
1472 | || saa->win.height == 0) | ||
1473 | return -EINVAL; | ||
1474 | saa->cap |= 1; | ||
1475 | saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, | ||
1476 | SAA7146_MC1); | ||
1477 | } | ||
1478 | return 0; | ||
1479 | } | ||
1480 | case VIDIOCGFBUF: | ||
1481 | { | ||
1482 | struct video_buffer v; | ||
1483 | v.base = (void *) saa->win.vidadr; | ||
1484 | v.height = saa->win.sheight; | ||
1485 | v.width = saa->win.swidth; | ||
1486 | v.depth = saa->win.depth; | ||
1487 | v.bytesperline = saa->win.bpl; | ||
1488 | if (copy_to_user(arg, &v, sizeof(v))) | ||
1489 | return -EFAULT; | ||
1490 | return 0; | ||
1491 | |||
1492 | } | ||
1493 | case VIDIOCSFBUF: | ||
1494 | { | ||
1495 | struct video_buffer v; | ||
1496 | if (!capable(CAP_SYS_ADMIN)) | ||
1497 | return -EPERM; | ||
1498 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1499 | return -EFAULT; | ||
1500 | if (v.depth != 8 && v.depth != 15 && v.depth != 16 && | ||
1501 | v.depth != 24 && v.depth != 32 && v.width > 16 && | ||
1502 | v.height > 16 && v.bytesperline > 16) | ||
1503 | return -EINVAL; | ||
1504 | if (v.base) | ||
1505 | saa->win.vidadr = (unsigned long) v.base; | ||
1506 | saa->win.sheight = v.height; | ||
1507 | saa->win.swidth = v.width; | ||
1508 | saa->win.bpp = ((v.depth + 7) & 0x38) / 8; | ||
1509 | saa->win.depth = v.depth; | ||
1510 | saa->win.bpl = v.bytesperline; | ||
1511 | |||
1512 | DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", | ||
1513 | v.base, v.width, v.height, saa->win.bpp, saa->win.bpl)); | ||
1514 | saa7146_set_winsize(saa); | ||
1515 | return 0; | ||
1516 | } | ||
1517 | case VIDIOCKEY: | ||
1518 | { | ||
1519 | /* Will be handled higher up .. */ | ||
1520 | return 0; | ||
1521 | } | ||
1522 | |||
1523 | case VIDIOCGAUDIO: | ||
1524 | { | ||
1525 | struct video_audio v; | ||
1526 | v = saa->audio_dev; | ||
1527 | v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); | ||
1528 | v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; | ||
1529 | strcpy(v.name, "MPEG"); | ||
1530 | v.mode = VIDEO_SOUND_STEREO; | ||
1531 | if (copy_to_user(arg, &v, sizeof(v))) | ||
1532 | return -EFAULT; | ||
1533 | return 0; | ||
1534 | } | ||
1535 | case VIDIOCSAUDIO: | ||
1536 | { | ||
1537 | struct video_audio v; | ||
1538 | int i; | ||
1539 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1540 | return -EFAULT; | ||
1541 | i = (~(v.volume>>8))&0xff; | ||
1542 | if (!HaveCS4341) { | ||
1543 | if (v.flags & VIDEO_AUDIO_MUTE) { | ||
1544 | debiwrite(saa, debNormal, | ||
1545 | IBM_MP2_FRNT_ATTEN, | ||
1546 | 0xffff, 2); | ||
1547 | } | ||
1548 | if (!(v.flags & VIDEO_AUDIO_MUTE)) | ||
1549 | debiwrite(saa, debNormal, | ||
1550 | IBM_MP2_FRNT_ATTEN, | ||
1551 | 0x0000, 2); | ||
1552 | if (v.flags & VIDEO_AUDIO_VOLUME) | ||
1553 | debiwrite(saa, debNormal, | ||
1554 | IBM_MP2_FRNT_ATTEN, | ||
1555 | (i<<8)|i, 2); | ||
1556 | } else { | ||
1557 | if (v.flags & VIDEO_AUDIO_MUTE) | ||
1558 | cs4341_setlevel(saa, 0xff, 0xff); | ||
1559 | if (!(v.flags & VIDEO_AUDIO_MUTE)) | ||
1560 | cs4341_setlevel(saa, 0, 0); | ||
1561 | if (v.flags & VIDEO_AUDIO_VOLUME) | ||
1562 | cs4341_setlevel(saa, i, i); | ||
1563 | } | ||
1564 | saa->audio_dev = v; | ||
1565 | return 0; | ||
1566 | } | ||
1567 | |||
1568 | case VIDIOCGUNIT: | ||
1569 | { | ||
1570 | struct video_unit vu; | ||
1571 | vu.video = saa->video_dev.minor; | ||
1572 | vu.vbi = VIDEO_NO_UNIT; | ||
1573 | vu.radio = VIDEO_NO_UNIT; | ||
1574 | vu.audio = VIDEO_NO_UNIT; | ||
1575 | vu.teletext = VIDEO_NO_UNIT; | ||
1576 | if (copy_to_user(arg, &vu, sizeof(vu))) | ||
1577 | return -EFAULT; | ||
1578 | return 0; | ||
1579 | } | ||
1580 | case VIDIOCSPLAYMODE: | ||
1581 | { | ||
1582 | struct video_play_mode pmode; | ||
1583 | if (copy_from_user((void *) &pmode, arg, | ||
1584 | sizeof(struct video_play_mode))) | ||
1585 | return -EFAULT; | ||
1586 | switch (pmode.mode) { | ||
1587 | case VID_PLAY_VID_OUT_MODE: | ||
1588 | if (pmode.p1 != VIDEO_MODE_NTSC && | ||
1589 | pmode.p1 != VIDEO_MODE_PAL) | ||
1590 | return -EINVAL; | ||
1591 | set_out_format(saa, pmode.p1); | ||
1592 | return 0; | ||
1593 | case VID_PLAY_GENLOCK: | ||
1594 | debiwrite(saa, debNormal, | ||
1595 | XILINX_CTL0, | ||
1596 | (pmode.p1 ? 0x8000 : 0x8080), | ||
1597 | 2); | ||
1598 | if (NewCard) | ||
1599 | set_genlock_offset(saa, | ||
1600 | pmode.p2); | ||
1601 | return 0; | ||
1602 | case VID_PLAY_NORMAL: | ||
1603 | debiwrite(saa, debNormal, | ||
1604 | IBM_MP2_CHIP_CONTROL, | ||
1605 | ChipControl, 2); | ||
1606 | ibm_send_command(saa, | ||
1607 | IBM_MP2_PLAY, 0, 0); | ||
1608 | saa->playmode = pmode.mode; | ||
1609 | return 0; | ||
1610 | case VID_PLAY_PAUSE: | ||
1611 | /* IBM removed the PAUSE command */ | ||
1612 | /* they say use SINGLE_FRAME now */ | ||
1613 | case VID_PLAY_SINGLE_FRAME: | ||
1614 | ibm_send_command(saa, | ||
1615 | IBM_MP2_SINGLE_FRAME, | ||
1616 | 0, 0); | ||
1617 | if (saa->playmode == pmode.mode) { | ||
1618 | debiwrite(saa, debNormal, | ||
1619 | IBM_MP2_CHIP_CONTROL, | ||
1620 | ChipControl, 2); | ||
1621 | } | ||
1622 | saa->playmode = pmode.mode; | ||
1623 | return 0; | ||
1624 | case VID_PLAY_FAST_FORWARD: | ||
1625 | ibm_send_command(saa, | ||
1626 | IBM_MP2_FAST_FORWARD, 0, 0); | ||
1627 | saa->playmode = pmode.mode; | ||
1628 | return 0; | ||
1629 | case VID_PLAY_SLOW_MOTION: | ||
1630 | ibm_send_command(saa, | ||
1631 | IBM_MP2_SLOW_MOTION, | ||
1632 | pmode.p1, 0); | ||
1633 | saa->playmode = pmode.mode; | ||
1634 | return 0; | ||
1635 | case VID_PLAY_IMMEDIATE_NORMAL: | ||
1636 | /* ensure transfers resume */ | ||
1637 | debiwrite(saa, debNormal, | ||
1638 | IBM_MP2_CHIP_CONTROL, | ||
1639 | ChipControl, 2); | ||
1640 | ibm_send_command(saa, | ||
1641 | IBM_MP2_IMED_NORM_PLAY, 0, 0); | ||
1642 | saa->playmode = VID_PLAY_NORMAL; | ||
1643 | return 0; | ||
1644 | case VID_PLAY_SWITCH_CHANNELS: | ||
1645 | saa->audhead = saa->audtail = 0; | ||
1646 | saa->vidhead = saa->vidtail = 0; | ||
1647 | ibm_send_command(saa, | ||
1648 | IBM_MP2_FREEZE_FRAME, 0, 1); | ||
1649 | ibm_send_command(saa, | ||
1650 | IBM_MP2_RESET_AUD_RATE, 0, 1); | ||
1651 | debiwrite(saa, debNormal, | ||
1652 | IBM_MP2_CHIP_CONTROL, 0, 2); | ||
1653 | ibm_send_command(saa, | ||
1654 | IBM_MP2_CHANNEL_SWITCH, 0, 1); | ||
1655 | debiwrite(saa, debNormal, | ||
1656 | IBM_MP2_CHIP_CONTROL, | ||
1657 | ChipControl, 2); | ||
1658 | ibm_send_command(saa, | ||
1659 | IBM_MP2_PLAY, 0, 0); | ||
1660 | saa->playmode = VID_PLAY_NORMAL; | ||
1661 | return 0; | ||
1662 | case VID_PLAY_FREEZE_FRAME: | ||
1663 | ibm_send_command(saa, | ||
1664 | IBM_MP2_FREEZE_FRAME, 0, 0); | ||
1665 | saa->playmode = pmode.mode; | ||
1666 | return 0; | ||
1667 | case VID_PLAY_STILL_MODE: | ||
1668 | ibm_send_command(saa, | ||
1669 | IBM_MP2_SET_STILL_MODE, 0, 0); | ||
1670 | saa->playmode = pmode.mode; | ||
1671 | return 0; | ||
1672 | case VID_PLAY_MASTER_MODE: | ||
1673 | if (pmode.p1 == VID_PLAY_MASTER_NONE) | ||
1674 | saa->boardcfg[1] = 0x13; | ||
1675 | else if (pmode.p1 == | ||
1676 | VID_PLAY_MASTER_VIDEO) | ||
1677 | saa->boardcfg[1] = 0x23; | ||
1678 | else if (pmode.p1 == | ||
1679 | VID_PLAY_MASTER_AUDIO) | ||
1680 | saa->boardcfg[1] = 0x43; | ||
1681 | else | ||
1682 | return -EINVAL; | ||
1683 | debiwrite(saa, debNormal, | ||
1684 | IBM_MP2_CHIP_CONTROL, | ||
1685 | ChipControl, 2); | ||
1686 | return 0; | ||
1687 | case VID_PLAY_ACTIVE_SCANLINES: | ||
1688 | if (CurrentMode == VIDEO_MODE_PAL) { | ||
1689 | if (pmode.p1 < 1 || | ||
1690 | pmode.p2 > 625) | ||
1691 | return -EINVAL; | ||
1692 | saa->boardcfg[5] = pmode.p1; | ||
1693 | saa->boardcfg[55] = (pmode.p1 + | ||
1694 | (pmode.p2/2) - 1) & | ||
1695 | 0xff; | ||
1696 | } else { | ||
1697 | if (pmode.p1 < 4 || | ||
1698 | pmode.p2 > 525) | ||
1699 | return -EINVAL; | ||
1700 | saa->boardcfg[4] = pmode.p1; | ||
1701 | saa->boardcfg[54] = (pmode.p1 + | ||
1702 | (pmode.p2/2) - 4) & | ||
1703 | 0xff; | ||
1704 | } | ||
1705 | set_out_format(saa, CurrentMode); | ||
1706 | case VID_PLAY_RESET: | ||
1707 | return do_ibm_reset(saa); | ||
1708 | case VID_PLAY_END_MARK: | ||
1709 | if (saa->endmarktail < | ||
1710 | saa->endmarkhead) { | ||
1711 | if (saa->endmarkhead - | ||
1712 | saa->endmarktail < 2) | ||
1713 | return -ENOSPC; | ||
1714 | } else if (saa->endmarkhead <= | ||
1715 | saa->endmarktail) { | ||
1716 | if (saa->endmarktail - | ||
1717 | saa->endmarkhead > | ||
1718 | (MAX_MARKS - 2)) | ||
1719 | return -ENOSPC; | ||
1720 | } else | ||
1721 | return -ENOSPC; | ||
1722 | saa->endmark[saa->endmarktail] = | ||
1723 | saa->audtail; | ||
1724 | saa->endmarktail++; | ||
1725 | if (saa->endmarktail >= MAX_MARKS) | ||
1726 | saa->endmarktail = 0; | ||
1727 | } | ||
1728 | return -EINVAL; | ||
1729 | } | ||
1730 | case VIDIOCSWRITEMODE: | ||
1731 | { | ||
1732 | int mode; | ||
1733 | if (copy_from_user((void *) &mode, arg, sizeof(int))) | ||
1734 | return -EFAULT; | ||
1735 | if (mode == VID_WRITE_MPEG_AUD || | ||
1736 | mode == VID_WRITE_MPEG_VID || | ||
1737 | mode == VID_WRITE_CC || | ||
1738 | mode == VID_WRITE_TTX || | ||
1739 | mode == VID_WRITE_OSD) { | ||
1740 | saa->writemode = mode; | ||
1741 | return 0; | ||
1742 | } | ||
1743 | return -EINVAL; | ||
1744 | } | ||
1745 | case VIDIOCSMICROCODE: | ||
1746 | { | ||
1747 | struct video_code ucode; | ||
1748 | __u8 *udata; | ||
1749 | int i; | ||
1750 | if (copy_from_user(&ucode, arg, sizeof(ucode))) | ||
1751 | return -EFAULT; | ||
1752 | if (ucode.datasize > 65536 || ucode.datasize < 1024 || | ||
1753 | strncmp(ucode.loadwhat, "dec", 3)) | ||
1754 | return -EINVAL; | ||
1755 | if ((udata = vmalloc(ucode.datasize)) == NULL) | ||
1756 | return -ENOMEM; | ||
1757 | if (copy_from_user(udata, ucode.data, ucode.datasize)) { | ||
1758 | vfree(udata); | ||
1759 | return -EFAULT; | ||
1760 | } | ||
1761 | ucode.data = udata; | ||
1762 | if (!strncmp(ucode.loadwhat, "decoder.aud", 11) | ||
1763 | || !strncmp(ucode.loadwhat, "decoder.vid", 11)) | ||
1764 | i = initialize_ibmmpeg2(&ucode); | ||
1765 | else | ||
1766 | i = initialize_fpga(&ucode); | ||
1767 | vfree(udata); | ||
1768 | if (i) | ||
1769 | return -EINVAL; | ||
1770 | return 0; | ||
1771 | |||
1772 | } | ||
1773 | case VIDIOCGCHAN: /* this makes xawtv happy */ | ||
1774 | { | ||
1775 | struct video_channel v; | ||
1776 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1777 | return -EFAULT; | ||
1778 | v.flags = VIDEO_VC_AUDIO; | ||
1779 | v.tuners = 0; | ||
1780 | v.type = VID_TYPE_MPEG_DECODER; | ||
1781 | v.norm = CurrentMode; | ||
1782 | strcpy(v.name, "MPEG2"); | ||
1783 | if (copy_to_user(arg, &v, sizeof(v))) | ||
1784 | return -EFAULT; | ||
1785 | return 0; | ||
1786 | } | ||
1787 | case VIDIOCSCHAN: /* this makes xawtv happy */ | ||
1788 | { | ||
1789 | struct video_channel v; | ||
1790 | if (copy_from_user(&v, arg, sizeof(v))) | ||
1791 | return -EFAULT; | ||
1792 | /* do nothing */ | ||
1793 | return 0; | ||
1794 | } | ||
1795 | default: | ||
1796 | return -ENOIOCTLCMD; | ||
1797 | } | ||
1798 | return 0; | ||
1799 | } | ||
1800 | |||
1801 | static int saa_mmap(struct file *file, struct vm_area_struct *vma) | ||
1802 | { | ||
1803 | struct saa7146 *saa = file->private_data; | ||
1804 | printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); | ||
1805 | return -EINVAL; | ||
1806 | } | ||
1807 | |||
1808 | static ssize_t saa_read(struct file *file, char __user *buf, | ||
1809 | size_t count, loff_t *ppos) | ||
1810 | { | ||
1811 | return -EINVAL; | ||
1812 | } | ||
1813 | |||
1814 | static ssize_t saa_write(struct file *file, const char __user *buf, | ||
1815 | size_t count, loff_t *ppos) | ||
1816 | { | ||
1817 | struct saa7146 *saa = file->private_data; | ||
1818 | unsigned long todo = count; | ||
1819 | int blocksize, split; | ||
1820 | unsigned long flags; | ||
1821 | |||
1822 | while (todo > 0) { | ||
1823 | if (saa->writemode == VID_WRITE_MPEG_AUD) { | ||
1824 | spin_lock_irqsave(&saa->lock, flags); | ||
1825 | if (saa->audhead <= saa->audtail) | ||
1826 | blocksize = 65536-(saa->audtail - saa->audhead); | ||
1827 | else | ||
1828 | blocksize = saa->audhead - saa->audtail; | ||
1829 | spin_unlock_irqrestore(&saa->lock, flags); | ||
1830 | if (blocksize < 16384) { | ||
1831 | saawrite(SAA7146_PSR_DEBI_S | | ||
1832 | SAA7146_PSR_PIN1, SAA7146_IER); | ||
1833 | saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); | ||
1834 | /* wait for buffer space to open */ | ||
1835 | interruptible_sleep_on(&saa->audq); | ||
1836 | } | ||
1837 | spin_lock_irqsave(&saa->lock, flags); | ||
1838 | if (saa->audhead <= saa->audtail) { | ||
1839 | blocksize = 65536-(saa->audtail - saa->audhead); | ||
1840 | split = 65536 - saa->audtail; | ||
1841 | } else { | ||
1842 | blocksize = saa->audhead - saa->audtail; | ||
1843 | split = 65536; | ||
1844 | } | ||
1845 | spin_unlock_irqrestore(&saa->lock, flags); | ||
1846 | blocksize--; | ||
1847 | if (blocksize > todo) | ||
1848 | blocksize = todo; | ||
1849 | /* double check that we really have space */ | ||
1850 | if (!blocksize) | ||
1851 | return -ENOSPC; | ||
1852 | if (split < blocksize) { | ||
1853 | if (copy_from_user(saa->audbuf + | ||
1854 | saa->audtail, buf, split)) | ||
1855 | return -EFAULT; | ||
1856 | buf += split; | ||
1857 | todo -= split; | ||
1858 | blocksize -= split; | ||
1859 | saa->audtail = 0; | ||
1860 | } | ||
1861 | if (copy_from_user(saa->audbuf + saa->audtail, buf, | ||
1862 | blocksize)) | ||
1863 | return -EFAULT; | ||
1864 | saa->audtail += blocksize; | ||
1865 | todo -= blocksize; | ||
1866 | buf += blocksize; | ||
1867 | saa->audtail &= 0xffff; | ||
1868 | } else if (saa->writemode == VID_WRITE_MPEG_VID) { | ||
1869 | spin_lock_irqsave(&saa->lock, flags); | ||
1870 | if (saa->vidhead <= saa->vidtail) | ||
1871 | blocksize=524288-(saa->vidtail - saa->vidhead); | ||
1872 | else | ||
1873 | blocksize = saa->vidhead - saa->vidtail; | ||
1874 | spin_unlock_irqrestore(&saa->lock, flags); | ||
1875 | if (blocksize < 65536) { | ||
1876 | saawrite(SAA7146_PSR_DEBI_S | | ||
1877 | SAA7146_PSR_PIN1, SAA7146_IER); | ||
1878 | saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); | ||
1879 | /* wait for buffer space to open */ | ||
1880 | interruptible_sleep_on(&saa->vidq); | ||
1881 | } | ||
1882 | spin_lock_irqsave(&saa->lock, flags); | ||
1883 | if (saa->vidhead <= saa->vidtail) { | ||
1884 | blocksize=524288-(saa->vidtail - saa->vidhead); | ||
1885 | split = 524288 - saa->vidtail; | ||
1886 | } else { | ||
1887 | blocksize = saa->vidhead - saa->vidtail; | ||
1888 | split = 524288; | ||
1889 | } | ||
1890 | spin_unlock_irqrestore(&saa->lock, flags); | ||
1891 | blocksize--; | ||
1892 | if (blocksize > todo) | ||
1893 | blocksize = todo; | ||
1894 | /* double check that we really have space */ | ||
1895 | if (!blocksize) | ||
1896 | return -ENOSPC; | ||
1897 | if (split < blocksize) { | ||
1898 | if (copy_from_user(saa->vidbuf + | ||
1899 | saa->vidtail, buf, split)) | ||
1900 | return -EFAULT; | ||
1901 | buf += split; | ||
1902 | todo -= split; | ||
1903 | blocksize -= split; | ||
1904 | saa->vidtail = 0; | ||
1905 | } | ||
1906 | if (copy_from_user(saa->vidbuf + saa->vidtail, buf, | ||
1907 | blocksize)) | ||
1908 | return -EFAULT; | ||
1909 | saa->vidtail += blocksize; | ||
1910 | todo -= blocksize; | ||
1911 | buf += blocksize; | ||
1912 | saa->vidtail &= 0x7ffff; | ||
1913 | } else if (saa->writemode == VID_WRITE_OSD) { | ||
1914 | if (count > 131072) | ||
1915 | return -ENOSPC; | ||
1916 | if (copy_from_user(saa->osdbuf, buf, count)) | ||
1917 | return -EFAULT; | ||
1918 | buf += count; | ||
1919 | saa->osdhead = 0; | ||
1920 | saa->osdtail = count; | ||
1921 | debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); | ||
1922 | debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2); | ||
1923 | debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2); | ||
1924 | debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, | ||
1925 | debiread(saa, debNormal, | ||
1926 | IBM_MP2_DISP_MODE, 2) | 1, 2); | ||
1927 | /* trigger osd data transfer */ | ||
1928 | saawrite(SAA7146_PSR_DEBI_S | | ||
1929 | SAA7146_PSR_PIN1, SAA7146_IER); | ||
1930 | saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); | ||
1931 | } | ||
1932 | } | ||
1933 | return count; | ||
1934 | } | ||
1935 | |||
1936 | static int saa_open(struct inode *inode, struct file *file) | ||
1937 | { | ||
1938 | struct saa7146 *saa = NULL; | ||
1939 | unsigned int minor = iminor(inode); | ||
1940 | int i; | ||
1941 | |||
1942 | for (i = 0; i < SAA7146_MAX; i++) { | ||
1943 | if (saa7146s[i].video_dev.minor == minor) { | ||
1944 | saa = &saa7146s[i]; | ||
1945 | } | ||
1946 | } | ||
1947 | if (saa == NULL) { | ||
1948 | return -ENODEV; | ||
1949 | } | ||
1950 | file->private_data = saa; | ||
1951 | |||
1952 | //saa->video_dev.busy = 0; /* old hack to support multiple open */ | ||
1953 | saa->user++; | ||
1954 | if (saa->user > 1) | ||
1955 | return 0; /* device open already, don't reset */ | ||
1956 | saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ | ||
1957 | return 0; | ||
1958 | } | ||
1959 | |||
1960 | static int saa_release(struct inode *inode, struct file *file) | ||
1961 | { | ||
1962 | struct saa7146 *saa = file->private_data; | ||
1963 | saa->user--; | ||
1964 | //saa->video_dev.busy = 0; /* old hack to support multiple open */ | ||
1965 | if (saa->user > 0) /* still someone using device */ | ||
1966 | return 0; | ||
1967 | saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ | ||
1968 | return 0; | ||
1969 | } | ||
1970 | |||
1971 | static struct file_operations saa_fops = | ||
1972 | { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .open = saa_open, | ||
1975 | .release = saa_release, | ||
1976 | .ioctl = saa_ioctl, | ||
1977 | .read = saa_read, | ||
1978 | .llseek = no_llseek, | ||
1979 | .write = saa_write, | ||
1980 | .mmap = saa_mmap, | ||
1981 | }; | ||
1982 | |||
1983 | /* template for video_device-structure */ | ||
1984 | static struct video_device saa_template = | ||
1985 | { | ||
1986 | .name = "SAA7146A", | ||
1987 | .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, | ||
1988 | .hardware = VID_HARDWARE_SAA7146, | ||
1989 | .fops = &saa_fops, | ||
1990 | .minor = -1, | ||
1991 | }; | ||
1992 | |||
1993 | static int configure_saa7146(struct pci_dev *dev, int num) | ||
1994 | { | ||
1995 | int result; | ||
1996 | struct saa7146 *saa; | ||
1997 | |||
1998 | saa = &saa7146s[num]; | ||
1999 | |||
2000 | saa->endmarkhead = saa->endmarktail = 0; | ||
2001 | saa->win.x = saa->win.y = 0; | ||
2002 | saa->win.width = saa->win.cropwidth = 720; | ||
2003 | saa->win.height = saa->win.cropheight = 480; | ||
2004 | saa->win.cropx = saa->win.cropy = 0; | ||
2005 | saa->win.bpp = 2; | ||
2006 | saa->win.depth = 16; | ||
2007 | saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; | ||
2008 | saa->win.bpl = 1024 * saa->win.bpp; | ||
2009 | saa->win.swidth = 1024; | ||
2010 | saa->win.sheight = 768; | ||
2011 | saa->picture.brightness = 32768; | ||
2012 | saa->picture.contrast = 38768; | ||
2013 | saa->picture.colour = 32768; | ||
2014 | saa->cap = 0; | ||
2015 | saa->dev = dev; | ||
2016 | saa->nr = num; | ||
2017 | saa->playmode = VID_PLAY_NORMAL; | ||
2018 | memset(saa->boardcfg, 0, 64); /* clear board config area */ | ||
2019 | saa->saa7146_mem = NULL; | ||
2020 | saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = | ||
2021 | saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = | ||
2022 | saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = | ||
2023 | saa->pagea1out = saa->pagea2in = saa->pagea2out = | ||
2024 | saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = | ||
2025 | saa->pageRPS2 = NULL; | ||
2026 | saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; | ||
2027 | saa->audhead = saa->vidtail = 0; | ||
2028 | |||
2029 | init_waitqueue_head(&saa->i2cq); | ||
2030 | init_waitqueue_head(&saa->audq); | ||
2031 | init_waitqueue_head(&saa->debiq); | ||
2032 | init_waitqueue_head(&saa->vidq); | ||
2033 | spin_lock_init(&saa->lock); | ||
2034 | |||
2035 | if (pci_enable_device(dev)) | ||
2036 | return -EIO; | ||
2037 | |||
2038 | saa->id = dev->device; | ||
2039 | saa->irq = dev->irq; | ||
2040 | saa->video_dev.minor = -1; | ||
2041 | saa->saa7146_adr = pci_resource_start(dev, 0); | ||
2042 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision); | ||
2043 | |||
2044 | saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200); | ||
2045 | if (!saa->saa7146_mem) | ||
2046 | return -EIO; | ||
2047 | |||
2048 | memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); | ||
2049 | saawrite(0, SAA7146_IER); /* turn off all interrupts */ | ||
2050 | result = request_irq(saa->irq, saa7146_irq, | ||
2051 | SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa); | ||
2052 | if (result == -EINVAL) | ||
2053 | printk(KERN_ERR "stradis%d: Bad irq number or handler\n", | ||
2054 | num); | ||
2055 | if (result == -EBUSY) | ||
2056 | printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP" | ||
2057 | " config in BIOS\n", num, saa->irq); | ||
2058 | if (result < 0) { | ||
2059 | iounmap(saa->saa7146_mem); | ||
2060 | return result; | ||
2061 | } | ||
2062 | pci_set_master(dev); | ||
2063 | if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) { | ||
2064 | iounmap(saa->saa7146_mem); | ||
2065 | return -1; | ||
2066 | } | ||
2067 | return 0; | ||
2068 | } | ||
2069 | |||
2070 | static int init_saa7146(int i) | ||
2071 | { | ||
2072 | struct saa7146 *saa = &saa7146s[i]; | ||
2073 | |||
2074 | saa->user = 0; | ||
2075 | /* reset the saa7146 */ | ||
2076 | saawrite(0xffff0000, SAA7146_MC1); | ||
2077 | mdelay(5); | ||
2078 | /* enable debi and i2c transfers and pins */ | ||
2079 | saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | | ||
2080 | SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); | ||
2081 | /* ensure proper state of chip */ | ||
2082 | saawrite(0x00000000, SAA7146_PAGE1); | ||
2083 | saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); | ||
2084 | saawrite(0x00000000, SAA7146_PAGE2); | ||
2085 | saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); | ||
2086 | saawrite(0x00000000, SAA7146_DD1_INIT); | ||
2087 | saawrite(0x00000000, SAA7146_DD1_STREAM_B); | ||
2088 | saawrite(0x00000000, SAA7146_DD1_STREAM_A); | ||
2089 | saawrite(0x00000000, SAA7146_BRS_CTRL); | ||
2090 | saawrite(0x80400040, SAA7146_BCS_CTRL); | ||
2091 | saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL); | ||
2092 | saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL); | ||
2093 | saawrite(0x00000000, SAA7146_ACON1); | ||
2094 | saawrite(0x00000000, SAA7146_ACON2); | ||
2095 | saawrite(0x00000600, SAA7146_I2C_STATUS); | ||
2096 | saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A | | ||
2097 | SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H | | ||
2098 | SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 | | ||
2099 | SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff, | ||
2100 | SAA7146_MC2); | ||
2101 | /* setup arbitration control registers */ | ||
2102 | saawrite(0x1412121a, SAA7146_PCI_BT_V1); | ||
2103 | |||
2104 | /* allocate 32k dma buffer + 4k for page table */ | ||
2105 | if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) { | ||
2106 | printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i); | ||
2107 | return -1; | ||
2108 | } | ||
2109 | #if 0 | ||
2110 | saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ | ||
2111 | saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); | ||
2112 | for (i = 0; i < 12; i++) /* setup mmu page table */ | ||
2113 | saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096)); | ||
2114 | #endif | ||
2115 | saa->audhead = saa->vidhead = saa->osdhead = 0; | ||
2116 | saa->audtail = saa->vidtail = saa->osdtail = 0; | ||
2117 | if (saa->vidbuf == NULL) | ||
2118 | if ((saa->vidbuf = vmalloc(524288)) == NULL) { | ||
2119 | printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); | ||
2120 | return -ENOMEM; | ||
2121 | } | ||
2122 | if (saa->audbuf == NULL) | ||
2123 | if ((saa->audbuf = vmalloc(65536)) == NULL) { | ||
2124 | printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); | ||
2125 | vfree(saa->vidbuf); | ||
2126 | saa->vidbuf = NULL; | ||
2127 | return -ENOMEM; | ||
2128 | } | ||
2129 | if (saa->osdbuf == NULL) | ||
2130 | if ((saa->osdbuf = vmalloc(131072)) == NULL) { | ||
2131 | printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); | ||
2132 | vfree(saa->vidbuf); | ||
2133 | vfree(saa->audbuf); | ||
2134 | saa->vidbuf = saa->audbuf = NULL; | ||
2135 | return -ENOMEM; | ||
2136 | } | ||
2137 | /* allocate 81920 byte buffer for clipping */ | ||
2138 | if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { | ||
2139 | printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr); | ||
2140 | vfree(saa->vidbuf); | ||
2141 | vfree(saa->audbuf); | ||
2142 | vfree(saa->osdbuf); | ||
2143 | saa->vidbuf = saa->audbuf = saa->osdbuf = NULL; | ||
2144 | saa->dmavid2 = NULL; | ||
2145 | return -1; | ||
2146 | } | ||
2147 | memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */ | ||
2148 | /* setup clipping registers */ | ||
2149 | saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); | ||
2150 | saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); | ||
2151 | saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE, | ||
2152 | SAA7146_PROT_ADDR2); | ||
2153 | saawrite(256, SAA7146_PITCH2); | ||
2154 | saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ | ||
2155 | saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, | ||
2156 | SAA7146_MC2); | ||
2157 | I2CBusScan(saa); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | static void release_saa(void) | ||
2162 | { | ||
2163 | u8 command; | ||
2164 | int i; | ||
2165 | struct saa7146 *saa; | ||
2166 | |||
2167 | for (i = 0; i < saa_num; i++) { | ||
2168 | saa = &saa7146s[i]; | ||
2169 | |||
2170 | /* turn off all capturing, DMA and IRQs */ | ||
2171 | saawrite(0xffff0000, SAA7146_MC1); /* reset chip */ | ||
2172 | saawrite(0, SAA7146_MC2); | ||
2173 | saawrite(0, SAA7146_IER); | ||
2174 | saawrite(0xffffffffUL, SAA7146_ISR); | ||
2175 | |||
2176 | /* disable PCI bus-mastering */ | ||
2177 | pci_read_config_byte(saa->dev, PCI_COMMAND, &command); | ||
2178 | command &= ~PCI_COMMAND_MASTER; | ||
2179 | pci_write_config_byte(saa->dev, PCI_COMMAND, command); | ||
2180 | |||
2181 | /* unmap and free memory */ | ||
2182 | saa->audhead = saa->audtail = saa->osdhead = 0; | ||
2183 | saa->vidhead = saa->vidtail = saa->osdtail = 0; | ||
2184 | vfree(saa->vidbuf); | ||
2185 | vfree(saa->audbuf); | ||
2186 | vfree(saa->osdbuf); | ||
2187 | if (saa->dmavid2) | ||
2188 | kfree((void *) saa->dmavid2); | ||
2189 | saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; | ||
2190 | saa->dmavid2 = NULL; | ||
2191 | if (saa->dmadebi) | ||
2192 | kfree((void *) saa->dmadebi); | ||
2193 | if (saa->dmavid1) | ||
2194 | kfree((void *) saa->dmavid1); | ||
2195 | if (saa->dmavid2) | ||
2196 | kfree((void *) saa->dmavid2); | ||
2197 | if (saa->dmavid3) | ||
2198 | kfree((void *) saa->dmavid3); | ||
2199 | if (saa->dmaa1in) | ||
2200 | kfree((void *) saa->dmaa1in); | ||
2201 | if (saa->dmaa1out) | ||
2202 | kfree((void *) saa->dmaa1out); | ||
2203 | if (saa->dmaa2in) | ||
2204 | kfree((void *) saa->dmaa2in); | ||
2205 | if (saa->dmaa2out) | ||
2206 | kfree((void *) saa->dmaa2out); | ||
2207 | if (saa->dmaRPS1) | ||
2208 | kfree((void *) saa->dmaRPS1); | ||
2209 | if (saa->dmaRPS2) | ||
2210 | kfree((void *) saa->dmaRPS2); | ||
2211 | free_irq(saa->irq, saa); | ||
2212 | if (saa->saa7146_mem) | ||
2213 | iounmap(saa->saa7146_mem); | ||
2214 | if (saa->video_dev.minor != -1) | ||
2215 | video_unregister_device(&saa->video_dev); | ||
2216 | } | ||
2217 | } | ||
2218 | |||
2219 | |||
2220 | static int __init stradis_init (void) | ||
2221 | { | ||
2222 | struct pci_dev *dev = NULL; | ||
2223 | int result = 0, i; | ||
2224 | |||
2225 | saa_num = 0; | ||
2226 | |||
2227 | while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) { | ||
2228 | if (!dev->subsystem_vendor) | ||
2229 | printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num); | ||
2230 | else | ||
2231 | printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); | ||
2232 | result = configure_saa7146(dev, saa_num++); | ||
2233 | if (result) | ||
2234 | return result; | ||
2235 | } | ||
2236 | if (saa_num) | ||
2237 | printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num); | ||
2238 | else | ||
2239 | return -EINVAL; | ||
2240 | for (i = 0; i < saa_num; i++) | ||
2241 | if (init_saa7146(i) < 0) { | ||
2242 | release_saa(); | ||
2243 | return -EIO; | ||
2244 | } | ||
2245 | return 0; | ||
2246 | } | ||
2247 | |||
2248 | |||
2249 | static void __exit stradis_exit (void) | ||
2250 | { | ||
2251 | release_saa(); | ||
2252 | printk(KERN_INFO "stradis: module cleanup complete\n"); | ||
2253 | } | ||
2254 | |||
2255 | |||
2256 | module_init(stradis_init); | ||
2257 | module_exit(stradis_exit); | ||
2258 | |||