blob: 525d81288d55aada3b9308d871e1505a6d3edb11 [file] [log] [blame]
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * 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>
Mauro Carvalho Chehab5e87efa2006-06-05 10:26:32 -030045#include <media/v4l2-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#include "saa7146.h"
48#include "saa7146reg.h"
49#include "ibmmpeg2.h"
50#include "saa7121.h"
51#include "cs8420.h"
52
Jiri Slabyf823f672006-01-11 19:41:32 -020053#define DEBUG(x) /* debug driver */
54#undef IDEBUG /* debug irq handler */
55#undef MDEBUG /* debug memory management */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#define SAA7146_MAX 6
58
59static struct saa7146 saa7146s[SAA7146_MAX];
60
61static int saa_num = 0; /* number of SAA7146s in use */
62
63static int video_nr = -1;
64module_param(video_nr, int, 0);
65MODULE_LICENSE("GPL");
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#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
101static unsigned char rescue_eeprom[64] = {
Jiri Slabyf823f672006-01-11 19:41:32 -0200102 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
103 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
104 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
105 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
106 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108};
109#endif
110
111/* ----------------------------------------------------------------------- */
112/* Hardware I2C functions */
113static void I2CWipe(struct saa7146 *saa)
114{
115 int i;
116 /* set i2c to ~=100kHz, abort transfer, clear busy */
117 saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
118 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
119 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
120 /* wait for i2c registers to be programmed */
121 for (i = 0; i < 1000 &&
122 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
123 schedule();
124 saawrite(0x600, SAA7146_I2C_STATUS);
125 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
126 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
127 /* wait for i2c registers to be programmed */
128 for (i = 0; i < 1000 &&
129 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
130 schedule();
131 saawrite(0x600, SAA7146_I2C_STATUS);
132 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
133 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
134 /* wait for i2c registers to be programmed */
135 for (i = 0; i < 1000 &&
136 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
137 schedule();
138}
139
140/* read I2C */
141static int I2CRead(struct saa7146 *saa, unsigned char addr,
142 unsigned char subaddr, int dosub)
143{
144 int i;
145
146 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
147 I2CWipe(saa);
Jiri Slabyf823f672006-01-11 19:41:32 -0200148 for (i = 0;
149 i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
150 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 schedule();
152 if (i == 1000)
153 I2CWipe(saa);
154 if (dosub)
155 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200156 ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 else
158 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200159 0xf1, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
161 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
162 /* wait for i2c registers to be programmed */
163 for (i = 0; i < 1000 &&
164 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
165 schedule();
166 /* wait for valid data */
167 for (i = 0; i < 1000 &&
168 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
169 schedule();
170 if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
171 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200172 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 printk("i2c setup read timeout\n");
174 saawrite(0x41, SAA7146_I2C_TRANSFER);
175 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
176 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
177 /* wait for i2c registers to be programmed */
178 for (i = 0; i < 1000 &&
179 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
180 schedule();
181 /* wait for valid data */
182 for (i = 0; i < 1000 &&
183 (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
184 schedule();
185 if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
186 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200187 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 printk("i2c read timeout\n");
189 return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
190}
191
192/* set both to write both bytes, reset it to write only b1 */
193
194static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
195 unsigned char b2, int both)
196{
197 int i;
198 u32 data;
199
200 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
201 I2CWipe(saa);
202 for (i = 0; i < 1000 &&
203 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
204 schedule();
205 if (i == 1000)
206 I2CWipe(saa);
207 data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
208 if (both)
209 data |= ((b2 & 0xff) << 8) | 0xe5;
210 else
211 data |= 0xd1;
212 saawrite(data, SAA7146_I2C_TRANSFER);
213 saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
214 SAA7146_MC2);
215 return 0;
216}
217
218static void attach_inform(struct saa7146 *saa, int id)
219{
220 int i;
221
Jiri Slabyf823f672006-01-11 19:41:32 -0200222 DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
223 id));
224 if (id == 0xa0) { /* we have rev2 or later board, fill in info */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 for (i = 0; i < 64; i++)
226 saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
227#ifdef USE_RESCUE_EEPROM_SDM275
228 if (saa->boardcfg[0] != 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200229 printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
230 "BEEN IGNORED\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 for (i = 0; i < 64; i++)
232 saa->boardcfg[i] = rescue_eeprom[i];
233 }
234#endif
235 printk("stradis%d: config =", saa->nr);
236 for (i = 0; i < 51; i++) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200237 printk(" %02x", saa->boardcfg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 }
239 printk("\n");
240 }
241}
242
243static void I2CBusScan(struct saa7146 *saa)
244{
245 int i;
246 for (i = 0; i < 0xff; i += 2)
247 if ((I2CRead(saa, i, 0, 0)) >= 0)
248 attach_inform(saa, i);
249}
250
251static int debiwait_maxwait = 0;
252
253static int wait_for_debi_done(struct saa7146 *saa)
254{
255 int i;
256
257 /* wait for registers to be programmed */
258 for (i = 0; i < 100000 &&
259 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
260 saaread(SAA7146_MC2);
261 /* wait for transfer to complete */
262 for (i = 0; i < 500000 &&
263 (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
264 saaread(SAA7146_MC2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 if (i > debiwait_maxwait)
267 printk("wait-for-debi-done maxwait: %d\n",
268 debiwait_maxwait = i);
Jiri Slabyf823f672006-01-11 19:41:32 -0200269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 if (i == 500000)
271 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return 0;
274}
275
276static int debiwrite(struct saa7146 *saa, u32 config, int addr,
Jiri Slabyf823f672006-01-11 19:41:32 -0200277 u32 val, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
279 u32 cmd;
280 if (count <= 0 || count > 32764)
281 return -1;
282 if (wait_for_debi_done(saa) < 0)
283 return -1;
284 saawrite(config, SAA7146_DEBI_CONFIG);
285 if (count <= 4) /* immediate transfer */
286 saawrite(val, SAA7146_DEBI_AD);
287 else /* block transfer */
288 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
289 saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
290 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
291 SAA7146_MC2);
292 return 0;
293}
294
295static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
296{
297 u32 result = 0;
298
299 if (count > 32764 || count <= 0)
300 return 0;
301 if (wait_for_debi_done(saa) < 0)
302 return 0;
303 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
304 saawrite((count << 17) | 0x10000 | (addr & 0xffff),
305 SAA7146_DEBI_COMMAND);
306 saawrite(config, SAA7146_DEBI_CONFIG);
307 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
308 SAA7146_MC2);
309 if (count > 4) /* not an immediate transfer */
310 return count;
311 wait_for_debi_done(saa);
312 result = saaread(SAA7146_DEBI_AD);
313 if (count == 1)
314 result &= 0xff;
315 if (count == 2)
316 result &= 0xffff;
317 if (count == 3)
318 result &= 0xffffff;
319 return result;
320}
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322static void do_irq_send_data(struct saa7146 *saa)
323{
324 int split, audbytes, vidbytes;
325
326 saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
327 /* if special feature mode in effect, disable audio sending */
328 if (saa->playmode != VID_PLAY_NORMAL)
329 saa->audtail = saa->audhead = 0;
330 if (saa->audhead <= saa->audtail)
331 audbytes = saa->audtail - saa->audhead;
332 else
333 audbytes = 65536 - (saa->audhead - saa->audtail);
334 if (saa->vidhead <= saa->vidtail)
335 vidbytes = saa->vidtail - saa->vidhead;
336 else
337 vidbytes = 524288 - (saa->vidhead - saa->vidtail);
338 if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
339 saawrite(0, SAA7146_IER);
340 return;
341 }
342 /* if at least 1 block audio waiting and audio fifo isn't full */
Jiri Slabyf823f672006-01-11 19:41:32 -0200343 if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
344 & 0xff) < 60) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 if (saa->audhead > saa->audtail)
346 split = 65536 - saa->audhead;
347 else
348 split = 0;
349 audbytes = 2048;
350 if (split > 0 && split < 2048) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200351 memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 saa->audhead = 0;
353 audbytes -= split;
354 } else
355 split = 0;
356 memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
357 audbytes);
358 saa->audhead += audbytes;
359 saa->audhead &= 0xffff;
Jiri Slabyf823f672006-01-11 19:41:32 -0200360 debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
361 IBM_MP2_AUD_FIFOW), 0, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 wake_up_interruptible(&saa->audq);
Jiri Slabyf823f672006-01-11 19:41:32 -0200363 /* if at least 1 block video waiting and video fifo isn't full */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 } else if (vidbytes >= 30720 && (debiread(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -0200365 IBM_MP2_FIFO, 2)) < 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (saa->vidhead > saa->vidtail)
367 split = 524288 - saa->vidhead;
368 else
369 split = 0;
370 vidbytes = 30720;
371 if (split > 0 && split < 30720) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200372 memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 saa->vidhead = 0;
374 vidbytes -= split;
375 } else
376 split = 0;
377 memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
378 vidbytes);
379 saa->vidhead += vidbytes;
380 saa->vidhead &= 0x7ffff;
381 debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
Jiri Slabyf823f672006-01-11 19:41:32 -0200382 IBM_MP2_FIFOW), 0, 30720);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 wake_up_interruptible(&saa->vidq);
384 }
385 saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
386}
387
388static void send_osd_data(struct saa7146 *saa)
389{
390 int size = saa->osdtail - saa->osdhead;
391 if (size > 30720)
392 size = 30720;
393 /* ensure some multiple of 8 bytes is transferred */
Jiri Slabyf823f672006-01-11 19:41:32 -0200394 size = 8 * ((size + 8) >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 if (size) {
396 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
Jiri Slabyf823f672006-01-11 19:41:32 -0200397 (saa->osdhead >> 3), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
399 saa->osdhead += size;
400 /* block transfer of next 8 bytes to ~32k bytes */
401 debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
402 }
403 if (saa->osdhead >= saa->osdtail) {
404 saa->osdhead = saa->osdtail = 0;
405 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
406 }
407}
408
David Howells7d12e782006-10-05 14:55:46 +0100409static irqreturn_t saa7146_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
Jiri Slabyf823f672006-01-11 19:41:32 -0200411 struct saa7146 *saa = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 u32 stat, astat;
413 int count;
414 int handled = 0;
415
416 count = 0;
417 while (1) {
418 /* get/clear interrupt status bits */
419 stat = saaread(SAA7146_ISR);
420 astat = stat & saaread(SAA7146_IER);
421 if (!astat)
422 break;
423 handled = 1;
424 saawrite(astat, SAA7146_ISR);
425 if (astat & SAA7146_PSR_DEBI_S) {
426 do_irq_send_data(saa);
427 }
428 if (astat & SAA7146_PSR_PIN1) {
429 int istat;
430 /* the following read will trigger DEBI_S */
431 istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
432 if (istat & 1) {
433 saawrite(0, SAA7146_IER);
434 send_osd_data(saa);
435 saawrite(SAA7146_PSR_DEBI_S |
436 SAA7146_PSR_PIN1, SAA7146_IER);
437 }
438 if (istat & 0x20) { /* Video Start */
439 saa->vidinfo.frame_count++;
440 }
441 if (istat & 0x400) { /* Picture Start */
442 /* update temporal reference */
443 }
444 if (istat & 0x200) { /* Picture Resolution Change */
445 /* read new resolution */
446 }
447 if (istat & 0x100) { /* New User Data found */
448 /* read new user data */
449 }
450 if (istat & 0x1000) { /* new GOP/SMPTE */
451 /* read new SMPTE */
452 }
453 if (istat & 0x8000) { /* Sequence Start Code */
454 /* reset frame counter, load sizes */
455 saa->vidinfo.frame_count = 0;
456 saa->vidinfo.h_size = 704;
457 saa->vidinfo.v_size = 480;
458#if 0
459 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200460 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 saa->endmark[saa->endmarkhead];
462 saa->endmarkhead++;
463 if (saa->endmarkhead >= MAX_MARKS)
464 saa->endmarkhead = 0;
465 }
466#endif
467 }
468 if (istat & 0x4000) { /* Sequence Error Code */
469 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200470 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 saa->endmark[saa->endmarkhead];
472 saa->endmarkhead++;
473 if (saa->endmarkhead >= MAX_MARKS)
474 saa->endmarkhead = 0;
475 }
476 }
477 }
478#ifdef IDEBUG
479 if (astat & SAA7146_PSR_PPEF) {
480 IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
481 }
482 if (astat & SAA7146_PSR_PABO) {
483 IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
484 }
485 if (astat & SAA7146_PSR_PPED) {
486 IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
487 }
488 if (astat & SAA7146_PSR_RPS_I1) {
489 IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
490 }
491 if (astat & SAA7146_PSR_RPS_I0) {
492 IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
493 }
494 if (astat & SAA7146_PSR_RPS_LATE1) {
495 IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
496 }
497 if (astat & SAA7146_PSR_RPS_LATE0) {
498 IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
499 }
500 if (astat & SAA7146_PSR_RPS_E1) {
501 IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
502 }
503 if (astat & SAA7146_PSR_RPS_E0) {
504 IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
505 }
506 if (astat & SAA7146_PSR_RPS_TO1) {
507 IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
508 }
509 if (astat & SAA7146_PSR_RPS_TO0) {
510 IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
511 }
512 if (astat & SAA7146_PSR_UPLD) {
513 IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
514 }
515 if (astat & SAA7146_PSR_DEBI_E) {
516 IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
517 }
518 if (astat & SAA7146_PSR_I2C_S) {
519 IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
520 }
521 if (astat & SAA7146_PSR_I2C_E) {
522 IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
523 }
524 if (astat & SAA7146_PSR_A2_IN) {
525 IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
526 }
527 if (astat & SAA7146_PSR_A2_OUT) {
528 IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
529 }
530 if (astat & SAA7146_PSR_A1_IN) {
531 IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
532 }
533 if (astat & SAA7146_PSR_A1_OUT) {
534 IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
535 }
536 if (astat & SAA7146_PSR_AFOU) {
537 IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
538 }
539 if (astat & SAA7146_PSR_V_PE) {
540 IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
541 }
542 if (astat & SAA7146_PSR_VFOU) {
543 IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
544 }
545 if (astat & SAA7146_PSR_FIDA) {
546 IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
547 }
548 if (astat & SAA7146_PSR_FIDB) {
549 IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
550 }
551 if (astat & SAA7146_PSR_PIN3) {
552 IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
553 }
554 if (astat & SAA7146_PSR_PIN2) {
555 IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
556 }
557 if (astat & SAA7146_PSR_PIN0) {
558 IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
559 }
560 if (astat & SAA7146_PSR_ECS) {
561 IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
562 }
563 if (astat & SAA7146_PSR_EC3S) {
564 IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
565 }
566 if (astat & SAA7146_PSR_EC0S) {
567 IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
568 }
569#endif
570 count++;
571 if (count > 15)
572 printk(KERN_WARNING "stradis%d: irq loop %d\n",
573 saa->nr, count);
574 if (count > 20) {
575 saawrite(0, SAA7146_IER);
576 printk(KERN_ERR
577 "stradis%d: IRQ loop cleared\n", saa->nr);
578 }
579 }
580 return IRQ_RETVAL(handled);
581}
582
583static int ibm_send_command(struct saa7146 *saa,
584 int command, int data, int chain)
585{
586 int i;
587
588 if (chain)
Jiri Slabyf823f672006-01-11 19:41:32 -0200589 debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 else
591 debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
592 debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
593 debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
594 for (i = 0; i < 100 &&
595 (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
596 schedule();
597 if (i == 100)
598 return -1;
599 return 0;
600}
601
602static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
603{
604 I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
605 I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
606}
607
608static void initialize_cs4341(struct saa7146 *saa)
609{
610 int i;
611 for (i = 0; i < 200; i++) {
612 /* auto mute off, power on, no de-emphasis */
613 /* I2S data up to 24-bit 64xFs internal SCLK */
614 I2CWrite(saa, 0x22, 0x01, 0x11, 2);
615 /* ATAPI mixer settings */
616 I2CWrite(saa, 0x22, 0x02, 0x49, 2);
617 /* attenuation left 3db */
618 I2CWrite(saa, 0x22, 0x03, 0x00, 2);
619 /* attenuation right 3db */
620 I2CWrite(saa, 0x22, 0x04, 0x00, 2);
621 I2CWrite(saa, 0x22, 0x01, 0x10, 2);
622 if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
623 break;
624 schedule();
625 }
626 printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
627 return;
628}
629
630static void initialize_cs8420(struct saa7146 *saa, int pro)
631{
632 int i;
633 u8 *sequence;
634 if (pro)
635 sequence = mode8420pro;
636 else
637 sequence = mode8420con;
638 for (i = 0; i < INIT8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200639 I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 for (i = 0; i < MODE8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200641 I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 printk("stradis%d: CS8420 initialized\n", saa->nr);
643}
644
645static void initialize_saa7121(struct saa7146 *saa, int dopal)
646{
647 int i, mod;
648 u8 *sequence;
649 if (dopal)
650 sequence = init7121pal;
651 else
652 sequence = init7121ntsc;
653 mod = saaread(SAA7146_PSR) & 0x08;
654 /* initialize PAL/NTSC video encoder */
655 for (i = 0; i < INIT7121LEN; i++) {
656 if (NewCard) { /* handle new card encoder differences */
Jiri Slabyf823f672006-01-11 19:41:32 -0200657 if (sequence[i * 2] == 0x3a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200659 else if (sequence[i * 2] == 0x6b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200661 else if (sequence[i * 2] == 0x6c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 I2CWrite(saa, 0x88, 0x6c,
663 dopal ? 0x09 : 0xf5, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200664 else if (sequence[i * 2] == 0x6d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 I2CWrite(saa, 0x88, 0x6d,
666 dopal ? 0x20 : 0x00, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200667 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 I2CWrite(saa, 0x88, 0x7a,
669 dopal ? (PALFirstActive - 1) :
670 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200671 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 I2CWrite(saa, 0x88, 0x7b,
673 dopal ? PALLastActive :
674 NTSCLastActive, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200675 else
676 I2CWrite(saa, 0x88, sequence[i * 2],
677 sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -0200679 if (sequence[i * 2] == 0x6b && mod)
680 I2CWrite(saa, 0x88, 0x6b,
681 (sequence[i * 2 + 1] ^ 0x09), 2);
682 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 I2CWrite(saa, 0x88, 0x7a,
684 dopal ? (PALFirstActive - 1) :
685 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200686 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 I2CWrite(saa, 0x88, 0x7b,
688 dopal ? PALLastActive :
689 NTSCLastActive, 2);
690 else
691 I2CWrite(saa, 0x88, sequence[i * 2],
692 sequence[i * 2 + 1], 2);
693 }
694 }
695}
696
697static void set_genlock_offset(struct saa7146 *saa, int noffset)
698{
699 int nCode;
700 int PixelsPerLine = 858;
701 if (CurrentMode == VIDEO_MODE_PAL)
702 PixelsPerLine = 864;
703 if (noffset > 500)
704 noffset = 500;
705 else if (noffset < -500)
706 noffset = -500;
707 nCode = noffset + 0x100;
708 if (nCode == 1)
709 nCode = 0x401;
Jiri Slabyf823f672006-01-11 19:41:32 -0200710 else if (nCode < 1)
711 nCode = 0x400 + PixelsPerLine + nCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
713}
714
715static void set_out_format(struct saa7146 *saa, int mode)
716{
717 initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
718 saa->boardcfg[2] = mode;
719 /* do not adjust analog video parameters here, use saa7121 init */
720 /* you will affect the SDI output on the new card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200721 if (mode == VIDEO_MODE_PAL) { /* PAL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
723 mdelay(50);
724 saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
725 if (NewCard) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200726 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 mdelay(50);
728 }
729 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200730 NewCard ? 0xe500 : 0x6500, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
732 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200733 (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 } else { /* NTSC */
735 debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
736 mdelay(50);
737 saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
738 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200739 NewCard ? 0xe100 : 0x6100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
741 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200742 (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
744}
745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746/* Intialize bitmangler to map from a byte value to the mangled word that
747 * must be output to program the Xilinx part through the DEBI port.
748 * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
749 * transfer FPGA code, init IBM chip, transfer IBM microcode
750 * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
751 */
752static u16 bitmangler[256];
753
754static int initialize_fpga(struct video_code *bitdata)
755{
756 int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
757 u16 *dmabuf;
758 u8 *newdma;
759 struct saa7146 *saa;
760
761 /* verify fpga code */
762 for (startindex = 0; startindex < bitdata->datasize; startindex++)
763 if (bitdata->data[startindex] == 255)
764 break;
765 if (startindex == bitdata->datasize) {
766 printk(KERN_INFO "stradis: bad fpga code\n");
767 return -1;
768 }
769 /* initialize all detected cards */
770 for (num = 0; num < saa_num; num++) {
771 saa = &saa7146s[num];
772 if (saa->boardcfg[0] > 20)
Jiri Slabyf823f672006-01-11 19:41:32 -0200773 continue; /* card was programmed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 loadtwo = (saa->boardcfg[18] & 0x10);
775 if (!NewCard) /* we have an old board */
776 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200777 bitmangler[i] = ((i & 0x01) << 15) |
778 ((i & 0x02) << 6) | ((i & 0x04) << 4) |
779 ((i & 0x08) << 9) | ((i & 0x10) << 7) |
780 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
781 ((i & 0x80) >> 7);
782 else /* else we have a new board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200784 bitmangler[i] = ((i & 0x01) << 7) |
785 ((i & 0x02) << 5) | ((i & 0x04) << 3) |
786 ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
787 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
788 ((i & 0x80) >> 7);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 dmabuf = (u16 *) saa->dmadebi;
791 newdma = (u8 *) saa->dmadebi;
792 if (NewCard) { /* SDM2xxx */
793 if (!strncmp(bitdata->loadwhat, "decoder2", 8))
794 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200795 if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 loadfile = 1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200797 else if (loadtwo && !strncmp(&saa->boardcfg[19],
798 bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 loadfile = 2;
Jiri Slabyf823f672006-01-11 19:41:32 -0200800 else if (!saa->boardcfg[42] && !strncmp("decxl",
801 bitdata->loadwhat, 8))
802 loadfile = 1; /* special */
803 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200805 if (loadfile != 1 && loadfile != 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 continue; /* skip to next card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200807 if (saa->boardcfg[0] && loadfile == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 continue; /* skip to next card */
809 if (saa->boardcfg[0] != 1 && loadfile == 2)
810 continue; /* skip to next card */
811 saa->boardcfg[0]++; /* mark fpga handled */
812 printk("stradis%d: loading %s\n", saa->nr,
813 bitdata->loadwhat);
814 if (loadtwo && loadfile == 2)
815 goto send_fpga_stuff;
816 /* turn on the Audio interface to set PROG low */
817 saawrite(0x00400040, SAA7146_GPIO_CTRL);
818 saaread(SAA7146_PSR); /* ensure posted write */
819 /* wait for everyone to reset */
820 mdelay(10);
821 saawrite(0x00400000, SAA7146_GPIO_CTRL);
822 } else { /* original card */
823 if (strncmp(bitdata->loadwhat, "decoder2", 8))
824 continue; /* fpga not for this card */
825 /* Pull the Xilinx PROG signal WS3 low */
826 saawrite(0x02000200, SAA7146_MC1);
827 /* Turn on the Audio interface so can set PROG low */
828 saawrite(0x000000c0, SAA7146_ACON1);
829 /* Pull the Xilinx INIT signal (GPIO2) low */
830 saawrite(0x00400000, SAA7146_GPIO_CTRL);
831 /* Make sure everybody resets */
832 saaread(SAA7146_PSR); /* ensure posted write */
833 mdelay(10);
834 /* Release the Xilinx PROG signal */
835 saawrite(0x00000000, SAA7146_ACON1);
836 /* Turn off the Audio interface */
837 saawrite(0x02000000, SAA7146_MC1);
838 }
839 /* Release Xilinx INIT signal (WS2) */
840 saawrite(0x00000000, SAA7146_GPIO_CTRL);
841 /* Wait for the INIT to go High */
Jiri Slabyf823f672006-01-11 19:41:32 -0200842 for (i = 0;
843 i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
844 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 schedule();
846 if (i == 1000) {
847 printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
848 return -1;
849 }
850send_fpga_stuff:
851 if (NewCard) {
852 for (i = startindex; i < bitdata->datasize; i++)
853 newdma[i - startindex] =
Jiri Slabyf823f672006-01-11 19:41:32 -0200854 bitmangler[bitdata->data[i]];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 debiwrite(saa, 0x01420000, 0, 0,
856 ((bitdata->datasize - startindex) + 5));
Jiri Slabyf823f672006-01-11 19:41:32 -0200857 if (loadtwo && loadfile == 1) {
858 printk("stradis%d: awaiting 2nd FPGA bitfile\n",
859 saa->nr);
860 continue; /* skip to next card */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 }
862 } else {
863 for (i = startindex; i < bitdata->datasize; i++)
864 dmabuf[i - startindex] =
865 bitmangler[bitdata->data[i]];
866 debiwrite(saa, 0x014a0000, 0, 0,
867 ((bitdata->datasize - startindex) + 5) * 2);
868 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200869 for (i = 0;
870 i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
871 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 schedule();
873 if (i == 1000) {
874 printk(KERN_INFO "stradis%d: FPGA load failed\n",
875 saa->nr);
876 failure++;
877 continue;
878 }
879 if (!NewCard) {
880 /* Pull the Xilinx INIT signal (GPIO2) low */
881 saawrite(0x00400000, SAA7146_GPIO_CTRL);
882 saaread(SAA7146_PSR); /* ensure posted write */
883 mdelay(2);
884 saawrite(0x00000000, SAA7146_GPIO_CTRL);
885 mdelay(2);
886 }
887 printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
888 saa->boardcfg[0] = 26; /* mark fpga programmed */
889 /* set VXCO to its lowest frequency */
890 debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
891 if (NewCard) {
892 /* mute CS3310 */
893 if (HaveCS3310)
894 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
Jiri Slabyf823f672006-01-11 19:41:32 -0200895 0, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 /* set VXCO to PWM mode, release reset, blank on */
897 debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
898 mdelay(10);
899 /* unmute CS3310 */
900 if (HaveCS3310)
901 debiwrite(saa, debNormal, XILINX_CTL0,
Jiri Slabyf823f672006-01-11 19:41:32 -0200902 0x2020, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
904 /* set source Black */
905 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
906 saa->boardcfg[4] = 22; /* set NTSC First Active Line */
907 saa->boardcfg[5] = 23; /* set PAL First Active Line */
908 saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */
909 saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */
910 set_out_format(saa, VIDEO_MODE_NTSC);
911 mdelay(50);
912 /* begin IBM chip init */
913 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
914 saaread(SAA7146_PSR); /* wait for reset */
915 mdelay(5);
916 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
917 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
918 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
919 debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
920 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
921 if (NewCard) {
922 mdelay(5);
923 /* set i2s rate converter to 48KHz */
924 debiwrite(saa, debNormal, 0x80c0, 6, 2);
925 /* we must init CS8420 first since rev b pulls i2s */
926 /* master clock low and CS4341 needs i2s master to */
927 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200928 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 /* 0=consumer, 1=pro */
930 initialize_cs8420(saa, 0);
Jiri Slabyf823f672006-01-11 19:41:32 -0200931
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 mdelay(5);
933 if (HaveCS4341)
934 initialize_cs4341(saa);
935 }
936 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
937 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
938 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
939 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
940 if (NewCard)
941 set_genlock_offset(saa, 0);
942 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
943#if 0
944 /* enable genlock */
945 debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
946#else
947 /* disable genlock */
948 debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
949#endif
950 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 return failure;
953}
954
955static int do_ibm_reset(struct saa7146 *saa)
956{
957 /* failure if decoder not previously programmed */
958 if (saa->boardcfg[0] < 37)
959 return -EIO;
960 /* mute CS3310 */
961 if (HaveCS3310)
962 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
963 /* disable interrupts */
964 saawrite(0, SAA7146_IER);
965 saa->audhead = saa->audtail = 0;
966 saa->vidhead = saa->vidtail = 0;
967 /* tristate debi bus, disable debi transfers */
968 saawrite(0x00880000, SAA7146_MC1);
969 /* ensure posted write */
970 saaread(SAA7146_MC1);
971 mdelay(50);
972 /* re-enable debi transfers */
973 saawrite(0x00880088, SAA7146_MC1);
974 /* set source Black */
975 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
976 /* begin IBM chip init */
977 set_out_format(saa, CurrentMode);
978 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
979 saaread(SAA7146_PSR); /* wait for reset */
980 mdelay(5);
981 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
982 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
983 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
984 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
985 if (NewCard) {
986 mdelay(5);
987 /* set i2s rate converter to 48KHz */
988 debiwrite(saa, debNormal, 0x80c0, 6, 2);
989 /* we must init CS8420 first since rev b pulls i2s */
990 /* master clock low and CS4341 needs i2s master to */
991 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200992 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 /* 0=consumer, 1=pro */
994 initialize_cs8420(saa, 1);
Jiri Slabyf823f672006-01-11 19:41:32 -0200995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 mdelay(5);
997 if (HaveCS4341)
998 initialize_cs4341(saa);
999 }
1000 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
1001 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
1002 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
1003 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
1004 if (NewCard)
1005 set_genlock_offset(saa, 0);
1006 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
1007 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1008 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1009 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001010 (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
1012 }
1013 if (HaveCS3310) {
1014 int i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001015 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017 /* start video decoder */
1018 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1019 /* 256k vid, 3520 bytes aud */
1020 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
1021 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1022 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1023 /* enable buffer threshold irq */
1024 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1025 /* clear pending interrupts */
1026 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1027 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return 0;
1030}
1031
1032/* load the decoder microcode */
1033static int initialize_ibmmpeg2(struct video_code *microcode)
1034{
1035 int i, num;
1036 struct saa7146 *saa;
1037
1038 for (num = 0; num < saa_num; num++) {
1039 saa = &saa7146s[num];
1040 /* check that FPGA is loaded */
1041 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001042 i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
1043 if (i != 0xa55a) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
1045 saa->nr, i);
1046#if 0
1047 return -1;
1048#endif
1049 }
1050 if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
1051 if (saa->boardcfg[0] > 27)
1052 continue; /* skip to next card */
1053 /* load video control store */
Jiri Slabyf823f672006-01-11 19:41:32 -02001054 saa->boardcfg[1] = 0x13; /* no-sync default */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1056 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1057 for (i = 0; i < microcode->datasize / 2; i++)
1058 debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
1059 (microcode->data[i * 2] << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001060 microcode->data[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1062 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1063 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
Jiri Slabyf823f672006-01-11 19:41:32 -02001064 ChipControl, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 saa->boardcfg[0] = 28;
1066 }
1067 if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
1068 if (saa->boardcfg[0] > 35)
1069 continue; /* skip to next card */
1070 /* load audio control store */
1071 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1072 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1073 for (i = 0; i < microcode->datasize; i++)
1074 debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
1075 microcode->data[i], 1);
1076 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1077 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1078 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1079 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1080 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001081 0xe000, 1)) {
1082 printk(KERN_ERR "stradis%d: IBM config "
1083 "failed\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 return -1;
1085 }
1086 /* set PWM to center value */
1087 if (NewCard) {
1088 debiwrite(saa, debNormal, XILINX_PWM,
Jiri Slabyf823f672006-01-11 19:41:32 -02001089 saa->boardcfg[14] +
1090 (saa->boardcfg[13] << 8), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 } else
Jiri Slabyf823f672006-01-11 19:41:32 -02001092 debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
1093
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 if (HaveCS3310) {
1095 i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001096 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
1097 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001099 printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
1100 saa->nr, 18 + (debiread(saa, debNormal,
1101 IBM_MP2_CHIP_CONTROL, 2) >> 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 /* start video decoder */
1103 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1104 ChipControl, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001105 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
1106 2); /* 256k vid, 3520 bytes aud */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1108 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1109 /* enable buffer threshold irq */
1110 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1111 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1112 /* enable gpio irq */
1113 saawrite(0x00002000, SAA7146_GPIO_CTRL);
1114 /* enable decoder output to HPS */
1115 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
1116 saa->boardcfg[0] = 37;
1117 }
1118 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return 0;
1121}
1122
Jiri Slabyf823f672006-01-11 19:41:32 -02001123static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
1124 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
1125 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
1126 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127};
Jiri Slabyf823f672006-01-11 19:41:32 -02001128static int bpp2fmt[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
1130 VIDEO_PALETTE_RGB32
1131};
1132
1133/* I wish I could find a formula to calculate these... */
Jiri Slabyf823f672006-01-11 19:41:32 -02001134static u32 h_prescale[64] = {
1135 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
1136 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
1137 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
1138 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
1139 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
1140 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
1141 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
1142 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
1143 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
1144 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
1145 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146};
Jiri Slabyf823f672006-01-11 19:41:32 -02001147static u32 v_gain[64] = {
1148 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
1149 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
1150 0x016300ff, 0x016300ff, 0x016300ff, 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, 0x016400ff, 0x016400ff,
1158 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159};
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161static void saa7146_set_winsize(struct saa7146 *saa)
1162{
1163 u32 format;
1164 int offset, yacl, ysci;
1165 saa->win.color_fmt = format =
1166 (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
1167 palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
1168 offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
1169 saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
1170 saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
1171 saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
1172 saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
1173 SAA7146_PROT_ADDR1);
1174 saawrite(0, SAA7146_PAGE1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001175 saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 offset = (704 / (saa->win.width - 1)) & 0x3f;
1177 saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
1178 offset = (720896 / saa->win.width) / (offset + 1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001179 saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 if (CurrentMode == VIDEO_MODE_NTSC) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001181 yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 ysci = 1024 - (saa->win.height * 1024 / 480);
1183 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -02001184 yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 ysci = 1024 - (saa->win.height * 1024 / 576);
1186 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001187 saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
1189 saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
Jiri Slabyf823f672006-01-11 19:41:32 -02001190 SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
1191 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192}
1193
1194/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001195 * bitmap is fixed width, 128 bytes (1024 pixels represented)
1196 * arranged most-sigificant-bit-left in 32-bit words
1197 * based on saa7146 clipping hardware, it swaps bytes if LE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 * much of this makes up for egcs brain damage -- so if you
1199 * are wondering "why did he do this?" it is because the C
1200 * was adjusted to generate the optimal asm output without
1201 * writing non-portable __asm__ directives.
1202 */
1203
1204static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
1205{
1206 register int startword, endword;
1207 register u32 bitsleft, bitsright;
1208 u32 *temp;
1209 if (x < 0) {
1210 w += x;
1211 x = 0;
1212 }
1213 if (y < 0) {
1214 h += y;
1215 y = 0;
1216 }
1217 if (w <= 0 || h <= 0 || x > 1023 || y > 639)
1218 return; /* throw away bad clips */
1219 if (x + w > 1024)
1220 w = 1024 - x;
1221 if (y + h > 640)
1222 h = 640 - y;
1223 startword = (x >> 5);
1224 endword = ((x + w) >> 5);
1225 bitsleft = (0xffffffff >> (x & 31));
Jiri Slabyf823f672006-01-11 19:41:32 -02001226 bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
1227 temp = &clipmap[(y << 5) + startword];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 w = endword - startword;
1229 if (!w) {
1230 bitsleft |= bitsright;
1231 for (y = 0; y < h; y++) {
1232 *temp |= bitsleft;
1233 temp += 32;
1234 }
1235 } else {
1236 for (y = 0; y < h; y++) {
1237 *temp++ |= bitsleft;
1238 for (x = 1; x < w; x++)
1239 *temp++ = 0xffffffff;
1240 *temp |= bitsright;
1241 temp += (32 - w);
1242 }
1243 }
1244}
1245
1246static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
1247{
1248 int i, width, height;
1249 u32 *clipmap;
1250
1251 clipmap = saa->dmavid2;
Jiri Slabyf823f672006-01-11 19:41:32 -02001252 if ((width = saa->win.width) > 1023)
1253 width = 1023; /* sanity check */
1254 if ((height = saa->win.height) > 640)
1255 height = 639; /* sanity check */
1256 if (ncr > 0) { /* rectangles pased */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 /* convert rectangular clips to a bitmap */
Jiri Slabyf823f672006-01-11 19:41:32 -02001258 memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 for (i = 0; i < ncr; i++)
1260 clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
1261 cr[i].width, cr[i].height);
1262 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001263 /* clip against viewing window AND screen
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 so we do not have to rely on the user program
1265 */
Jiri Slabyf823f672006-01-11 19:41:32 -02001266 clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
1267 (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
1268 clip_draw_rectangle(clipmap, 0,
1269 (saa->win.y + height > saa->win.sheight) ?
1270 (saa->win.sheight - saa->win.y) : height, 1024, 768);
1271 if (saa->win.x < 0)
1272 clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
1273 if (saa->win.y < 0)
1274 clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275}
1276
1277static int saa_ioctl(struct inode *inode, struct file *file,
1278 unsigned int cmd, unsigned long argl)
1279{
1280 struct saa7146 *saa = file->private_data;
1281 void __user *arg = (void __user *)argl;
1282
1283 switch (cmd) {
1284 case VIDIOCGCAP:
1285 {
1286 struct video_capability b;
1287 strcpy(b.name, saa->video_dev.name);
Jiri Slabyf823f672006-01-11 19:41:32 -02001288 b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
1289 VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
1290 VID_TYPE_SCALES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 b.channels = 1;
1292 b.audios = 1;
1293 b.maxwidth = 768;
1294 b.maxheight = 576;
1295 b.minwidth = 32;
1296 b.minheight = 32;
1297 if (copy_to_user(arg, &b, sizeof(b)))
1298 return -EFAULT;
1299 return 0;
1300 }
1301 case VIDIOCGPICT:
1302 {
1303 struct video_picture p = saa->picture;
1304 if (saa->win.depth == 8)
1305 p.palette = VIDEO_PALETTE_HI240;
1306 if (saa->win.depth == 15)
1307 p.palette = VIDEO_PALETTE_RGB555;
1308 if (saa->win.depth == 16)
1309 p.palette = VIDEO_PALETTE_RGB565;
1310 if (saa->win.depth == 24)
1311 p.palette = VIDEO_PALETTE_RGB24;
1312 if (saa->win.depth == 32)
1313 p.palette = VIDEO_PALETTE_RGB32;
1314 if (copy_to_user(arg, &p, sizeof(p)))
1315 return -EFAULT;
1316 return 0;
1317 }
1318 case VIDIOCSPICT:
1319 {
1320 struct video_picture p;
1321 u32 format;
1322 if (copy_from_user(&p, arg, sizeof(p)))
1323 return -EFAULT;
1324 if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
1325 format = palette2fmt[p.palette];
1326 saa->win.color_fmt = format;
Jiri Slabyf823f672006-01-11 19:41:32 -02001327 saawrite(format | 0x60,
1328 SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 }
1330 saawrite(((p.brightness & 0xff00) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001331 ((p.contrast & 0xfe00) << 7) |
1332 ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 saa->picture = p;
1334 /* upload changed registers */
1335 saawrite(((SAA7146_MC2_UPLD_HPS_H |
Jiri Slabyf823f672006-01-11 19:41:32 -02001336 SAA7146_MC2_UPLD_HPS_V) << 16) |
1337 SAA7146_MC2_UPLD_HPS_H |
1338 SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return 0;
1340 }
1341 case VIDIOCSWIN:
1342 {
1343 struct video_window vw;
1344 struct video_clip *vcp = NULL;
1345
1346 if (copy_from_user(&vw, arg, sizeof(vw)))
1347 return -EFAULT;
1348
Jiri Slabyf823f672006-01-11 19:41:32 -02001349 /* stop capture */
1350 if (vw.flags || vw.width < 16 || vw.height < 16) {
1351 saawrite((SAA7146_MC1_TR_E_1 << 16),
1352 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 return -EINVAL;
1354 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001355 /* 32-bit align start and adjust width */
1356 if (saa->win.bpp < 4) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 int i = vw.x;
1358 vw.x = (vw.x + 3) & ~3;
1359 i = vw.x - i;
1360 vw.width -= i;
1361 }
1362 saa->win.x = vw.x;
1363 saa->win.y = vw.y;
1364 saa->win.width = vw.width;
1365 if (saa->win.width > 768)
1366 saa->win.width = 768;
1367 saa->win.height = vw.height;
1368 if (CurrentMode == VIDEO_MODE_NTSC) {
1369 if (saa->win.height > 480)
1370 saa->win.height = 480;
1371 } else {
1372 if (saa->win.height > 576)
1373 saa->win.height = 576;
1374 }
1375
1376 /* stop capture */
1377 saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
1378 saa7146_set_winsize(saa);
1379
1380 /*
1381 * Do any clips.
1382 */
1383 if (vw.clipcount < 0) {
1384 if (copy_from_user(saa->dmavid2, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001385 VIDEO_CLIPMAP_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001387 } else if (vw.clipcount > 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 return -EINVAL;
1389 } else if (vw.clipcount > 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001390 vcp = vmalloc(sizeof(struct video_clip) *
1391 vw.clipcount);
1392 if (vcp == NULL)
1393 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 if (copy_from_user(vcp, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001395 sizeof(struct video_clip) *
1396 vw.clipcount)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 vfree(vcp);
1398 return -EFAULT;
1399 }
1400 } else /* nothing clipped */
1401 memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
Jiri Slabyf823f672006-01-11 19:41:32 -02001402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 make_clip_tab(saa, vcp, vw.clipcount);
1404 if (vw.clipcount > 0)
1405 vfree(vcp);
1406
1407 /* start capture & clip dma if we have an address */
1408 if ((saa->cap & 3) && saa->win.vidadr != 0)
1409 saawrite(((SAA7146_MC1_TR_E_1 |
1410 SAA7146_MC1_TR_E_2) << 16) | 0xffff,
1411 SAA7146_MC1);
1412 return 0;
1413 }
1414 case VIDIOCGWIN:
1415 {
1416 struct video_window vw;
1417 vw.x = saa->win.x;
1418 vw.y = saa->win.y;
1419 vw.width = saa->win.width;
1420 vw.height = saa->win.height;
1421 vw.chromakey = 0;
1422 vw.flags = 0;
1423 if (copy_to_user(arg, &vw, sizeof(vw)))
1424 return -EFAULT;
1425 return 0;
1426 }
1427 case VIDIOCCAPTURE:
1428 {
1429 int v;
1430 if (copy_from_user(&v, arg, sizeof(v)))
1431 return -EFAULT;
1432 if (v == 0) {
1433 saa->cap &= ~1;
1434 saawrite((SAA7146_MC1_TR_E_1 << 16),
Jiri Slabyf823f672006-01-11 19:41:32 -02001435 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 } else {
1437 if (saa->win.vidadr == 0 || saa->win.width == 0
Jiri Slabyf823f672006-01-11 19:41:32 -02001438 || saa->win.height == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return -EINVAL;
1440 saa->cap |= 1;
1441 saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
Jiri Slabyf823f672006-01-11 19:41:32 -02001442 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 }
1444 return 0;
1445 }
1446 case VIDIOCGFBUF:
1447 {
1448 struct video_buffer v;
Jiri Slabyf823f672006-01-11 19:41:32 -02001449 v.base = (void *)saa->win.vidadr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 v.height = saa->win.sheight;
1451 v.width = saa->win.swidth;
1452 v.depth = saa->win.depth;
1453 v.bytesperline = saa->win.bpl;
1454 if (copy_to_user(arg, &v, sizeof(v)))
1455 return -EFAULT;
1456 return 0;
1457
1458 }
1459 case VIDIOCSFBUF:
1460 {
1461 struct video_buffer v;
1462 if (!capable(CAP_SYS_ADMIN))
1463 return -EPERM;
1464 if (copy_from_user(&v, arg, sizeof(v)))
1465 return -EFAULT;
1466 if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
Jiri Slabyf823f672006-01-11 19:41:32 -02001467 v.depth != 24 && v.depth != 32 && v.width > 16 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 v.height > 16 && v.bytesperline > 16)
1469 return -EINVAL;
1470 if (v.base)
Jiri Slabyf823f672006-01-11 19:41:32 -02001471 saa->win.vidadr = (unsigned long)v.base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 saa->win.sheight = v.height;
1473 saa->win.swidth = v.width;
1474 saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
1475 saa->win.depth = v.depth;
1476 saa->win.bpl = v.bytesperline;
1477
Jiri Slabyf823f672006-01-11 19:41:32 -02001478 DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
1479 "bpl %d\n", v.base, v.width, v.height,
1480 saa->win.bpp, saa->win.bpl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 saa7146_set_winsize(saa);
1482 return 0;
1483 }
1484 case VIDIOCKEY:
1485 {
1486 /* Will be handled higher up .. */
1487 return 0;
1488 }
1489
1490 case VIDIOCGAUDIO:
1491 {
1492 struct video_audio v;
1493 v = saa->audio_dev;
1494 v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
1495 v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
1496 strcpy(v.name, "MPEG");
1497 v.mode = VIDEO_SOUND_STEREO;
1498 if (copy_to_user(arg, &v, sizeof(v)))
1499 return -EFAULT;
1500 return 0;
1501 }
1502 case VIDIOCSAUDIO:
1503 {
1504 struct video_audio v;
1505 int i;
1506 if (copy_from_user(&v, arg, sizeof(v)))
1507 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001508 i = (~(v.volume >> 8)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 if (!HaveCS4341) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001510 if (v.flags & VIDEO_AUDIO_MUTE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001512 IBM_MP2_FRNT_ATTEN, 0xffff, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 if (!(v.flags & VIDEO_AUDIO_MUTE))
1514 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001515 IBM_MP2_FRNT_ATTEN, 0x0000, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 if (v.flags & VIDEO_AUDIO_VOLUME)
1517 debiwrite(saa, debNormal,
1518 IBM_MP2_FRNT_ATTEN,
Jiri Slabyf823f672006-01-11 19:41:32 -02001519 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 } else {
1521 if (v.flags & VIDEO_AUDIO_MUTE)
1522 cs4341_setlevel(saa, 0xff, 0xff);
1523 if (!(v.flags & VIDEO_AUDIO_MUTE))
1524 cs4341_setlevel(saa, 0, 0);
1525 if (v.flags & VIDEO_AUDIO_VOLUME)
1526 cs4341_setlevel(saa, i, i);
1527 }
1528 saa->audio_dev = v;
1529 return 0;
1530 }
1531
1532 case VIDIOCGUNIT:
1533 {
1534 struct video_unit vu;
1535 vu.video = saa->video_dev.minor;
1536 vu.vbi = VIDEO_NO_UNIT;
1537 vu.radio = VIDEO_NO_UNIT;
1538 vu.audio = VIDEO_NO_UNIT;
1539 vu.teletext = VIDEO_NO_UNIT;
1540 if (copy_to_user(arg, &vu, sizeof(vu)))
1541 return -EFAULT;
1542 return 0;
1543 }
1544 case VIDIOCSPLAYMODE:
1545 {
1546 struct video_play_mode pmode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001547 if (copy_from_user((void *)&pmode, arg,
1548 sizeof(struct video_play_mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 return -EFAULT;
1550 switch (pmode.mode) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001551 case VID_PLAY_VID_OUT_MODE:
1552 if (pmode.p1 != VIDEO_MODE_NTSC &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 pmode.p1 != VIDEO_MODE_PAL)
Jiri Slabyf823f672006-01-11 19:41:32 -02001554 return -EINVAL;
1555 set_out_format(saa, pmode.p1);
1556 return 0;
1557 case VID_PLAY_GENLOCK:
1558 debiwrite(saa, debNormal, XILINX_CTL0,
1559 pmode.p1 ? 0x8000 : 0x8080, 2);
1560 if (NewCard)
1561 set_genlock_offset(saa, pmode.p2);
1562 return 0;
1563 case VID_PLAY_NORMAL:
1564 debiwrite(saa, debNormal,
1565 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1566 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1567 saa->playmode = pmode.mode;
1568 return 0;
1569 case VID_PLAY_PAUSE:
1570 /* IBM removed the PAUSE command */
1571 /* they say use SINGLE_FRAME now */
1572 case VID_PLAY_SINGLE_FRAME:
1573 ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
1574 if (saa->playmode == pmode.mode) {
1575 debiwrite(saa, debNormal,
1576 IBM_MP2_CHIP_CONTROL,
1577 ChipControl, 2);
1578 }
1579 saa->playmode = pmode.mode;
1580 return 0;
1581 case VID_PLAY_FAST_FORWARD:
1582 ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
1583 saa->playmode = pmode.mode;
1584 return 0;
1585 case VID_PLAY_SLOW_MOTION:
1586 ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
1587 pmode.p1, 0);
1588 saa->playmode = pmode.mode;
1589 return 0;
1590 case VID_PLAY_IMMEDIATE_NORMAL:
1591 /* ensure transfers resume */
1592 debiwrite(saa, debNormal,
1593 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1594 ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
1595 0, 0);
1596 saa->playmode = VID_PLAY_NORMAL;
1597 return 0;
1598 case VID_PLAY_SWITCH_CHANNELS:
1599 saa->audhead = saa->audtail = 0;
1600 saa->vidhead = saa->vidtail = 0;
1601 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
1602 ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
1603 0, 1);
1604 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1605 0, 2);
1606 ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
1607 0, 1);
1608 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1609 ChipControl, 2);
1610 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1611 saa->playmode = VID_PLAY_NORMAL;
1612 return 0;
1613 case VID_PLAY_FREEZE_FRAME:
1614 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
1615 saa->playmode = pmode.mode;
1616 return 0;
1617 case VID_PLAY_STILL_MODE:
1618 ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
1619 0, 0);
1620 saa->playmode = pmode.mode;
1621 return 0;
1622 case VID_PLAY_MASTER_MODE:
1623 if (pmode.p1 == VID_PLAY_MASTER_NONE)
1624 saa->boardcfg[1] = 0x13;
1625 else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
1626 saa->boardcfg[1] = 0x23;
1627 else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
1628 saa->boardcfg[1] = 0x43;
1629 else
1630 return -EINVAL;
1631 debiwrite(saa, debNormal,
1632 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1633 return 0;
1634 case VID_PLAY_ACTIVE_SCANLINES:
1635 if (CurrentMode == VIDEO_MODE_PAL) {
1636 if (pmode.p1 < 1 || pmode.p2 > 625)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001638 saa->boardcfg[5] = pmode.p1;
1639 saa->boardcfg[55] = (pmode.p1 +
1640 (pmode.p2 / 2) - 1) & 0xff;
1641 } else {
1642 if (pmode.p1 < 4 || pmode.p2 > 525)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001644 saa->boardcfg[4] = pmode.p1;
1645 saa->boardcfg[54] = (pmode.p1 +
1646 (pmode.p2 / 2) - 4) & 0xff;
1647 }
1648 set_out_format(saa, CurrentMode);
1649 case VID_PLAY_RESET:
1650 return do_ibm_reset(saa);
1651 case VID_PLAY_END_MARK:
1652 if (saa->endmarktail < saa->endmarkhead) {
1653 if (saa->endmarkhead -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 saa->endmarktail < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 return -ENOSPC;
Jiri Slabyf823f672006-01-11 19:41:32 -02001656 } else if (saa->endmarkhead <=saa->endmarktail){
1657 if (saa->endmarktail - saa->endmarkhead
1658 > (MAX_MARKS - 2))
1659 return -ENOSPC;
1660 } else
1661 return -ENOSPC;
1662 saa->endmark[saa->endmarktail] = saa->audtail;
1663 saa->endmarktail++;
1664 if (saa->endmarktail >= MAX_MARKS)
1665 saa->endmarktail = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 }
1667 return -EINVAL;
1668 }
1669 case VIDIOCSWRITEMODE:
1670 {
1671 int mode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001672 if (copy_from_user((void *)&mode, arg, sizeof(int)))
1673 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 if (mode == VID_WRITE_MPEG_AUD ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001675 mode == VID_WRITE_MPEG_VID ||
1676 mode == VID_WRITE_CC ||
1677 mode == VID_WRITE_TTX ||
1678 mode == VID_WRITE_OSD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 saa->writemode = mode;
1680 return 0;
1681 }
1682 return -EINVAL;
1683 }
1684 case VIDIOCSMICROCODE:
1685 {
1686 struct video_code ucode;
1687 __u8 *udata;
1688 int i;
1689 if (copy_from_user(&ucode, arg, sizeof(ucode)))
1690 return -EFAULT;
1691 if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001692 strncmp(ucode.loadwhat, "dec", 3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 return -EINVAL;
1694 if ((udata = vmalloc(ucode.datasize)) == NULL)
1695 return -ENOMEM;
1696 if (copy_from_user(udata, ucode.data, ucode.datasize)) {
1697 vfree(udata);
1698 return -EFAULT;
1699 }
1700 ucode.data = udata;
Jiri Slabyf823f672006-01-11 19:41:32 -02001701 if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
1702 !strncmp(ucode.loadwhat, "decoder.vid", 11))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 i = initialize_ibmmpeg2(&ucode);
1704 else
1705 i = initialize_fpga(&ucode);
1706 vfree(udata);
1707 if (i)
1708 return -EINVAL;
1709 return 0;
1710
1711 }
1712 case VIDIOCGCHAN: /* this makes xawtv happy */
1713 {
1714 struct video_channel v;
1715 if (copy_from_user(&v, arg, sizeof(v)))
1716 return -EFAULT;
1717 v.flags = VIDEO_VC_AUDIO;
1718 v.tuners = 0;
1719 v.type = VID_TYPE_MPEG_DECODER;
1720 v.norm = CurrentMode;
1721 strcpy(v.name, "MPEG2");
1722 if (copy_to_user(arg, &v, sizeof(v)))
1723 return -EFAULT;
1724 return 0;
1725 }
1726 case VIDIOCSCHAN: /* this makes xawtv happy */
1727 {
1728 struct video_channel v;
1729 if (copy_from_user(&v, arg, sizeof(v)))
1730 return -EFAULT;
1731 /* do nothing */
1732 return 0;
1733 }
1734 default:
1735 return -ENOIOCTLCMD;
1736 }
1737 return 0;
1738}
1739
1740static int saa_mmap(struct file *file, struct vm_area_struct *vma)
1741{
1742 struct saa7146 *saa = file->private_data;
1743 printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
1744 return -EINVAL;
1745}
1746
Jiri Slabyf823f672006-01-11 19:41:32 -02001747static ssize_t saa_read(struct file *file, char __user * buf,
1748 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749{
1750 return -EINVAL;
1751}
1752
Jiri Slabyf823f672006-01-11 19:41:32 -02001753static ssize_t saa_write(struct file *file, const char __user * buf,
1754 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755{
1756 struct saa7146 *saa = file->private_data;
1757 unsigned long todo = count;
1758 int blocksize, split;
1759 unsigned long flags;
1760
1761 while (todo > 0) {
1762 if (saa->writemode == VID_WRITE_MPEG_AUD) {
1763 spin_lock_irqsave(&saa->lock, flags);
1764 if (saa->audhead <= saa->audtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001765 blocksize = 65536 -
1766 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 else
1768 blocksize = saa->audhead - saa->audtail;
1769 spin_unlock_irqrestore(&saa->lock, flags);
1770 if (blocksize < 16384) {
1771 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001772 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1774 /* wait for buffer space to open */
1775 interruptible_sleep_on(&saa->audq);
1776 }
1777 spin_lock_irqsave(&saa->lock, flags);
1778 if (saa->audhead <= saa->audtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001779 blocksize = 65536 -
1780 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 split = 65536 - saa->audtail;
1782 } else {
1783 blocksize = saa->audhead - saa->audtail;
1784 split = 65536;
1785 }
1786 spin_unlock_irqrestore(&saa->lock, flags);
1787 blocksize--;
1788 if (blocksize > todo)
1789 blocksize = todo;
1790 /* double check that we really have space */
1791 if (!blocksize)
1792 return -ENOSPC;
1793 if (split < blocksize) {
1794 if (copy_from_user(saa->audbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001795 saa->audtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 return -EFAULT;
1797 buf += split;
1798 todo -= split;
1799 blocksize -= split;
1800 saa->audtail = 0;
1801 }
1802 if (copy_from_user(saa->audbuf + saa->audtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001803 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 return -EFAULT;
1805 saa->audtail += blocksize;
1806 todo -= blocksize;
1807 buf += blocksize;
1808 saa->audtail &= 0xffff;
1809 } else if (saa->writemode == VID_WRITE_MPEG_VID) {
1810 spin_lock_irqsave(&saa->lock, flags);
1811 if (saa->vidhead <= saa->vidtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001812 blocksize = 524288 -
1813 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 else
1815 blocksize = saa->vidhead - saa->vidtail;
1816 spin_unlock_irqrestore(&saa->lock, flags);
1817 if (blocksize < 65536) {
1818 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001819 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1821 /* wait for buffer space to open */
1822 interruptible_sleep_on(&saa->vidq);
1823 }
1824 spin_lock_irqsave(&saa->lock, flags);
1825 if (saa->vidhead <= saa->vidtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001826 blocksize = 524288 -
1827 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 split = 524288 - saa->vidtail;
1829 } else {
1830 blocksize = saa->vidhead - saa->vidtail;
1831 split = 524288;
1832 }
1833 spin_unlock_irqrestore(&saa->lock, flags);
1834 blocksize--;
1835 if (blocksize > todo)
1836 blocksize = todo;
1837 /* double check that we really have space */
1838 if (!blocksize)
1839 return -ENOSPC;
1840 if (split < blocksize) {
1841 if (copy_from_user(saa->vidbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001842 saa->vidtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 return -EFAULT;
1844 buf += split;
1845 todo -= split;
1846 blocksize -= split;
1847 saa->vidtail = 0;
1848 }
1849 if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001850 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 return -EFAULT;
1852 saa->vidtail += blocksize;
1853 todo -= blocksize;
1854 buf += blocksize;
1855 saa->vidtail &= 0x7ffff;
1856 } else if (saa->writemode == VID_WRITE_OSD) {
1857 if (count > 131072)
1858 return -ENOSPC;
1859 if (copy_from_user(saa->osdbuf, buf, count))
1860 return -EFAULT;
1861 buf += count;
1862 saa->osdhead = 0;
1863 saa->osdtail = count;
1864 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
1865 debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
1866 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
1867 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -02001868 debiread(saa, debNormal,
1869 IBM_MP2_DISP_MODE, 2) | 1, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 /* trigger osd data transfer */
1871 saawrite(SAA7146_PSR_DEBI_S |
1872 SAA7146_PSR_PIN1, SAA7146_IER);
1873 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1874 }
1875 }
1876 return count;
1877}
1878
1879static int saa_open(struct inode *inode, struct file *file)
1880{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001881 struct video_device *vdev = video_devdata(file);
1882 struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 file->private_data = saa;
1885
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 saa->user++;
1887 if (saa->user > 1)
1888 return 0; /* device open already, don't reset */
1889 saa->writemode = VID_WRITE_MPEG_VID; /* default to video */
1890 return 0;
1891}
1892
1893static int saa_release(struct inode *inode, struct file *file)
1894{
1895 struct saa7146 *saa = file->private_data;
1896 saa->user--;
Jiri Slaby91fb8352006-01-11 19:41:21 -02001897
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 if (saa->user > 0) /* still someone using device */
1899 return 0;
1900 saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
1901 return 0;
1902}
1903
Jiri Slabyf823f672006-01-11 19:41:32 -02001904static struct file_operations saa_fops = {
1905 .owner = THIS_MODULE,
1906 .open = saa_open,
1907 .release = saa_release,
1908 .ioctl = saa_ioctl,
1909 .compat_ioctl = v4l_compat_ioctl32,
1910 .read = saa_read,
1911 .llseek = no_llseek,
1912 .write = saa_write,
1913 .mmap = saa_mmap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914};
1915
1916/* template for video_device-structure */
Jiri Slabyf823f672006-01-11 19:41:32 -02001917static struct video_device saa_template = {
1918 .name = "SAA7146A",
1919 .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
1920 .hardware = VID_HARDWARE_SAA7146,
1921 .fops = &saa_fops,
1922 .minor = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923};
1924
Jiri Slaby9ae82292006-01-11 19:41:13 -02001925static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001927 int retval;
1928 struct saa7146 *saa = pci_get_drvdata(pdev);
Jiri Slabyf823f672006-01-11 19:41:32 -02001929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 saa->endmarkhead = saa->endmarktail = 0;
1931 saa->win.x = saa->win.y = 0;
1932 saa->win.width = saa->win.cropwidth = 720;
1933 saa->win.height = saa->win.cropheight = 480;
1934 saa->win.cropx = saa->win.cropy = 0;
1935 saa->win.bpp = 2;
1936 saa->win.depth = 16;
1937 saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
1938 saa->win.bpl = 1024 * saa->win.bpp;
1939 saa->win.swidth = 1024;
1940 saa->win.sheight = 768;
1941 saa->picture.brightness = 32768;
1942 saa->picture.contrast = 38768;
1943 saa->picture.colour = 32768;
1944 saa->cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 saa->nr = num;
1946 saa->playmode = VID_PLAY_NORMAL;
1947 memset(saa->boardcfg, 0, 64); /* clear board config area */
1948 saa->saa7146_mem = NULL;
1949 saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
1950 saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
1951 saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
1952 saa->pagea1out = saa->pagea2in = saa->pagea2out =
1953 saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
1954 saa->pageRPS2 = NULL;
1955 saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
1956 saa->audhead = saa->vidtail = 0;
1957
1958 init_waitqueue_head(&saa->i2cq);
1959 init_waitqueue_head(&saa->audq);
1960 init_waitqueue_head(&saa->debiq);
1961 init_waitqueue_head(&saa->vidq);
1962 spin_lock_init(&saa->lock);
1963
Jiri Slaby91fb8352006-01-11 19:41:21 -02001964 retval = pci_enable_device(pdev);
1965 if (retval) {
1966 dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
1967 goto err;
1968 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001969
Jiri Slaby9ae82292006-01-11 19:41:13 -02001970 saa->id = pdev->device;
1971 saa->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 saa->video_dev.minor = -1;
Jiri Slaby9ae82292006-01-11 19:41:13 -02001973 saa->saa7146_adr = pci_resource_start(pdev, 0);
1974 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
1976 saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001977 if (saa->saa7146_mem == NULL) {
1978 dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
1979 retval = -EIO;
1980 goto err;
1981 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
1983 memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
1984 saawrite(0, SAA7146_IER); /* turn off all interrupts */
Jiri Slaby91fb8352006-01-11 19:41:21 -02001985
Thomas Gleixner8076fe32006-07-01 19:29:37 -07001986 retval = request_irq(saa->irq, saa7146_irq, IRQF_SHARED | IRQF_DISABLED,
Jiri Slaby91fb8352006-01-11 19:41:21 -02001987 "stradis", saa);
1988 if (retval == -EINVAL)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001989 dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001990 else if (retval == -EBUSY)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001991 dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
1992 "in BIOS\n", num, saa->irq);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001993 if (retval < 0)
1994 goto errio;
1995
Jiri Slaby9ae82292006-01-11 19:41:13 -02001996 pci_set_master(pdev);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001997 retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
1998 video_nr);
Jiri Slabyf823f672006-01-11 19:41:32 -02001999 if (retval < 0) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002000 dev_err(&pdev->dev, "%d: error in registering video device!\n",
2001 num);
2002 goto errio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 return 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002006errio:
2007 iounmap(saa->saa7146_mem);
2008err:
2009 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010}
2011
Jiri Slaby91fb8352006-01-11 19:41:21 -02002012static int __devinit init_saa7146(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Jiri Slaby91fb8352006-01-11 19:41:21 -02002014 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
2016 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);
Jiri Slaby805f1232006-01-24 13:15:06 -08002065 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002066 }
2067 if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
2068 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002069 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002070 }
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);
Jiri Slaby805f1232006-01-24 13:15:06 -08002074 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002075 }
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 Slaby805f1232006-01-24 13:15:06 -08002088errfree:
Jiri Slaby91fb8352006-01-11 19:41:21 -02002089 vfree(saa->osdbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002090 vfree(saa->audbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002091 vfree(saa->vidbuf);
Jiri Slaby805f1232006-01-24 13:15:06 -08002092 saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002093err:
2094 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095}
2096
Jiri Slaby9ae82292006-01-11 19:41:13 -02002097static void stradis_release_saa(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098{
2099 u8 command;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002100 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Jiri Slaby9ae82292006-01-11 19:41:13 -02002102 /* turn off all capturing, DMA and IRQs */
2103 saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
2104 saawrite(0, SAA7146_MC2);
2105 saawrite(0, SAA7146_IER);
2106 saawrite(0xffffffffUL, SAA7146_ISR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Jiri Slaby9ae82292006-01-11 19:41:13 -02002108 /* disable PCI bus-mastering */
2109 pci_read_config_byte(pdev, PCI_COMMAND, &command);
2110 command &= ~PCI_COMMAND_MASTER;
2111 pci_write_config_byte(pdev, PCI_COMMAND, command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Jiri Slaby9ae82292006-01-11 19:41:13 -02002113 /* unmap and free memory */
2114 saa->audhead = saa->audtail = saa->osdhead = 0;
2115 saa->vidhead = saa->vidtail = saa->osdtail = 0;
2116 vfree(saa->vidbuf);
2117 vfree(saa->audbuf);
2118 vfree(saa->osdbuf);
2119 kfree(saa->dmavid2);
2120 saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
2121 saa->dmavid2 = NULL;
2122 kfree(saa->dmadebi);
2123 kfree(saa->dmavid1);
2124 kfree(saa->dmavid3);
2125 kfree(saa->dmaa1in);
2126 kfree(saa->dmaa1out);
2127 kfree(saa->dmaa2in);
2128 kfree(saa->dmaa2out);
2129 kfree(saa->dmaRPS1);
2130 kfree(saa->dmaRPS2);
2131 free_irq(saa->irq, saa);
2132 if (saa->saa7146_mem)
2133 iounmap(saa->saa7146_mem);
2134 if (saa->video_dev.minor != -1)
2135 video_unregister_device(&saa->video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136}
2137
Jiri Slaby9ae82292006-01-11 19:41:13 -02002138static int __devinit stradis_probe(struct pci_dev *pdev,
2139 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002141 int retval = -EINVAL;
2142
2143 if (saa_num >= SAA7146_MAX)
2144 goto err;
2145
2146 if (!pdev->subsystem_vendor)
2147 dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
2148 else
2149 dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
2150
Jiri Slaby91fb8352006-01-11 19:41:21 -02002151 pci_set_drvdata(pdev, &saa7146s[saa_num]);
Jiri Slaby9ae82292006-01-11 19:41:13 -02002152
2153 retval = configure_saa7146(pdev, saa_num);
2154 if (retval) {
2155 dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
2156 goto err;
2157 }
2158
Jiri Slaby91fb8352006-01-11 19:41:21 -02002159 if (init_saa7146(pdev) < 0) {
Jiri Slaby9ae82292006-01-11 19:41:13 -02002160 dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
2161 retval = -EIO;
2162 goto errrel;
2163 }
2164
2165 saa_num++;
2166
2167 return 0;
2168errrel:
2169 stradis_release_saa(pdev);
2170err:
2171 return retval;
2172}
2173
2174static void __devexit stradis_remove(struct pci_dev *pdev)
2175{
2176 stradis_release_saa(pdev);
2177}
2178
2179static struct pci_device_id stradis_pci_tbl[] = {
2180 { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
2181 { 0 }
2182};
Jiri Slabyf823f672006-01-11 19:41:32 -02002183
Jiri Slaby9ae82292006-01-11 19:41:13 -02002184
2185static struct pci_driver stradis_driver = {
Jiri Slabyf823f672006-01-11 19:41:32 -02002186 .name = "stradis",
2187 .id_table = stradis_pci_tbl,
2188 .probe = stradis_probe,
2189 .remove = __devexit_p(stradis_remove)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002190};
2191
Adrian Bunkb9553d7b2006-06-26 22:40:20 -03002192static int __init stradis_init(void)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002193{
2194 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
2196 saa_num = 0;
2197
Jiri Slaby9ae82292006-01-11 19:41:13 -02002198 retval = pci_register_driver(&stradis_driver);
2199 if (retval)
2200 printk(KERN_ERR "stradis: Unable to register pci driver.\n");
2201
2202 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203}
2204
Adrian Bunkb9553d7b2006-06-26 22:40:20 -03002205static void __exit stradis_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002207 pci_unregister_driver(&stradis_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 printk(KERN_INFO "stradis: module cleanup complete\n");
2209}
2210
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211module_init(stradis_init);
2212module_exit(stradis_exit);