📄 stradis.c
字号:
/* * stradis.c - stradis 4:2:2 mpeg decoder driver * * Stradis 4:2:2 MPEG-2 Decoder Driver * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/module.h>#include <linux/version.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/pci.h>#include <linux/signal.h>#include <asm/io.h>#include <linux/ioport.h>#include <asm/pgtable.h>#include <asm/page.h>#include <linux/sched.h>#include <asm/segment.h>#include <asm/types.h>#include <linux/types.h>#include <linux/wrapper.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <linux/vmalloc.h>#include <linux/videodev.h>#include <linux/i2c-old.h>#include "saa7146.h"#include "saa7146reg.h"#include "ibmmpeg2.h"#include "saa7121.h"#include "cs8420.h"#define DEBUG(x) /* debug driver */#undef IDEBUG /* debug irq handler */#undef MDEBUG /* debug memory management */#define SAA7146_MAX 6static struct saa7146 saa7146s[SAA7146_MAX];static int saa_num = 0; /* number of SAA7146s in use */static int video_nr = -1;MODULE_PARM(video_nr,"i");MODULE_LICENSE("GPL");#define nDebNormal 0x00480000#define nDebNoInc 0x00480000#define nDebVideo 0xd0480000#define nDebAudio 0xd0400000#define nDebDMA 0x02c80000#define oDebNormal 0x13c80000#define oDebNoInc 0x13c80000#define oDebVideo 0xd1080000#define oDebAudio 0xd1080000#define oDebDMA 0x03080000#define NewCard (saa->boardcfg[3])#define ChipControl (saa->boardcfg[1])#define NTSCFirstActive (saa->boardcfg[4])#define PALFirstActive (saa->boardcfg[5])#define NTSCLastActive (saa->boardcfg[54])#define PALLastActive (saa->boardcfg[55])#define Have2MB (saa->boardcfg[18] & 0x40)#define HaveCS8420 (saa->boardcfg[18] & 0x04)#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20)#define HaveCS3310 (saa->boardcfg[18] & 0x01)#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31])#define HaveCS4341 (saa->boardcfg[40] == 2)#define SDIType (saa->boardcfg[27])#define CurrentMode (saa->boardcfg[2])#define debNormal (NewCard ? nDebNormal : oDebNormal)#define debNoInc (NewCard ? nDebNoInc : oDebNoInc)#define debVideo (NewCard ? nDebVideo : oDebVideo)#define debAudio (NewCard ? nDebAudio : oDebAudio)#define debDMA (NewCard ? nDebDMA : oDebDMA)#ifdef DEBUGint stradis_driver(void) /* for the benefit of ksymoops */{ return 1;}#endif#ifdef USE_RESCUE_EEPROM_SDM275static unsigned char rescue_eeprom[64] = {0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};#endif/* ----------------------------------------------------------------------- *//* Hardware I2C functions */static void I2CWipe(struct saa7146 *saa){ int i; /* set i2c to ~=100kHz, abort transfer, clear busy */ saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); /* wait for i2c registers to be programmed */ for (i = 0; i < 1000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) schedule(); saawrite(0x600, SAA7146_I2C_STATUS); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); /* wait for i2c registers to be programmed */ for (i = 0; i < 1000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) schedule(); saawrite(0x600, SAA7146_I2C_STATUS); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); /* wait for i2c registers to be programmed */ for (i = 0; i < 1000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) schedule();}/* read I2C */static int I2CRead(struct i2c_bus *bus, unsigned char addr, unsigned char subaddr, int dosub){ struct saa7146 *saa = (struct saa7146 *) bus->data; int i; if (saaread(SAA7146_I2C_STATUS) & 0x3c) I2CWipe(saa); for (i = 0; i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) schedule(); if (i == 1000) I2CWipe(saa); if (dosub) saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) | ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER); else saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | 0xf1, SAA7146_I2C_TRANSFER); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); /* wait for i2c registers to be programmed */ for (i = 0; i < 1000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) schedule(); /* wait for valid data */ for (i = 0; i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) schedule(); if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) return -1; if (i == 1000) printk("i2c setup read timeout\n"); saawrite(0x41, SAA7146_I2C_TRANSFER); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); /* wait for i2c registers to be programmed */ for (i = 0; i < 1000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) schedule(); /* wait for valid data */ for (i = 0; i < 1000 && (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) schedule(); if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) return -1; if (i == 1000) printk("i2c read timeout\n"); return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);}static int I2CReadOld(struct i2c_bus *bus, unsigned char addr){ return I2CRead(bus, addr, 0, 0);}/* set both to write both bytes, reset it to write only b1 */static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, unsigned char b2, int both){ struct saa7146 *saa = (struct saa7146 *) bus->data; int i; u32 data; if (saaread(SAA7146_I2C_STATUS) & 0x3c) I2CWipe(saa); for (i = 0; i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) schedule(); if (i == 1000) I2CWipe(saa); data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); if (both) data |= ((b2 & 0xff) << 8) | 0xe5; else data |= 0xd1; saawrite(data, SAA7146_I2C_TRANSFER); saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, SAA7146_MC2); return 0;}static void attach_inform(struct i2c_bus *bus, int id){ struct saa7146 *saa = (struct saa7146 *) bus->data; int i; DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id)); if (id == 0xa0) { /* we have rev2 or later board, fill in info */ for (i = 0; i < 64; i++) saa->boardcfg[i] = I2CRead(bus, 0xa0, i, 1);#ifdef USE_RESCUE_EEPROM_SDM275 if (saa->boardcfg[0] != 0) { printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr); for (i = 0; i < 64; i++) saa->boardcfg[i] = rescue_eeprom[i]; }#endif printk("stradis%d: config =", saa->nr); for (i = 0; i < 51; i++) { printk(" %02x",saa->boardcfg[i]); } printk("\n"); }}static void detach_inform(struct i2c_bus *bus, int id){ struct saa7146 *saa = (struct saa7146 *) bus->data; int i; i = saa->nr;}static void I2CBusScan(struct i2c_bus *bus){ int i; for (i = 0; i < 0xff; i += 2) if ((I2CRead(bus, i, 0, 0)) >= 0) attach_inform(bus, i);}static struct i2c_bus saa7146_i2c_bus_template ={ "saa7146", I2C_BUSID_BT848, NULL, SPIN_LOCK_UNLOCKED, attach_inform, detach_inform, NULL, NULL, I2CReadOld, I2CWrite,};static int debiwait_maxwait = 0;static int wait_for_debi_done(struct saa7146 *saa){ int i; /* wait for registers to be programmed */ for (i = 0; i < 100000 && !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) saaread(SAA7146_MC2); /* wait for transfer to complete */ for (i = 0; i < 500000 && (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++) saaread(SAA7146_MC2); if (i > debiwait_maxwait) printk("wait-for-debi-done maxwait: %d\n", debiwait_maxwait = i); if (i == 500000) return -1; return 0;}static int debiwrite(struct saa7146 *saa, u32 config, int addr, u32 val, int count){ u32 cmd; if (count <= 0 || count > 32764) return -1; if (wait_for_debi_done(saa) < 0) return -1; saawrite(config, SAA7146_DEBI_CONFIG); if (count <= 4) /* immediate transfer */ saawrite(val, SAA7146_DEBI_AD); else /* block transfer */ saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, SAA7146_MC2); return 0;}static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count){ u32 result = 0; if (count > 32764 || count <= 0) return 0; if (wait_for_debi_done(saa) < 0) return 0; saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); saawrite((count << 17) | 0x10000 | (addr & 0xffff), SAA7146_DEBI_COMMAND); saawrite(config, SAA7146_DEBI_CONFIG); saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, SAA7146_MC2); if (count > 4) /* not an immediate transfer */ return count; wait_for_debi_done(saa); result = saaread(SAA7146_DEBI_AD); if (count == 1) result &= 0xff; if (count == 2) result &= 0xffff; if (count == 3) result &= 0xffffff; return result;}#if 0 /* unused *//* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes *//* data copied into saa->dmadebi buffer, caller must re-enable interrupts */static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes){ int i, j; u32 *buf; buf = (u32 *) saa->dmadebi; if (bytes > 0x7000) bytes = 0x7000; saawrite(0, SAA7146_IER); /* disable interrupts */ for (i=0; i < 10000 && (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) & 0x8000); i++) saaread(SAA7146_MC2); if (i == 10000) printk(KERN_ERR "stradis%d: dram_busy never cleared\n", saa->nr); debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) | (address>>16), 4); debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2); debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2); for (j = 0; j < bytes/4; j++) { for (i = 0; i < 10000 && (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) & 0x4000)); i++) saaread(SAA7146_MC2); if (i == 10000) printk(KERN_ERR "stradis%d: dram_ready never set\n", saa->nr); buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4); }}#endif /* unused */static void do_irq_send_data(struct saa7146 *saa){ int split, audbytes, vidbytes; saawrite(SAA7146_PSR_PIN1, SAA7146_IER); /* if special feature mode in effect, disable audio sending */ if (saa->playmode != VID_PLAY_NORMAL) saa->audtail = saa->audhead = 0; if (saa->audhead <= saa->audtail) audbytes = saa->audtail - saa->audhead; else audbytes = 65536 - (saa->audhead - saa->audtail); if (saa->vidhead <= saa->vidtail) vidbytes = saa->vidtail - saa->vidhead; else vidbytes = 524288 - (saa->vidhead - saa->vidtail); if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { saawrite(0, SAA7146_IER); return; } /* if at least 1 block audio waiting and audio fifo isn't full */ if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) { if (saa->audhead > saa->audtail) split = 65536 - saa->audhead; else split = 0; audbytes = 2048; if (split > 0 && split < 2048) { memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split); saa->audhead = 0; audbytes -= split; } else split = 0; memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, audbytes); saa->audhead += audbytes; saa->audhead &= 0xffff; debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO : IBM_MP2_AUD_FIFOW), 0, 2048); wake_up_interruptible(&saa->audq); /* if at least 1 block video waiting and video fifo isn't full */ } else if (vidbytes >= 30720 && (debiread(saa, debNormal, IBM_MP2_FIFO, 2)) < 16384) { if (saa->vidhead > saa->vidtail) split = 524288 - saa->vidhead; else split = 0; vidbytes = 30720; if (split > 0 && split < 30720) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -