blob: 54fc33011ffb4b1b1b03cea41bea8b04eaa77c46 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Jiri Slabyf823f672006-01-11 19:41:32 -020052#define DEBUG(x) /* debug driver */
53#undef IDEBUG /* debug irq handler */
54#undef MDEBUG /* debug memory management */
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define SAA7146_MAX 6
57
58static struct saa7146 saa7146s[SAA7146_MAX];
59
60static int saa_num = 0; /* number of SAA7146s in use */
61
62static int video_nr = -1;
63module_param(video_nr, int, 0);
64MODULE_LICENSE("GPL");
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#define nDebNormal 0x00480000
67#define nDebNoInc 0x00480000
68#define nDebVideo 0xd0480000
69#define nDebAudio 0xd0400000
70#define nDebDMA 0x02c80000
71
72#define oDebNormal 0x13c80000
73#define oDebNoInc 0x13c80000
74#define oDebVideo 0xd1080000
75#define oDebAudio 0xd1080000
76#define oDebDMA 0x03080000
77
78#define NewCard (saa->boardcfg[3])
79#define ChipControl (saa->boardcfg[1])
80#define NTSCFirstActive (saa->boardcfg[4])
81#define PALFirstActive (saa->boardcfg[5])
82#define NTSCLastActive (saa->boardcfg[54])
83#define PALLastActive (saa->boardcfg[55])
84#define Have2MB (saa->boardcfg[18] & 0x40)
85#define HaveCS8420 (saa->boardcfg[18] & 0x04)
86#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20)
87#define HaveCS3310 (saa->boardcfg[18] & 0x01)
88#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31])
89#define HaveCS4341 (saa->boardcfg[40] == 2)
90#define SDIType (saa->boardcfg[27])
91#define CurrentMode (saa->boardcfg[2])
92
93#define debNormal (NewCard ? nDebNormal : oDebNormal)
94#define debNoInc (NewCard ? nDebNoInc : oDebNoInc)
95#define debVideo (NewCard ? nDebVideo : oDebVideo)
96#define debAudio (NewCard ? nDebAudio : oDebAudio)
97#define debDMA (NewCard ? nDebDMA : oDebDMA)
98
99#ifdef USE_RESCUE_EEPROM_SDM275
100static unsigned char rescue_eeprom[64] = {
Jiri Slabyf823f672006-01-11 19:41:32 -0200101 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
102 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
103 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
104 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
105 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107};
108#endif
109
110/* ----------------------------------------------------------------------- */
111/* Hardware I2C functions */
112static void I2CWipe(struct saa7146 *saa)
113{
114 int i;
115 /* set i2c to ~=100kHz, abort transfer, clear busy */
116 saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
117 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
118 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
119 /* wait for i2c registers to be programmed */
120 for (i = 0; i < 1000 &&
121 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
122 schedule();
123 saawrite(0x600, SAA7146_I2C_STATUS);
124 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
125 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
126 /* wait for i2c registers to be programmed */
127 for (i = 0; i < 1000 &&
128 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
129 schedule();
130 saawrite(0x600, SAA7146_I2C_STATUS);
131 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
132 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
133 /* wait for i2c registers to be programmed */
134 for (i = 0; i < 1000 &&
135 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
136 schedule();
137}
138
139/* read I2C */
140static int I2CRead(struct saa7146 *saa, unsigned char addr,
141 unsigned char subaddr, int dosub)
142{
143 int i;
144
145 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
146 I2CWipe(saa);
Jiri Slabyf823f672006-01-11 19:41:32 -0200147 for (i = 0;
148 i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
149 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 schedule();
151 if (i == 1000)
152 I2CWipe(saa);
153 if (dosub)
154 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200155 ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 else
157 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200158 0xf1, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
160 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
161 /* wait for i2c registers to be programmed */
162 for (i = 0; i < 1000 &&
163 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
164 schedule();
165 /* wait for valid data */
166 for (i = 0; i < 1000 &&
167 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
168 schedule();
169 if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
170 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200171 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 printk("i2c setup read timeout\n");
173 saawrite(0x41, SAA7146_I2C_TRANSFER);
174 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
175 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
176 /* wait for i2c registers to be programmed */
177 for (i = 0; i < 1000 &&
178 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
179 schedule();
180 /* wait for valid data */
181 for (i = 0; i < 1000 &&
182 (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
183 schedule();
184 if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
185 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200186 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 printk("i2c read timeout\n");
188 return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
189}
190
191/* set both to write both bytes, reset it to write only b1 */
192
193static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
194 unsigned char b2, int both)
195{
196 int i;
197 u32 data;
198
199 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
200 I2CWipe(saa);
201 for (i = 0; i < 1000 &&
202 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
203 schedule();
204 if (i == 1000)
205 I2CWipe(saa);
206 data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
207 if (both)
208 data |= ((b2 & 0xff) << 8) | 0xe5;
209 else
210 data |= 0xd1;
211 saawrite(data, SAA7146_I2C_TRANSFER);
212 saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
213 SAA7146_MC2);
214 return 0;
215}
216
217static void attach_inform(struct saa7146 *saa, int id)
218{
219 int i;
220
Jiri Slabyf823f672006-01-11 19:41:32 -0200221 DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
222 id));
223 if (id == 0xa0) { /* we have rev2 or later board, fill in info */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 for (i = 0; i < 64; i++)
225 saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
226#ifdef USE_RESCUE_EEPROM_SDM275
227 if (saa->boardcfg[0] != 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200228 printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
229 "BEEN IGNORED\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 for (i = 0; i < 64; i++)
231 saa->boardcfg[i] = rescue_eeprom[i];
232 }
233#endif
234 printk("stradis%d: config =", saa->nr);
235 for (i = 0; i < 51; i++) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200236 printk(" %02x", saa->boardcfg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
238 printk("\n");
239 }
240}
241
242static void I2CBusScan(struct saa7146 *saa)
243{
244 int i;
245 for (i = 0; i < 0xff; i += 2)
246 if ((I2CRead(saa, i, 0, 0)) >= 0)
247 attach_inform(saa, i);
248}
249
250static int debiwait_maxwait = 0;
251
252static int wait_for_debi_done(struct saa7146 *saa)
253{
254 int i;
255
256 /* wait for registers to be programmed */
257 for (i = 0; i < 100000 &&
258 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
259 saaread(SAA7146_MC2);
260 /* wait for transfer to complete */
261 for (i = 0; i < 500000 &&
262 (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
263 saaread(SAA7146_MC2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200264
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 if (i > debiwait_maxwait)
266 printk("wait-for-debi-done maxwait: %d\n",
267 debiwait_maxwait = i);
Jiri Slabyf823f672006-01-11 19:41:32 -0200268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (i == 500000)
270 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 return 0;
273}
274
275static int debiwrite(struct saa7146 *saa, u32 config, int addr,
Jiri Slabyf823f672006-01-11 19:41:32 -0200276 u32 val, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
278 u32 cmd;
279 if (count <= 0 || count > 32764)
280 return -1;
281 if (wait_for_debi_done(saa) < 0)
282 return -1;
283 saawrite(config, SAA7146_DEBI_CONFIG);
284 if (count <= 4) /* immediate transfer */
285 saawrite(val, SAA7146_DEBI_AD);
286 else /* block transfer */
287 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
288 saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
289 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
290 SAA7146_MC2);
291 return 0;
292}
293
294static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
295{
296 u32 result = 0;
297
298 if (count > 32764 || count <= 0)
299 return 0;
300 if (wait_for_debi_done(saa) < 0)
301 return 0;
302 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
303 saawrite((count << 17) | 0x10000 | (addr & 0xffff),
304 SAA7146_DEBI_COMMAND);
305 saawrite(config, SAA7146_DEBI_CONFIG);
306 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
307 SAA7146_MC2);
308 if (count > 4) /* not an immediate transfer */
309 return count;
310 wait_for_debi_done(saa);
311 result = saaread(SAA7146_DEBI_AD);
312 if (count == 1)
313 result &= 0xff;
314 if (count == 2)
315 result &= 0xffff;
316 if (count == 3)
317 result &= 0xffffff;
318 return result;
319}
320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321static void do_irq_send_data(struct saa7146 *saa)
322{
323 int split, audbytes, vidbytes;
324
325 saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
326 /* if special feature mode in effect, disable audio sending */
327 if (saa->playmode != VID_PLAY_NORMAL)
328 saa->audtail = saa->audhead = 0;
329 if (saa->audhead <= saa->audtail)
330 audbytes = saa->audtail - saa->audhead;
331 else
332 audbytes = 65536 - (saa->audhead - saa->audtail);
333 if (saa->vidhead <= saa->vidtail)
334 vidbytes = saa->vidtail - saa->vidhead;
335 else
336 vidbytes = 524288 - (saa->vidhead - saa->vidtail);
337 if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
338 saawrite(0, SAA7146_IER);
339 return;
340 }
341 /* if at least 1 block audio waiting and audio fifo isn't full */
Jiri Slabyf823f672006-01-11 19:41:32 -0200342 if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
343 & 0xff) < 60) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (saa->audhead > saa->audtail)
345 split = 65536 - saa->audhead;
346 else
347 split = 0;
348 audbytes = 2048;
349 if (split > 0 && split < 2048) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200350 memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 saa->audhead = 0;
352 audbytes -= split;
353 } else
354 split = 0;
355 memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
356 audbytes);
357 saa->audhead += audbytes;
358 saa->audhead &= 0xffff;
Jiri Slabyf823f672006-01-11 19:41:32 -0200359 debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
360 IBM_MP2_AUD_FIFOW), 0, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 wake_up_interruptible(&saa->audq);
Jiri Slabyf823f672006-01-11 19:41:32 -0200362 /* if at least 1 block video waiting and video fifo isn't full */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 } else if (vidbytes >= 30720 && (debiread(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -0200364 IBM_MP2_FIFO, 2)) < 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (saa->vidhead > saa->vidtail)
366 split = 524288 - saa->vidhead;
367 else
368 split = 0;
369 vidbytes = 30720;
370 if (split > 0 && split < 30720) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200371 memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 saa->vidhead = 0;
373 vidbytes -= split;
374 } else
375 split = 0;
376 memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
377 vidbytes);
378 saa->vidhead += vidbytes;
379 saa->vidhead &= 0x7ffff;
380 debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
Jiri Slabyf823f672006-01-11 19:41:32 -0200381 IBM_MP2_FIFOW), 0, 30720);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 wake_up_interruptible(&saa->vidq);
383 }
384 saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
385}
386
387static void send_osd_data(struct saa7146 *saa)
388{
389 int size = saa->osdtail - saa->osdhead;
390 if (size > 30720)
391 size = 30720;
392 /* ensure some multiple of 8 bytes is transferred */
Jiri Slabyf823f672006-01-11 19:41:32 -0200393 size = 8 * ((size + 8) >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 if (size) {
395 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
Jiri Slabyf823f672006-01-11 19:41:32 -0200396 (saa->osdhead >> 3), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
398 saa->osdhead += size;
399 /* block transfer of next 8 bytes to ~32k bytes */
400 debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
401 }
402 if (saa->osdhead >= saa->osdtail) {
403 saa->osdhead = saa->osdtail = 0;
404 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
405 }
406}
407
408static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
409{
Jiri Slabyf823f672006-01-11 19:41:32 -0200410 struct saa7146 *saa = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 u32 stat, astat;
412 int count;
413 int handled = 0;
414
415 count = 0;
416 while (1) {
417 /* get/clear interrupt status bits */
418 stat = saaread(SAA7146_ISR);
419 astat = stat & saaread(SAA7146_IER);
420 if (!astat)
421 break;
422 handled = 1;
423 saawrite(astat, SAA7146_ISR);
424 if (astat & SAA7146_PSR_DEBI_S) {
425 do_irq_send_data(saa);
426 }
427 if (astat & SAA7146_PSR_PIN1) {
428 int istat;
429 /* the following read will trigger DEBI_S */
430 istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
431 if (istat & 1) {
432 saawrite(0, SAA7146_IER);
433 send_osd_data(saa);
434 saawrite(SAA7146_PSR_DEBI_S |
435 SAA7146_PSR_PIN1, SAA7146_IER);
436 }
437 if (istat & 0x20) { /* Video Start */
438 saa->vidinfo.frame_count++;
439 }
440 if (istat & 0x400) { /* Picture Start */
441 /* update temporal reference */
442 }
443 if (istat & 0x200) { /* Picture Resolution Change */
444 /* read new resolution */
445 }
446 if (istat & 0x100) { /* New User Data found */
447 /* read new user data */
448 }
449 if (istat & 0x1000) { /* new GOP/SMPTE */
450 /* read new SMPTE */
451 }
452 if (istat & 0x8000) { /* Sequence Start Code */
453 /* reset frame counter, load sizes */
454 saa->vidinfo.frame_count = 0;
455 saa->vidinfo.h_size = 704;
456 saa->vidinfo.v_size = 480;
457#if 0
458 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200459 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 saa->endmark[saa->endmarkhead];
461 saa->endmarkhead++;
462 if (saa->endmarkhead >= MAX_MARKS)
463 saa->endmarkhead = 0;
464 }
465#endif
466 }
467 if (istat & 0x4000) { /* Sequence Error Code */
468 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200469 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 saa->endmark[saa->endmarkhead];
471 saa->endmarkhead++;
472 if (saa->endmarkhead >= MAX_MARKS)
473 saa->endmarkhead = 0;
474 }
475 }
476 }
477#ifdef IDEBUG
478 if (astat & SAA7146_PSR_PPEF) {
479 IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
480 }
481 if (astat & SAA7146_PSR_PABO) {
482 IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
483 }
484 if (astat & SAA7146_PSR_PPED) {
485 IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
486 }
487 if (astat & SAA7146_PSR_RPS_I1) {
488 IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
489 }
490 if (astat & SAA7146_PSR_RPS_I0) {
491 IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
492 }
493 if (astat & SAA7146_PSR_RPS_LATE1) {
494 IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
495 }
496 if (astat & SAA7146_PSR_RPS_LATE0) {
497 IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
498 }
499 if (astat & SAA7146_PSR_RPS_E1) {
500 IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
501 }
502 if (astat & SAA7146_PSR_RPS_E0) {
503 IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
504 }
505 if (astat & SAA7146_PSR_RPS_TO1) {
506 IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
507 }
508 if (astat & SAA7146_PSR_RPS_TO0) {
509 IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
510 }
511 if (astat & SAA7146_PSR_UPLD) {
512 IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
513 }
514 if (astat & SAA7146_PSR_DEBI_E) {
515 IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
516 }
517 if (astat & SAA7146_PSR_I2C_S) {
518 IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
519 }
520 if (astat & SAA7146_PSR_I2C_E) {
521 IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
522 }
523 if (astat & SAA7146_PSR_A2_IN) {
524 IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
525 }
526 if (astat & SAA7146_PSR_A2_OUT) {
527 IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
528 }
529 if (astat & SAA7146_PSR_A1_IN) {
530 IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
531 }
532 if (astat & SAA7146_PSR_A1_OUT) {
533 IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
534 }
535 if (astat & SAA7146_PSR_AFOU) {
536 IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
537 }
538 if (astat & SAA7146_PSR_V_PE) {
539 IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
540 }
541 if (astat & SAA7146_PSR_VFOU) {
542 IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
543 }
544 if (astat & SAA7146_PSR_FIDA) {
545 IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
546 }
547 if (astat & SAA7146_PSR_FIDB) {
548 IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
549 }
550 if (astat & SAA7146_PSR_PIN3) {
551 IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
552 }
553 if (astat & SAA7146_PSR_PIN2) {
554 IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
555 }
556 if (astat & SAA7146_PSR_PIN0) {
557 IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
558 }
559 if (astat & SAA7146_PSR_ECS) {
560 IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
561 }
562 if (astat & SAA7146_PSR_EC3S) {
563 IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
564 }
565 if (astat & SAA7146_PSR_EC0S) {
566 IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
567 }
568#endif
569 count++;
570 if (count > 15)
571 printk(KERN_WARNING "stradis%d: irq loop %d\n",
572 saa->nr, count);
573 if (count > 20) {
574 saawrite(0, SAA7146_IER);
575 printk(KERN_ERR
576 "stradis%d: IRQ loop cleared\n", saa->nr);
577 }
578 }
579 return IRQ_RETVAL(handled);
580}
581
582static int ibm_send_command(struct saa7146 *saa,
583 int command, int data, int chain)
584{
585 int i;
586
587 if (chain)
Jiri Slabyf823f672006-01-11 19:41:32 -0200588 debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 else
590 debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
591 debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
592 debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
593 for (i = 0; i < 100 &&
594 (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
595 schedule();
596 if (i == 100)
597 return -1;
598 return 0;
599}
600
601static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
602{
603 I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
604 I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
605}
606
607static void initialize_cs4341(struct saa7146 *saa)
608{
609 int i;
610 for (i = 0; i < 200; i++) {
611 /* auto mute off, power on, no de-emphasis */
612 /* I2S data up to 24-bit 64xFs internal SCLK */
613 I2CWrite(saa, 0x22, 0x01, 0x11, 2);
614 /* ATAPI mixer settings */
615 I2CWrite(saa, 0x22, 0x02, 0x49, 2);
616 /* attenuation left 3db */
617 I2CWrite(saa, 0x22, 0x03, 0x00, 2);
618 /* attenuation right 3db */
619 I2CWrite(saa, 0x22, 0x04, 0x00, 2);
620 I2CWrite(saa, 0x22, 0x01, 0x10, 2);
621 if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
622 break;
623 schedule();
624 }
625 printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
626 return;
627}
628
629static void initialize_cs8420(struct saa7146 *saa, int pro)
630{
631 int i;
632 u8 *sequence;
633 if (pro)
634 sequence = mode8420pro;
635 else
636 sequence = mode8420con;
637 for (i = 0; i < INIT8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200638 I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 for (i = 0; i < MODE8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200640 I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 printk("stradis%d: CS8420 initialized\n", saa->nr);
642}
643
644static void initialize_saa7121(struct saa7146 *saa, int dopal)
645{
646 int i, mod;
647 u8 *sequence;
648 if (dopal)
649 sequence = init7121pal;
650 else
651 sequence = init7121ntsc;
652 mod = saaread(SAA7146_PSR) & 0x08;
653 /* initialize PAL/NTSC video encoder */
654 for (i = 0; i < INIT7121LEN; i++) {
655 if (NewCard) { /* handle new card encoder differences */
Jiri Slabyf823f672006-01-11 19:41:32 -0200656 if (sequence[i * 2] == 0x3a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200658 else if (sequence[i * 2] == 0x6b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200660 else if (sequence[i * 2] == 0x6c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 I2CWrite(saa, 0x88, 0x6c,
662 dopal ? 0x09 : 0xf5, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200663 else if (sequence[i * 2] == 0x6d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 I2CWrite(saa, 0x88, 0x6d,
665 dopal ? 0x20 : 0x00, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200666 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 I2CWrite(saa, 0x88, 0x7a,
668 dopal ? (PALFirstActive - 1) :
669 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200670 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 I2CWrite(saa, 0x88, 0x7b,
672 dopal ? PALLastActive :
673 NTSCLastActive, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200674 else
675 I2CWrite(saa, 0x88, sequence[i * 2],
676 sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -0200678 if (sequence[i * 2] == 0x6b && mod)
679 I2CWrite(saa, 0x88, 0x6b,
680 (sequence[i * 2 + 1] ^ 0x09), 2);
681 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 I2CWrite(saa, 0x88, 0x7a,
683 dopal ? (PALFirstActive - 1) :
684 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200685 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 I2CWrite(saa, 0x88, 0x7b,
687 dopal ? PALLastActive :
688 NTSCLastActive, 2);
689 else
690 I2CWrite(saa, 0x88, sequence[i * 2],
691 sequence[i * 2 + 1], 2);
692 }
693 }
694}
695
696static void set_genlock_offset(struct saa7146 *saa, int noffset)
697{
698 int nCode;
699 int PixelsPerLine = 858;
700 if (CurrentMode == VIDEO_MODE_PAL)
701 PixelsPerLine = 864;
702 if (noffset > 500)
703 noffset = 500;
704 else if (noffset < -500)
705 noffset = -500;
706 nCode = noffset + 0x100;
707 if (nCode == 1)
708 nCode = 0x401;
Jiri Slabyf823f672006-01-11 19:41:32 -0200709 else if (nCode < 1)
710 nCode = 0x400 + PixelsPerLine + nCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
712}
713
714static void set_out_format(struct saa7146 *saa, int mode)
715{
716 initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
717 saa->boardcfg[2] = mode;
718 /* do not adjust analog video parameters here, use saa7121 init */
719 /* you will affect the SDI output on the new card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200720 if (mode == VIDEO_MODE_PAL) { /* PAL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
722 mdelay(50);
723 saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
724 if (NewCard) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200725 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 mdelay(50);
727 }
728 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200729 NewCard ? 0xe500 : 0x6500, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
731 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200732 (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 } else { /* NTSC */
734 debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
735 mdelay(50);
736 saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
737 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200738 NewCard ? 0xe100 : 0x6100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
740 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200741 (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
743}
744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745/* Intialize bitmangler to map from a byte value to the mangled word that
746 * must be output to program the Xilinx part through the DEBI port.
747 * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
748 * transfer FPGA code, init IBM chip, transfer IBM microcode
749 * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
750 */
751static u16 bitmangler[256];
752
753static int initialize_fpga(struct video_code *bitdata)
754{
755 int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
756 u16 *dmabuf;
757 u8 *newdma;
758 struct saa7146 *saa;
759
760 /* verify fpga code */
761 for (startindex = 0; startindex < bitdata->datasize; startindex++)
762 if (bitdata->data[startindex] == 255)
763 break;
764 if (startindex == bitdata->datasize) {
765 printk(KERN_INFO "stradis: bad fpga code\n");
766 return -1;
767 }
768 /* initialize all detected cards */
769 for (num = 0; num < saa_num; num++) {
770 saa = &saa7146s[num];
771 if (saa->boardcfg[0] > 20)
Jiri Slabyf823f672006-01-11 19:41:32 -0200772 continue; /* card was programmed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 loadtwo = (saa->boardcfg[18] & 0x10);
774 if (!NewCard) /* we have an old board */
775 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200776 bitmangler[i] = ((i & 0x01) << 15) |
777 ((i & 0x02) << 6) | ((i & 0x04) << 4) |
778 ((i & 0x08) << 9) | ((i & 0x10) << 7) |
779 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
780 ((i & 0x80) >> 7);
781 else /* else we have a new board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200783 bitmangler[i] = ((i & 0x01) << 7) |
784 ((i & 0x02) << 5) | ((i & 0x04) << 3) |
785 ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
786 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
787 ((i & 0x80) >> 7);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 dmabuf = (u16 *) saa->dmadebi;
790 newdma = (u8 *) saa->dmadebi;
791 if (NewCard) { /* SDM2xxx */
792 if (!strncmp(bitdata->loadwhat, "decoder2", 8))
793 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200794 if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 loadfile = 1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200796 else if (loadtwo && !strncmp(&saa->boardcfg[19],
797 bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 loadfile = 2;
Jiri Slabyf823f672006-01-11 19:41:32 -0200799 else if (!saa->boardcfg[42] && !strncmp("decxl",
800 bitdata->loadwhat, 8))
801 loadfile = 1; /* special */
802 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200804 if (loadfile != 1 && loadfile != 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 continue; /* skip to next card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200806 if (saa->boardcfg[0] && loadfile == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 continue; /* skip to next card */
808 if (saa->boardcfg[0] != 1 && loadfile == 2)
809 continue; /* skip to next card */
810 saa->boardcfg[0]++; /* mark fpga handled */
811 printk("stradis%d: loading %s\n", saa->nr,
812 bitdata->loadwhat);
813 if (loadtwo && loadfile == 2)
814 goto send_fpga_stuff;
815 /* turn on the Audio interface to set PROG low */
816 saawrite(0x00400040, SAA7146_GPIO_CTRL);
817 saaread(SAA7146_PSR); /* ensure posted write */
818 /* wait for everyone to reset */
819 mdelay(10);
820 saawrite(0x00400000, SAA7146_GPIO_CTRL);
821 } else { /* original card */
822 if (strncmp(bitdata->loadwhat, "decoder2", 8))
823 continue; /* fpga not for this card */
824 /* Pull the Xilinx PROG signal WS3 low */
825 saawrite(0x02000200, SAA7146_MC1);
826 /* Turn on the Audio interface so can set PROG low */
827 saawrite(0x000000c0, SAA7146_ACON1);
828 /* Pull the Xilinx INIT signal (GPIO2) low */
829 saawrite(0x00400000, SAA7146_GPIO_CTRL);
830 /* Make sure everybody resets */
831 saaread(SAA7146_PSR); /* ensure posted write */
832 mdelay(10);
833 /* Release the Xilinx PROG signal */
834 saawrite(0x00000000, SAA7146_ACON1);
835 /* Turn off the Audio interface */
836 saawrite(0x02000000, SAA7146_MC1);
837 }
838 /* Release Xilinx INIT signal (WS2) */
839 saawrite(0x00000000, SAA7146_GPIO_CTRL);
840 /* Wait for the INIT to go High */
Jiri Slabyf823f672006-01-11 19:41:32 -0200841 for (i = 0;
842 i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
843 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 schedule();
845 if (i == 1000) {
846 printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
847 return -1;
848 }
849send_fpga_stuff:
850 if (NewCard) {
851 for (i = startindex; i < bitdata->datasize; i++)
852 newdma[i - startindex] =
Jiri Slabyf823f672006-01-11 19:41:32 -0200853 bitmangler[bitdata->data[i]];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 debiwrite(saa, 0x01420000, 0, 0,
855 ((bitdata->datasize - startindex) + 5));
Jiri Slabyf823f672006-01-11 19:41:32 -0200856 if (loadtwo && loadfile == 1) {
857 printk("stradis%d: awaiting 2nd FPGA bitfile\n",
858 saa->nr);
859 continue; /* skip to next card */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
861 } else {
862 for (i = startindex; i < bitdata->datasize; i++)
863 dmabuf[i - startindex] =
864 bitmangler[bitdata->data[i]];
865 debiwrite(saa, 0x014a0000, 0, 0,
866 ((bitdata->datasize - startindex) + 5) * 2);
867 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200868 for (i = 0;
869 i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
870 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 schedule();
872 if (i == 1000) {
873 printk(KERN_INFO "stradis%d: FPGA load failed\n",
874 saa->nr);
875 failure++;
876 continue;
877 }
878 if (!NewCard) {
879 /* Pull the Xilinx INIT signal (GPIO2) low */
880 saawrite(0x00400000, SAA7146_GPIO_CTRL);
881 saaread(SAA7146_PSR); /* ensure posted write */
882 mdelay(2);
883 saawrite(0x00000000, SAA7146_GPIO_CTRL);
884 mdelay(2);
885 }
886 printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
887 saa->boardcfg[0] = 26; /* mark fpga programmed */
888 /* set VXCO to its lowest frequency */
889 debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
890 if (NewCard) {
891 /* mute CS3310 */
892 if (HaveCS3310)
893 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
Jiri Slabyf823f672006-01-11 19:41:32 -0200894 0, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 /* set VXCO to PWM mode, release reset, blank on */
896 debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
897 mdelay(10);
898 /* unmute CS3310 */
899 if (HaveCS3310)
900 debiwrite(saa, debNormal, XILINX_CTL0,
Jiri Slabyf823f672006-01-11 19:41:32 -0200901 0x2020, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
903 /* set source Black */
904 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
905 saa->boardcfg[4] = 22; /* set NTSC First Active Line */
906 saa->boardcfg[5] = 23; /* set PAL First Active Line */
907 saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */
908 saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */
909 set_out_format(saa, VIDEO_MODE_NTSC);
910 mdelay(50);
911 /* begin IBM chip init */
912 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
913 saaread(SAA7146_PSR); /* wait for reset */
914 mdelay(5);
915 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
916 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
917 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
918 debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
919 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
920 if (NewCard) {
921 mdelay(5);
922 /* set i2s rate converter to 48KHz */
923 debiwrite(saa, debNormal, 0x80c0, 6, 2);
924 /* we must init CS8420 first since rev b pulls i2s */
925 /* master clock low and CS4341 needs i2s master to */
926 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200927 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 /* 0=consumer, 1=pro */
929 initialize_cs8420(saa, 0);
Jiri Slabyf823f672006-01-11 19:41:32 -0200930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 mdelay(5);
932 if (HaveCS4341)
933 initialize_cs4341(saa);
934 }
935 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
936 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
937 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
938 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
939 if (NewCard)
940 set_genlock_offset(saa, 0);
941 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
942#if 0
943 /* enable genlock */
944 debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
945#else
946 /* disable genlock */
947 debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
948#endif
949 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 return failure;
952}
953
954static int do_ibm_reset(struct saa7146 *saa)
955{
956 /* failure if decoder not previously programmed */
957 if (saa->boardcfg[0] < 37)
958 return -EIO;
959 /* mute CS3310 */
960 if (HaveCS3310)
961 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
962 /* disable interrupts */
963 saawrite(0, SAA7146_IER);
964 saa->audhead = saa->audtail = 0;
965 saa->vidhead = saa->vidtail = 0;
966 /* tristate debi bus, disable debi transfers */
967 saawrite(0x00880000, SAA7146_MC1);
968 /* ensure posted write */
969 saaread(SAA7146_MC1);
970 mdelay(50);
971 /* re-enable debi transfers */
972 saawrite(0x00880088, SAA7146_MC1);
973 /* set source Black */
974 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
975 /* begin IBM chip init */
976 set_out_format(saa, CurrentMode);
977 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
978 saaread(SAA7146_PSR); /* wait for reset */
979 mdelay(5);
980 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
981 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
982 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
983 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
984 if (NewCard) {
985 mdelay(5);
986 /* set i2s rate converter to 48KHz */
987 debiwrite(saa, debNormal, 0x80c0, 6, 2);
988 /* we must init CS8420 first since rev b pulls i2s */
989 /* master clock low and CS4341 needs i2s master to */
990 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200991 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 /* 0=consumer, 1=pro */
993 initialize_cs8420(saa, 1);
Jiri Slabyf823f672006-01-11 19:41:32 -0200994
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 mdelay(5);
996 if (HaveCS4341)
997 initialize_cs4341(saa);
998 }
999 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
1000 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
1001 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
1002 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
1003 if (NewCard)
1004 set_genlock_offset(saa, 0);
1005 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
1006 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1007 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1008 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001009 (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
1011 }
1012 if (HaveCS3310) {
1013 int i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001014 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
1016 /* start video decoder */
1017 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1018 /* 256k vid, 3520 bytes aud */
1019 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
1020 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1021 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1022 /* enable buffer threshold irq */
1023 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1024 /* clear pending interrupts */
1025 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1026 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 return 0;
1029}
1030
1031/* load the decoder microcode */
1032static int initialize_ibmmpeg2(struct video_code *microcode)
1033{
1034 int i, num;
1035 struct saa7146 *saa;
1036
1037 for (num = 0; num < saa_num; num++) {
1038 saa = &saa7146s[num];
1039 /* check that FPGA is loaded */
1040 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001041 i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
1042 if (i != 0xa55a) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
1044 saa->nr, i);
1045#if 0
1046 return -1;
1047#endif
1048 }
1049 if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
1050 if (saa->boardcfg[0] > 27)
1051 continue; /* skip to next card */
1052 /* load video control store */
Jiri Slabyf823f672006-01-11 19:41:32 -02001053 saa->boardcfg[1] = 0x13; /* no-sync default */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1055 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1056 for (i = 0; i < microcode->datasize / 2; i++)
1057 debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
1058 (microcode->data[i * 2] << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001059 microcode->data[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1061 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1062 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
Jiri Slabyf823f672006-01-11 19:41:32 -02001063 ChipControl, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 saa->boardcfg[0] = 28;
1065 }
1066 if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
1067 if (saa->boardcfg[0] > 35)
1068 continue; /* skip to next card */
1069 /* load audio control store */
1070 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1071 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1072 for (i = 0; i < microcode->datasize; i++)
1073 debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
1074 microcode->data[i], 1);
1075 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1076 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1077 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1078 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1079 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001080 0xe000, 1)) {
1081 printk(KERN_ERR "stradis%d: IBM config "
1082 "failed\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 return -1;
1084 }
1085 /* set PWM to center value */
1086 if (NewCard) {
1087 debiwrite(saa, debNormal, XILINX_PWM,
Jiri Slabyf823f672006-01-11 19:41:32 -02001088 saa->boardcfg[14] +
1089 (saa->boardcfg[13] << 8), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 } else
Jiri Slabyf823f672006-01-11 19:41:32 -02001091 debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
1092
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 if (HaveCS3310) {
1094 i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001095 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
1096 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001098 printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
1099 saa->nr, 18 + (debiread(saa, debNormal,
1100 IBM_MP2_CHIP_CONTROL, 2) >> 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 /* start video decoder */
1102 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1103 ChipControl, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001104 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
1105 2); /* 256k vid, 3520 bytes aud */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1107 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1108 /* enable buffer threshold irq */
1109 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1110 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1111 /* enable gpio irq */
1112 saawrite(0x00002000, SAA7146_GPIO_CTRL);
1113 /* enable decoder output to HPS */
1114 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
1115 saa->boardcfg[0] = 37;
1116 }
1117 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001118
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 return 0;
1120}
1121
Jiri Slabyf823f672006-01-11 19:41:32 -02001122static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
1123 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
1124 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
1125 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126};
Jiri Slabyf823f672006-01-11 19:41:32 -02001127static int bpp2fmt[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
1129 VIDEO_PALETTE_RGB32
1130};
1131
1132/* I wish I could find a formula to calculate these... */
Jiri Slabyf823f672006-01-11 19:41:32 -02001133static u32 h_prescale[64] = {
1134 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
1135 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
1136 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
1137 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
1138 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
1139 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
1140 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
1141 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
1142 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
1143 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
1144 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145};
Jiri Slabyf823f672006-01-11 19:41:32 -02001146static u32 v_gain[64] = {
1147 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
1148 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
1149 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
1150 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1151 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1152 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1153 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1154 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1155 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1156 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
1157 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158};
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160static void saa7146_set_winsize(struct saa7146 *saa)
1161{
1162 u32 format;
1163 int offset, yacl, ysci;
1164 saa->win.color_fmt = format =
1165 (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
1166 palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
1167 offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
1168 saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
1169 saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
1170 saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
1171 saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
1172 SAA7146_PROT_ADDR1);
1173 saawrite(0, SAA7146_PAGE1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001174 saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 offset = (704 / (saa->win.width - 1)) & 0x3f;
1176 saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
1177 offset = (720896 / saa->win.width) / (offset + 1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001178 saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 if (CurrentMode == VIDEO_MODE_NTSC) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001180 yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 ysci = 1024 - (saa->win.height * 1024 / 480);
1182 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -02001183 yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 ysci = 1024 - (saa->win.height * 1024 / 576);
1185 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001186 saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
1188 saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
Jiri Slabyf823f672006-01-11 19:41:32 -02001189 SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
1190 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191}
1192
1193/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
1194 * bitmap is fixed width, 128 bytes (1024 pixels represented)
1195 * arranged most-sigificant-bit-left in 32-bit words
1196 * based on saa7146 clipping hardware, it swaps bytes if LE
1197 * much of this makes up for egcs brain damage -- so if you
1198 * are wondering "why did he do this?" it is because the C
1199 * was adjusted to generate the optimal asm output without
1200 * writing non-portable __asm__ directives.
1201 */
1202
1203static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
1204{
1205 register int startword, endword;
1206 register u32 bitsleft, bitsright;
1207 u32 *temp;
1208 if (x < 0) {
1209 w += x;
1210 x = 0;
1211 }
1212 if (y < 0) {
1213 h += y;
1214 y = 0;
1215 }
1216 if (w <= 0 || h <= 0 || x > 1023 || y > 639)
1217 return; /* throw away bad clips */
1218 if (x + w > 1024)
1219 w = 1024 - x;
1220 if (y + h > 640)
1221 h = 640 - y;
1222 startword = (x >> 5);
1223 endword = ((x + w) >> 5);
1224 bitsleft = (0xffffffff >> (x & 31));
Jiri Slabyf823f672006-01-11 19:41:32 -02001225 bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
1226 temp = &clipmap[(y << 5) + startword];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 w = endword - startword;
1228 if (!w) {
1229 bitsleft |= bitsright;
1230 for (y = 0; y < h; y++) {
1231 *temp |= bitsleft;
1232 temp += 32;
1233 }
1234 } else {
1235 for (y = 0; y < h; y++) {
1236 *temp++ |= bitsleft;
1237 for (x = 1; x < w; x++)
1238 *temp++ = 0xffffffff;
1239 *temp |= bitsright;
1240 temp += (32 - w);
1241 }
1242 }
1243}
1244
1245static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
1246{
1247 int i, width, height;
1248 u32 *clipmap;
1249
1250 clipmap = saa->dmavid2;
Jiri Slabyf823f672006-01-11 19:41:32 -02001251 if ((width = saa->win.width) > 1023)
1252 width = 1023; /* sanity check */
1253 if ((height = saa->win.height) > 640)
1254 height = 639; /* sanity check */
1255 if (ncr > 0) { /* rectangles pased */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 /* convert rectangular clips to a bitmap */
Jiri Slabyf823f672006-01-11 19:41:32 -02001257 memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 for (i = 0; i < ncr; i++)
1259 clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
1260 cr[i].width, cr[i].height);
1261 }
1262 /* clip against viewing window AND screen
1263 so we do not have to rely on the user program
1264 */
Jiri Slabyf823f672006-01-11 19:41:32 -02001265 clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
1266 (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
1267 clip_draw_rectangle(clipmap, 0,
1268 (saa->win.y + height > saa->win.sheight) ?
1269 (saa->win.sheight - saa->win.y) : height, 1024, 768);
1270 if (saa->win.x < 0)
1271 clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
1272 if (saa->win.y < 0)
1273 clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274}
1275
1276static int saa_ioctl(struct inode *inode, struct file *file,
1277 unsigned int cmd, unsigned long argl)
1278{
1279 struct saa7146 *saa = file->private_data;
1280 void __user *arg = (void __user *)argl;
1281
1282 switch (cmd) {
1283 case VIDIOCGCAP:
1284 {
1285 struct video_capability b;
1286 strcpy(b.name, saa->video_dev.name);
Jiri Slabyf823f672006-01-11 19:41:32 -02001287 b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
1288 VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
1289 VID_TYPE_SCALES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 b.channels = 1;
1291 b.audios = 1;
1292 b.maxwidth = 768;
1293 b.maxheight = 576;
1294 b.minwidth = 32;
1295 b.minheight = 32;
1296 if (copy_to_user(arg, &b, sizeof(b)))
1297 return -EFAULT;
1298 return 0;
1299 }
1300 case VIDIOCGPICT:
1301 {
1302 struct video_picture p = saa->picture;
1303 if (saa->win.depth == 8)
1304 p.palette = VIDEO_PALETTE_HI240;
1305 if (saa->win.depth == 15)
1306 p.palette = VIDEO_PALETTE_RGB555;
1307 if (saa->win.depth == 16)
1308 p.palette = VIDEO_PALETTE_RGB565;
1309 if (saa->win.depth == 24)
1310 p.palette = VIDEO_PALETTE_RGB24;
1311 if (saa->win.depth == 32)
1312 p.palette = VIDEO_PALETTE_RGB32;
1313 if (copy_to_user(arg, &p, sizeof(p)))
1314 return -EFAULT;
1315 return 0;
1316 }
1317 case VIDIOCSPICT:
1318 {
1319 struct video_picture p;
1320 u32 format;
1321 if (copy_from_user(&p, arg, sizeof(p)))
1322 return -EFAULT;
1323 if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
1324 format = palette2fmt[p.palette];
1325 saa->win.color_fmt = format;
Jiri Slabyf823f672006-01-11 19:41:32 -02001326 saawrite(format | 0x60,
1327 SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
1329 saawrite(((p.brightness & 0xff00) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001330 ((p.contrast & 0xfe00) << 7) |
1331 ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 saa->picture = p;
1333 /* upload changed registers */
1334 saawrite(((SAA7146_MC2_UPLD_HPS_H |
Jiri Slabyf823f672006-01-11 19:41:32 -02001335 SAA7146_MC2_UPLD_HPS_V) << 16) |
1336 SAA7146_MC2_UPLD_HPS_H |
1337 SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return 0;
1339 }
1340 case VIDIOCSWIN:
1341 {
1342 struct video_window vw;
1343 struct video_clip *vcp = NULL;
1344
1345 if (copy_from_user(&vw, arg, sizeof(vw)))
1346 return -EFAULT;
1347
Jiri Slabyf823f672006-01-11 19:41:32 -02001348 /* stop capture */
1349 if (vw.flags || vw.width < 16 || vw.height < 16) {
1350 saawrite((SAA7146_MC1_TR_E_1 << 16),
1351 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 return -EINVAL;
1353 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001354 /* 32-bit align start and adjust width */
1355 if (saa->win.bpp < 4) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 int i = vw.x;
1357 vw.x = (vw.x + 3) & ~3;
1358 i = vw.x - i;
1359 vw.width -= i;
1360 }
1361 saa->win.x = vw.x;
1362 saa->win.y = vw.y;
1363 saa->win.width = vw.width;
1364 if (saa->win.width > 768)
1365 saa->win.width = 768;
1366 saa->win.height = vw.height;
1367 if (CurrentMode == VIDEO_MODE_NTSC) {
1368 if (saa->win.height > 480)
1369 saa->win.height = 480;
1370 } else {
1371 if (saa->win.height > 576)
1372 saa->win.height = 576;
1373 }
1374
1375 /* stop capture */
1376 saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
1377 saa7146_set_winsize(saa);
1378
1379 /*
1380 * Do any clips.
1381 */
1382 if (vw.clipcount < 0) {
1383 if (copy_from_user(saa->dmavid2, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001384 VIDEO_CLIPMAP_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001386 } else if (vw.clipcount > 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return -EINVAL;
1388 } else if (vw.clipcount > 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001389 vcp = vmalloc(sizeof(struct video_clip) *
1390 vw.clipcount);
1391 if (vcp == NULL)
1392 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (copy_from_user(vcp, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001394 sizeof(struct video_clip) *
1395 vw.clipcount)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 vfree(vcp);
1397 return -EFAULT;
1398 }
1399 } else /* nothing clipped */
1400 memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
Jiri Slabyf823f672006-01-11 19:41:32 -02001401
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 make_clip_tab(saa, vcp, vw.clipcount);
1403 if (vw.clipcount > 0)
1404 vfree(vcp);
1405
1406 /* start capture & clip dma if we have an address */
1407 if ((saa->cap & 3) && saa->win.vidadr != 0)
1408 saawrite(((SAA7146_MC1_TR_E_1 |
1409 SAA7146_MC1_TR_E_2) << 16) | 0xffff,
1410 SAA7146_MC1);
1411 return 0;
1412 }
1413 case VIDIOCGWIN:
1414 {
1415 struct video_window vw;
1416 vw.x = saa->win.x;
1417 vw.y = saa->win.y;
1418 vw.width = saa->win.width;
1419 vw.height = saa->win.height;
1420 vw.chromakey = 0;
1421 vw.flags = 0;
1422 if (copy_to_user(arg, &vw, sizeof(vw)))
1423 return -EFAULT;
1424 return 0;
1425 }
1426 case VIDIOCCAPTURE:
1427 {
1428 int v;
1429 if (copy_from_user(&v, arg, sizeof(v)))
1430 return -EFAULT;
1431 if (v == 0) {
1432 saa->cap &= ~1;
1433 saawrite((SAA7146_MC1_TR_E_1 << 16),
Jiri Slabyf823f672006-01-11 19:41:32 -02001434 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 } else {
1436 if (saa->win.vidadr == 0 || saa->win.width == 0
Jiri Slabyf823f672006-01-11 19:41:32 -02001437 || saa->win.height == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 return -EINVAL;
1439 saa->cap |= 1;
1440 saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
Jiri Slabyf823f672006-01-11 19:41:32 -02001441 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 }
1443 return 0;
1444 }
1445 case VIDIOCGFBUF:
1446 {
1447 struct video_buffer v;
Jiri Slabyf823f672006-01-11 19:41:32 -02001448 v.base = (void *)saa->win.vidadr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 v.height = saa->win.sheight;
1450 v.width = saa->win.swidth;
1451 v.depth = saa->win.depth;
1452 v.bytesperline = saa->win.bpl;
1453 if (copy_to_user(arg, &v, sizeof(v)))
1454 return -EFAULT;
1455 return 0;
1456
1457 }
1458 case VIDIOCSFBUF:
1459 {
1460 struct video_buffer v;
1461 if (!capable(CAP_SYS_ADMIN))
1462 return -EPERM;
1463 if (copy_from_user(&v, arg, sizeof(v)))
1464 return -EFAULT;
1465 if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
Jiri Slabyf823f672006-01-11 19:41:32 -02001466 v.depth != 24 && v.depth != 32 && v.width > 16 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 v.height > 16 && v.bytesperline > 16)
1468 return -EINVAL;
1469 if (v.base)
Jiri Slabyf823f672006-01-11 19:41:32 -02001470 saa->win.vidadr = (unsigned long)v.base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 saa->win.sheight = v.height;
1472 saa->win.swidth = v.width;
1473 saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
1474 saa->win.depth = v.depth;
1475 saa->win.bpl = v.bytesperline;
1476
Jiri Slabyf823f672006-01-11 19:41:32 -02001477 DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
1478 "bpl %d\n", v.base, v.width, v.height,
1479 saa->win.bpp, saa->win.bpl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 saa7146_set_winsize(saa);
1481 return 0;
1482 }
1483 case VIDIOCKEY:
1484 {
1485 /* Will be handled higher up .. */
1486 return 0;
1487 }
1488
1489 case VIDIOCGAUDIO:
1490 {
1491 struct video_audio v;
1492 v = saa->audio_dev;
1493 v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
1494 v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
1495 strcpy(v.name, "MPEG");
1496 v.mode = VIDEO_SOUND_STEREO;
1497 if (copy_to_user(arg, &v, sizeof(v)))
1498 return -EFAULT;
1499 return 0;
1500 }
1501 case VIDIOCSAUDIO:
1502 {
1503 struct video_audio v;
1504 int i;
1505 if (copy_from_user(&v, arg, sizeof(v)))
1506 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001507 i = (~(v.volume >> 8)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 if (!HaveCS4341) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001509 if (v.flags & VIDEO_AUDIO_MUTE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001511 IBM_MP2_FRNT_ATTEN, 0xffff, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 if (!(v.flags & VIDEO_AUDIO_MUTE))
1513 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001514 IBM_MP2_FRNT_ATTEN, 0x0000, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (v.flags & VIDEO_AUDIO_VOLUME)
1516 debiwrite(saa, debNormal,
1517 IBM_MP2_FRNT_ATTEN,
Jiri Slabyf823f672006-01-11 19:41:32 -02001518 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 } else {
1520 if (v.flags & VIDEO_AUDIO_MUTE)
1521 cs4341_setlevel(saa, 0xff, 0xff);
1522 if (!(v.flags & VIDEO_AUDIO_MUTE))
1523 cs4341_setlevel(saa, 0, 0);
1524 if (v.flags & VIDEO_AUDIO_VOLUME)
1525 cs4341_setlevel(saa, i, i);
1526 }
1527 saa->audio_dev = v;
1528 return 0;
1529 }
1530
1531 case VIDIOCGUNIT:
1532 {
1533 struct video_unit vu;
1534 vu.video = saa->video_dev.minor;
1535 vu.vbi = VIDEO_NO_UNIT;
1536 vu.radio = VIDEO_NO_UNIT;
1537 vu.audio = VIDEO_NO_UNIT;
1538 vu.teletext = VIDEO_NO_UNIT;
1539 if (copy_to_user(arg, &vu, sizeof(vu)))
1540 return -EFAULT;
1541 return 0;
1542 }
1543 case VIDIOCSPLAYMODE:
1544 {
1545 struct video_play_mode pmode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001546 if (copy_from_user((void *)&pmode, arg,
1547 sizeof(struct video_play_mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 return -EFAULT;
1549 switch (pmode.mode) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001550 case VID_PLAY_VID_OUT_MODE:
1551 if (pmode.p1 != VIDEO_MODE_NTSC &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 pmode.p1 != VIDEO_MODE_PAL)
Jiri Slabyf823f672006-01-11 19:41:32 -02001553 return -EINVAL;
1554 set_out_format(saa, pmode.p1);
1555 return 0;
1556 case VID_PLAY_GENLOCK:
1557 debiwrite(saa, debNormal, XILINX_CTL0,
1558 pmode.p1 ? 0x8000 : 0x8080, 2);
1559 if (NewCard)
1560 set_genlock_offset(saa, pmode.p2);
1561 return 0;
1562 case VID_PLAY_NORMAL:
1563 debiwrite(saa, debNormal,
1564 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1565 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1566 saa->playmode = pmode.mode;
1567 return 0;
1568 case VID_PLAY_PAUSE:
1569 /* IBM removed the PAUSE command */
1570 /* they say use SINGLE_FRAME now */
1571 case VID_PLAY_SINGLE_FRAME:
1572 ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
1573 if (saa->playmode == pmode.mode) {
1574 debiwrite(saa, debNormal,
1575 IBM_MP2_CHIP_CONTROL,
1576 ChipControl, 2);
1577 }
1578 saa->playmode = pmode.mode;
1579 return 0;
1580 case VID_PLAY_FAST_FORWARD:
1581 ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
1582 saa->playmode = pmode.mode;
1583 return 0;
1584 case VID_PLAY_SLOW_MOTION:
1585 ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
1586 pmode.p1, 0);
1587 saa->playmode = pmode.mode;
1588 return 0;
1589 case VID_PLAY_IMMEDIATE_NORMAL:
1590 /* ensure transfers resume */
1591 debiwrite(saa, debNormal,
1592 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1593 ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
1594 0, 0);
1595 saa->playmode = VID_PLAY_NORMAL;
1596 return 0;
1597 case VID_PLAY_SWITCH_CHANNELS:
1598 saa->audhead = saa->audtail = 0;
1599 saa->vidhead = saa->vidtail = 0;
1600 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
1601 ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
1602 0, 1);
1603 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1604 0, 2);
1605 ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
1606 0, 1);
1607 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1608 ChipControl, 2);
1609 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1610 saa->playmode = VID_PLAY_NORMAL;
1611 return 0;
1612 case VID_PLAY_FREEZE_FRAME:
1613 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
1614 saa->playmode = pmode.mode;
1615 return 0;
1616 case VID_PLAY_STILL_MODE:
1617 ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
1618 0, 0);
1619 saa->playmode = pmode.mode;
1620 return 0;
1621 case VID_PLAY_MASTER_MODE:
1622 if (pmode.p1 == VID_PLAY_MASTER_NONE)
1623 saa->boardcfg[1] = 0x13;
1624 else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
1625 saa->boardcfg[1] = 0x23;
1626 else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
1627 saa->boardcfg[1] = 0x43;
1628 else
1629 return -EINVAL;
1630 debiwrite(saa, debNormal,
1631 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1632 return 0;
1633 case VID_PLAY_ACTIVE_SCANLINES:
1634 if (CurrentMode == VIDEO_MODE_PAL) {
1635 if (pmode.p1 < 1 || pmode.p2 > 625)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001637 saa->boardcfg[5] = pmode.p1;
1638 saa->boardcfg[55] = (pmode.p1 +
1639 (pmode.p2 / 2) - 1) & 0xff;
1640 } else {
1641 if (pmode.p1 < 4 || pmode.p2 > 525)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001643 saa->boardcfg[4] = pmode.p1;
1644 saa->boardcfg[54] = (pmode.p1 +
1645 (pmode.p2 / 2) - 4) & 0xff;
1646 }
1647 set_out_format(saa, CurrentMode);
1648 case VID_PLAY_RESET:
1649 return do_ibm_reset(saa);
1650 case VID_PLAY_END_MARK:
1651 if (saa->endmarktail < saa->endmarkhead) {
1652 if (saa->endmarkhead -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 saa->endmarktail < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 return -ENOSPC;
Jiri Slabyf823f672006-01-11 19:41:32 -02001655 } else if (saa->endmarkhead <=saa->endmarktail){
1656 if (saa->endmarktail - saa->endmarkhead
1657 > (MAX_MARKS - 2))
1658 return -ENOSPC;
1659 } else
1660 return -ENOSPC;
1661 saa->endmark[saa->endmarktail] = saa->audtail;
1662 saa->endmarktail++;
1663 if (saa->endmarktail >= MAX_MARKS)
1664 saa->endmarktail = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 }
1666 return -EINVAL;
1667 }
1668 case VIDIOCSWRITEMODE:
1669 {
1670 int mode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001671 if (copy_from_user((void *)&mode, arg, sizeof(int)))
1672 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 if (mode == VID_WRITE_MPEG_AUD ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001674 mode == VID_WRITE_MPEG_VID ||
1675 mode == VID_WRITE_CC ||
1676 mode == VID_WRITE_TTX ||
1677 mode == VID_WRITE_OSD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 saa->writemode = mode;
1679 return 0;
1680 }
1681 return -EINVAL;
1682 }
1683 case VIDIOCSMICROCODE:
1684 {
1685 struct video_code ucode;
1686 __u8 *udata;
1687 int i;
1688 if (copy_from_user(&ucode, arg, sizeof(ucode)))
1689 return -EFAULT;
1690 if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001691 strncmp(ucode.loadwhat, "dec", 3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 return -EINVAL;
1693 if ((udata = vmalloc(ucode.datasize)) == NULL)
1694 return -ENOMEM;
1695 if (copy_from_user(udata, ucode.data, ucode.datasize)) {
1696 vfree(udata);
1697 return -EFAULT;
1698 }
1699 ucode.data = udata;
Jiri Slabyf823f672006-01-11 19:41:32 -02001700 if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
1701 !strncmp(ucode.loadwhat, "decoder.vid", 11))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 i = initialize_ibmmpeg2(&ucode);
1703 else
1704 i = initialize_fpga(&ucode);
1705 vfree(udata);
1706 if (i)
1707 return -EINVAL;
1708 return 0;
1709
1710 }
1711 case VIDIOCGCHAN: /* this makes xawtv happy */
1712 {
1713 struct video_channel v;
1714 if (copy_from_user(&v, arg, sizeof(v)))
1715 return -EFAULT;
1716 v.flags = VIDEO_VC_AUDIO;
1717 v.tuners = 0;
1718 v.type = VID_TYPE_MPEG_DECODER;
1719 v.norm = CurrentMode;
1720 strcpy(v.name, "MPEG2");
1721 if (copy_to_user(arg, &v, sizeof(v)))
1722 return -EFAULT;
1723 return 0;
1724 }
1725 case VIDIOCSCHAN: /* this makes xawtv happy */
1726 {
1727 struct video_channel v;
1728 if (copy_from_user(&v, arg, sizeof(v)))
1729 return -EFAULT;
1730 /* do nothing */
1731 return 0;
1732 }
1733 default:
1734 return -ENOIOCTLCMD;
1735 }
1736 return 0;
1737}
1738
1739static int saa_mmap(struct file *file, struct vm_area_struct *vma)
1740{
1741 struct saa7146 *saa = file->private_data;
1742 printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
1743 return -EINVAL;
1744}
1745
Jiri Slabyf823f672006-01-11 19:41:32 -02001746static ssize_t saa_read(struct file *file, char __user * buf,
1747 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748{
1749 return -EINVAL;
1750}
1751
Jiri Slabyf823f672006-01-11 19:41:32 -02001752static ssize_t saa_write(struct file *file, const char __user * buf,
1753 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754{
1755 struct saa7146 *saa = file->private_data;
1756 unsigned long todo = count;
1757 int blocksize, split;
1758 unsigned long flags;
1759
1760 while (todo > 0) {
1761 if (saa->writemode == VID_WRITE_MPEG_AUD) {
1762 spin_lock_irqsave(&saa->lock, flags);
1763 if (saa->audhead <= saa->audtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001764 blocksize = 65536 -
1765 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 else
1767 blocksize = saa->audhead - saa->audtail;
1768 spin_unlock_irqrestore(&saa->lock, flags);
1769 if (blocksize < 16384) {
1770 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001771 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1773 /* wait for buffer space to open */
1774 interruptible_sleep_on(&saa->audq);
1775 }
1776 spin_lock_irqsave(&saa->lock, flags);
1777 if (saa->audhead <= saa->audtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001778 blocksize = 65536 -
1779 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 split = 65536 - saa->audtail;
1781 } else {
1782 blocksize = saa->audhead - saa->audtail;
1783 split = 65536;
1784 }
1785 spin_unlock_irqrestore(&saa->lock, flags);
1786 blocksize--;
1787 if (blocksize > todo)
1788 blocksize = todo;
1789 /* double check that we really have space */
1790 if (!blocksize)
1791 return -ENOSPC;
1792 if (split < blocksize) {
1793 if (copy_from_user(saa->audbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001794 saa->audtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 return -EFAULT;
1796 buf += split;
1797 todo -= split;
1798 blocksize -= split;
1799 saa->audtail = 0;
1800 }
1801 if (copy_from_user(saa->audbuf + saa->audtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001802 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 return -EFAULT;
1804 saa->audtail += blocksize;
1805 todo -= blocksize;
1806 buf += blocksize;
1807 saa->audtail &= 0xffff;
1808 } else if (saa->writemode == VID_WRITE_MPEG_VID) {
1809 spin_lock_irqsave(&saa->lock, flags);
1810 if (saa->vidhead <= saa->vidtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001811 blocksize = 524288 -
1812 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 else
1814 blocksize = saa->vidhead - saa->vidtail;
1815 spin_unlock_irqrestore(&saa->lock, flags);
1816 if (blocksize < 65536) {
1817 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001818 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1820 /* wait for buffer space to open */
1821 interruptible_sleep_on(&saa->vidq);
1822 }
1823 spin_lock_irqsave(&saa->lock, flags);
1824 if (saa->vidhead <= saa->vidtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001825 blocksize = 524288 -
1826 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 split = 524288 - saa->vidtail;
1828 } else {
1829 blocksize = saa->vidhead - saa->vidtail;
1830 split = 524288;
1831 }
1832 spin_unlock_irqrestore(&saa->lock, flags);
1833 blocksize--;
1834 if (blocksize > todo)
1835 blocksize = todo;
1836 /* double check that we really have space */
1837 if (!blocksize)
1838 return -ENOSPC;
1839 if (split < blocksize) {
1840 if (copy_from_user(saa->vidbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001841 saa->vidtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 return -EFAULT;
1843 buf += split;
1844 todo -= split;
1845 blocksize -= split;
1846 saa->vidtail = 0;
1847 }
1848 if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001849 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 return -EFAULT;
1851 saa->vidtail += blocksize;
1852 todo -= blocksize;
1853 buf += blocksize;
1854 saa->vidtail &= 0x7ffff;
1855 } else if (saa->writemode == VID_WRITE_OSD) {
1856 if (count > 131072)
1857 return -ENOSPC;
1858 if (copy_from_user(saa->osdbuf, buf, count))
1859 return -EFAULT;
1860 buf += count;
1861 saa->osdhead = 0;
1862 saa->osdtail = count;
1863 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
1864 debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
1865 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
1866 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -02001867 debiread(saa, debNormal,
1868 IBM_MP2_DISP_MODE, 2) | 1, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 /* trigger osd data transfer */
1870 saawrite(SAA7146_PSR_DEBI_S |
1871 SAA7146_PSR_PIN1, SAA7146_IER);
1872 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1873 }
1874 }
1875 return count;
1876}
1877
1878static int saa_open(struct inode *inode, struct file *file)
1879{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001880 struct video_device *vdev = video_devdata(file);
1881 struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 file->private_data = saa;
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 saa->user++;
1886 if (saa->user > 1)
1887 return 0; /* device open already, don't reset */
1888 saa->writemode = VID_WRITE_MPEG_VID; /* default to video */
1889 return 0;
1890}
1891
1892static int saa_release(struct inode *inode, struct file *file)
1893{
1894 struct saa7146 *saa = file->private_data;
1895 saa->user--;
Jiri Slaby91fb8352006-01-11 19:41:21 -02001896
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (saa->user > 0) /* still someone using device */
1898 return 0;
1899 saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
1900 return 0;
1901}
1902
Jiri Slabyf823f672006-01-11 19:41:32 -02001903static struct file_operations saa_fops = {
1904 .owner = THIS_MODULE,
1905 .open = saa_open,
1906 .release = saa_release,
1907 .ioctl = saa_ioctl,
1908 .compat_ioctl = v4l_compat_ioctl32,
1909 .read = saa_read,
1910 .llseek = no_llseek,
1911 .write = saa_write,
1912 .mmap = saa_mmap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913};
1914
1915/* template for video_device-structure */
Jiri Slabyf823f672006-01-11 19:41:32 -02001916static struct video_device saa_template = {
1917 .name = "SAA7146A",
1918 .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
1919 .hardware = VID_HARDWARE_SAA7146,
1920 .fops = &saa_fops,
1921 .minor = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922};
1923
Jiri Slaby9ae82292006-01-11 19:41:13 -02001924static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001926 int retval;
1927 struct saa7146 *saa = pci_get_drvdata(pdev);
Jiri Slabyf823f672006-01-11 19:41:32 -02001928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 saa->endmarkhead = saa->endmarktail = 0;
1930 saa->win.x = saa->win.y = 0;
1931 saa->win.width = saa->win.cropwidth = 720;
1932 saa->win.height = saa->win.cropheight = 480;
1933 saa->win.cropx = saa->win.cropy = 0;
1934 saa->win.bpp = 2;
1935 saa->win.depth = 16;
1936 saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
1937 saa->win.bpl = 1024 * saa->win.bpp;
1938 saa->win.swidth = 1024;
1939 saa->win.sheight = 768;
1940 saa->picture.brightness = 32768;
1941 saa->picture.contrast = 38768;
1942 saa->picture.colour = 32768;
1943 saa->cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 saa->nr = num;
1945 saa->playmode = VID_PLAY_NORMAL;
1946 memset(saa->boardcfg, 0, 64); /* clear board config area */
1947 saa->saa7146_mem = NULL;
1948 saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
1949 saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
1950 saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
1951 saa->pagea1out = saa->pagea2in = saa->pagea2out =
1952 saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
1953 saa->pageRPS2 = NULL;
1954 saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
1955 saa->audhead = saa->vidtail = 0;
1956
1957 init_waitqueue_head(&saa->i2cq);
1958 init_waitqueue_head(&saa->audq);
1959 init_waitqueue_head(&saa->debiq);
1960 init_waitqueue_head(&saa->vidq);
1961 spin_lock_init(&saa->lock);
1962
Jiri Slaby91fb8352006-01-11 19:41:21 -02001963 retval = pci_enable_device(pdev);
1964 if (retval) {
1965 dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
1966 goto err;
1967 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001968
Jiri Slaby9ae82292006-01-11 19:41:13 -02001969 saa->id = pdev->device;
1970 saa->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 saa->video_dev.minor = -1;
Jiri Slaby9ae82292006-01-11 19:41:13 -02001972 saa->saa7146_adr = pci_resource_start(pdev, 0);
1973 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
1975 saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001976 if (saa->saa7146_mem == NULL) {
1977 dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
1978 retval = -EIO;
1979 goto err;
1980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
1982 memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
1983 saawrite(0, SAA7146_IER); /* turn off all interrupts */
Jiri Slaby91fb8352006-01-11 19:41:21 -02001984
1985 retval = request_irq(saa->irq, saa7146_irq, SA_SHIRQ | SA_INTERRUPT,
1986 "stradis", saa);
1987 if (retval == -EINVAL)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001988 dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001989 else if (retval == -EBUSY)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001990 dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
1991 "in BIOS\n", num, saa->irq);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001992 if (retval < 0)
1993 goto errio;
1994
Jiri Slaby9ae82292006-01-11 19:41:13 -02001995 pci_set_master(pdev);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001996 retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
1997 video_nr);
Jiri Slabyf823f672006-01-11 19:41:32 -02001998 if (retval < 0) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02001999 dev_err(&pdev->dev, "%d: error in registering video device!\n",
2000 num);
2001 goto errio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002003
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 return 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002005errio:
2006 iounmap(saa->saa7146_mem);
2007err:
2008 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009}
2010
Jiri Slaby91fb8352006-01-11 19:41:21 -02002011static int __devinit init_saa7146(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012{
Jiri Slaby91fb8352006-01-11 19:41:21 -02002013 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Jiri Slaby9ae82292006-01-11 19:41:13 -02002015 memset(saa, 0, sizeof(*saa));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 saa->user = 0;
2017 /* reset the saa7146 */
2018 saawrite(0xffff0000, SAA7146_MC1);
2019 mdelay(5);
2020 /* enable debi and i2c transfers and pins */
2021 saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C |
2022 SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1);
2023 /* ensure proper state of chip */
2024 saawrite(0x00000000, SAA7146_PAGE1);
2025 saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1);
2026 saawrite(0x00000000, SAA7146_PAGE2);
2027 saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2);
2028 saawrite(0x00000000, SAA7146_DD1_INIT);
2029 saawrite(0x00000000, SAA7146_DD1_STREAM_B);
2030 saawrite(0x00000000, SAA7146_DD1_STREAM_A);
2031 saawrite(0x00000000, SAA7146_BRS_CTRL);
2032 saawrite(0x80400040, SAA7146_BCS_CTRL);
Jiri Slabyf823f672006-01-11 19:41:32 -02002033 saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
2035 saawrite(0x00000000, SAA7146_ACON1);
2036 saawrite(0x00000000, SAA7146_ACON2);
2037 saawrite(0x00000600, SAA7146_I2C_STATUS);
2038 saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
Jiri Slabyf823f672006-01-11 19:41:32 -02002039 SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
2040 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
2041 SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
2042 SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 /* setup arbitration control registers */
2044 saawrite(0x1412121a, SAA7146_PCI_BT_V1);
2045
2046 /* allocate 32k dma buffer + 4k for page table */
2047 if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002048 dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
2049 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 }
2051#if 0
2052 saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */
2053 saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE);
2054 for (i = 0; i < 12; i++) /* setup mmu page table */
2055 saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));
2056#endif
2057 saa->audhead = saa->vidhead = saa->osdhead = 0;
2058 saa->audtail = saa->vidtail = saa->osdtail = 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002059 if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
2060 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
2061 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002063 if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
2064 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
2065 goto errvid;
2066 }
2067 if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
2068 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
2069 goto erraud;
2070 }
2071 /* allocate 81920 byte buffer for clipping */
2072 if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
2073 dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
2074 goto errosd;
2075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 /* setup clipping registers */
2077 saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
2078 saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
2079 saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
Jiri Slabyf823f672006-01-11 19:41:32 -02002080 SAA7146_PROT_ADDR2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 saawrite(256, SAA7146_PITCH2);
Jiri Slabyf823f672006-01-11 19:41:32 -02002082 saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
2084 SAA7146_MC2);
2085 I2CBusScan(saa);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002086
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 return 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002088errosd:
2089 vfree(saa->osdbuf);
2090 saa->osdbuf = NULL;
2091erraud:
2092 vfree(saa->audbuf);
2093 saa->audbuf = NULL;
2094errvid:
2095 vfree(saa->vidbuf);
2096 saa->vidbuf = NULL;
2097err:
2098 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099}
2100
Jiri Slaby9ae82292006-01-11 19:41:13 -02002101static void stradis_release_saa(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102{
2103 u8 command;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002104 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Jiri Slaby9ae82292006-01-11 19:41:13 -02002106 /* turn off all capturing, DMA and IRQs */
2107 saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
2108 saawrite(0, SAA7146_MC2);
2109 saawrite(0, SAA7146_IER);
2110 saawrite(0xffffffffUL, SAA7146_ISR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
Jiri Slaby9ae82292006-01-11 19:41:13 -02002112 /* disable PCI bus-mastering */
2113 pci_read_config_byte(pdev, PCI_COMMAND, &command);
2114 command &= ~PCI_COMMAND_MASTER;
2115 pci_write_config_byte(pdev, PCI_COMMAND, command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Jiri Slaby9ae82292006-01-11 19:41:13 -02002117 /* unmap and free memory */
2118 saa->audhead = saa->audtail = saa->osdhead = 0;
2119 saa->vidhead = saa->vidtail = saa->osdtail = 0;
2120 vfree(saa->vidbuf);
2121 vfree(saa->audbuf);
2122 vfree(saa->osdbuf);
2123 kfree(saa->dmavid2);
2124 saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
2125 saa->dmavid2 = NULL;
2126 kfree(saa->dmadebi);
2127 kfree(saa->dmavid1);
2128 kfree(saa->dmavid3);
2129 kfree(saa->dmaa1in);
2130 kfree(saa->dmaa1out);
2131 kfree(saa->dmaa2in);
2132 kfree(saa->dmaa2out);
2133 kfree(saa->dmaRPS1);
2134 kfree(saa->dmaRPS2);
2135 free_irq(saa->irq, saa);
2136 if (saa->saa7146_mem)
2137 iounmap(saa->saa7146_mem);
2138 if (saa->video_dev.minor != -1)
2139 video_unregister_device(&saa->video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140}
2141
Jiri Slaby9ae82292006-01-11 19:41:13 -02002142static int __devinit stradis_probe(struct pci_dev *pdev,
2143 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002145 int retval = -EINVAL;
2146
2147 if (saa_num >= SAA7146_MAX)
2148 goto err;
2149
2150 if (!pdev->subsystem_vendor)
2151 dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
2152 else
2153 dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
2154
Jiri Slaby91fb8352006-01-11 19:41:21 -02002155 pci_set_drvdata(pdev, &saa7146s[saa_num]);
Jiri Slaby9ae82292006-01-11 19:41:13 -02002156
2157 retval = configure_saa7146(pdev, saa_num);
2158 if (retval) {
2159 dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
2160 goto err;
2161 }
2162
Jiri Slaby91fb8352006-01-11 19:41:21 -02002163 if (init_saa7146(pdev) < 0) {
Jiri Slaby9ae82292006-01-11 19:41:13 -02002164 dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
2165 retval = -EIO;
2166 goto errrel;
2167 }
2168
2169 saa_num++;
2170
2171 return 0;
2172errrel:
2173 stradis_release_saa(pdev);
2174err:
2175 return retval;
2176}
2177
2178static void __devexit stradis_remove(struct pci_dev *pdev)
2179{
2180 stradis_release_saa(pdev);
2181}
2182
2183static struct pci_device_id stradis_pci_tbl[] = {
2184 { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
2185 { 0 }
2186};
Jiri Slabyf823f672006-01-11 19:41:32 -02002187
Jiri Slaby9ae82292006-01-11 19:41:13 -02002188MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
2189
2190static struct pci_driver stradis_driver = {
Jiri Slabyf823f672006-01-11 19:41:32 -02002191 .name = "stradis",
2192 .id_table = stradis_pci_tbl,
2193 .probe = stradis_probe,
2194 .remove = __devexit_p(stradis_remove)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002195};
2196
2197int __init stradis_init(void)
2198{
2199 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
2201 saa_num = 0;
2202
Jiri Slaby9ae82292006-01-11 19:41:13 -02002203 retval = pci_register_driver(&stradis_driver);
2204 if (retval)
2205 printk(KERN_ERR "stradis: Unable to register pci driver.\n");
2206
2207 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208}
2209
Jiri Slaby9ae82292006-01-11 19:41:13 -02002210void __exit stradis_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002212 pci_unregister_driver(&stradis_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 printk(KERN_INFO "stradis: module cleanup complete\n");
2214}
2215
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216module_init(stradis_init);
2217module_exit(stradis_exit);