blob: 6ace8923b797b25ca944368e44fae0b7bc965d90 [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>
Mauro Carvalho Chehab28644622008-07-20 20:26:54 -030046#include <media/v4l2-ioctl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48#include "saa7146.h"
49#include "saa7146reg.h"
50#include "ibmmpeg2.h"
51#include "saa7121.h"
52#include "cs8420.h"
53
Jiri Slabyf823f672006-01-11 19:41:32 -020054#define DEBUG(x) /* debug driver */
55#undef IDEBUG /* debug irq handler */
56#undef MDEBUG /* debug memory management */
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#define SAA7146_MAX 6
59
60static struct saa7146 saa7146s[SAA7146_MAX];
61
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030062static int saa_num; /* number of SAA7146s in use */
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64static int video_nr = -1;
65module_param(video_nr, int, 0);
66MODULE_LICENSE("GPL");
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#define nDebNormal 0x00480000
69#define nDebNoInc 0x00480000
70#define nDebVideo 0xd0480000
71#define nDebAudio 0xd0400000
72#define nDebDMA 0x02c80000
73
74#define oDebNormal 0x13c80000
75#define oDebNoInc 0x13c80000
76#define oDebVideo 0xd1080000
77#define oDebAudio 0xd1080000
78#define oDebDMA 0x03080000
79
80#define NewCard (saa->boardcfg[3])
81#define ChipControl (saa->boardcfg[1])
82#define NTSCFirstActive (saa->boardcfg[4])
83#define PALFirstActive (saa->boardcfg[5])
84#define NTSCLastActive (saa->boardcfg[54])
85#define PALLastActive (saa->boardcfg[55])
86#define Have2MB (saa->boardcfg[18] & 0x40)
87#define HaveCS8420 (saa->boardcfg[18] & 0x04)
88#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20)
89#define HaveCS3310 (saa->boardcfg[18] & 0x01)
90#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31])
91#define HaveCS4341 (saa->boardcfg[40] == 2)
92#define SDIType (saa->boardcfg[27])
93#define CurrentMode (saa->boardcfg[2])
94
95#define debNormal (NewCard ? nDebNormal : oDebNormal)
96#define debNoInc (NewCard ? nDebNoInc : oDebNoInc)
97#define debVideo (NewCard ? nDebVideo : oDebVideo)
98#define debAudio (NewCard ? nDebAudio : oDebAudio)
99#define debDMA (NewCard ? nDebDMA : oDebDMA)
100
101#ifdef USE_RESCUE_EEPROM_SDM275
102static unsigned char rescue_eeprom[64] = {
Jiri Slabyf823f672006-01-11 19:41:32 -0200103 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
104 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
105 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
106 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
107 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109};
110#endif
111
112/* ----------------------------------------------------------------------- */
113/* Hardware I2C functions */
114static void I2CWipe(struct saa7146 *saa)
115{
116 int i;
117 /* set i2c to ~=100kHz, abort transfer, clear busy */
118 saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
119 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
120 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
121 /* wait for i2c registers to be programmed */
122 for (i = 0; i < 1000 &&
123 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
124 schedule();
125 saawrite(0x600, SAA7146_I2C_STATUS);
126 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
127 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
128 /* wait for i2c registers to be programmed */
129 for (i = 0; i < 1000 &&
130 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
131 schedule();
132 saawrite(0x600, SAA7146_I2C_STATUS);
133 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
134 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
135 /* wait for i2c registers to be programmed */
136 for (i = 0; i < 1000 &&
137 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
138 schedule();
139}
140
141/* read I2C */
142static int I2CRead(struct saa7146 *saa, unsigned char addr,
143 unsigned char subaddr, int dosub)
144{
145 int i;
146
147 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
148 I2CWipe(saa);
Jiri Slabyf823f672006-01-11 19:41:32 -0200149 for (i = 0;
150 i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
151 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 schedule();
153 if (i == 1000)
154 I2CWipe(saa);
155 if (dosub)
156 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200157 ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 else
159 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200160 0xf1, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
162 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
163 /* wait for i2c registers to be programmed */
164 for (i = 0; i < 1000 &&
165 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
166 schedule();
167 /* wait for valid data */
168 for (i = 0; i < 1000 &&
169 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
170 schedule();
171 if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
172 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200173 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 printk("i2c setup read timeout\n");
175 saawrite(0x41, SAA7146_I2C_TRANSFER);
176 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
177 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
178 /* wait for i2c registers to be programmed */
179 for (i = 0; i < 1000 &&
180 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
181 schedule();
182 /* wait for valid data */
183 for (i = 0; i < 1000 &&
184 (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
185 schedule();
186 if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
187 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200188 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 printk("i2c read timeout\n");
190 return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
191}
192
193/* set both to write both bytes, reset it to write only b1 */
194
195static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
196 unsigned char b2, int both)
197{
198 int i;
199 u32 data;
200
201 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
202 I2CWipe(saa);
203 for (i = 0; i < 1000 &&
204 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
205 schedule();
206 if (i == 1000)
207 I2CWipe(saa);
208 data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
209 if (both)
210 data |= ((b2 & 0xff) << 8) | 0xe5;
211 else
212 data |= 0xd1;
213 saawrite(data, SAA7146_I2C_TRANSFER);
214 saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
215 SAA7146_MC2);
216 return 0;
217}
218
219static void attach_inform(struct saa7146 *saa, int id)
220{
221 int i;
222
Jiri Slabyf823f672006-01-11 19:41:32 -0200223 DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
224 id));
225 if (id == 0xa0) { /* we have rev2 or later board, fill in info */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 for (i = 0; i < 64; i++)
227 saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
228#ifdef USE_RESCUE_EEPROM_SDM275
229 if (saa->boardcfg[0] != 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200230 printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
231 "BEEN IGNORED\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 for (i = 0; i < 64; i++)
233 saa->boardcfg[i] = rescue_eeprom[i];
234 }
235#endif
236 printk("stradis%d: config =", saa->nr);
237 for (i = 0; i < 51; i++) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200238 printk(" %02x", saa->boardcfg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 printk("\n");
241 }
242}
243
244static void I2CBusScan(struct saa7146 *saa)
245{
246 int i;
247 for (i = 0; i < 0xff; i += 2)
248 if ((I2CRead(saa, i, 0, 0)) >= 0)
249 attach_inform(saa, i);
250}
251
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300252static int debiwait_maxwait;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254static int wait_for_debi_done(struct saa7146 *saa)
255{
256 int i;
257
258 /* wait for registers to be programmed */
259 for (i = 0; i < 100000 &&
260 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
261 saaread(SAA7146_MC2);
262 /* wait for transfer to complete */
263 for (i = 0; i < 500000 &&
264 (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
265 saaread(SAA7146_MC2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 if (i > debiwait_maxwait)
268 printk("wait-for-debi-done maxwait: %d\n",
269 debiwait_maxwait = i);
Jiri Slabyf823f672006-01-11 19:41:32 -0200270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 if (i == 500000)
272 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 return 0;
275}
276
277static int debiwrite(struct saa7146 *saa, u32 config, int addr,
Jiri Slabyf823f672006-01-11 19:41:32 -0200278 u32 val, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279{
280 u32 cmd;
281 if (count <= 0 || count > 32764)
282 return -1;
283 if (wait_for_debi_done(saa) < 0)
284 return -1;
285 saawrite(config, SAA7146_DEBI_CONFIG);
286 if (count <= 4) /* immediate transfer */
287 saawrite(val, SAA7146_DEBI_AD);
288 else /* block transfer */
289 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
290 saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
291 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
292 SAA7146_MC2);
293 return 0;
294}
295
296static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
297{
298 u32 result = 0;
299
300 if (count > 32764 || count <= 0)
301 return 0;
302 if (wait_for_debi_done(saa) < 0)
303 return 0;
304 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
305 saawrite((count << 17) | 0x10000 | (addr & 0xffff),
306 SAA7146_DEBI_COMMAND);
307 saawrite(config, SAA7146_DEBI_CONFIG);
308 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
309 SAA7146_MC2);
310 if (count > 4) /* not an immediate transfer */
311 return count;
312 wait_for_debi_done(saa);
313 result = saaread(SAA7146_DEBI_AD);
314 if (count == 1)
315 result &= 0xff;
316 if (count == 2)
317 result &= 0xffff;
318 if (count == 3)
319 result &= 0xffffff;
320 return result;
321}
322
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323static void do_irq_send_data(struct saa7146 *saa)
324{
325 int split, audbytes, vidbytes;
326
327 saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
328 /* if special feature mode in effect, disable audio sending */
329 if (saa->playmode != VID_PLAY_NORMAL)
330 saa->audtail = saa->audhead = 0;
331 if (saa->audhead <= saa->audtail)
332 audbytes = saa->audtail - saa->audhead;
333 else
334 audbytes = 65536 - (saa->audhead - saa->audtail);
335 if (saa->vidhead <= saa->vidtail)
336 vidbytes = saa->vidtail - saa->vidhead;
337 else
338 vidbytes = 524288 - (saa->vidhead - saa->vidtail);
339 if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
340 saawrite(0, SAA7146_IER);
341 return;
342 }
343 /* if at least 1 block audio waiting and audio fifo isn't full */
Jiri Slabyf823f672006-01-11 19:41:32 -0200344 if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
345 & 0xff) < 60) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 if (saa->audhead > saa->audtail)
347 split = 65536 - saa->audhead;
348 else
349 split = 0;
350 audbytes = 2048;
351 if (split > 0 && split < 2048) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200352 memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 saa->audhead = 0;
354 audbytes -= split;
355 } else
356 split = 0;
357 memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
358 audbytes);
359 saa->audhead += audbytes;
360 saa->audhead &= 0xffff;
Jiri Slabyf823f672006-01-11 19:41:32 -0200361 debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
362 IBM_MP2_AUD_FIFOW), 0, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 wake_up_interruptible(&saa->audq);
Jiri Slabyf823f672006-01-11 19:41:32 -0200364 /* if at least 1 block video waiting and video fifo isn't full */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 } else if (vidbytes >= 30720 && (debiread(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -0200366 IBM_MP2_FIFO, 2)) < 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (saa->vidhead > saa->vidtail)
368 split = 524288 - saa->vidhead;
369 else
370 split = 0;
371 vidbytes = 30720;
372 if (split > 0 && split < 30720) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200373 memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 saa->vidhead = 0;
375 vidbytes -= split;
376 } else
377 split = 0;
378 memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
379 vidbytes);
380 saa->vidhead += vidbytes;
381 saa->vidhead &= 0x7ffff;
382 debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
Jiri Slabyf823f672006-01-11 19:41:32 -0200383 IBM_MP2_FIFOW), 0, 30720);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 wake_up_interruptible(&saa->vidq);
385 }
386 saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
387}
388
389static void send_osd_data(struct saa7146 *saa)
390{
391 int size = saa->osdtail - saa->osdhead;
392 if (size > 30720)
393 size = 30720;
394 /* ensure some multiple of 8 bytes is transferred */
Jiri Slabyf823f672006-01-11 19:41:32 -0200395 size = 8 * ((size + 8) >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 if (size) {
397 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
Jiri Slabyf823f672006-01-11 19:41:32 -0200398 (saa->osdhead >> 3), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
400 saa->osdhead += size;
401 /* block transfer of next 8 bytes to ~32k bytes */
402 debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
403 }
404 if (saa->osdhead >= saa->osdtail) {
405 saa->osdhead = saa->osdtail = 0;
406 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
407 }
408}
409
David Howells7d12e782006-10-05 14:55:46 +0100410static irqreturn_t saa7146_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Jiri Slabyf823f672006-01-11 19:41:32 -0200412 struct saa7146 *saa = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 u32 stat, astat;
414 int count;
415 int handled = 0;
416
417 count = 0;
418 while (1) {
419 /* get/clear interrupt status bits */
420 stat = saaread(SAA7146_ISR);
421 astat = stat & saaread(SAA7146_IER);
422 if (!astat)
423 break;
424 handled = 1;
425 saawrite(astat, SAA7146_ISR);
426 if (astat & SAA7146_PSR_DEBI_S) {
427 do_irq_send_data(saa);
428 }
429 if (astat & SAA7146_PSR_PIN1) {
430 int istat;
431 /* the following read will trigger DEBI_S */
432 istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
433 if (istat & 1) {
434 saawrite(0, SAA7146_IER);
435 send_osd_data(saa);
436 saawrite(SAA7146_PSR_DEBI_S |
437 SAA7146_PSR_PIN1, SAA7146_IER);
438 }
439 if (istat & 0x20) { /* Video Start */
440 saa->vidinfo.frame_count++;
441 }
442 if (istat & 0x400) { /* Picture Start */
443 /* update temporal reference */
444 }
445 if (istat & 0x200) { /* Picture Resolution Change */
446 /* read new resolution */
447 }
448 if (istat & 0x100) { /* New User Data found */
449 /* read new user data */
450 }
451 if (istat & 0x1000) { /* new GOP/SMPTE */
452 /* read new SMPTE */
453 }
454 if (istat & 0x8000) { /* Sequence Start Code */
455 /* reset frame counter, load sizes */
456 saa->vidinfo.frame_count = 0;
457 saa->vidinfo.h_size = 704;
458 saa->vidinfo.v_size = 480;
459#if 0
460 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200461 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 saa->endmark[saa->endmarkhead];
463 saa->endmarkhead++;
464 if (saa->endmarkhead >= MAX_MARKS)
465 saa->endmarkhead = 0;
466 }
467#endif
468 }
469 if (istat & 0x4000) { /* Sequence Error Code */
470 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200471 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 saa->endmark[saa->endmarkhead];
473 saa->endmarkhead++;
474 if (saa->endmarkhead >= MAX_MARKS)
475 saa->endmarkhead = 0;
476 }
477 }
478 }
479#ifdef IDEBUG
480 if (astat & SAA7146_PSR_PPEF) {
481 IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
482 }
483 if (astat & SAA7146_PSR_PABO) {
484 IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
485 }
486 if (astat & SAA7146_PSR_PPED) {
487 IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
488 }
489 if (astat & SAA7146_PSR_RPS_I1) {
490 IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
491 }
492 if (astat & SAA7146_PSR_RPS_I0) {
493 IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
494 }
495 if (astat & SAA7146_PSR_RPS_LATE1) {
496 IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
497 }
498 if (astat & SAA7146_PSR_RPS_LATE0) {
499 IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
500 }
501 if (astat & SAA7146_PSR_RPS_E1) {
502 IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
503 }
504 if (astat & SAA7146_PSR_RPS_E0) {
505 IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
506 }
507 if (astat & SAA7146_PSR_RPS_TO1) {
508 IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
509 }
510 if (astat & SAA7146_PSR_RPS_TO0) {
511 IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
512 }
513 if (astat & SAA7146_PSR_UPLD) {
514 IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
515 }
516 if (astat & SAA7146_PSR_DEBI_E) {
517 IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
518 }
519 if (astat & SAA7146_PSR_I2C_S) {
520 IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
521 }
522 if (astat & SAA7146_PSR_I2C_E) {
523 IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
524 }
525 if (astat & SAA7146_PSR_A2_IN) {
526 IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
527 }
528 if (astat & SAA7146_PSR_A2_OUT) {
529 IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
530 }
531 if (astat & SAA7146_PSR_A1_IN) {
532 IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
533 }
534 if (astat & SAA7146_PSR_A1_OUT) {
535 IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
536 }
537 if (astat & SAA7146_PSR_AFOU) {
538 IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
539 }
540 if (astat & SAA7146_PSR_V_PE) {
541 IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
542 }
543 if (astat & SAA7146_PSR_VFOU) {
544 IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
545 }
546 if (astat & SAA7146_PSR_FIDA) {
547 IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
548 }
549 if (astat & SAA7146_PSR_FIDB) {
550 IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
551 }
552 if (astat & SAA7146_PSR_PIN3) {
553 IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
554 }
555 if (astat & SAA7146_PSR_PIN2) {
556 IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
557 }
558 if (astat & SAA7146_PSR_PIN0) {
559 IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
560 }
561 if (astat & SAA7146_PSR_ECS) {
562 IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
563 }
564 if (astat & SAA7146_PSR_EC3S) {
565 IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
566 }
567 if (astat & SAA7146_PSR_EC0S) {
568 IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
569 }
570#endif
571 count++;
572 if (count > 15)
573 printk(KERN_WARNING "stradis%d: irq loop %d\n",
574 saa->nr, count);
575 if (count > 20) {
576 saawrite(0, SAA7146_IER);
577 printk(KERN_ERR
578 "stradis%d: IRQ loop cleared\n", saa->nr);
579 }
580 }
581 return IRQ_RETVAL(handled);
582}
583
584static int ibm_send_command(struct saa7146 *saa,
585 int command, int data, int chain)
586{
587 int i;
588
589 if (chain)
Jiri Slabyf823f672006-01-11 19:41:32 -0200590 debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 else
592 debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
593 debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
594 debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
595 for (i = 0; i < 100 &&
596 (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
597 schedule();
598 if (i == 100)
599 return -1;
600 return 0;
601}
602
603static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
604{
605 I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
606 I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
607}
608
609static void initialize_cs4341(struct saa7146 *saa)
610{
611 int i;
612 for (i = 0; i < 200; i++) {
613 /* auto mute off, power on, no de-emphasis */
614 /* I2S data up to 24-bit 64xFs internal SCLK */
615 I2CWrite(saa, 0x22, 0x01, 0x11, 2);
616 /* ATAPI mixer settings */
617 I2CWrite(saa, 0x22, 0x02, 0x49, 2);
618 /* attenuation left 3db */
619 I2CWrite(saa, 0x22, 0x03, 0x00, 2);
620 /* attenuation right 3db */
621 I2CWrite(saa, 0x22, 0x04, 0x00, 2);
622 I2CWrite(saa, 0x22, 0x01, 0x10, 2);
623 if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
624 break;
625 schedule();
626 }
627 printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
628 return;
629}
630
631static void initialize_cs8420(struct saa7146 *saa, int pro)
632{
633 int i;
634 u8 *sequence;
635 if (pro)
636 sequence = mode8420pro;
637 else
638 sequence = mode8420con;
639 for (i = 0; i < INIT8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200640 I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 for (i = 0; i < MODE8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200642 I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 printk("stradis%d: CS8420 initialized\n", saa->nr);
644}
645
646static void initialize_saa7121(struct saa7146 *saa, int dopal)
647{
648 int i, mod;
649 u8 *sequence;
650 if (dopal)
651 sequence = init7121pal;
652 else
653 sequence = init7121ntsc;
654 mod = saaread(SAA7146_PSR) & 0x08;
655 /* initialize PAL/NTSC video encoder */
656 for (i = 0; i < INIT7121LEN; i++) {
657 if (NewCard) { /* handle new card encoder differences */
Jiri Slabyf823f672006-01-11 19:41:32 -0200658 if (sequence[i * 2] == 0x3a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200660 else if (sequence[i * 2] == 0x6b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200662 else if (sequence[i * 2] == 0x6c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 I2CWrite(saa, 0x88, 0x6c,
664 dopal ? 0x09 : 0xf5, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200665 else if (sequence[i * 2] == 0x6d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 I2CWrite(saa, 0x88, 0x6d,
667 dopal ? 0x20 : 0x00, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200668 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 I2CWrite(saa, 0x88, 0x7a,
670 dopal ? (PALFirstActive - 1) :
671 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200672 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 I2CWrite(saa, 0x88, 0x7b,
674 dopal ? PALLastActive :
675 NTSCLastActive, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200676 else
677 I2CWrite(saa, 0x88, sequence[i * 2],
678 sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -0200680 if (sequence[i * 2] == 0x6b && mod)
681 I2CWrite(saa, 0x88, 0x6b,
682 (sequence[i * 2 + 1] ^ 0x09), 2);
683 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 I2CWrite(saa, 0x88, 0x7a,
685 dopal ? (PALFirstActive - 1) :
686 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200687 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 I2CWrite(saa, 0x88, 0x7b,
689 dopal ? PALLastActive :
690 NTSCLastActive, 2);
691 else
692 I2CWrite(saa, 0x88, sequence[i * 2],
693 sequence[i * 2 + 1], 2);
694 }
695 }
696}
697
698static void set_genlock_offset(struct saa7146 *saa, int noffset)
699{
700 int nCode;
701 int PixelsPerLine = 858;
702 if (CurrentMode == VIDEO_MODE_PAL)
703 PixelsPerLine = 864;
704 if (noffset > 500)
705 noffset = 500;
706 else if (noffset < -500)
707 noffset = -500;
708 nCode = noffset + 0x100;
709 if (nCode == 1)
710 nCode = 0x401;
Jiri Slabyf823f672006-01-11 19:41:32 -0200711 else if (nCode < 1)
712 nCode = 0x400 + PixelsPerLine + nCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
714}
715
716static void set_out_format(struct saa7146 *saa, int mode)
717{
718 initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
719 saa->boardcfg[2] = mode;
720 /* do not adjust analog video parameters here, use saa7121 init */
721 /* you will affect the SDI output on the new card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200722 if (mode == VIDEO_MODE_PAL) { /* PAL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
724 mdelay(50);
725 saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
726 if (NewCard) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200727 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 mdelay(50);
729 }
730 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200731 NewCard ? 0xe500 : 0x6500, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
733 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200734 (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 } else { /* NTSC */
736 debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
737 mdelay(50);
738 saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
739 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200740 NewCard ? 0xe100 : 0x6100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
742 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200743 (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 }
745}
746
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747/* Intialize bitmangler to map from a byte value to the mangled word that
748 * must be output to program the Xilinx part through the DEBI port.
749 * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
750 * transfer FPGA code, init IBM chip, transfer IBM microcode
751 * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
752 */
753static u16 bitmangler[256];
754
755static int initialize_fpga(struct video_code *bitdata)
756{
757 int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
758 u16 *dmabuf;
759 u8 *newdma;
760 struct saa7146 *saa;
761
762 /* verify fpga code */
763 for (startindex = 0; startindex < bitdata->datasize; startindex++)
764 if (bitdata->data[startindex] == 255)
765 break;
766 if (startindex == bitdata->datasize) {
767 printk(KERN_INFO "stradis: bad fpga code\n");
768 return -1;
769 }
770 /* initialize all detected cards */
771 for (num = 0; num < saa_num; num++) {
772 saa = &saa7146s[num];
773 if (saa->boardcfg[0] > 20)
Jiri Slabyf823f672006-01-11 19:41:32 -0200774 continue; /* card was programmed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 loadtwo = (saa->boardcfg[18] & 0x10);
776 if (!NewCard) /* we have an old board */
777 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200778 bitmangler[i] = ((i & 0x01) << 15) |
779 ((i & 0x02) << 6) | ((i & 0x04) << 4) |
780 ((i & 0x08) << 9) | ((i & 0x10) << 7) |
781 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
782 ((i & 0x80) >> 7);
783 else /* else we have a new board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200785 bitmangler[i] = ((i & 0x01) << 7) |
786 ((i & 0x02) << 5) | ((i & 0x04) << 3) |
787 ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
788 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
789 ((i & 0x80) >> 7);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 dmabuf = (u16 *) saa->dmadebi;
792 newdma = (u8 *) saa->dmadebi;
793 if (NewCard) { /* SDM2xxx */
794 if (!strncmp(bitdata->loadwhat, "decoder2", 8))
795 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200796 if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 loadfile = 1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200798 else if (loadtwo && !strncmp(&saa->boardcfg[19],
799 bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 loadfile = 2;
Jiri Slabyf823f672006-01-11 19:41:32 -0200801 else if (!saa->boardcfg[42] && !strncmp("decxl",
802 bitdata->loadwhat, 8))
803 loadfile = 1; /* special */
804 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200806 if (loadfile != 1 && loadfile != 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 continue; /* skip to next card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200808 if (saa->boardcfg[0] && loadfile == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 continue; /* skip to next card */
810 if (saa->boardcfg[0] != 1 && loadfile == 2)
811 continue; /* skip to next card */
812 saa->boardcfg[0]++; /* mark fpga handled */
813 printk("stradis%d: loading %s\n", saa->nr,
814 bitdata->loadwhat);
815 if (loadtwo && loadfile == 2)
816 goto send_fpga_stuff;
817 /* turn on the Audio interface to set PROG low */
818 saawrite(0x00400040, SAA7146_GPIO_CTRL);
819 saaread(SAA7146_PSR); /* ensure posted write */
820 /* wait for everyone to reset */
821 mdelay(10);
822 saawrite(0x00400000, SAA7146_GPIO_CTRL);
823 } else { /* original card */
824 if (strncmp(bitdata->loadwhat, "decoder2", 8))
825 continue; /* fpga not for this card */
826 /* Pull the Xilinx PROG signal WS3 low */
827 saawrite(0x02000200, SAA7146_MC1);
828 /* Turn on the Audio interface so can set PROG low */
829 saawrite(0x000000c0, SAA7146_ACON1);
830 /* Pull the Xilinx INIT signal (GPIO2) low */
831 saawrite(0x00400000, SAA7146_GPIO_CTRL);
832 /* Make sure everybody resets */
833 saaread(SAA7146_PSR); /* ensure posted write */
834 mdelay(10);
835 /* Release the Xilinx PROG signal */
836 saawrite(0x00000000, SAA7146_ACON1);
837 /* Turn off the Audio interface */
838 saawrite(0x02000000, SAA7146_MC1);
839 }
840 /* Release Xilinx INIT signal (WS2) */
841 saawrite(0x00000000, SAA7146_GPIO_CTRL);
842 /* Wait for the INIT to go High */
Jiri Slabyf823f672006-01-11 19:41:32 -0200843 for (i = 0;
844 i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
845 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 schedule();
847 if (i == 1000) {
848 printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
849 return -1;
850 }
851send_fpga_stuff:
852 if (NewCard) {
853 for (i = startindex; i < bitdata->datasize; i++)
854 newdma[i - startindex] =
Jiri Slabyf823f672006-01-11 19:41:32 -0200855 bitmangler[bitdata->data[i]];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 debiwrite(saa, 0x01420000, 0, 0,
857 ((bitdata->datasize - startindex) + 5));
Jiri Slabyf823f672006-01-11 19:41:32 -0200858 if (loadtwo && loadfile == 1) {
859 printk("stradis%d: awaiting 2nd FPGA bitfile\n",
860 saa->nr);
861 continue; /* skip to next card */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863 } else {
864 for (i = startindex; i < bitdata->datasize; i++)
865 dmabuf[i - startindex] =
866 bitmangler[bitdata->data[i]];
867 debiwrite(saa, 0x014a0000, 0, 0,
868 ((bitdata->datasize - startindex) + 5) * 2);
869 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200870 for (i = 0;
871 i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
872 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 schedule();
874 if (i == 1000) {
875 printk(KERN_INFO "stradis%d: FPGA load failed\n",
876 saa->nr);
877 failure++;
878 continue;
879 }
880 if (!NewCard) {
881 /* Pull the Xilinx INIT signal (GPIO2) low */
882 saawrite(0x00400000, SAA7146_GPIO_CTRL);
883 saaread(SAA7146_PSR); /* ensure posted write */
884 mdelay(2);
885 saawrite(0x00000000, SAA7146_GPIO_CTRL);
886 mdelay(2);
887 }
888 printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
889 saa->boardcfg[0] = 26; /* mark fpga programmed */
890 /* set VXCO to its lowest frequency */
891 debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
892 if (NewCard) {
893 /* mute CS3310 */
894 if (HaveCS3310)
895 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
Jiri Slabyf823f672006-01-11 19:41:32 -0200896 0, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 /* set VXCO to PWM mode, release reset, blank on */
898 debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
899 mdelay(10);
900 /* unmute CS3310 */
901 if (HaveCS3310)
902 debiwrite(saa, debNormal, XILINX_CTL0,
Jiri Slabyf823f672006-01-11 19:41:32 -0200903 0x2020, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 }
905 /* set source Black */
906 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
907 saa->boardcfg[4] = 22; /* set NTSC First Active Line */
908 saa->boardcfg[5] = 23; /* set PAL First Active Line */
909 saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */
910 saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */
911 set_out_format(saa, VIDEO_MODE_NTSC);
912 mdelay(50);
913 /* begin IBM chip init */
914 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
915 saaread(SAA7146_PSR); /* wait for reset */
916 mdelay(5);
917 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
918 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
919 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
920 debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
921 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
922 if (NewCard) {
923 mdelay(5);
924 /* set i2s rate converter to 48KHz */
925 debiwrite(saa, debNormal, 0x80c0, 6, 2);
926 /* we must init CS8420 first since rev b pulls i2s */
927 /* master clock low and CS4341 needs i2s master to */
928 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200929 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 /* 0=consumer, 1=pro */
931 initialize_cs8420(saa, 0);
Jiri Slabyf823f672006-01-11 19:41:32 -0200932
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 mdelay(5);
934 if (HaveCS4341)
935 initialize_cs4341(saa);
936 }
937 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
938 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
939 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
940 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
941 if (NewCard)
942 set_genlock_offset(saa, 0);
943 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
944#if 0
945 /* enable genlock */
946 debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
947#else
948 /* disable genlock */
949 debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
950#endif
951 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return failure;
954}
955
956static int do_ibm_reset(struct saa7146 *saa)
957{
958 /* failure if decoder not previously programmed */
959 if (saa->boardcfg[0] < 37)
960 return -EIO;
961 /* mute CS3310 */
962 if (HaveCS3310)
963 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
964 /* disable interrupts */
965 saawrite(0, SAA7146_IER);
966 saa->audhead = saa->audtail = 0;
967 saa->vidhead = saa->vidtail = 0;
968 /* tristate debi bus, disable debi transfers */
969 saawrite(0x00880000, SAA7146_MC1);
970 /* ensure posted write */
971 saaread(SAA7146_MC1);
972 mdelay(50);
973 /* re-enable debi transfers */
974 saawrite(0x00880088, SAA7146_MC1);
975 /* set source Black */
976 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
977 /* begin IBM chip init */
978 set_out_format(saa, CurrentMode);
979 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
980 saaread(SAA7146_PSR); /* wait for reset */
981 mdelay(5);
982 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
983 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
984 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
985 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
986 if (NewCard) {
987 mdelay(5);
988 /* set i2s rate converter to 48KHz */
989 debiwrite(saa, debNormal, 0x80c0, 6, 2);
990 /* we must init CS8420 first since rev b pulls i2s */
991 /* master clock low and CS4341 needs i2s master to */
992 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200993 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 /* 0=consumer, 1=pro */
995 initialize_cs8420(saa, 1);
Jiri Slabyf823f672006-01-11 19:41:32 -0200996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 mdelay(5);
998 if (HaveCS4341)
999 initialize_cs4341(saa);
1000 }
1001 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
1002 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
1003 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
1004 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
1005 if (NewCard)
1006 set_genlock_offset(saa, 0);
1007 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
1008 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1009 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1010 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001011 (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
1013 }
1014 if (HaveCS3310) {
1015 int i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001016 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 }
1018 /* start video decoder */
1019 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1020 /* 256k vid, 3520 bytes aud */
1021 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
1022 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1023 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1024 /* enable buffer threshold irq */
1025 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1026 /* clear pending interrupts */
1027 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1028 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 return 0;
1031}
1032
1033/* load the decoder microcode */
1034static int initialize_ibmmpeg2(struct video_code *microcode)
1035{
1036 int i, num;
1037 struct saa7146 *saa;
1038
1039 for (num = 0; num < saa_num; num++) {
1040 saa = &saa7146s[num];
1041 /* check that FPGA is loaded */
1042 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001043 i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
1044 if (i != 0xa55a) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
1046 saa->nr, i);
1047#if 0
1048 return -1;
1049#endif
1050 }
1051 if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
1052 if (saa->boardcfg[0] > 27)
1053 continue; /* skip to next card */
1054 /* load video control store */
Jiri Slabyf823f672006-01-11 19:41:32 -02001055 saa->boardcfg[1] = 0x13; /* no-sync default */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1057 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1058 for (i = 0; i < microcode->datasize / 2; i++)
1059 debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
1060 (microcode->data[i * 2] << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001061 microcode->data[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1063 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1064 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
Jiri Slabyf823f672006-01-11 19:41:32 -02001065 ChipControl, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 saa->boardcfg[0] = 28;
1067 }
1068 if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
1069 if (saa->boardcfg[0] > 35)
1070 continue; /* skip to next card */
1071 /* load audio control store */
1072 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1073 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1074 for (i = 0; i < microcode->datasize; i++)
1075 debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
1076 microcode->data[i], 1);
1077 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1078 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1079 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1080 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1081 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001082 0xe000, 1)) {
1083 printk(KERN_ERR "stradis%d: IBM config "
1084 "failed\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 return -1;
1086 }
1087 /* set PWM to center value */
1088 if (NewCard) {
1089 debiwrite(saa, debNormal, XILINX_PWM,
Jiri Slabyf823f672006-01-11 19:41:32 -02001090 saa->boardcfg[14] +
1091 (saa->boardcfg[13] << 8), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 } else
Jiri Slabyf823f672006-01-11 19:41:32 -02001093 debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
1094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 if (HaveCS3310) {
1096 i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001097 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
1098 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001100 printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
1101 saa->nr, 18 + (debiread(saa, debNormal,
1102 IBM_MP2_CHIP_CONTROL, 2) >> 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 /* start video decoder */
1104 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1105 ChipControl, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001106 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
1107 2); /* 256k vid, 3520 bytes aud */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1109 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1110 /* enable buffer threshold irq */
1111 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1112 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1113 /* enable gpio irq */
1114 saawrite(0x00002000, SAA7146_GPIO_CTRL);
1115 /* enable decoder output to HPS */
1116 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
1117 saa->boardcfg[0] = 37;
1118 }
1119 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return 0;
1122}
1123
Jiri Slabyf823f672006-01-11 19:41:32 -02001124static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
1125 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
1126 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
1127 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128};
Jiri Slabyf823f672006-01-11 19:41:32 -02001129static int bpp2fmt[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
1131 VIDEO_PALETTE_RGB32
1132};
1133
1134/* I wish I could find a formula to calculate these... */
Jiri Slabyf823f672006-01-11 19:41:32 -02001135static u32 h_prescale[64] = {
1136 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
1137 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
1138 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
1139 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
1140 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
1141 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
1142 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
1143 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
1144 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
1145 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
1146 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147};
Jiri Slabyf823f672006-01-11 19:41:32 -02001148static u32 v_gain[64] = {
1149 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
1150 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
1151 0x016300ff, 0x016300ff, 0x016300ff, 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, 0x016400ff, 0x016400ff,
1159 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160};
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162static void saa7146_set_winsize(struct saa7146 *saa)
1163{
1164 u32 format;
1165 int offset, yacl, ysci;
1166 saa->win.color_fmt = format =
1167 (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
1168 palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
1169 offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
1170 saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
1171 saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
1172 saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
1173 saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
1174 SAA7146_PROT_ADDR1);
1175 saawrite(0, SAA7146_PAGE1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001176 saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 offset = (704 / (saa->win.width - 1)) & 0x3f;
1178 saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
1179 offset = (720896 / saa->win.width) / (offset + 1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001180 saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 if (CurrentMode == VIDEO_MODE_NTSC) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001182 yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 ysci = 1024 - (saa->win.height * 1024 / 480);
1184 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -02001185 yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 ysci = 1024 - (saa->win.height * 1024 / 576);
1187 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001188 saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
1190 saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
Jiri Slabyf823f672006-01-11 19:41:32 -02001191 SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
1192 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193}
1194
1195/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001196 * bitmap is fixed width, 128 bytes (1024 pixels represented)
1197 * arranged most-sigificant-bit-left in 32-bit words
1198 * based on saa7146 clipping hardware, it swaps bytes if LE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 * much of this makes up for egcs brain damage -- so if you
1200 * are wondering "why did he do this?" it is because the C
1201 * was adjusted to generate the optimal asm output without
1202 * writing non-portable __asm__ directives.
1203 */
1204
1205static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
1206{
1207 register int startword, endword;
1208 register u32 bitsleft, bitsright;
1209 u32 *temp;
1210 if (x < 0) {
1211 w += x;
1212 x = 0;
1213 }
1214 if (y < 0) {
1215 h += y;
1216 y = 0;
1217 }
1218 if (w <= 0 || h <= 0 || x > 1023 || y > 639)
1219 return; /* throw away bad clips */
1220 if (x + w > 1024)
1221 w = 1024 - x;
1222 if (y + h > 640)
1223 h = 640 - y;
1224 startword = (x >> 5);
1225 endword = ((x + w) >> 5);
1226 bitsleft = (0xffffffff >> (x & 31));
Jiri Slabyf823f672006-01-11 19:41:32 -02001227 bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
1228 temp = &clipmap[(y << 5) + startword];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 w = endword - startword;
1230 if (!w) {
1231 bitsleft |= bitsright;
1232 for (y = 0; y < h; y++) {
1233 *temp |= bitsleft;
1234 temp += 32;
1235 }
1236 } else {
1237 for (y = 0; y < h; y++) {
1238 *temp++ |= bitsleft;
1239 for (x = 1; x < w; x++)
1240 *temp++ = 0xffffffff;
1241 *temp |= bitsright;
1242 temp += (32 - w);
1243 }
1244 }
1245}
1246
1247static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
1248{
1249 int i, width, height;
1250 u32 *clipmap;
1251
1252 clipmap = saa->dmavid2;
Jiri Slabyf823f672006-01-11 19:41:32 -02001253 if ((width = saa->win.width) > 1023)
1254 width = 1023; /* sanity check */
1255 if ((height = saa->win.height) > 640)
1256 height = 639; /* sanity check */
1257 if (ncr > 0) { /* rectangles pased */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 /* convert rectangular clips to a bitmap */
Jiri Slabyf823f672006-01-11 19:41:32 -02001259 memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 for (i = 0; i < ncr; i++)
1261 clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
1262 cr[i].width, cr[i].height);
1263 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001264 /* clip against viewing window AND screen
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 so we do not have to rely on the user program
1266 */
Jiri Slabyf823f672006-01-11 19:41:32 -02001267 clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
1268 (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
1269 clip_draw_rectangle(clipmap, 0,
1270 (saa->win.y + height > saa->win.sheight) ?
1271 (saa->win.sheight - saa->win.y) : height, 1024, 768);
1272 if (saa->win.x < 0)
1273 clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
1274 if (saa->win.y < 0)
1275 clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276}
1277
1278static int saa_ioctl(struct inode *inode, struct file *file,
1279 unsigned int cmd, unsigned long argl)
1280{
1281 struct saa7146 *saa = file->private_data;
1282 void __user *arg = (void __user *)argl;
1283
1284 switch (cmd) {
1285 case VIDIOCGCAP:
1286 {
1287 struct video_capability b;
1288 strcpy(b.name, saa->video_dev.name);
Jiri Slabyf823f672006-01-11 19:41:32 -02001289 b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
1290 VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
1291 VID_TYPE_SCALES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 b.channels = 1;
1293 b.audios = 1;
1294 b.maxwidth = 768;
1295 b.maxheight = 576;
1296 b.minwidth = 32;
1297 b.minheight = 32;
1298 if (copy_to_user(arg, &b, sizeof(b)))
1299 return -EFAULT;
1300 return 0;
1301 }
1302 case VIDIOCGPICT:
1303 {
1304 struct video_picture p = saa->picture;
1305 if (saa->win.depth == 8)
1306 p.palette = VIDEO_PALETTE_HI240;
1307 if (saa->win.depth == 15)
1308 p.palette = VIDEO_PALETTE_RGB555;
1309 if (saa->win.depth == 16)
1310 p.palette = VIDEO_PALETTE_RGB565;
1311 if (saa->win.depth == 24)
1312 p.palette = VIDEO_PALETTE_RGB24;
1313 if (saa->win.depth == 32)
1314 p.palette = VIDEO_PALETTE_RGB32;
1315 if (copy_to_user(arg, &p, sizeof(p)))
1316 return -EFAULT;
1317 return 0;
1318 }
1319 case VIDIOCSPICT:
1320 {
1321 struct video_picture p;
1322 u32 format;
1323 if (copy_from_user(&p, arg, sizeof(p)))
1324 return -EFAULT;
Trent Piephoba2cf982007-07-05 19:04:27 -03001325 if (p.palette < ARRAY_SIZE(palette2fmt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 format = palette2fmt[p.palette];
1327 saa->win.color_fmt = format;
Jiri Slabyf823f672006-01-11 19:41:32 -02001328 saawrite(format | 0x60,
1329 SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331 saawrite(((p.brightness & 0xff00) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001332 ((p.contrast & 0xfe00) << 7) |
1333 ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 saa->picture = p;
1335 /* upload changed registers */
1336 saawrite(((SAA7146_MC2_UPLD_HPS_H |
Jiri Slabyf823f672006-01-11 19:41:32 -02001337 SAA7146_MC2_UPLD_HPS_V) << 16) |
1338 SAA7146_MC2_UPLD_HPS_H |
1339 SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return 0;
1341 }
1342 case VIDIOCSWIN:
1343 {
1344 struct video_window vw;
1345 struct video_clip *vcp = NULL;
1346
1347 if (copy_from_user(&vw, arg, sizeof(vw)))
1348 return -EFAULT;
1349
Jiri Slabyf823f672006-01-11 19:41:32 -02001350 /* stop capture */
1351 if (vw.flags || vw.width < 16 || vw.height < 16) {
1352 saawrite((SAA7146_MC1_TR_E_1 << 16),
1353 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 return -EINVAL;
1355 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001356 /* 32-bit align start and adjust width */
1357 if (saa->win.bpp < 4) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 int i = vw.x;
1359 vw.x = (vw.x + 3) & ~3;
1360 i = vw.x - i;
1361 vw.width -= i;
1362 }
1363 saa->win.x = vw.x;
1364 saa->win.y = vw.y;
1365 saa->win.width = vw.width;
1366 if (saa->win.width > 768)
1367 saa->win.width = 768;
1368 saa->win.height = vw.height;
1369 if (CurrentMode == VIDEO_MODE_NTSC) {
1370 if (saa->win.height > 480)
1371 saa->win.height = 480;
1372 } else {
1373 if (saa->win.height > 576)
1374 saa->win.height = 576;
1375 }
1376
1377 /* stop capture */
1378 saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
1379 saa7146_set_winsize(saa);
1380
1381 /*
1382 * Do any clips.
1383 */
1384 if (vw.clipcount < 0) {
1385 if (copy_from_user(saa->dmavid2, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001386 VIDEO_CLIPMAP_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001388 } else if (vw.clipcount > 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return -EINVAL;
1390 } else if (vw.clipcount > 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001391 vcp = vmalloc(sizeof(struct video_clip) *
1392 vw.clipcount);
1393 if (vcp == NULL)
1394 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 if (copy_from_user(vcp, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001396 sizeof(struct video_clip) *
1397 vw.clipcount)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 vfree(vcp);
1399 return -EFAULT;
1400 }
1401 } else /* nothing clipped */
1402 memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
Jiri Slabyf823f672006-01-11 19:41:32 -02001403
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 make_clip_tab(saa, vcp, vw.clipcount);
1405 if (vw.clipcount > 0)
1406 vfree(vcp);
1407
1408 /* start capture & clip dma if we have an address */
1409 if ((saa->cap & 3) && saa->win.vidadr != 0)
1410 saawrite(((SAA7146_MC1_TR_E_1 |
1411 SAA7146_MC1_TR_E_2) << 16) | 0xffff,
1412 SAA7146_MC1);
1413 return 0;
1414 }
1415 case VIDIOCGWIN:
1416 {
1417 struct video_window vw;
1418 vw.x = saa->win.x;
1419 vw.y = saa->win.y;
1420 vw.width = saa->win.width;
1421 vw.height = saa->win.height;
1422 vw.chromakey = 0;
1423 vw.flags = 0;
1424 if (copy_to_user(arg, &vw, sizeof(vw)))
1425 return -EFAULT;
1426 return 0;
1427 }
1428 case VIDIOCCAPTURE:
1429 {
1430 int v;
1431 if (copy_from_user(&v, arg, sizeof(v)))
1432 return -EFAULT;
1433 if (v == 0) {
1434 saa->cap &= ~1;
1435 saawrite((SAA7146_MC1_TR_E_1 << 16),
Jiri Slabyf823f672006-01-11 19:41:32 -02001436 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 } else {
1438 if (saa->win.vidadr == 0 || saa->win.width == 0
Jiri Slabyf823f672006-01-11 19:41:32 -02001439 || saa->win.height == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return -EINVAL;
1441 saa->cap |= 1;
1442 saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
Jiri Slabyf823f672006-01-11 19:41:32 -02001443 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 }
1445 return 0;
1446 }
1447 case VIDIOCGFBUF:
1448 {
1449 struct video_buffer v;
Jiri Slabyf823f672006-01-11 19:41:32 -02001450 v.base = (void *)saa->win.vidadr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 v.height = saa->win.sheight;
1452 v.width = saa->win.swidth;
1453 v.depth = saa->win.depth;
1454 v.bytesperline = saa->win.bpl;
1455 if (copy_to_user(arg, &v, sizeof(v)))
1456 return -EFAULT;
1457 return 0;
1458
1459 }
1460 case VIDIOCSFBUF:
1461 {
1462 struct video_buffer v;
1463 if (!capable(CAP_SYS_ADMIN))
1464 return -EPERM;
1465 if (copy_from_user(&v, arg, sizeof(v)))
1466 return -EFAULT;
1467 if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
Jiri Slabyf823f672006-01-11 19:41:32 -02001468 v.depth != 24 && v.depth != 32 && v.width > 16 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 v.height > 16 && v.bytesperline > 16)
1470 return -EINVAL;
1471 if (v.base)
Jiri Slabyf823f672006-01-11 19:41:32 -02001472 saa->win.vidadr = (unsigned long)v.base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 saa->win.sheight = v.height;
1474 saa->win.swidth = v.width;
1475 saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
1476 saa->win.depth = v.depth;
1477 saa->win.bpl = v.bytesperline;
1478
Jiri Slabyf823f672006-01-11 19:41:32 -02001479 DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
1480 "bpl %d\n", v.base, v.width, v.height,
1481 saa->win.bpp, saa->win.bpl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 saa7146_set_winsize(saa);
1483 return 0;
1484 }
1485 case VIDIOCKEY:
1486 {
1487 /* Will be handled higher up .. */
1488 return 0;
1489 }
1490
1491 case VIDIOCGAUDIO:
1492 {
1493 struct video_audio v;
1494 v = saa->audio_dev;
1495 v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
1496 v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
1497 strcpy(v.name, "MPEG");
1498 v.mode = VIDEO_SOUND_STEREO;
1499 if (copy_to_user(arg, &v, sizeof(v)))
1500 return -EFAULT;
1501 return 0;
1502 }
1503 case VIDIOCSAUDIO:
1504 {
1505 struct video_audio v;
1506 int i;
1507 if (copy_from_user(&v, arg, sizeof(v)))
1508 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001509 i = (~(v.volume >> 8)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 if (!HaveCS4341) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001511 if (v.flags & VIDEO_AUDIO_MUTE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001513 IBM_MP2_FRNT_ATTEN, 0xffff, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (!(v.flags & VIDEO_AUDIO_MUTE))
1515 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001516 IBM_MP2_FRNT_ATTEN, 0x0000, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 if (v.flags & VIDEO_AUDIO_VOLUME)
1518 debiwrite(saa, debNormal,
1519 IBM_MP2_FRNT_ATTEN,
Jiri Slabyf823f672006-01-11 19:41:32 -02001520 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 } else {
1522 if (v.flags & VIDEO_AUDIO_MUTE)
1523 cs4341_setlevel(saa, 0xff, 0xff);
1524 if (!(v.flags & VIDEO_AUDIO_MUTE))
1525 cs4341_setlevel(saa, 0, 0);
1526 if (v.flags & VIDEO_AUDIO_VOLUME)
1527 cs4341_setlevel(saa, i, i);
1528 }
1529 saa->audio_dev = v;
1530 return 0;
1531 }
1532
1533 case VIDIOCGUNIT:
1534 {
1535 struct video_unit vu;
1536 vu.video = saa->video_dev.minor;
1537 vu.vbi = VIDEO_NO_UNIT;
1538 vu.radio = VIDEO_NO_UNIT;
1539 vu.audio = VIDEO_NO_UNIT;
1540 vu.teletext = VIDEO_NO_UNIT;
1541 if (copy_to_user(arg, &vu, sizeof(vu)))
1542 return -EFAULT;
1543 return 0;
1544 }
1545 case VIDIOCSPLAYMODE:
1546 {
1547 struct video_play_mode pmode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001548 if (copy_from_user((void *)&pmode, arg,
1549 sizeof(struct video_play_mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 return -EFAULT;
1551 switch (pmode.mode) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001552 case VID_PLAY_VID_OUT_MODE:
1553 if (pmode.p1 != VIDEO_MODE_NTSC &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 pmode.p1 != VIDEO_MODE_PAL)
Jiri Slabyf823f672006-01-11 19:41:32 -02001555 return -EINVAL;
1556 set_out_format(saa, pmode.p1);
1557 return 0;
1558 case VID_PLAY_GENLOCK:
1559 debiwrite(saa, debNormal, XILINX_CTL0,
1560 pmode.p1 ? 0x8000 : 0x8080, 2);
1561 if (NewCard)
1562 set_genlock_offset(saa, pmode.p2);
1563 return 0;
1564 case VID_PLAY_NORMAL:
1565 debiwrite(saa, debNormal,
1566 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1567 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1568 saa->playmode = pmode.mode;
1569 return 0;
1570 case VID_PLAY_PAUSE:
1571 /* IBM removed the PAUSE command */
1572 /* they say use SINGLE_FRAME now */
1573 case VID_PLAY_SINGLE_FRAME:
1574 ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
1575 if (saa->playmode == pmode.mode) {
1576 debiwrite(saa, debNormal,
1577 IBM_MP2_CHIP_CONTROL,
1578 ChipControl, 2);
1579 }
1580 saa->playmode = pmode.mode;
1581 return 0;
1582 case VID_PLAY_FAST_FORWARD:
1583 ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
1584 saa->playmode = pmode.mode;
1585 return 0;
1586 case VID_PLAY_SLOW_MOTION:
1587 ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
1588 pmode.p1, 0);
1589 saa->playmode = pmode.mode;
1590 return 0;
1591 case VID_PLAY_IMMEDIATE_NORMAL:
1592 /* ensure transfers resume */
1593 debiwrite(saa, debNormal,
1594 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1595 ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
1596 0, 0);
1597 saa->playmode = VID_PLAY_NORMAL;
1598 return 0;
1599 case VID_PLAY_SWITCH_CHANNELS:
1600 saa->audhead = saa->audtail = 0;
1601 saa->vidhead = saa->vidtail = 0;
1602 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
1603 ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
1604 0, 1);
1605 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1606 0, 2);
1607 ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
1608 0, 1);
1609 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1610 ChipControl, 2);
1611 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1612 saa->playmode = VID_PLAY_NORMAL;
1613 return 0;
1614 case VID_PLAY_FREEZE_FRAME:
1615 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
1616 saa->playmode = pmode.mode;
1617 return 0;
1618 case VID_PLAY_STILL_MODE:
1619 ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
1620 0, 0);
1621 saa->playmode = pmode.mode;
1622 return 0;
1623 case VID_PLAY_MASTER_MODE:
1624 if (pmode.p1 == VID_PLAY_MASTER_NONE)
1625 saa->boardcfg[1] = 0x13;
1626 else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
1627 saa->boardcfg[1] = 0x23;
1628 else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
1629 saa->boardcfg[1] = 0x43;
1630 else
1631 return -EINVAL;
1632 debiwrite(saa, debNormal,
1633 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1634 return 0;
1635 case VID_PLAY_ACTIVE_SCANLINES:
1636 if (CurrentMode == VIDEO_MODE_PAL) {
1637 if (pmode.p1 < 1 || pmode.p2 > 625)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001639 saa->boardcfg[5] = pmode.p1;
1640 saa->boardcfg[55] = (pmode.p1 +
1641 (pmode.p2 / 2) - 1) & 0xff;
1642 } else {
1643 if (pmode.p1 < 4 || pmode.p2 > 525)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001645 saa->boardcfg[4] = pmode.p1;
1646 saa->boardcfg[54] = (pmode.p1 +
1647 (pmode.p2 / 2) - 4) & 0xff;
1648 }
1649 set_out_format(saa, CurrentMode);
1650 case VID_PLAY_RESET:
1651 return do_ibm_reset(saa);
1652 case VID_PLAY_END_MARK:
1653 if (saa->endmarktail < saa->endmarkhead) {
1654 if (saa->endmarkhead -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 saa->endmarktail < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 return -ENOSPC;
Jiri Slabyf823f672006-01-11 19:41:32 -02001657 } else if (saa->endmarkhead <=saa->endmarktail){
1658 if (saa->endmarktail - saa->endmarkhead
1659 > (MAX_MARKS - 2))
1660 return -ENOSPC;
1661 } else
1662 return -ENOSPC;
1663 saa->endmark[saa->endmarktail] = saa->audtail;
1664 saa->endmarktail++;
1665 if (saa->endmarktail >= MAX_MARKS)
1666 saa->endmarktail = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 }
1668 return -EINVAL;
1669 }
1670 case VIDIOCSWRITEMODE:
1671 {
1672 int mode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001673 if (copy_from_user((void *)&mode, arg, sizeof(int)))
1674 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 if (mode == VID_WRITE_MPEG_AUD ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001676 mode == VID_WRITE_MPEG_VID ||
1677 mode == VID_WRITE_CC ||
1678 mode == VID_WRITE_TTX ||
1679 mode == VID_WRITE_OSD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 saa->writemode = mode;
1681 return 0;
1682 }
1683 return -EINVAL;
1684 }
1685 case VIDIOCSMICROCODE:
1686 {
1687 struct video_code ucode;
1688 __u8 *udata;
1689 int i;
1690 if (copy_from_user(&ucode, arg, sizeof(ucode)))
1691 return -EFAULT;
1692 if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001693 strncmp(ucode.loadwhat, "dec", 3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 return -EINVAL;
1695 if ((udata = vmalloc(ucode.datasize)) == NULL)
1696 return -ENOMEM;
1697 if (copy_from_user(udata, ucode.data, ucode.datasize)) {
1698 vfree(udata);
1699 return -EFAULT;
1700 }
1701 ucode.data = udata;
Jiri Slabyf823f672006-01-11 19:41:32 -02001702 if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
1703 !strncmp(ucode.loadwhat, "decoder.vid", 11))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 i = initialize_ibmmpeg2(&ucode);
1705 else
1706 i = initialize_fpga(&ucode);
1707 vfree(udata);
1708 if (i)
1709 return -EINVAL;
1710 return 0;
1711
1712 }
1713 case VIDIOCGCHAN: /* this makes xawtv happy */
1714 {
1715 struct video_channel v;
1716 if (copy_from_user(&v, arg, sizeof(v)))
1717 return -EFAULT;
1718 v.flags = VIDEO_VC_AUDIO;
1719 v.tuners = 0;
1720 v.type = VID_TYPE_MPEG_DECODER;
1721 v.norm = CurrentMode;
1722 strcpy(v.name, "MPEG2");
1723 if (copy_to_user(arg, &v, sizeof(v)))
1724 return -EFAULT;
1725 return 0;
1726 }
1727 case VIDIOCSCHAN: /* this makes xawtv happy */
1728 {
1729 struct video_channel v;
1730 if (copy_from_user(&v, arg, sizeof(v)))
1731 return -EFAULT;
1732 /* do nothing */
1733 return 0;
1734 }
1735 default:
1736 return -ENOIOCTLCMD;
1737 }
1738 return 0;
1739}
1740
1741static int saa_mmap(struct file *file, struct vm_area_struct *vma)
1742{
1743 struct saa7146 *saa = file->private_data;
1744 printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
1745 return -EINVAL;
1746}
1747
Jiri Slabyf823f672006-01-11 19:41:32 -02001748static ssize_t saa_read(struct file *file, char __user * buf,
1749 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750{
1751 return -EINVAL;
1752}
1753
Jiri Slabyf823f672006-01-11 19:41:32 -02001754static ssize_t saa_write(struct file *file, const char __user * buf,
1755 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756{
1757 struct saa7146 *saa = file->private_data;
1758 unsigned long todo = count;
1759 int blocksize, split;
1760 unsigned long flags;
1761
1762 while (todo > 0) {
1763 if (saa->writemode == VID_WRITE_MPEG_AUD) {
1764 spin_lock_irqsave(&saa->lock, flags);
1765 if (saa->audhead <= saa->audtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001766 blocksize = 65536 -
1767 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 else
1769 blocksize = saa->audhead - saa->audtail;
1770 spin_unlock_irqrestore(&saa->lock, flags);
1771 if (blocksize < 16384) {
1772 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001773 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1775 /* wait for buffer space to open */
1776 interruptible_sleep_on(&saa->audq);
1777 }
1778 spin_lock_irqsave(&saa->lock, flags);
1779 if (saa->audhead <= saa->audtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001780 blocksize = 65536 -
1781 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 split = 65536 - saa->audtail;
1783 } else {
1784 blocksize = saa->audhead - saa->audtail;
1785 split = 65536;
1786 }
1787 spin_unlock_irqrestore(&saa->lock, flags);
1788 blocksize--;
1789 if (blocksize > todo)
1790 blocksize = todo;
1791 /* double check that we really have space */
1792 if (!blocksize)
1793 return -ENOSPC;
1794 if (split < blocksize) {
1795 if (copy_from_user(saa->audbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001796 saa->audtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return -EFAULT;
1798 buf += split;
1799 todo -= split;
1800 blocksize -= split;
1801 saa->audtail = 0;
1802 }
1803 if (copy_from_user(saa->audbuf + saa->audtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001804 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 return -EFAULT;
1806 saa->audtail += blocksize;
1807 todo -= blocksize;
1808 buf += blocksize;
1809 saa->audtail &= 0xffff;
1810 } else if (saa->writemode == VID_WRITE_MPEG_VID) {
1811 spin_lock_irqsave(&saa->lock, flags);
1812 if (saa->vidhead <= saa->vidtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001813 blocksize = 524288 -
1814 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 else
1816 blocksize = saa->vidhead - saa->vidtail;
1817 spin_unlock_irqrestore(&saa->lock, flags);
1818 if (blocksize < 65536) {
1819 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001820 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1822 /* wait for buffer space to open */
1823 interruptible_sleep_on(&saa->vidq);
1824 }
1825 spin_lock_irqsave(&saa->lock, flags);
1826 if (saa->vidhead <= saa->vidtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001827 blocksize = 524288 -
1828 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 split = 524288 - saa->vidtail;
1830 } else {
1831 blocksize = saa->vidhead - saa->vidtail;
1832 split = 524288;
1833 }
1834 spin_unlock_irqrestore(&saa->lock, flags);
1835 blocksize--;
1836 if (blocksize > todo)
1837 blocksize = todo;
1838 /* double check that we really have space */
1839 if (!blocksize)
1840 return -ENOSPC;
1841 if (split < blocksize) {
1842 if (copy_from_user(saa->vidbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001843 saa->vidtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 return -EFAULT;
1845 buf += split;
1846 todo -= split;
1847 blocksize -= split;
1848 saa->vidtail = 0;
1849 }
1850 if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001851 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 return -EFAULT;
1853 saa->vidtail += blocksize;
1854 todo -= blocksize;
1855 buf += blocksize;
1856 saa->vidtail &= 0x7ffff;
1857 } else if (saa->writemode == VID_WRITE_OSD) {
1858 if (count > 131072)
1859 return -ENOSPC;
1860 if (copy_from_user(saa->osdbuf, buf, count))
1861 return -EFAULT;
1862 buf += count;
1863 saa->osdhead = 0;
1864 saa->osdtail = count;
1865 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
1866 debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
1867 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
1868 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -02001869 debiread(saa, debNormal,
1870 IBM_MP2_DISP_MODE, 2) | 1, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 /* trigger osd data transfer */
1872 saawrite(SAA7146_PSR_DEBI_S |
1873 SAA7146_PSR_PIN1, SAA7146_IER);
1874 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1875 }
1876 }
1877 return count;
1878}
1879
1880static int saa_open(struct inode *inode, struct file *file)
1881{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001882 struct video_device *vdev = video_devdata(file);
1883 struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 file->private_data = saa;
1886
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 saa->user++;
1888 if (saa->user > 1)
1889 return 0; /* device open already, don't reset */
1890 saa->writemode = VID_WRITE_MPEG_VID; /* default to video */
1891 return 0;
1892}
1893
1894static int saa_release(struct inode *inode, struct file *file)
1895{
1896 struct saa7146 *saa = file->private_data;
1897 saa->user--;
Jiri Slaby91fb8352006-01-11 19:41:21 -02001898
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 if (saa->user > 0) /* still someone using device */
1900 return 0;
1901 saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
1902 return 0;
1903}
1904
Arjan van de Venfa027c22007-02-12 00:55:33 -08001905static const struct file_operations saa_fops = {
Jiri Slabyf823f672006-01-11 19:41:32 -02001906 .owner = THIS_MODULE,
1907 .open = saa_open,
1908 .release = saa_release,
1909 .ioctl = saa_ioctl,
Douglas Schilling Landgraf078ff792008-04-22 14:46:11 -03001910#ifdef CONFIG_COMPAT
Jiri Slabyf823f672006-01-11 19:41:32 -02001911 .compat_ioctl = v4l_compat_ioctl32,
Douglas Schilling Landgraf078ff792008-04-22 14:46:11 -03001912#endif
Jiri Slabyf823f672006-01-11 19:41:32 -02001913 .read = saa_read,
1914 .llseek = no_llseek,
1915 .write = saa_write,
1916 .mmap = saa_mmap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917};
1918
1919/* template for video_device-structure */
Jiri Slabyf823f672006-01-11 19:41:32 -02001920static struct video_device saa_template = {
1921 .name = "SAA7146A",
1922 .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
Jiri Slabyf823f672006-01-11 19:41:32 -02001923 .fops = &saa_fops,
1924 .minor = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925};
1926
Jiri Slaby9ae82292006-01-11 19:41:13 -02001927static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001929 int retval;
1930 struct saa7146 *saa = pci_get_drvdata(pdev);
Jiri Slabyf823f672006-01-11 19:41:32 -02001931
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 saa->endmarkhead = saa->endmarktail = 0;
1933 saa->win.x = saa->win.y = 0;
1934 saa->win.width = saa->win.cropwidth = 720;
1935 saa->win.height = saa->win.cropheight = 480;
1936 saa->win.cropx = saa->win.cropy = 0;
1937 saa->win.bpp = 2;
1938 saa->win.depth = 16;
1939 saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
1940 saa->win.bpl = 1024 * saa->win.bpp;
1941 saa->win.swidth = 1024;
1942 saa->win.sheight = 768;
1943 saa->picture.brightness = 32768;
1944 saa->picture.contrast = 38768;
1945 saa->picture.colour = 32768;
1946 saa->cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 saa->nr = num;
1948 saa->playmode = VID_PLAY_NORMAL;
1949 memset(saa->boardcfg, 0, 64); /* clear board config area */
1950 saa->saa7146_mem = NULL;
1951 saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
1952 saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
1953 saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
1954 saa->pagea1out = saa->pagea2in = saa->pagea2out =
1955 saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
1956 saa->pageRPS2 = NULL;
1957 saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
1958 saa->audhead = saa->vidtail = 0;
1959
1960 init_waitqueue_head(&saa->i2cq);
1961 init_waitqueue_head(&saa->audq);
1962 init_waitqueue_head(&saa->debiq);
1963 init_waitqueue_head(&saa->vidq);
1964 spin_lock_init(&saa->lock);
1965
Jiri Slaby91fb8352006-01-11 19:41:21 -02001966 retval = pci_enable_device(pdev);
1967 if (retval) {
1968 dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
1969 goto err;
1970 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001971
Jiri Slaby9ae82292006-01-11 19:41:13 -02001972 saa->id = pdev->device;
1973 saa->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 saa->video_dev.minor = -1;
Jiri Slaby9ae82292006-01-11 19:41:13 -02001975 saa->saa7146_adr = pci_resource_start(pdev, 0);
1976 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977
1978 saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001979 if (saa->saa7146_mem == NULL) {
1980 dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
1981 retval = -EIO;
1982 goto err;
1983 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
1986 saawrite(0, SAA7146_IER); /* turn off all interrupts */
Jiri Slaby91fb8352006-01-11 19:41:21 -02001987
Thomas Gleixner8076fe32006-07-01 19:29:37 -07001988 retval = request_irq(saa->irq, saa7146_irq, IRQF_SHARED | IRQF_DISABLED,
Jiri Slaby91fb8352006-01-11 19:41:21 -02001989 "stradis", saa);
1990 if (retval == -EINVAL)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001991 dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001992 else if (retval == -EBUSY)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001993 dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
1994 "in BIOS\n", num, saa->irq);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001995 if (retval < 0)
1996 goto errio;
1997
Jiri Slaby9ae82292006-01-11 19:41:13 -02001998 pci_set_master(pdev);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001999 retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
2000 video_nr);
Jiri Slabyf823f672006-01-11 19:41:32 -02002001 if (retval < 0) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002002 dev_err(&pdev->dev, "%d: error in registering video device!\n",
2003 num);
2004 goto errio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002006
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 return 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002008errio:
2009 iounmap(saa->saa7146_mem);
2010err:
2011 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012}
2013
Jiri Slaby91fb8352006-01-11 19:41:21 -02002014static int __devinit init_saa7146(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015{
Jiri Slaby91fb8352006-01-11 19:41:21 -02002016 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018 saa->user = 0;
2019 /* reset the saa7146 */
2020 saawrite(0xffff0000, SAA7146_MC1);
2021 mdelay(5);
2022 /* enable debi and i2c transfers and pins */
2023 saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C |
2024 SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1);
2025 /* ensure proper state of chip */
2026 saawrite(0x00000000, SAA7146_PAGE1);
2027 saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1);
2028 saawrite(0x00000000, SAA7146_PAGE2);
2029 saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2);
2030 saawrite(0x00000000, SAA7146_DD1_INIT);
2031 saawrite(0x00000000, SAA7146_DD1_STREAM_B);
2032 saawrite(0x00000000, SAA7146_DD1_STREAM_A);
2033 saawrite(0x00000000, SAA7146_BRS_CTRL);
2034 saawrite(0x80400040, SAA7146_BCS_CTRL);
Jiri Slabyf823f672006-01-11 19:41:32 -02002035 saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
2037 saawrite(0x00000000, SAA7146_ACON1);
2038 saawrite(0x00000000, SAA7146_ACON2);
2039 saawrite(0x00000600, SAA7146_I2C_STATUS);
2040 saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
Jiri Slabyf823f672006-01-11 19:41:32 -02002041 SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
2042 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
2043 SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
2044 SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 /* setup arbitration control registers */
2046 saawrite(0x1412121a, SAA7146_PCI_BT_V1);
2047
2048 /* allocate 32k dma buffer + 4k for page table */
2049 if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002050 dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
2051 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 }
2053#if 0
2054 saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */
2055 saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE);
2056 for (i = 0; i < 12; i++) /* setup mmu page table */
2057 saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));
2058#endif
2059 saa->audhead = saa->vidhead = saa->osdhead = 0;
2060 saa->audtail = saa->vidtail = saa->osdtail = 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002061 if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
2062 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
2063 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002065 if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
2066 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002067 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002068 }
2069 if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
2070 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002071 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002072 }
2073 /* allocate 81920 byte buffer for clipping */
2074 if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
2075 dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002076 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 /* setup clipping registers */
2079 saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
2080 saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
2081 saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
Jiri Slabyf823f672006-01-11 19:41:32 -02002082 SAA7146_PROT_ADDR2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 saawrite(256, SAA7146_PITCH2);
Jiri Slabyf823f672006-01-11 19:41:32 -02002084 saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
2086 SAA7146_MC2);
2087 I2CBusScan(saa);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002088
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 return 0;
Jiri Slaby805f1232006-01-24 13:15:06 -08002090errfree:
Jiri Slaby91fb8352006-01-11 19:41:21 -02002091 vfree(saa->osdbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002092 vfree(saa->audbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002093 vfree(saa->vidbuf);
Jiri Slaby805f1232006-01-24 13:15:06 -08002094 saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002095err:
2096 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097}
2098
Jiri Slaby9ae82292006-01-11 19:41:13 -02002099static void stradis_release_saa(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100{
2101 u8 command;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002102 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Jiri Slaby9ae82292006-01-11 19:41:13 -02002104 /* turn off all capturing, DMA and IRQs */
2105 saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
2106 saawrite(0, SAA7146_MC2);
2107 saawrite(0, SAA7146_IER);
2108 saawrite(0xffffffffUL, SAA7146_ISR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Jiri Slaby9ae82292006-01-11 19:41:13 -02002110 /* disable PCI bus-mastering */
2111 pci_read_config_byte(pdev, PCI_COMMAND, &command);
2112 command &= ~PCI_COMMAND_MASTER;
2113 pci_write_config_byte(pdev, PCI_COMMAND, command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Jiri Slaby9ae82292006-01-11 19:41:13 -02002115 /* unmap and free memory */
2116 saa->audhead = saa->audtail = saa->osdhead = 0;
2117 saa->vidhead = saa->vidtail = saa->osdtail = 0;
2118 vfree(saa->vidbuf);
2119 vfree(saa->audbuf);
2120 vfree(saa->osdbuf);
2121 kfree(saa->dmavid2);
2122 saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
2123 saa->dmavid2 = NULL;
2124 kfree(saa->dmadebi);
2125 kfree(saa->dmavid1);
2126 kfree(saa->dmavid3);
2127 kfree(saa->dmaa1in);
2128 kfree(saa->dmaa1out);
2129 kfree(saa->dmaa2in);
2130 kfree(saa->dmaa2out);
2131 kfree(saa->dmaRPS1);
2132 kfree(saa->dmaRPS2);
2133 free_irq(saa->irq, saa);
2134 if (saa->saa7146_mem)
2135 iounmap(saa->saa7146_mem);
2136 if (saa->video_dev.minor != -1)
2137 video_unregister_device(&saa->video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138}
2139
Jiri Slaby9ae82292006-01-11 19:41:13 -02002140static int __devinit stradis_probe(struct pci_dev *pdev,
2141 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002143 int retval = -EINVAL;
2144
2145 if (saa_num >= SAA7146_MAX)
2146 goto err;
2147
2148 if (!pdev->subsystem_vendor)
2149 dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
2150 else
2151 dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
2152
Jiri Slaby91fb8352006-01-11 19:41:21 -02002153 pci_set_drvdata(pdev, &saa7146s[saa_num]);
Jiri Slaby9ae82292006-01-11 19:41:13 -02002154
2155 retval = configure_saa7146(pdev, saa_num);
2156 if (retval) {
2157 dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
2158 goto err;
2159 }
2160
Jiri Slaby91fb8352006-01-11 19:41:21 -02002161 if (init_saa7146(pdev) < 0) {
Jiri Slaby9ae82292006-01-11 19:41:13 -02002162 dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
2163 retval = -EIO;
2164 goto errrel;
2165 }
2166
2167 saa_num++;
2168
2169 return 0;
2170errrel:
2171 stradis_release_saa(pdev);
2172err:
2173 return retval;
2174}
2175
2176static void __devexit stradis_remove(struct pci_dev *pdev)
2177{
2178 stradis_release_saa(pdev);
2179}
2180
2181static struct pci_device_id stradis_pci_tbl[] = {
2182 { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
2183 { 0 }
2184};
Jiri Slabyf823f672006-01-11 19:41:32 -02002185
Jiri Slaby9ae82292006-01-11 19:41:13 -02002186
2187static struct pci_driver stradis_driver = {
Jiri Slabyf823f672006-01-11 19:41:32 -02002188 .name = "stradis",
2189 .id_table = stradis_pci_tbl,
2190 .probe = stradis_probe,
2191 .remove = __devexit_p(stradis_remove)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002192};
2193
Adrian Bunkb9553d72006-06-26 22:40:20 -03002194static int __init stradis_init(void)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002195{
2196 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
2198 saa_num = 0;
2199
Jiri Slaby9ae82292006-01-11 19:41:13 -02002200 retval = pci_register_driver(&stradis_driver);
2201 if (retval)
2202 printk(KERN_ERR "stradis: Unable to register pci driver.\n");
2203
2204 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205}
2206
Adrian Bunkb9553d72006-06-26 22:40:20 -03002207static void __exit stradis_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002209 pci_unregister_driver(&stradis_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 printk(KERN_INFO "stradis: module cleanup complete\n");
2211}
2212
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213module_init(stradis_init);
2214module_exit(stradis_exit);