⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 av7110.c

📁 linux TV 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * av7110.c: driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB) *           and Nova/Budget DVB cards  * * Copyright (C) 1999-2002 Ralph  Metzler  *                       & Marcus Metzler for convergence integrated media GmbH * * originally based on code by: * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html *  * * the project's page is at http://www.linuxtv.org/dvb/ */#define NEW_CI 1/* for debuggin ARM communication: *///#define COM_DEBUG#define __KERNEL_SYSCALLS__#include <linux/module.h>#include <linux/init.h>#include <linux/kmod.h>#include <linux/delay.h>#include <linux/fs.h>#include <linux/timer.h>#include <linux/unistd.h>#include <linux/byteorder/swabb.h>#include <linux/poll.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <stdarg.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/pci.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/semaphore.h>#include <linux/init.h>#include <linux/vmalloc.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/dvb/frontend.h>#include "dvb_i2c.h"#include "dvb_frontend.h"#include "compat.h"#include "av7110.h"#include "saa7146_core.h"#include "saa7146_v4l.h"#include "saa7146_defs.h"#include "ttpci_eeprom.h"static int AV_StartPlay(av7110_t *av7110, int av);static void restart_feeds(av7110_t *av7110);static int bootarm(av7110_t *av7110);static inline int i2c_writereg(av7110_t *av7110, u8 id, u8 reg, u8 val);static inline u8 i2c_readreg(av7110_t *av7110, u8 id, u8 reg);static int  outcom(av7110_t *av7110, int type, int com, int num, ...);static void SetMode(av7110_t *av7110, int mode);static void dvb_video_add_event (av7110_t *av7110, struct video_event *event);void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p);void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed);static u32 vidmem	= 0;static u32 vidlow	= 0;static int av7110_debug = 0;#define dprintk(a...)	do { if (av7110_debug) printk(a); } while (0)static int vidmode=CVBS_RGB_OUT;static int pids_off;static int adac=DVB_ADAC_TI;/** *  crc32 is not implemented in the av7110 firmware, section filter checksum *  checks work  for hw_sections=0! */static int hw_sections = 0;#define saacomm(x,y) av7110->saa->command(av7110->saa->i2c_bus, (x), (y))#define FW_CI_LL_SUPPORT(arm_app) (arm_app & 0x80000000)#define FW_VERSION(arm_app)       (arm_app & 0x0000FFFF)/**************************************************************************** * General helper functions ****************************************************************************/static inline void ddelay(int i) {        current->state=TASK_INTERRUPTIBLE;        schedule_timeout((HZ*i)/100);}static inline intmsp_writereg(av7110_t *av7110, u8 dev, u16 reg, u16 val){        u8 msg[5]={ dev, reg>>8, reg&0xff, val>>8 , val&0xff };         struct dvb_i2c_bus *i2c = av7110->saa->i2c_bus;        struct i2c_msg msgs;        msgs.flags=0;        msgs.addr=0x40;        msgs.len=5;        msgs.buf=msg;        return i2c->xfer(i2c, &msgs, 1);}/**************************************************************************** * GPIO and DEBI functions ****************************************************************************/#define saaread(adr)            saa7146_read(saamem,(adr))#define saawrite(dat,adr) 	saa7146_write(saamem,(adr),(dat))inline static void setgpio(av7110_t *av7110, int port, u32 data){        void *saamem=av7110->saa_mem;        u32 val;        val=saaread(GPIO_CTRL);        val&=~(0xff << (8*(port)));        val|=(data)<<(8*(port));        saawrite(val, GPIO_CTRL);}/* This DEBI code is based on the Stradis driver    by Nathan Laredo <laredo@gnu.org> */staticint wait_for_debi_done(av7110_t *av7110){        void *saamem=av7110->saa_mem;	int start;	/* wait for registers to be programmed */	start = jiffies;	while (1) {                if (saaread(MC2) & 2)                        break;		if (jiffies-start > HZ/20) {			printk ("%s: timed out while waiting for registers "				"getting programmed\n", __FUNCTION__);			return -ETIMEDOUT;		}	}	/* wait for transfer to complete */	start = jiffies;	while (1) {		if (!(saaread(PSR) & SPCI_DEBI_S))			break;		saaread(MC2);		if (jiffies-start > HZ/4) {			printk ("%s: timed out while waiting for transfer "				"completion\n", __FUNCTION__);			return -ETIMEDOUT;		}	}	return 0;}static int debiwrite(av7110_t *av7110, u32 config,                      int addr, u32 val, int count){        void *saamem=av7110->saa_mem;	u32 cmd;	if (count <= 0 || count > 32764)		return -1;	if (wait_for_debi_done(av7110) < 0)		return -1;	saawrite(config, DEBI_CONFIG);	if (count <= 4)		/* immediate transfer */		saawrite(val, DEBI_AD);	else			/* block transfer */		saawrite(av7110->debi_bus, DEBI_AD);	saawrite((cmd = (count << 17) | (addr & 0xffff)), DEBI_COMMAND);	saawrite((2 << 16) | 2, MC2);	return 0;}static u32 debiread(av7110_t *av7110, u32 config, int addr, int count){        void *saamem=av7110->saa_mem;	u32 result = 0;	if (count > 32764 || count <= 0)		return 0;	if (wait_for_debi_done(av7110) < 0)		return 0;	saawrite(av7110->debi_bus, DEBI_AD);	saawrite((count << 17) | 0x10000 | (addr & 0xffff),		 DEBI_COMMAND);	saawrite(config, DEBI_CONFIG);	saawrite((2 << 16) | 2, MC2);	if (count > 4)			return count;	wait_for_debi_done(av7110);	result = saaread(DEBI_AD);        result &= (0xffffffffUL >> ((4-count)*8));	return result;}/* DEBI during interrupt */static inline void iwdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count){        if (count>4 && val)                memcpy(av7110->debi_virt, (char *) val, count);        debiwrite(av7110, config, addr, val, count);}static inline u32 irdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count){        u32 res;        res=debiread(av7110, config, addr, count);        if (count<=4)                 memcpy(av7110->debi_virt, (char *) &res, count);        return res;}/* DEBI outside interrupts, only for count<=4! */static inline void wdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count){        unsigned long flags;        spin_lock_irqsave(&av7110->debilock, flags);        debiwrite(av7110, config, addr, val, count);        spin_unlock_irqrestore(&av7110->debilock, flags);}static inline u32 rdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count){        unsigned long flags;        u32 res;        spin_lock_irqsave(&av7110->debilock, flags);        res=debiread(av7110, config, addr, count);        spin_unlock_irqrestore(&av7110->debilock, flags);        return res;}static inline char chtrans(char c){        if (c<32 || c>126)                c=0x20;        return c;}/* handle mailbox registers of the dual ported RAM */static inline void ARM_ResetMailBox(av7110_t *av7110){        unsigned long flags;        spin_lock_irqsave(&av7110->debilock, flags);        debiread(av7110, DEBINOSWAP, IRQ_RX, 2);        //printk("dvb: IRQ_RX=%d\n", debiread(av7110, DEBINOSWAP, IRQ_RX, 2));        debiwrite(av7110, DEBINOSWAP, IRQ_RX, 0, 2);        spin_unlock_irqrestore(&av7110->debilock, flags);}static inline void ARM_ClearMailBox(av7110_t *av7110){        iwdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);}static inline void ARM_ClearIrq(av7110_t *av7110){	irdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);}static void reset_arm(av7110_t *av7110){        setgpio(av7110, RESET_LINE, GPIO_OUTLO);        /* Disable DEBI and GPIO irq */        saa7146_write(av7110->saa_mem, IER,                       saa7146_read(av7110->saa_mem, IER) & ~(MASK_19 | MASK_03));        saa7146_write(av7110->saa_mem, ISR, (MASK_19 | MASK_03));        mdelay(800);        setgpio(av7110, RESET_LINE, GPIO_OUTHI);        mdelay(800);        ARM_ResetMailBox(av7110);         saa7146_write(av7110->saa_mem, ISR, (MASK_19 | MASK_03));        saa7146_write(av7110->saa_mem, IER,                       saa7146_read(av7110->saa_mem, IER) | MASK_03 );        av7110->arm_ready=1;        printk("av7110: ARM RESET\n");}static void recover_arm(av7110_t *av7110){        if (current->files)                bootarm(av7110);        else {                printk("OOPS, no current->files\n");                reset_arm(av7110);        }        ddelay(10);         restart_feeds(av7110);        outcom(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);}static void arm_error(av7110_t *av7110){        av7110->arm_errors++;        av7110->arm_ready=0;        recover_arm(av7110);}static int arm_thread(void *data){	av7110_t *av7110 = data;        u16 newloops;    	lock_kernel();#if 1	daemonize();	reparent_to_init ();#else        exit_mm(current);        current->session=current->pgrp=1;#endif	sigfillset(&current->blocked);	strncpy(current->comm, "kdvb-av7110", sizeof(current->comm));	av7110->arm_thread = current;	unlock_kernel();	while (!av7110->arm_rmmod && !signal_pending(current)) {                interruptible_sleep_on_timeout(&av7110->arm_wait, 5*HZ);                if (!av7110->arm_ready)                        continue;                if (down_interruptible(&av7110->dcomlock))                        break;                newloops=rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);                up(&av7110->dcomlock);                if (newloops==av7110->arm_loops) {                        printk(KERN_ERR "av7110%d: ARM crashed!\n",				av7110->saa->dvb_adapter->num);			arm_error(av7110);                        if (down_interruptible(&av7110->dcomlock))                                break;                        newloops=rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2)-1;                        up(&av7110->dcomlock);                }                av7110->arm_loops=newloops;	}	av7110->arm_thread = NULL;	return 0;}static intrecord_cb(dvb_filter_pes2ts_t *p2t, u8 *buf, size_t len)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -