blob: eaada39c76fdfcf5d2273bd3c31af6dca0350da1 [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>
Alexey Dobriyan405f5572009-07-11 22:08:37 +040029#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/mm.h>
31#include <linux/init.h>
32#include <linux/poll.h>
33#include <linux/pci.h>
34#include <linux/signal.h>
35#include <asm/io.h>
36#include <linux/ioport.h>
37#include <asm/pgtable.h>
38#include <asm/page.h>
39#include <linux/sched.h>
40#include <asm/types.h>
41#include <linux/types.h>
42#include <linux/interrupt.h>
43#include <asm/uaccess.h>
44#include <linux/vmalloc.h>
45#include <linux/videodev.h>
Mauro Carvalho Chehab5e87efa2006-06-05 10:26:32 -030046#include <media/v4l2-common.h>
Mauro Carvalho Chehab28644622008-07-20 20:26:54 -030047#include <media/v4l2-ioctl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#include "saa7146.h"
50#include "saa7146reg.h"
51#include "ibmmpeg2.h"
52#include "saa7121.h"
53#include "cs8420.h"
54
Jiri Slabyf823f672006-01-11 19:41:32 -020055#define DEBUG(x) /* debug driver */
56#undef IDEBUG /* debug irq handler */
57#undef MDEBUG /* debug memory management */
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59#define SAA7146_MAX 6
60
61static struct saa7146 saa7146s[SAA7146_MAX];
62
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030063static int saa_num; /* number of SAA7146s in use */
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65static int video_nr = -1;
66module_param(video_nr, int, 0);
67MODULE_LICENSE("GPL");
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#define nDebNormal 0x00480000
70#define nDebNoInc 0x00480000
71#define nDebVideo 0xd0480000
72#define nDebAudio 0xd0400000
73#define nDebDMA 0x02c80000
74
75#define oDebNormal 0x13c80000
76#define oDebNoInc 0x13c80000
77#define oDebVideo 0xd1080000
78#define oDebAudio 0xd1080000
79#define oDebDMA 0x03080000
80
81#define NewCard (saa->boardcfg[3])
82#define ChipControl (saa->boardcfg[1])
83#define NTSCFirstActive (saa->boardcfg[4])
84#define PALFirstActive (saa->boardcfg[5])
85#define NTSCLastActive (saa->boardcfg[54])
86#define PALLastActive (saa->boardcfg[55])
87#define Have2MB (saa->boardcfg[18] & 0x40)
88#define HaveCS8420 (saa->boardcfg[18] & 0x04)
89#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20)
90#define HaveCS3310 (saa->boardcfg[18] & 0x01)
91#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31])
92#define HaveCS4341 (saa->boardcfg[40] == 2)
93#define SDIType (saa->boardcfg[27])
94#define CurrentMode (saa->boardcfg[2])
95
96#define debNormal (NewCard ? nDebNormal : oDebNormal)
97#define debNoInc (NewCard ? nDebNoInc : oDebNoInc)
98#define debVideo (NewCard ? nDebVideo : oDebVideo)
99#define debAudio (NewCard ? nDebAudio : oDebAudio)
100#define debDMA (NewCard ? nDebDMA : oDebDMA)
101
102#ifdef USE_RESCUE_EEPROM_SDM275
103static unsigned char rescue_eeprom[64] = {
Jiri Slabyf823f672006-01-11 19:41:32 -0200104 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
105 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
106 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
107 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
108 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110};
111#endif
112
113/* ----------------------------------------------------------------------- */
114/* Hardware I2C functions */
115static void I2CWipe(struct saa7146 *saa)
116{
117 int i;
118 /* set i2c to ~=100kHz, abort transfer, clear busy */
119 saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
120 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
121 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
122 /* wait for i2c registers to be programmed */
123 for (i = 0; i < 1000 &&
124 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
125 schedule();
126 saawrite(0x600, SAA7146_I2C_STATUS);
127 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
128 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
129 /* wait for i2c registers to be programmed */
130 for (i = 0; i < 1000 &&
131 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
132 schedule();
133 saawrite(0x600, SAA7146_I2C_STATUS);
134 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
135 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
136 /* wait for i2c registers to be programmed */
137 for (i = 0; i < 1000 &&
138 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
139 schedule();
140}
141
142/* read I2C */
143static int I2CRead(struct saa7146 *saa, unsigned char addr,
144 unsigned char subaddr, int dosub)
145{
146 int i;
147
148 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
149 I2CWipe(saa);
Jiri Slabyf823f672006-01-11 19:41:32 -0200150 for (i = 0;
151 i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
152 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 schedule();
154 if (i == 1000)
155 I2CWipe(saa);
156 if (dosub)
157 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200158 ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 else
160 saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200161 0xf1, SAA7146_I2C_TRANSFER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
163 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
164 /* wait for i2c registers to be programmed */
165 for (i = 0; i < 1000 &&
166 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
167 schedule();
168 /* wait for valid data */
169 for (i = 0; i < 1000 &&
170 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
171 schedule();
172 if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
173 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200174 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 printk("i2c setup read timeout\n");
176 saawrite(0x41, SAA7146_I2C_TRANSFER);
177 saawrite((SAA7146_MC2_UPLD_I2C << 16) |
178 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
179 /* wait for i2c registers to be programmed */
180 for (i = 0; i < 1000 &&
181 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
182 schedule();
183 /* wait for valid data */
184 for (i = 0; i < 1000 &&
185 (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
186 schedule();
187 if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
188 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200189 if (i == 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 printk("i2c read timeout\n");
191 return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
192}
193
194/* set both to write both bytes, reset it to write only b1 */
195
196static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
197 unsigned char b2, int both)
198{
199 int i;
200 u32 data;
201
202 if (saaread(SAA7146_I2C_STATUS) & 0x3c)
203 I2CWipe(saa);
204 for (i = 0; i < 1000 &&
205 (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
206 schedule();
207 if (i == 1000)
208 I2CWipe(saa);
209 data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
210 if (both)
211 data |= ((b2 & 0xff) << 8) | 0xe5;
212 else
213 data |= 0xd1;
214 saawrite(data, SAA7146_I2C_TRANSFER);
215 saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
216 SAA7146_MC2);
217 return 0;
218}
219
220static void attach_inform(struct saa7146 *saa, int id)
221{
222 int i;
223
Jiri Slabyf823f672006-01-11 19:41:32 -0200224 DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
225 id));
226 if (id == 0xa0) { /* we have rev2 or later board, fill in info */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 for (i = 0; i < 64; i++)
228 saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
229#ifdef USE_RESCUE_EEPROM_SDM275
230 if (saa->boardcfg[0] != 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200231 printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
232 "BEEN IGNORED\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 for (i = 0; i < 64; i++)
234 saa->boardcfg[i] = rescue_eeprom[i];
235 }
236#endif
237 printk("stradis%d: config =", saa->nr);
238 for (i = 0; i < 51; i++) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200239 printk(" %02x", saa->boardcfg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 }
241 printk("\n");
242 }
243}
244
245static void I2CBusScan(struct saa7146 *saa)
246{
247 int i;
248 for (i = 0; i < 0xff; i += 2)
249 if ((I2CRead(saa, i, 0, 0)) >= 0)
250 attach_inform(saa, i);
251}
252
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300253static int debiwait_maxwait;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255static int wait_for_debi_done(struct saa7146 *saa)
256{
257 int i;
258
259 /* wait for registers to be programmed */
260 for (i = 0; i < 100000 &&
261 !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
262 saaread(SAA7146_MC2);
263 /* wait for transfer to complete */
264 for (i = 0; i < 500000 &&
265 (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
266 saaread(SAA7146_MC2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 if (i > debiwait_maxwait)
269 printk("wait-for-debi-done maxwait: %d\n",
270 debiwait_maxwait = i);
Jiri Slabyf823f672006-01-11 19:41:32 -0200271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 if (i == 500000)
273 return -1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 return 0;
276}
277
278static int debiwrite(struct saa7146 *saa, u32 config, int addr,
Jiri Slabyf823f672006-01-11 19:41:32 -0200279 u32 val, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
281 u32 cmd;
282 if (count <= 0 || count > 32764)
283 return -1;
284 if (wait_for_debi_done(saa) < 0)
285 return -1;
286 saawrite(config, SAA7146_DEBI_CONFIG);
287 if (count <= 4) /* immediate transfer */
288 saawrite(val, SAA7146_DEBI_AD);
289 else /* block transfer */
290 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
291 saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
292 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
293 SAA7146_MC2);
294 return 0;
295}
296
297static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
298{
299 u32 result = 0;
300
301 if (count > 32764 || count <= 0)
302 return 0;
303 if (wait_for_debi_done(saa) < 0)
304 return 0;
305 saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
306 saawrite((count << 17) | 0x10000 | (addr & 0xffff),
307 SAA7146_DEBI_COMMAND);
308 saawrite(config, SAA7146_DEBI_CONFIG);
309 saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
310 SAA7146_MC2);
311 if (count > 4) /* not an immediate transfer */
312 return count;
313 wait_for_debi_done(saa);
314 result = saaread(SAA7146_DEBI_AD);
315 if (count == 1)
316 result &= 0xff;
317 if (count == 2)
318 result &= 0xffff;
319 if (count == 3)
320 result &= 0xffffff;
321 return result;
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324static void do_irq_send_data(struct saa7146 *saa)
325{
326 int split, audbytes, vidbytes;
327
328 saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
329 /* if special feature mode in effect, disable audio sending */
330 if (saa->playmode != VID_PLAY_NORMAL)
331 saa->audtail = saa->audhead = 0;
332 if (saa->audhead <= saa->audtail)
333 audbytes = saa->audtail - saa->audhead;
334 else
335 audbytes = 65536 - (saa->audhead - saa->audtail);
336 if (saa->vidhead <= saa->vidtail)
337 vidbytes = saa->vidtail - saa->vidhead;
338 else
339 vidbytes = 524288 - (saa->vidhead - saa->vidtail);
340 if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
341 saawrite(0, SAA7146_IER);
342 return;
343 }
344 /* if at least 1 block audio waiting and audio fifo isn't full */
Jiri Slabyf823f672006-01-11 19:41:32 -0200345 if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
346 & 0xff) < 60) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 if (saa->audhead > saa->audtail)
348 split = 65536 - saa->audhead;
349 else
350 split = 0;
351 audbytes = 2048;
352 if (split > 0 && split < 2048) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200353 memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 saa->audhead = 0;
355 audbytes -= split;
356 } else
357 split = 0;
358 memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
359 audbytes);
360 saa->audhead += audbytes;
361 saa->audhead &= 0xffff;
Jiri Slabyf823f672006-01-11 19:41:32 -0200362 debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
363 IBM_MP2_AUD_FIFOW), 0, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 wake_up_interruptible(&saa->audq);
Jiri Slabyf823f672006-01-11 19:41:32 -0200365 /* if at least 1 block video waiting and video fifo isn't full */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 } else if (vidbytes >= 30720 && (debiread(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -0200367 IBM_MP2_FIFO, 2)) < 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 if (saa->vidhead > saa->vidtail)
369 split = 524288 - saa->vidhead;
370 else
371 split = 0;
372 vidbytes = 30720;
373 if (split > 0 && split < 30720) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200374 memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 saa->vidhead = 0;
376 vidbytes -= split;
377 } else
378 split = 0;
379 memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
380 vidbytes);
381 saa->vidhead += vidbytes;
382 saa->vidhead &= 0x7ffff;
383 debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
Jiri Slabyf823f672006-01-11 19:41:32 -0200384 IBM_MP2_FIFOW), 0, 30720);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 wake_up_interruptible(&saa->vidq);
386 }
387 saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
388}
389
390static void send_osd_data(struct saa7146 *saa)
391{
392 int size = saa->osdtail - saa->osdhead;
393 if (size > 30720)
394 size = 30720;
395 /* ensure some multiple of 8 bytes is transferred */
Jiri Slabyf823f672006-01-11 19:41:32 -0200396 size = 8 * ((size + 8) >> 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 if (size) {
398 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
Jiri Slabyf823f672006-01-11 19:41:32 -0200399 (saa->osdhead >> 3), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
401 saa->osdhead += size;
402 /* block transfer of next 8 bytes to ~32k bytes */
403 debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
404 }
405 if (saa->osdhead >= saa->osdtail) {
406 saa->osdhead = saa->osdtail = 0;
407 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
408 }
409}
410
David Howells7d12e782006-10-05 14:55:46 +0100411static irqreturn_t saa7146_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
Jiri Slabyf823f672006-01-11 19:41:32 -0200413 struct saa7146 *saa = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 u32 stat, astat;
415 int count;
416 int handled = 0;
417
418 count = 0;
419 while (1) {
420 /* get/clear interrupt status bits */
421 stat = saaread(SAA7146_ISR);
422 astat = stat & saaread(SAA7146_IER);
423 if (!astat)
424 break;
425 handled = 1;
426 saawrite(astat, SAA7146_ISR);
427 if (astat & SAA7146_PSR_DEBI_S) {
428 do_irq_send_data(saa);
429 }
430 if (astat & SAA7146_PSR_PIN1) {
431 int istat;
432 /* the following read will trigger DEBI_S */
433 istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
434 if (istat & 1) {
435 saawrite(0, SAA7146_IER);
436 send_osd_data(saa);
437 saawrite(SAA7146_PSR_DEBI_S |
438 SAA7146_PSR_PIN1, SAA7146_IER);
439 }
440 if (istat & 0x20) { /* Video Start */
441 saa->vidinfo.frame_count++;
442 }
443 if (istat & 0x400) { /* Picture Start */
444 /* update temporal reference */
445 }
446 if (istat & 0x200) { /* Picture Resolution Change */
447 /* read new resolution */
448 }
449 if (istat & 0x100) { /* New User Data found */
450 /* read new user data */
451 }
452 if (istat & 0x1000) { /* new GOP/SMPTE */
453 /* read new SMPTE */
454 }
455 if (istat & 0x8000) { /* Sequence Start Code */
456 /* reset frame counter, load sizes */
457 saa->vidinfo.frame_count = 0;
458 saa->vidinfo.h_size = 704;
459 saa->vidinfo.v_size = 480;
460#if 0
461 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200462 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 saa->endmark[saa->endmarkhead];
464 saa->endmarkhead++;
465 if (saa->endmarkhead >= MAX_MARKS)
466 saa->endmarkhead = 0;
467 }
468#endif
469 }
470 if (istat & 0x4000) { /* Sequence Error Code */
471 if (saa->endmarkhead != saa->endmarktail) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200472 saa->audhead =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 saa->endmark[saa->endmarkhead];
474 saa->endmarkhead++;
475 if (saa->endmarkhead >= MAX_MARKS)
476 saa->endmarkhead = 0;
477 }
478 }
479 }
480#ifdef IDEBUG
481 if (astat & SAA7146_PSR_PPEF) {
482 IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
483 }
484 if (astat & SAA7146_PSR_PABO) {
485 IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
486 }
487 if (astat & SAA7146_PSR_PPED) {
488 IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
489 }
490 if (astat & SAA7146_PSR_RPS_I1) {
491 IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
492 }
493 if (astat & SAA7146_PSR_RPS_I0) {
494 IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
495 }
496 if (astat & SAA7146_PSR_RPS_LATE1) {
497 IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
498 }
499 if (astat & SAA7146_PSR_RPS_LATE0) {
500 IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
501 }
502 if (astat & SAA7146_PSR_RPS_E1) {
503 IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
504 }
505 if (astat & SAA7146_PSR_RPS_E0) {
506 IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
507 }
508 if (astat & SAA7146_PSR_RPS_TO1) {
509 IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
510 }
511 if (astat & SAA7146_PSR_RPS_TO0) {
512 IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
513 }
514 if (astat & SAA7146_PSR_UPLD) {
515 IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
516 }
517 if (astat & SAA7146_PSR_DEBI_E) {
518 IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
519 }
520 if (astat & SAA7146_PSR_I2C_S) {
521 IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
522 }
523 if (astat & SAA7146_PSR_I2C_E) {
524 IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
525 }
526 if (astat & SAA7146_PSR_A2_IN) {
527 IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
528 }
529 if (astat & SAA7146_PSR_A2_OUT) {
530 IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
531 }
532 if (astat & SAA7146_PSR_A1_IN) {
533 IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
534 }
535 if (astat & SAA7146_PSR_A1_OUT) {
536 IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
537 }
538 if (astat & SAA7146_PSR_AFOU) {
539 IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
540 }
541 if (astat & SAA7146_PSR_V_PE) {
542 IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
543 }
544 if (astat & SAA7146_PSR_VFOU) {
545 IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
546 }
547 if (astat & SAA7146_PSR_FIDA) {
548 IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
549 }
550 if (astat & SAA7146_PSR_FIDB) {
551 IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
552 }
553 if (astat & SAA7146_PSR_PIN3) {
554 IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
555 }
556 if (astat & SAA7146_PSR_PIN2) {
557 IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
558 }
559 if (astat & SAA7146_PSR_PIN0) {
560 IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
561 }
562 if (astat & SAA7146_PSR_ECS) {
563 IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
564 }
565 if (astat & SAA7146_PSR_EC3S) {
566 IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
567 }
568 if (astat & SAA7146_PSR_EC0S) {
569 IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
570 }
571#endif
572 count++;
573 if (count > 15)
574 printk(KERN_WARNING "stradis%d: irq loop %d\n",
575 saa->nr, count);
576 if (count > 20) {
577 saawrite(0, SAA7146_IER);
578 printk(KERN_ERR
579 "stradis%d: IRQ loop cleared\n", saa->nr);
580 }
581 }
582 return IRQ_RETVAL(handled);
583}
584
585static int ibm_send_command(struct saa7146 *saa,
586 int command, int data, int chain)
587{
588 int i;
589
590 if (chain)
Jiri Slabyf823f672006-01-11 19:41:32 -0200591 debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 else
593 debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
594 debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
595 debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
596 for (i = 0; i < 100 &&
597 (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
598 schedule();
599 if (i == 100)
600 return -1;
601 return 0;
602}
603
604static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
605{
606 I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
607 I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
608}
609
610static void initialize_cs4341(struct saa7146 *saa)
611{
612 int i;
613 for (i = 0; i < 200; i++) {
614 /* auto mute off, power on, no de-emphasis */
615 /* I2S data up to 24-bit 64xFs internal SCLK */
616 I2CWrite(saa, 0x22, 0x01, 0x11, 2);
617 /* ATAPI mixer settings */
618 I2CWrite(saa, 0x22, 0x02, 0x49, 2);
619 /* attenuation left 3db */
620 I2CWrite(saa, 0x22, 0x03, 0x00, 2);
621 /* attenuation right 3db */
622 I2CWrite(saa, 0x22, 0x04, 0x00, 2);
623 I2CWrite(saa, 0x22, 0x01, 0x10, 2);
624 if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
625 break;
626 schedule();
627 }
628 printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
629 return;
630}
631
632static void initialize_cs8420(struct saa7146 *saa, int pro)
633{
634 int i;
635 u8 *sequence;
636 if (pro)
637 sequence = mode8420pro;
638 else
639 sequence = mode8420con;
640 for (i = 0; i < INIT8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200641 I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 for (i = 0; i < MODE8420LEN; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200643 I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 printk("stradis%d: CS8420 initialized\n", saa->nr);
645}
646
647static void initialize_saa7121(struct saa7146 *saa, int dopal)
648{
649 int i, mod;
650 u8 *sequence;
651 if (dopal)
652 sequence = init7121pal;
653 else
654 sequence = init7121ntsc;
655 mod = saaread(SAA7146_PSR) & 0x08;
656 /* initialize PAL/NTSC video encoder */
657 for (i = 0; i < INIT7121LEN; i++) {
658 if (NewCard) { /* handle new card encoder differences */
Jiri Slabyf823f672006-01-11 19:41:32 -0200659 if (sequence[i * 2] == 0x3a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200661 else if (sequence[i * 2] == 0x6b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200663 else if (sequence[i * 2] == 0x6c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 I2CWrite(saa, 0x88, 0x6c,
665 dopal ? 0x09 : 0xf5, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200666 else if (sequence[i * 2] == 0x6d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 I2CWrite(saa, 0x88, 0x6d,
668 dopal ? 0x20 : 0x00, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200669 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 I2CWrite(saa, 0x88, 0x7a,
671 dopal ? (PALFirstActive - 1) :
672 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200673 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 I2CWrite(saa, 0x88, 0x7b,
675 dopal ? PALLastActive :
676 NTSCLastActive, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200677 else
678 I2CWrite(saa, 0x88, sequence[i * 2],
679 sequence[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -0200681 if (sequence[i * 2] == 0x6b && mod)
682 I2CWrite(saa, 0x88, 0x6b,
683 (sequence[i * 2 + 1] ^ 0x09), 2);
684 else if (sequence[i * 2] == 0x7a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 I2CWrite(saa, 0x88, 0x7a,
686 dopal ? (PALFirstActive - 1) :
687 (NTSCFirstActive - 4), 2);
Jiri Slabyf823f672006-01-11 19:41:32 -0200688 else if (sequence[i * 2] == 0x7b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 I2CWrite(saa, 0x88, 0x7b,
690 dopal ? PALLastActive :
691 NTSCLastActive, 2);
692 else
693 I2CWrite(saa, 0x88, sequence[i * 2],
694 sequence[i * 2 + 1], 2);
695 }
696 }
697}
698
699static void set_genlock_offset(struct saa7146 *saa, int noffset)
700{
701 int nCode;
702 int PixelsPerLine = 858;
703 if (CurrentMode == VIDEO_MODE_PAL)
704 PixelsPerLine = 864;
705 if (noffset > 500)
706 noffset = 500;
707 else if (noffset < -500)
708 noffset = -500;
709 nCode = noffset + 0x100;
710 if (nCode == 1)
711 nCode = 0x401;
Jiri Slabyf823f672006-01-11 19:41:32 -0200712 else if (nCode < 1)
713 nCode = 0x400 + PixelsPerLine + nCode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
715}
716
717static void set_out_format(struct saa7146 *saa, int mode)
718{
719 initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
720 saa->boardcfg[2] = mode;
721 /* do not adjust analog video parameters here, use saa7121 init */
722 /* you will affect the SDI output on the new card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200723 if (mode == VIDEO_MODE_PAL) { /* PAL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
725 mdelay(50);
726 saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
727 if (NewCard) {
Jiri Slabyf823f672006-01-11 19:41:32 -0200728 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 mdelay(50);
730 }
731 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200732 NewCard ? 0xe500 : 0x6500, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
734 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200735 (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 } else { /* NTSC */
737 debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
738 mdelay(50);
739 saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
740 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -0200741 NewCard ? 0xe100 : 0x6100, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
743 (1 << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -0200744 (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746}
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748/* Intialize bitmangler to map from a byte value to the mangled word that
749 * must be output to program the Xilinx part through the DEBI port.
750 * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
751 * transfer FPGA code, init IBM chip, transfer IBM microcode
752 * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
753 */
754static u16 bitmangler[256];
755
756static int initialize_fpga(struct video_code *bitdata)
757{
758 int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
759 u16 *dmabuf;
760 u8 *newdma;
761 struct saa7146 *saa;
762
763 /* verify fpga code */
764 for (startindex = 0; startindex < bitdata->datasize; startindex++)
765 if (bitdata->data[startindex] == 255)
766 break;
767 if (startindex == bitdata->datasize) {
768 printk(KERN_INFO "stradis: bad fpga code\n");
769 return -1;
770 }
771 /* initialize all detected cards */
772 for (num = 0; num < saa_num; num++) {
773 saa = &saa7146s[num];
774 if (saa->boardcfg[0] > 20)
Jiri Slabyf823f672006-01-11 19:41:32 -0200775 continue; /* card was programmed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 loadtwo = (saa->boardcfg[18] & 0x10);
777 if (!NewCard) /* we have an old board */
778 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200779 bitmangler[i] = ((i & 0x01) << 15) |
780 ((i & 0x02) << 6) | ((i & 0x04) << 4) |
781 ((i & 0x08) << 9) | ((i & 0x10) << 7) |
782 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
783 ((i & 0x80) >> 7);
784 else /* else we have a new board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 for (i = 0; i < 256; i++)
Jiri Slabyf823f672006-01-11 19:41:32 -0200786 bitmangler[i] = ((i & 0x01) << 7) |
787 ((i & 0x02) << 5) | ((i & 0x04) << 3) |
788 ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
789 ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
790 ((i & 0x80) >> 7);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 dmabuf = (u16 *) saa->dmadebi;
793 newdma = (u8 *) saa->dmadebi;
794 if (NewCard) { /* SDM2xxx */
795 if (!strncmp(bitdata->loadwhat, "decoder2", 8))
796 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200797 if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 loadfile = 1;
Jiri Slabyf823f672006-01-11 19:41:32 -0200799 else if (loadtwo && !strncmp(&saa->boardcfg[19],
800 bitdata->loadwhat, 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 loadfile = 2;
Jiri Slabyf823f672006-01-11 19:41:32 -0200802 else if (!saa->boardcfg[42] && !strncmp("decxl",
803 bitdata->loadwhat, 8))
804 loadfile = 1; /* special */
805 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 continue; /* fpga not for this card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200807 if (loadfile != 1 && loadfile != 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 continue; /* skip to next card */
Jiri Slabyf823f672006-01-11 19:41:32 -0200809 if (saa->boardcfg[0] && loadfile == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 continue; /* skip to next card */
811 if (saa->boardcfg[0] != 1 && loadfile == 2)
812 continue; /* skip to next card */
813 saa->boardcfg[0]++; /* mark fpga handled */
814 printk("stradis%d: loading %s\n", saa->nr,
815 bitdata->loadwhat);
816 if (loadtwo && loadfile == 2)
817 goto send_fpga_stuff;
818 /* turn on the Audio interface to set PROG low */
819 saawrite(0x00400040, SAA7146_GPIO_CTRL);
820 saaread(SAA7146_PSR); /* ensure posted write */
821 /* wait for everyone to reset */
822 mdelay(10);
823 saawrite(0x00400000, SAA7146_GPIO_CTRL);
824 } else { /* original card */
825 if (strncmp(bitdata->loadwhat, "decoder2", 8))
826 continue; /* fpga not for this card */
827 /* Pull the Xilinx PROG signal WS3 low */
828 saawrite(0x02000200, SAA7146_MC1);
829 /* Turn on the Audio interface so can set PROG low */
830 saawrite(0x000000c0, SAA7146_ACON1);
831 /* Pull the Xilinx INIT signal (GPIO2) low */
832 saawrite(0x00400000, SAA7146_GPIO_CTRL);
833 /* Make sure everybody resets */
834 saaread(SAA7146_PSR); /* ensure posted write */
835 mdelay(10);
836 /* Release the Xilinx PROG signal */
837 saawrite(0x00000000, SAA7146_ACON1);
838 /* Turn off the Audio interface */
839 saawrite(0x02000000, SAA7146_MC1);
840 }
841 /* Release Xilinx INIT signal (WS2) */
842 saawrite(0x00000000, SAA7146_GPIO_CTRL);
843 /* Wait for the INIT to go High */
Jiri Slabyf823f672006-01-11 19:41:32 -0200844 for (i = 0;
845 i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
846 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 schedule();
848 if (i == 1000) {
849 printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
850 return -1;
851 }
852send_fpga_stuff:
853 if (NewCard) {
854 for (i = startindex; i < bitdata->datasize; i++)
855 newdma[i - startindex] =
Jiri Slabyf823f672006-01-11 19:41:32 -0200856 bitmangler[bitdata->data[i]];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 debiwrite(saa, 0x01420000, 0, 0,
858 ((bitdata->datasize - startindex) + 5));
Jiri Slabyf823f672006-01-11 19:41:32 -0200859 if (loadtwo && loadfile == 1) {
860 printk("stradis%d: awaiting 2nd FPGA bitfile\n",
861 saa->nr);
862 continue; /* skip to next card */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 }
864 } else {
865 for (i = startindex; i < bitdata->datasize; i++)
866 dmabuf[i - startindex] =
867 bitmangler[bitdata->data[i]];
868 debiwrite(saa, 0x014a0000, 0, 0,
869 ((bitdata->datasize - startindex) + 5) * 2);
870 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200871 for (i = 0;
872 i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
873 i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 schedule();
875 if (i == 1000) {
876 printk(KERN_INFO "stradis%d: FPGA load failed\n",
877 saa->nr);
878 failure++;
879 continue;
880 }
881 if (!NewCard) {
882 /* Pull the Xilinx INIT signal (GPIO2) low */
883 saawrite(0x00400000, SAA7146_GPIO_CTRL);
884 saaread(SAA7146_PSR); /* ensure posted write */
885 mdelay(2);
886 saawrite(0x00000000, SAA7146_GPIO_CTRL);
887 mdelay(2);
888 }
889 printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
890 saa->boardcfg[0] = 26; /* mark fpga programmed */
891 /* set VXCO to its lowest frequency */
892 debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
893 if (NewCard) {
894 /* mute CS3310 */
895 if (HaveCS3310)
896 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
Jiri Slabyf823f672006-01-11 19:41:32 -0200897 0, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 /* set VXCO to PWM mode, release reset, blank on */
899 debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
900 mdelay(10);
901 /* unmute CS3310 */
902 if (HaveCS3310)
903 debiwrite(saa, debNormal, XILINX_CTL0,
Jiri Slabyf823f672006-01-11 19:41:32 -0200904 0x2020, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 }
906 /* set source Black */
907 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
908 saa->boardcfg[4] = 22; /* set NTSC First Active Line */
909 saa->boardcfg[5] = 23; /* set PAL First Active Line */
910 saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */
911 saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */
912 set_out_format(saa, VIDEO_MODE_NTSC);
913 mdelay(50);
914 /* begin IBM chip init */
915 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
916 saaread(SAA7146_PSR); /* wait for reset */
917 mdelay(5);
918 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
919 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
920 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
921 debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
922 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
923 if (NewCard) {
924 mdelay(5);
925 /* set i2s rate converter to 48KHz */
926 debiwrite(saa, debNormal, 0x80c0, 6, 2);
927 /* we must init CS8420 first since rev b pulls i2s */
928 /* master clock low and CS4341 needs i2s master to */
929 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200930 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 /* 0=consumer, 1=pro */
932 initialize_cs8420(saa, 0);
Jiri Slabyf823f672006-01-11 19:41:32 -0200933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 mdelay(5);
935 if (HaveCS4341)
936 initialize_cs4341(saa);
937 }
938 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
939 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
940 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
941 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
942 if (NewCard)
943 set_genlock_offset(saa, 0);
944 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
945#if 0
946 /* enable genlock */
947 debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
948#else
949 /* disable genlock */
950 debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
951#endif
952 }
Jiri Slabyf823f672006-01-11 19:41:32 -0200953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 return failure;
955}
956
957static int do_ibm_reset(struct saa7146 *saa)
958{
959 /* failure if decoder not previously programmed */
960 if (saa->boardcfg[0] < 37)
961 return -EIO;
962 /* mute CS3310 */
963 if (HaveCS3310)
964 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
965 /* disable interrupts */
966 saawrite(0, SAA7146_IER);
967 saa->audhead = saa->audtail = 0;
968 saa->vidhead = saa->vidtail = 0;
969 /* tristate debi bus, disable debi transfers */
970 saawrite(0x00880000, SAA7146_MC1);
971 /* ensure posted write */
972 saaread(SAA7146_MC1);
973 mdelay(50);
974 /* re-enable debi transfers */
975 saawrite(0x00880088, SAA7146_MC1);
976 /* set source Black */
977 debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
978 /* begin IBM chip init */
979 set_out_format(saa, CurrentMode);
980 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
981 saaread(SAA7146_PSR); /* wait for reset */
982 mdelay(5);
983 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
984 debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
985 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
986 debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
987 if (NewCard) {
988 mdelay(5);
989 /* set i2s rate converter to 48KHz */
990 debiwrite(saa, debNormal, 0x80c0, 6, 2);
991 /* we must init CS8420 first since rev b pulls i2s */
992 /* master clock low and CS4341 needs i2s master to */
993 /* run the i2c port. */
Jiri Slabyf823f672006-01-11 19:41:32 -0200994 if (HaveCS8420)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 /* 0=consumer, 1=pro */
996 initialize_cs8420(saa, 1);
Jiri Slabyf823f672006-01-11 19:41:32 -0200997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 mdelay(5);
999 if (HaveCS4341)
1000 initialize_cs4341(saa);
1001 }
1002 debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
1003 debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
1004 debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
1005 debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
1006 if (NewCard)
1007 set_genlock_offset(saa, 0);
1008 debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
1009 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1010 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1011 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001012 (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
1014 }
1015 if (HaveCS3310) {
1016 int i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001017 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 }
1019 /* start video decoder */
1020 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1021 /* 256k vid, 3520 bytes aud */
1022 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
1023 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1024 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1025 /* enable buffer threshold irq */
1026 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1027 /* clear pending interrupts */
1028 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1029 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return 0;
1032}
1033
1034/* load the decoder microcode */
1035static int initialize_ibmmpeg2(struct video_code *microcode)
1036{
1037 int i, num;
1038 struct saa7146 *saa;
1039
1040 for (num = 0; num < saa_num; num++) {
1041 saa = &saa7146s[num];
1042 /* check that FPGA is loaded */
1043 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001044 i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
1045 if (i != 0xa55a) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
1047 saa->nr, i);
1048#if 0
1049 return -1;
1050#endif
1051 }
1052 if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
1053 if (saa->boardcfg[0] > 27)
1054 continue; /* skip to next card */
1055 /* load video control store */
Jiri Slabyf823f672006-01-11 19:41:32 -02001056 saa->boardcfg[1] = 0x13; /* no-sync default */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1058 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1059 for (i = 0; i < microcode->datasize / 2; i++)
1060 debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
1061 (microcode->data[i * 2] << 8) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001062 microcode->data[i * 2 + 1], 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
1064 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1065 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
Jiri Slabyf823f672006-01-11 19:41:32 -02001066 ChipControl, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 saa->boardcfg[0] = 28;
1068 }
1069 if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
1070 if (saa->boardcfg[0] > 35)
1071 continue; /* skip to next card */
1072 /* load audio control store */
1073 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
1074 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1075 for (i = 0; i < microcode->datasize; i++)
1076 debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
1077 microcode->data[i], 1);
1078 debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
1079 debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
1080 debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
1081 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
1082 if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
Jiri Slabyf823f672006-01-11 19:41:32 -02001083 0xe000, 1)) {
1084 printk(KERN_ERR "stradis%d: IBM config "
1085 "failed\n", saa->nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 return -1;
1087 }
1088 /* set PWM to center value */
1089 if (NewCard) {
1090 debiwrite(saa, debNormal, XILINX_PWM,
Jiri Slabyf823f672006-01-11 19:41:32 -02001091 saa->boardcfg[14] +
1092 (saa->boardcfg[13] << 8), 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 } else
Jiri Slabyf823f672006-01-11 19:41:32 -02001094 debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
1095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 if (HaveCS3310) {
1097 i = CS3310MaxLvl;
Jiri Slabyf823f672006-01-11 19:41:32 -02001098 debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
1099 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001101 printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
1102 saa->nr, 18 + (debiread(saa, debNormal,
1103 IBM_MP2_CHIP_CONTROL, 2) >> 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 /* start video decoder */
1105 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1106 ChipControl, 2);
Jiri Slabyf823f672006-01-11 19:41:32 -02001107 debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
1108 2); /* 256k vid, 3520 bytes aud */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
1110 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1111 /* enable buffer threshold irq */
1112 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
1113 debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
1114 /* enable gpio irq */
1115 saawrite(0x00002000, SAA7146_GPIO_CTRL);
1116 /* enable decoder output to HPS */
1117 debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
1118 saa->boardcfg[0] = 37;
1119 }
1120 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return 0;
1123}
1124
Jiri Slabyf823f672006-01-11 19:41:32 -02001125static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
1126 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
1127 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
1128 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129};
Jiri Slabyf823f672006-01-11 19:41:32 -02001130static int bpp2fmt[4] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
1132 VIDEO_PALETTE_RGB32
1133};
1134
1135/* I wish I could find a formula to calculate these... */
Jiri Slabyf823f672006-01-11 19:41:32 -02001136static u32 h_prescale[64] = {
1137 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
1138 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
1139 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
1140 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
1141 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
1142 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
1143 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
1144 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
1145 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
1146 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
1147 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148};
Jiri Slabyf823f672006-01-11 19:41:32 -02001149static u32 v_gain[64] = {
1150 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
1151 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
1152 0x016300ff, 0x016300ff, 0x016300ff, 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, 0x016400ff, 0x016400ff,
1160 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161};
1162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163static void saa7146_set_winsize(struct saa7146 *saa)
1164{
1165 u32 format;
1166 int offset, yacl, ysci;
1167 saa->win.color_fmt = format =
1168 (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
1169 palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
1170 offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
1171 saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
1172 saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
1173 saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
1174 saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
1175 SAA7146_PROT_ADDR1);
1176 saawrite(0, SAA7146_PAGE1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001177 saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 offset = (704 / (saa->win.width - 1)) & 0x3f;
1179 saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
1180 offset = (720896 / saa->win.width) / (offset + 1);
Jiri Slabyf823f672006-01-11 19:41:32 -02001181 saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (CurrentMode == VIDEO_MODE_NTSC) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001183 yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 ysci = 1024 - (saa->win.height * 1024 / 480);
1185 } else {
Jiri Slabyf823f672006-01-11 19:41:32 -02001186 yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 ysci = 1024 - (saa->win.height * 1024 / 576);
1188 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001189 saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
1191 saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
Jiri Slabyf823f672006-01-11 19:41:32 -02001192 SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
1193 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194}
1195
1196/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001197 * bitmap is fixed width, 128 bytes (1024 pixels represented)
1198 * arranged most-sigificant-bit-left in 32-bit words
1199 * based on saa7146 clipping hardware, it swaps bytes if LE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 * much of this makes up for egcs brain damage -- so if you
1201 * are wondering "why did he do this?" it is because the C
1202 * was adjusted to generate the optimal asm output without
1203 * writing non-portable __asm__ directives.
1204 */
1205
1206static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
1207{
1208 register int startword, endword;
1209 register u32 bitsleft, bitsright;
1210 u32 *temp;
1211 if (x < 0) {
1212 w += x;
1213 x = 0;
1214 }
1215 if (y < 0) {
1216 h += y;
1217 y = 0;
1218 }
1219 if (w <= 0 || h <= 0 || x > 1023 || y > 639)
1220 return; /* throw away bad clips */
1221 if (x + w > 1024)
1222 w = 1024 - x;
1223 if (y + h > 640)
1224 h = 640 - y;
1225 startword = (x >> 5);
1226 endword = ((x + w) >> 5);
1227 bitsleft = (0xffffffff >> (x & 31));
Jiri Slabyf823f672006-01-11 19:41:32 -02001228 bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
1229 temp = &clipmap[(y << 5) + startword];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 w = endword - startword;
1231 if (!w) {
1232 bitsleft |= bitsright;
1233 for (y = 0; y < h; y++) {
1234 *temp |= bitsleft;
1235 temp += 32;
1236 }
1237 } else {
1238 for (y = 0; y < h; y++) {
1239 *temp++ |= bitsleft;
1240 for (x = 1; x < w; x++)
1241 *temp++ = 0xffffffff;
1242 *temp |= bitsright;
1243 temp += (32 - w);
1244 }
1245 }
1246}
1247
1248static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
1249{
1250 int i, width, height;
1251 u32 *clipmap;
1252
1253 clipmap = saa->dmavid2;
Jiri Slabyf823f672006-01-11 19:41:32 -02001254 if ((width = saa->win.width) > 1023)
1255 width = 1023; /* sanity check */
1256 if ((height = saa->win.height) > 640)
1257 height = 639; /* sanity check */
1258 if (ncr > 0) { /* rectangles pased */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 /* convert rectangular clips to a bitmap */
Jiri Slabyf823f672006-01-11 19:41:32 -02001260 memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 for (i = 0; i < ncr; i++)
1262 clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
1263 cr[i].width, cr[i].height);
1264 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001265 /* clip against viewing window AND screen
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 so we do not have to rely on the user program
1267 */
Jiri Slabyf823f672006-01-11 19:41:32 -02001268 clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
1269 (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
1270 clip_draw_rectangle(clipmap, 0,
1271 (saa->win.y + height > saa->win.sheight) ?
1272 (saa->win.sheight - saa->win.y) : height, 1024, 768);
1273 if (saa->win.x < 0)
1274 clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
1275 if (saa->win.y < 0)
1276 clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277}
1278
Hans Verkuil069b7472008-12-30 07:04:34 -03001279static long saa_ioctl(struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 unsigned int cmd, unsigned long argl)
1281{
1282 struct saa7146 *saa = file->private_data;
1283 void __user *arg = (void __user *)argl;
1284
1285 switch (cmd) {
1286 case VIDIOCGCAP:
1287 {
1288 struct video_capability b;
1289 strcpy(b.name, saa->video_dev.name);
Jiri Slabyf823f672006-01-11 19:41:32 -02001290 b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
1291 VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
1292 VID_TYPE_SCALES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 b.channels = 1;
1294 b.audios = 1;
1295 b.maxwidth = 768;
1296 b.maxheight = 576;
1297 b.minwidth = 32;
1298 b.minheight = 32;
1299 if (copy_to_user(arg, &b, sizeof(b)))
1300 return -EFAULT;
1301 return 0;
1302 }
1303 case VIDIOCGPICT:
1304 {
1305 struct video_picture p = saa->picture;
1306 if (saa->win.depth == 8)
1307 p.palette = VIDEO_PALETTE_HI240;
1308 if (saa->win.depth == 15)
1309 p.palette = VIDEO_PALETTE_RGB555;
1310 if (saa->win.depth == 16)
1311 p.palette = VIDEO_PALETTE_RGB565;
1312 if (saa->win.depth == 24)
1313 p.palette = VIDEO_PALETTE_RGB24;
1314 if (saa->win.depth == 32)
1315 p.palette = VIDEO_PALETTE_RGB32;
1316 if (copy_to_user(arg, &p, sizeof(p)))
1317 return -EFAULT;
1318 return 0;
1319 }
1320 case VIDIOCSPICT:
1321 {
1322 struct video_picture p;
1323 u32 format;
1324 if (copy_from_user(&p, arg, sizeof(p)))
1325 return -EFAULT;
Trent Piephoba2cf982007-07-05 19:04:27 -03001326 if (p.palette < ARRAY_SIZE(palette2fmt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 format = palette2fmt[p.palette];
1328 saa->win.color_fmt = format;
Jiri Slabyf823f672006-01-11 19:41:32 -02001329 saawrite(format | 0x60,
1330 SAA7146_CLIP_FORMAT_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
1332 saawrite(((p.brightness & 0xff00) << 16) |
Jiri Slabyf823f672006-01-11 19:41:32 -02001333 ((p.contrast & 0xfe00) << 7) |
1334 ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 saa->picture = p;
1336 /* upload changed registers */
1337 saawrite(((SAA7146_MC2_UPLD_HPS_H |
Jiri Slabyf823f672006-01-11 19:41:32 -02001338 SAA7146_MC2_UPLD_HPS_V) << 16) |
1339 SAA7146_MC2_UPLD_HPS_H |
1340 SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return 0;
1342 }
1343 case VIDIOCSWIN:
1344 {
1345 struct video_window vw;
1346 struct video_clip *vcp = NULL;
1347
1348 if (copy_from_user(&vw, arg, sizeof(vw)))
1349 return -EFAULT;
1350
Jiri Slabyf823f672006-01-11 19:41:32 -02001351 /* stop capture */
1352 if (vw.flags || vw.width < 16 || vw.height < 16) {
1353 saawrite((SAA7146_MC1_TR_E_1 << 16),
1354 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 return -EINVAL;
1356 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001357 /* 32-bit align start and adjust width */
1358 if (saa->win.bpp < 4) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 int i = vw.x;
1360 vw.x = (vw.x + 3) & ~3;
1361 i = vw.x - i;
1362 vw.width -= i;
1363 }
1364 saa->win.x = vw.x;
1365 saa->win.y = vw.y;
1366 saa->win.width = vw.width;
1367 if (saa->win.width > 768)
1368 saa->win.width = 768;
1369 saa->win.height = vw.height;
1370 if (CurrentMode == VIDEO_MODE_NTSC) {
1371 if (saa->win.height > 480)
1372 saa->win.height = 480;
1373 } else {
1374 if (saa->win.height > 576)
1375 saa->win.height = 576;
1376 }
1377
1378 /* stop capture */
1379 saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
1380 saa7146_set_winsize(saa);
1381
1382 /*
1383 * Do any clips.
1384 */
1385 if (vw.clipcount < 0) {
1386 if (copy_from_user(saa->dmavid2, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001387 VIDEO_CLIPMAP_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001389 } else if (vw.clipcount > 16384) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return -EINVAL;
1391 } else if (vw.clipcount > 0) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001392 vcp = vmalloc(sizeof(struct video_clip) *
1393 vw.clipcount);
1394 if (vcp == NULL)
1395 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 if (copy_from_user(vcp, vw.clips,
Jiri Slabyf823f672006-01-11 19:41:32 -02001397 sizeof(struct video_clip) *
1398 vw.clipcount)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 vfree(vcp);
1400 return -EFAULT;
1401 }
1402 } else /* nothing clipped */
1403 memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
Jiri Slabyf823f672006-01-11 19:41:32 -02001404
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 make_clip_tab(saa, vcp, vw.clipcount);
1406 if (vw.clipcount > 0)
1407 vfree(vcp);
1408
1409 /* start capture & clip dma if we have an address */
1410 if ((saa->cap & 3) && saa->win.vidadr != 0)
1411 saawrite(((SAA7146_MC1_TR_E_1 |
1412 SAA7146_MC1_TR_E_2) << 16) | 0xffff,
1413 SAA7146_MC1);
1414 return 0;
1415 }
1416 case VIDIOCGWIN:
1417 {
1418 struct video_window vw;
1419 vw.x = saa->win.x;
1420 vw.y = saa->win.y;
1421 vw.width = saa->win.width;
1422 vw.height = saa->win.height;
1423 vw.chromakey = 0;
1424 vw.flags = 0;
1425 if (copy_to_user(arg, &vw, sizeof(vw)))
1426 return -EFAULT;
1427 return 0;
1428 }
1429 case VIDIOCCAPTURE:
1430 {
1431 int v;
1432 if (copy_from_user(&v, arg, sizeof(v)))
1433 return -EFAULT;
1434 if (v == 0) {
1435 saa->cap &= ~1;
1436 saawrite((SAA7146_MC1_TR_E_1 << 16),
Jiri Slabyf823f672006-01-11 19:41:32 -02001437 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 } else {
1439 if (saa->win.vidadr == 0 || saa->win.width == 0
Jiri Slabyf823f672006-01-11 19:41:32 -02001440 || saa->win.height == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 return -EINVAL;
1442 saa->cap |= 1;
1443 saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
Jiri Slabyf823f672006-01-11 19:41:32 -02001444 SAA7146_MC1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 }
1446 return 0;
1447 }
1448 case VIDIOCGFBUF:
1449 {
1450 struct video_buffer v;
Jiri Slabyf823f672006-01-11 19:41:32 -02001451 v.base = (void *)saa->win.vidadr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 v.height = saa->win.sheight;
1453 v.width = saa->win.swidth;
1454 v.depth = saa->win.depth;
1455 v.bytesperline = saa->win.bpl;
1456 if (copy_to_user(arg, &v, sizeof(v)))
1457 return -EFAULT;
1458 return 0;
1459
1460 }
1461 case VIDIOCSFBUF:
1462 {
1463 struct video_buffer v;
1464 if (!capable(CAP_SYS_ADMIN))
1465 return -EPERM;
1466 if (copy_from_user(&v, arg, sizeof(v)))
1467 return -EFAULT;
1468 if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
Jiri Slabyf823f672006-01-11 19:41:32 -02001469 v.depth != 24 && v.depth != 32 && v.width > 16 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 v.height > 16 && v.bytesperline > 16)
1471 return -EINVAL;
1472 if (v.base)
Jiri Slabyf823f672006-01-11 19:41:32 -02001473 saa->win.vidadr = (unsigned long)v.base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 saa->win.sheight = v.height;
1475 saa->win.swidth = v.width;
1476 saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
1477 saa->win.depth = v.depth;
1478 saa->win.bpl = v.bytesperline;
1479
Jiri Slabyf823f672006-01-11 19:41:32 -02001480 DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
1481 "bpl %d\n", v.base, v.width, v.height,
1482 saa->win.bpp, saa->win.bpl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 saa7146_set_winsize(saa);
1484 return 0;
1485 }
1486 case VIDIOCKEY:
1487 {
1488 /* Will be handled higher up .. */
1489 return 0;
1490 }
1491
1492 case VIDIOCGAUDIO:
1493 {
1494 struct video_audio v;
1495 v = saa->audio_dev;
1496 v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
1497 v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
1498 strcpy(v.name, "MPEG");
1499 v.mode = VIDEO_SOUND_STEREO;
1500 if (copy_to_user(arg, &v, sizeof(v)))
1501 return -EFAULT;
1502 return 0;
1503 }
1504 case VIDIOCSAUDIO:
1505 {
1506 struct video_audio v;
1507 int i;
1508 if (copy_from_user(&v, arg, sizeof(v)))
1509 return -EFAULT;
Jiri Slabyf823f672006-01-11 19:41:32 -02001510 i = (~(v.volume >> 8)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 if (!HaveCS4341) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001512 if (v.flags & VIDEO_AUDIO_MUTE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001514 IBM_MP2_FRNT_ATTEN, 0xffff, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (!(v.flags & VIDEO_AUDIO_MUTE))
1516 debiwrite(saa, debNormal,
Jiri Slabyf823f672006-01-11 19:41:32 -02001517 IBM_MP2_FRNT_ATTEN, 0x0000, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 if (v.flags & VIDEO_AUDIO_VOLUME)
1519 debiwrite(saa, debNormal,
1520 IBM_MP2_FRNT_ATTEN,
Jiri Slabyf823f672006-01-11 19:41:32 -02001521 (i << 8) | i, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 } else {
1523 if (v.flags & VIDEO_AUDIO_MUTE)
1524 cs4341_setlevel(saa, 0xff, 0xff);
1525 if (!(v.flags & VIDEO_AUDIO_MUTE))
1526 cs4341_setlevel(saa, 0, 0);
1527 if (v.flags & VIDEO_AUDIO_VOLUME)
1528 cs4341_setlevel(saa, i, i);
1529 }
1530 saa->audio_dev = v;
1531 return 0;
1532 }
1533
1534 case VIDIOCGUNIT:
1535 {
1536 struct video_unit vu;
1537 vu.video = saa->video_dev.minor;
1538 vu.vbi = VIDEO_NO_UNIT;
1539 vu.radio = VIDEO_NO_UNIT;
1540 vu.audio = VIDEO_NO_UNIT;
1541 vu.teletext = VIDEO_NO_UNIT;
1542 if (copy_to_user(arg, &vu, sizeof(vu)))
1543 return -EFAULT;
1544 return 0;
1545 }
1546 case VIDIOCSPLAYMODE:
1547 {
1548 struct video_play_mode pmode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001549 if (copy_from_user((void *)&pmode, arg,
1550 sizeof(struct video_play_mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 return -EFAULT;
1552 switch (pmode.mode) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001553 case VID_PLAY_VID_OUT_MODE:
1554 if (pmode.p1 != VIDEO_MODE_NTSC &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 pmode.p1 != VIDEO_MODE_PAL)
Jiri Slabyf823f672006-01-11 19:41:32 -02001556 return -EINVAL;
1557 set_out_format(saa, pmode.p1);
1558 return 0;
1559 case VID_PLAY_GENLOCK:
1560 debiwrite(saa, debNormal, XILINX_CTL0,
1561 pmode.p1 ? 0x8000 : 0x8080, 2);
1562 if (NewCard)
1563 set_genlock_offset(saa, pmode.p2);
1564 return 0;
1565 case VID_PLAY_NORMAL:
1566 debiwrite(saa, debNormal,
1567 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1568 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1569 saa->playmode = pmode.mode;
1570 return 0;
1571 case VID_PLAY_PAUSE:
1572 /* IBM removed the PAUSE command */
1573 /* they say use SINGLE_FRAME now */
1574 case VID_PLAY_SINGLE_FRAME:
1575 ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
1576 if (saa->playmode == pmode.mode) {
1577 debiwrite(saa, debNormal,
1578 IBM_MP2_CHIP_CONTROL,
1579 ChipControl, 2);
1580 }
1581 saa->playmode = pmode.mode;
1582 return 0;
1583 case VID_PLAY_FAST_FORWARD:
1584 ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
1585 saa->playmode = pmode.mode;
1586 return 0;
1587 case VID_PLAY_SLOW_MOTION:
1588 ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
1589 pmode.p1, 0);
1590 saa->playmode = pmode.mode;
1591 return 0;
1592 case VID_PLAY_IMMEDIATE_NORMAL:
1593 /* ensure transfers resume */
1594 debiwrite(saa, debNormal,
1595 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1596 ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
1597 0, 0);
1598 saa->playmode = VID_PLAY_NORMAL;
1599 return 0;
1600 case VID_PLAY_SWITCH_CHANNELS:
1601 saa->audhead = saa->audtail = 0;
1602 saa->vidhead = saa->vidtail = 0;
1603 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
1604 ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
1605 0, 1);
1606 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1607 0, 2);
1608 ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
1609 0, 1);
1610 debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
1611 ChipControl, 2);
1612 ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
1613 saa->playmode = VID_PLAY_NORMAL;
1614 return 0;
1615 case VID_PLAY_FREEZE_FRAME:
1616 ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
1617 saa->playmode = pmode.mode;
1618 return 0;
1619 case VID_PLAY_STILL_MODE:
1620 ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
1621 0, 0);
1622 saa->playmode = pmode.mode;
1623 return 0;
1624 case VID_PLAY_MASTER_MODE:
1625 if (pmode.p1 == VID_PLAY_MASTER_NONE)
1626 saa->boardcfg[1] = 0x13;
1627 else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
1628 saa->boardcfg[1] = 0x23;
1629 else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
1630 saa->boardcfg[1] = 0x43;
1631 else
1632 return -EINVAL;
1633 debiwrite(saa, debNormal,
1634 IBM_MP2_CHIP_CONTROL, ChipControl, 2);
1635 return 0;
1636 case VID_PLAY_ACTIVE_SCANLINES:
1637 if (CurrentMode == VIDEO_MODE_PAL) {
1638 if (pmode.p1 < 1 || pmode.p2 > 625)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001640 saa->boardcfg[5] = pmode.p1;
1641 saa->boardcfg[55] = (pmode.p1 +
1642 (pmode.p2 / 2) - 1) & 0xff;
1643 } else {
1644 if (pmode.p1 < 4 || pmode.p2 > 525)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 return -EINVAL;
Jiri Slabyf823f672006-01-11 19:41:32 -02001646 saa->boardcfg[4] = pmode.p1;
1647 saa->boardcfg[54] = (pmode.p1 +
1648 (pmode.p2 / 2) - 4) & 0xff;
1649 }
1650 set_out_format(saa, CurrentMode);
1651 case VID_PLAY_RESET:
1652 return do_ibm_reset(saa);
1653 case VID_PLAY_END_MARK:
1654 if (saa->endmarktail < saa->endmarkhead) {
1655 if (saa->endmarkhead -
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 saa->endmarktail < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return -ENOSPC;
Jiri Slabyf823f672006-01-11 19:41:32 -02001658 } else if (saa->endmarkhead <=saa->endmarktail){
1659 if (saa->endmarktail - saa->endmarkhead
1660 > (MAX_MARKS - 2))
1661 return -ENOSPC;
1662 } else
1663 return -ENOSPC;
1664 saa->endmark[saa->endmarktail] = saa->audtail;
1665 saa->endmarktail++;
1666 if (saa->endmarktail >= MAX_MARKS)
1667 saa->endmarktail = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
1669 return -EINVAL;
1670 }
1671 case VIDIOCSWRITEMODE:
1672 {
1673 int mode;
Jiri Slabyf823f672006-01-11 19:41:32 -02001674 if (copy_from_user((void *)&mode, arg, sizeof(int)))
1675 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 if (mode == VID_WRITE_MPEG_AUD ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001677 mode == VID_WRITE_MPEG_VID ||
1678 mode == VID_WRITE_CC ||
1679 mode == VID_WRITE_TTX ||
1680 mode == VID_WRITE_OSD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 saa->writemode = mode;
1682 return 0;
1683 }
1684 return -EINVAL;
1685 }
1686 case VIDIOCSMICROCODE:
1687 {
1688 struct video_code ucode;
1689 __u8 *udata;
1690 int i;
1691 if (copy_from_user(&ucode, arg, sizeof(ucode)))
1692 return -EFAULT;
1693 if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
Jiri Slabyf823f672006-01-11 19:41:32 -02001694 strncmp(ucode.loadwhat, "dec", 3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 return -EINVAL;
1696 if ((udata = vmalloc(ucode.datasize)) == NULL)
1697 return -ENOMEM;
1698 if (copy_from_user(udata, ucode.data, ucode.datasize)) {
1699 vfree(udata);
1700 return -EFAULT;
1701 }
1702 ucode.data = udata;
Jiri Slabyf823f672006-01-11 19:41:32 -02001703 if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
1704 !strncmp(ucode.loadwhat, "decoder.vid", 11))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 i = initialize_ibmmpeg2(&ucode);
1706 else
1707 i = initialize_fpga(&ucode);
1708 vfree(udata);
1709 if (i)
1710 return -EINVAL;
1711 return 0;
1712
1713 }
1714 case VIDIOCGCHAN: /* this makes xawtv happy */
1715 {
1716 struct video_channel v;
1717 if (copy_from_user(&v, arg, sizeof(v)))
1718 return -EFAULT;
1719 v.flags = VIDEO_VC_AUDIO;
1720 v.tuners = 0;
1721 v.type = VID_TYPE_MPEG_DECODER;
1722 v.norm = CurrentMode;
1723 strcpy(v.name, "MPEG2");
1724 if (copy_to_user(arg, &v, sizeof(v)))
1725 return -EFAULT;
1726 return 0;
1727 }
1728 case VIDIOCSCHAN: /* this makes xawtv happy */
1729 {
1730 struct video_channel v;
1731 if (copy_from_user(&v, arg, sizeof(v)))
1732 return -EFAULT;
1733 /* do nothing */
1734 return 0;
1735 }
1736 default:
1737 return -ENOIOCTLCMD;
1738 }
1739 return 0;
1740}
1741
1742static int saa_mmap(struct file *file, struct vm_area_struct *vma)
1743{
1744 struct saa7146 *saa = file->private_data;
1745 printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
1746 return -EINVAL;
1747}
1748
Jiri Slabyf823f672006-01-11 19:41:32 -02001749static ssize_t saa_read(struct file *file, char __user * buf,
1750 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751{
1752 return -EINVAL;
1753}
1754
Jiri Slabyf823f672006-01-11 19:41:32 -02001755static ssize_t saa_write(struct file *file, const char __user * buf,
1756 size_t count, loff_t * ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
1758 struct saa7146 *saa = file->private_data;
1759 unsigned long todo = count;
1760 int blocksize, split;
1761 unsigned long flags;
1762
1763 while (todo > 0) {
1764 if (saa->writemode == VID_WRITE_MPEG_AUD) {
1765 spin_lock_irqsave(&saa->lock, flags);
1766 if (saa->audhead <= saa->audtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001767 blocksize = 65536 -
1768 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 else
1770 blocksize = saa->audhead - saa->audtail;
1771 spin_unlock_irqrestore(&saa->lock, flags);
1772 if (blocksize < 16384) {
1773 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001774 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1776 /* wait for buffer space to open */
1777 interruptible_sleep_on(&saa->audq);
1778 }
1779 spin_lock_irqsave(&saa->lock, flags);
1780 if (saa->audhead <= saa->audtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001781 blocksize = 65536 -
1782 (saa->audtail - saa->audhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 split = 65536 - saa->audtail;
1784 } else {
1785 blocksize = saa->audhead - saa->audtail;
1786 split = 65536;
1787 }
1788 spin_unlock_irqrestore(&saa->lock, flags);
1789 blocksize--;
1790 if (blocksize > todo)
1791 blocksize = todo;
1792 /* double check that we really have space */
1793 if (!blocksize)
1794 return -ENOSPC;
1795 if (split < blocksize) {
1796 if (copy_from_user(saa->audbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001797 saa->audtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 return -EFAULT;
1799 buf += split;
1800 todo -= split;
1801 blocksize -= split;
1802 saa->audtail = 0;
1803 }
1804 if (copy_from_user(saa->audbuf + saa->audtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001805 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 return -EFAULT;
1807 saa->audtail += blocksize;
1808 todo -= blocksize;
1809 buf += blocksize;
1810 saa->audtail &= 0xffff;
1811 } else if (saa->writemode == VID_WRITE_MPEG_VID) {
1812 spin_lock_irqsave(&saa->lock, flags);
1813 if (saa->vidhead <= saa->vidtail)
Jiri Slabyf823f672006-01-11 19:41:32 -02001814 blocksize = 524288 -
1815 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 else
1817 blocksize = saa->vidhead - saa->vidtail;
1818 spin_unlock_irqrestore(&saa->lock, flags);
1819 if (blocksize < 65536) {
1820 saawrite(SAA7146_PSR_DEBI_S |
Jiri Slabyf823f672006-01-11 19:41:32 -02001821 SAA7146_PSR_PIN1, SAA7146_IER);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1823 /* wait for buffer space to open */
1824 interruptible_sleep_on(&saa->vidq);
1825 }
1826 spin_lock_irqsave(&saa->lock, flags);
1827 if (saa->vidhead <= saa->vidtail) {
Jiri Slabyf823f672006-01-11 19:41:32 -02001828 blocksize = 524288 -
1829 (saa->vidtail - saa->vidhead);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 split = 524288 - saa->vidtail;
1831 } else {
1832 blocksize = saa->vidhead - saa->vidtail;
1833 split = 524288;
1834 }
1835 spin_unlock_irqrestore(&saa->lock, flags);
1836 blocksize--;
1837 if (blocksize > todo)
1838 blocksize = todo;
1839 /* double check that we really have space */
1840 if (!blocksize)
1841 return -ENOSPC;
1842 if (split < blocksize) {
1843 if (copy_from_user(saa->vidbuf +
Jiri Slabyf823f672006-01-11 19:41:32 -02001844 saa->vidtail, buf, split))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 return -EFAULT;
1846 buf += split;
1847 todo -= split;
1848 blocksize -= split;
1849 saa->vidtail = 0;
1850 }
1851 if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
Jiri Slabyf823f672006-01-11 19:41:32 -02001852 blocksize))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 return -EFAULT;
1854 saa->vidtail += blocksize;
1855 todo -= blocksize;
1856 buf += blocksize;
1857 saa->vidtail &= 0x7ffff;
1858 } else if (saa->writemode == VID_WRITE_OSD) {
1859 if (count > 131072)
1860 return -ENOSPC;
1861 if (copy_from_user(saa->osdbuf, buf, count))
1862 return -EFAULT;
1863 buf += count;
1864 saa->osdhead = 0;
1865 saa->osdtail = count;
1866 debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
1867 debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
1868 debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
1869 debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
Jiri Slabyf823f672006-01-11 19:41:32 -02001870 debiread(saa, debNormal,
1871 IBM_MP2_DISP_MODE, 2) | 1, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 /* trigger osd data transfer */
1873 saawrite(SAA7146_PSR_DEBI_S |
1874 SAA7146_PSR_PIN1, SAA7146_IER);
1875 saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
1876 }
1877 }
1878 return count;
1879}
1880
Hans Verkuilbec43662008-12-30 06:58:20 -03001881static int saa_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001883 struct video_device *vdev = video_devdata(file);
1884 struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
Hans Verkuild56dc612008-07-30 08:43:36 -03001886 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 file->private_data = saa;
1888
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 saa->user++;
Hans Verkuild56dc612008-07-30 08:43:36 -03001890 if (saa->user > 1) {
1891 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return 0; /* device open already, don't reset */
Hans Verkuild56dc612008-07-30 08:43:36 -03001893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 saa->writemode = VID_WRITE_MPEG_VID; /* default to video */
Hans Verkuild56dc612008-07-30 08:43:36 -03001895 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return 0;
1897}
1898
Hans Verkuilbec43662008-12-30 06:58:20 -03001899static int saa_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
1901 struct saa7146 *saa = file->private_data;
1902 saa->user--;
Jiri Slaby91fb8352006-01-11 19:41:21 -02001903
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 if (saa->user > 0) /* still someone using device */
1905 return 0;
1906 saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
1907 return 0;
1908}
1909
Hans Verkuilbec43662008-12-30 06:58:20 -03001910static const struct v4l2_file_operations saa_fops = {
Jiri Slabyf823f672006-01-11 19:41:32 -02001911 .owner = THIS_MODULE,
1912 .open = saa_open,
1913 .release = saa_release,
1914 .ioctl = saa_ioctl,
Jiri Slabyf823f672006-01-11 19:41:32 -02001915 .read = saa_read,
Jiri Slabyf823f672006-01-11 19:41:32 -02001916 .write = saa_write,
1917 .mmap = saa_mmap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918};
1919
1920/* template for video_device-structure */
Jiri Slabyf823f672006-01-11 19:41:32 -02001921static struct video_device saa_template = {
1922 .name = "SAA7146A",
Jiri Slabyf823f672006-01-11 19:41:32 -02001923 .fops = &saa_fops,
1924 .minor = -1,
Hans Verkuilaa5e90a2008-08-23 06:23:55 -03001925 .release = video_device_release_empty,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926};
1927
Jiri Slaby9ae82292006-01-11 19:41:13 -02001928static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
Jiri Slaby91fb8352006-01-11 19:41:21 -02001930 int retval;
1931 struct saa7146 *saa = pci_get_drvdata(pdev);
Jiri Slabyf823f672006-01-11 19:41:32 -02001932
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 saa->endmarkhead = saa->endmarktail = 0;
1934 saa->win.x = saa->win.y = 0;
1935 saa->win.width = saa->win.cropwidth = 720;
1936 saa->win.height = saa->win.cropheight = 480;
1937 saa->win.cropx = saa->win.cropy = 0;
1938 saa->win.bpp = 2;
1939 saa->win.depth = 16;
1940 saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
1941 saa->win.bpl = 1024 * saa->win.bpp;
1942 saa->win.swidth = 1024;
1943 saa->win.sheight = 768;
1944 saa->picture.brightness = 32768;
1945 saa->picture.contrast = 38768;
1946 saa->picture.colour = 32768;
1947 saa->cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 saa->nr = num;
1949 saa->playmode = VID_PLAY_NORMAL;
1950 memset(saa->boardcfg, 0, 64); /* clear board config area */
1951 saa->saa7146_mem = NULL;
1952 saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
1953 saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
1954 saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
1955 saa->pagea1out = saa->pagea2in = saa->pagea2out =
1956 saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
1957 saa->pageRPS2 = NULL;
1958 saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
1959 saa->audhead = saa->vidtail = 0;
1960
1961 init_waitqueue_head(&saa->i2cq);
1962 init_waitqueue_head(&saa->audq);
1963 init_waitqueue_head(&saa->debiq);
1964 init_waitqueue_head(&saa->vidq);
1965 spin_lock_init(&saa->lock);
1966
Jiri Slaby91fb8352006-01-11 19:41:21 -02001967 retval = pci_enable_device(pdev);
1968 if (retval) {
1969 dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
1970 goto err;
1971 }
Jiri Slabyf823f672006-01-11 19:41:32 -02001972
Jiri Slaby9ae82292006-01-11 19:41:13 -02001973 saa->id = pdev->device;
1974 saa->irq = pdev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 saa->video_dev.minor = -1;
Jiri Slaby9ae82292006-01-11 19:41:13 -02001976 saa->saa7146_adr = pci_resource_start(pdev, 0);
1977 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
1979 saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001980 if (saa->saa7146_mem == NULL) {
1981 dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
1982 retval = -EIO;
1983 goto err;
1984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
1987 saawrite(0, SAA7146_IER); /* turn off all interrupts */
Jiri Slaby91fb8352006-01-11 19:41:21 -02001988
Thomas Gleixner8076fe32006-07-01 19:29:37 -07001989 retval = request_irq(saa->irq, saa7146_irq, IRQF_SHARED | IRQF_DISABLED,
Jiri Slaby91fb8352006-01-11 19:41:21 -02001990 "stradis", saa);
1991 if (retval == -EINVAL)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001992 dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001993 else if (retval == -EBUSY)
Jiri Slaby9ae82292006-01-11 19:41:13 -02001994 dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
1995 "in BIOS\n", num, saa->irq);
Jiri Slaby91fb8352006-01-11 19:41:21 -02001996 if (retval < 0)
1997 goto errio;
1998
Jiri Slaby9ae82292006-01-11 19:41:13 -02001999 pci_set_master(pdev);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002000 retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
2001 video_nr);
Jiri Slabyf823f672006-01-11 19:41:32 -02002002 if (retval < 0) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002003 dev_err(&pdev->dev, "%d: error in registering video device!\n",
2004 num);
2005 goto errio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002007
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 return 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002009errio:
2010 iounmap(saa->saa7146_mem);
2011err:
2012 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013}
2014
Jiri Slaby91fb8352006-01-11 19:41:21 -02002015static int __devinit init_saa7146(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
Jiri Slaby91fb8352006-01-11 19:41:21 -02002017 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
2019 saa->user = 0;
2020 /* reset the saa7146 */
2021 saawrite(0xffff0000, SAA7146_MC1);
2022 mdelay(5);
2023 /* enable debi and i2c transfers and pins */
2024 saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C |
2025 SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1);
2026 /* ensure proper state of chip */
2027 saawrite(0x00000000, SAA7146_PAGE1);
2028 saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1);
2029 saawrite(0x00000000, SAA7146_PAGE2);
2030 saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2);
2031 saawrite(0x00000000, SAA7146_DD1_INIT);
2032 saawrite(0x00000000, SAA7146_DD1_STREAM_B);
2033 saawrite(0x00000000, SAA7146_DD1_STREAM_A);
2034 saawrite(0x00000000, SAA7146_BRS_CTRL);
2035 saawrite(0x80400040, SAA7146_BCS_CTRL);
Jiri Slabyf823f672006-01-11 19:41:32 -02002036 saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
2038 saawrite(0x00000000, SAA7146_ACON1);
2039 saawrite(0x00000000, SAA7146_ACON2);
2040 saawrite(0x00000600, SAA7146_I2C_STATUS);
2041 saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
Jiri Slabyf823f672006-01-11 19:41:32 -02002042 SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
2043 SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
2044 SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
2045 SAA7146_MC2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 /* setup arbitration control registers */
2047 saawrite(0x1412121a, SAA7146_PCI_BT_V1);
2048
2049 /* allocate 32k dma buffer + 4k for page table */
2050 if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
Jiri Slaby91fb8352006-01-11 19:41:21 -02002051 dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
2052 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 }
2054#if 0
2055 saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */
2056 saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE);
2057 for (i = 0; i < 12; i++) /* setup mmu page table */
2058 saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));
2059#endif
2060 saa->audhead = saa->vidhead = saa->osdhead = 0;
2061 saa->audtail = saa->vidtail = saa->osdtail = 0;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002062 if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
2063 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
2064 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 }
Jiri Slaby91fb8352006-01-11 19:41:21 -02002066 if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
2067 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002068 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002069 }
2070 if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
2071 dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002072 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002073 }
2074 /* allocate 81920 byte buffer for clipping */
2075 if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
2076 dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
Jiri Slaby805f1232006-01-24 13:15:06 -08002077 goto errfree;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 /* setup clipping registers */
2080 saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
2081 saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
2082 saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
Jiri Slabyf823f672006-01-11 19:41:32 -02002083 SAA7146_PROT_ADDR2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 saawrite(256, SAA7146_PITCH2);
Jiri Slabyf823f672006-01-11 19:41:32 -02002085 saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
2087 SAA7146_MC2);
2088 I2CBusScan(saa);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002089
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 return 0;
Jiri Slaby805f1232006-01-24 13:15:06 -08002091errfree:
Jiri Slaby91fb8352006-01-11 19:41:21 -02002092 vfree(saa->osdbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002093 vfree(saa->audbuf);
Jiri Slaby91fb8352006-01-11 19:41:21 -02002094 vfree(saa->vidbuf);
Jiri Slaby805f1232006-01-24 13:15:06 -08002095 saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002096err:
2097 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098}
2099
Jiri Slaby9ae82292006-01-11 19:41:13 -02002100static void stradis_release_saa(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101{
2102 u8 command;
Jiri Slaby91fb8352006-01-11 19:41:21 -02002103 struct saa7146 *saa = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Jiri Slaby9ae82292006-01-11 19:41:13 -02002105 /* turn off all capturing, DMA and IRQs */
2106 saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
2107 saawrite(0, SAA7146_MC2);
2108 saawrite(0, SAA7146_IER);
2109 saawrite(0xffffffffUL, SAA7146_ISR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
Jiri Slaby9ae82292006-01-11 19:41:13 -02002111 /* disable PCI bus-mastering */
2112 pci_read_config_byte(pdev, PCI_COMMAND, &command);
2113 command &= ~PCI_COMMAND_MASTER;
2114 pci_write_config_byte(pdev, PCI_COMMAND, command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Jiri Slaby9ae82292006-01-11 19:41:13 -02002116 /* unmap and free memory */
2117 saa->audhead = saa->audtail = saa->osdhead = 0;
2118 saa->vidhead = saa->vidtail = saa->osdtail = 0;
2119 vfree(saa->vidbuf);
2120 vfree(saa->audbuf);
2121 vfree(saa->osdbuf);
2122 kfree(saa->dmavid2);
2123 saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
2124 saa->dmavid2 = NULL;
2125 kfree(saa->dmadebi);
2126 kfree(saa->dmavid1);
2127 kfree(saa->dmavid3);
2128 kfree(saa->dmaa1in);
2129 kfree(saa->dmaa1out);
2130 kfree(saa->dmaa2in);
2131 kfree(saa->dmaa2out);
2132 kfree(saa->dmaRPS1);
2133 kfree(saa->dmaRPS2);
2134 free_irq(saa->irq, saa);
2135 if (saa->saa7146_mem)
2136 iounmap(saa->saa7146_mem);
2137 if (saa->video_dev.minor != -1)
2138 video_unregister_device(&saa->video_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139}
2140
Jiri Slaby9ae82292006-01-11 19:41:13 -02002141static int __devinit stradis_probe(struct pci_dev *pdev,
2142 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002144 int retval = -EINVAL;
2145
2146 if (saa_num >= SAA7146_MAX)
2147 goto err;
2148
2149 if (!pdev->subsystem_vendor)
2150 dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
2151 else
2152 dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
2153
Jiri Slaby91fb8352006-01-11 19:41:21 -02002154 pci_set_drvdata(pdev, &saa7146s[saa_num]);
Jiri Slaby9ae82292006-01-11 19:41:13 -02002155
2156 retval = configure_saa7146(pdev, saa_num);
2157 if (retval) {
2158 dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
2159 goto err;
2160 }
2161
Jiri Slaby91fb8352006-01-11 19:41:21 -02002162 if (init_saa7146(pdev) < 0) {
Jiri Slaby9ae82292006-01-11 19:41:13 -02002163 dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
2164 retval = -EIO;
2165 goto errrel;
2166 }
2167
2168 saa_num++;
2169
2170 return 0;
2171errrel:
2172 stradis_release_saa(pdev);
2173err:
2174 return retval;
2175}
2176
2177static void __devexit stradis_remove(struct pci_dev *pdev)
2178{
2179 stradis_release_saa(pdev);
2180}
2181
2182static struct pci_device_id stradis_pci_tbl[] = {
2183 { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
2184 { 0 }
2185};
Jiri Slabyf823f672006-01-11 19:41:32 -02002186
Jiri Slaby9ae82292006-01-11 19:41:13 -02002187
2188static struct pci_driver stradis_driver = {
Jiri Slabyf823f672006-01-11 19:41:32 -02002189 .name = "stradis",
2190 .id_table = stradis_pci_tbl,
2191 .probe = stradis_probe,
2192 .remove = __devexit_p(stradis_remove)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002193};
2194
Adrian Bunkb9553d72006-06-26 22:40:20 -03002195static int __init stradis_init(void)
Jiri Slaby9ae82292006-01-11 19:41:13 -02002196{
2197 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
2199 saa_num = 0;
2200
Jiri Slaby9ae82292006-01-11 19:41:13 -02002201 retval = pci_register_driver(&stradis_driver);
2202 if (retval)
2203 printk(KERN_ERR "stradis: Unable to register pci driver.\n");
2204
2205 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206}
2207
Adrian Bunkb9553d72006-06-26 22:40:20 -03002208static void __exit stradis_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
Jiri Slaby9ae82292006-01-11 19:41:13 -02002210 pci_unregister_driver(&stradis_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 printk(KERN_INFO "stradis: module cleanup complete\n");
2212}
2213
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214module_init(stradis_init);
2215module_exit(stradis_exit);