📄 at2041_inf.~c
字号:
/* * Copyright(C) 2004, Pentamicro Inc. All Right Reserved. * * Filename : at2041_inf.c * Description : Linux device driver of AT2041 * * Project : MPEG-4 4-channel SDVR * * Date : Apr., 20. 2004. * Company : Advanced Technology R&D Center * Pentamicro Inc. * * Linux version : */ /** ************************************************************************* ** ** includes ** ************************************************************************* **/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/ioctl.h>#include <linux/major.h>#include <linux/delay.h>#include <asm/errno.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/delay.h>#include "at2041_inf.h"#include "at2042_reg.h"#include <asm/irq.h> /*HJT*/ #include <asm/arch/s3c2410.h> /*HJT*/unsigned short * mux_buf[MAX_BUF_NUM];unsigned short * demux_buf[MAX_BUF_NUM];unsigned short * tx_buf[MAX_TXBUF_NUM];unsigned short * size_buf[MAX_BUF_NUM];unsigned int demux_size_buf[MAX_BUF_NUM];volatile unsigned short enc_txmsg_size = 4;volatile static unsigned short mux_ring_cnt = 0;volatile static unsigned short mux_rd_cnt = 0;volatile static unsigned short mux_wr_cnt = 0; volatile static unsigned short mux_full = 0;volatile static unsigned short demux_ring_cnt = 0;volatile static unsigned short demux_rd_cnt = 0;volatile static unsigned short demux_wr_cnt = 0; volatile static unsigned short txfifo_rd_cnt = 0;volatile static unsigned short txfifo_wr_cnt = 0;volatile static unsigned short txfifo_ring_cnt = 0;static struct semaphore muxfifo_read_sem;static struct semaphore demuxfifo_write_sem;unsigned int * pt;unsigned int ii;/** ************************************************************************* ** ** forward declarations ** ************************************************************************* **/void at2041_ioctl_init() { int count; unsigned short status; unsigned short temp; /* check tx fifo empty */ printk("[at2041_inf]at2041_ioctl_init start\n"); count = 0; do { status = *((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)); printk("Now in checking status register : 0x%x\n", status); count ++; udelay(10); } while ((status & 0x100) && (count < 1000));//printk("[at2041_inf]check status register\n"); if (count == 1000) { printk("ERROR !!!\n"); } else { printk("OK !!!\n");//printk("[at2041_inf]success check status register\n"); /* data read from Tx_FIFO of the AT2041 */ temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));//printk("temp= 0x%x\n", temp); if (temp != 0x8003) { printk("\n!!! the AT2041 Ready Error !!!\n"); return; } else { printk("\n!!! the AT2041 Ready OK !!!\n"); } /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; udelay(100); // execution fo check TxACK command#if 0 status = *((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)); if ((status & 0x0100) == 0x0100) { printk("Complete !!!\n"); } else { printk("Incomplete execution of TxACK command\n"); }#else /* Enable interrupts for EINT0/GPF0 */ /*HJT*/ printk ("__INTERRUPT_AVAILABLE__\n"); /*HJT*/ //(volatile unsigned long) (rINTMSK) &= ~0x00000001; //Intservice MASK ==> AVAILABLE /*HJT*/ (volatile unsigned long) (rINTMSK) &= ~0x00000004; //Intservice MASK ==> AVAILABLE /*HJT*/ #endif }}void pre_enc_config(void) // dec part(1) (set video output){ static unsigned short rx_id; printk("[pre_enc_config] start\n"); rx_id = RxID(GID_DEC_VIDEO, 0x00, PID_OUTPUT_VIDEO_FORMAT, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, rx_id, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, NTSC, 2, ZERO_BYTE_SWAP);#else *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR))=rx_id; *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR))=NTSC;#endif // dec part(2) (ver offset) rx_id = RxID(GID_DEC_VIDEO, 0x00, PID_VER_OFFESET, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)284, 2, ZERO_BYTE_SWAP); // even field DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)21, 2, ZERO_BYTE_SWAP); // odd field#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=284; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=21;#endif // dec part(3) (hor offset) rx_id = RxID(GID_DEC_VIDEO, 0x00, PID_HOR_OFFESET, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)32, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)160, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)1440, 2, ZERO_BYTE_SWAP); // dummy#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=32;// start pos *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=160;// end pos *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=1440;#endif // dec part(6) (ver sync control) rx_id = RxID(GID_DEC_VIDEO, 0x00, PID_VER_SYNC_CONTROL, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)1, 2, ZERO_BYTE_SWAP); // first start line DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)10, 2, ZERO_BYTE_SWAP); // first end line DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)128, 2, ZERO_BYTE_SWAP); // first transition pos DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)263, 2, ZERO_BYTE_SWAP); // second start line DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)272, 2, ZERO_BYTE_SWAP); // second end line DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)855, 2, ZERO_BYTE_SWAP); // second transition pos#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=1; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=10; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=128; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=263; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=272; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=855;#endif // maximum output data size rx_id = RxID(0x01, 0, 0x05, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); //DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)30, 2, ZERO_BYTE_SWAP); // 30KBytes DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)512, 2, ZERO_BYTE_SWAP); // 512KBytes#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; //*((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=30; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=512;#endif // Preprocessing rx_id = RxID(0x04, 0, 0x0A, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); if(preprocess) DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)3, 2, ZERO_BYTE_SWAP); else DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)0, 2, ZERO_BYTE_SWAP);#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; //if(preprocess) *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=3; //else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=0;#endif // Encoding Standard rx_id = RxID(GID_ENC_VIDEO_CHANNEL, 0, 0x03, W_FLAG); printk("[pre_enc_config] rx_id:0x%x\n", rx_id);#if 0 DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)rx_id, 2, ZERO_BYTE_SWAP); DEBI_Write(AT2041_RX_FIFO_ADDR, (DWORD)enc_std[i]+1, 2, ZERO_BYTE_SWAP);#else *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=rx_id; *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR))=4; /*MPEG4*/#endif printk("[pre_enc_config] end\n");}static int at2041_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ unsigned short rx_fifo; unsigned short cmd_reg, status_reg; printk("[at2041_inf]start at2041_ioctl : cmd= %d\n", cmd); switch(cmd) { case READ_Tx_FIFO : put_user(*tx_buf[txfifo_rd_cnt], (unsigned short *) arg); /* txfifo ring buffer control */ if (!txfifo_ring_cnt && txfifo_rd_cnt <= txfifo_wr_cnt) { txfifo_rd_cnt ++; if (txfifo_rd_cnt == MAX_BUF_NUM) { txfifo_ring_cnt --; txfifo_rd_cnt = 0; } } else if (txfifo_ring_cnt) { txfifo_rd_cnt ++; } break; case WRITE_Rx_FIFO : get_user(rx_fifo, (unsigned short *)arg); *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = rx_fifo; printk ("WRITE_Rx_FIFO : 0x%x\n", rx_fifo); break; case WRITE_COMMAND_REG : get_user(cmd_reg, (unsigned short *)arg); *((unsigned short *)((unsigned int)pt + AT2041_COMMAND_REG_ADDR)) = cmd_reg; printk ("WRITE_Rx_FIFO : 0x%x\n", cmd_reg); break; // case WRITE_CONTROL_REG :// get_user(ctrl_reg, (unsigned short *)arg);// *((unsigned short *)((unsigned int)pt + 0x00002800)) = ctrl_reg;// break; case READ_STATUS_REG : status_reg = *((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)); put_user(status_reg, (unsigned short *) arg); break; case AT2041_INIT : at2041_ioctl_init(); //pre_enc_config(); break; default : break; } return 0;}static ssize_t muxfifo_read(struct file *file, char *buffer,size_t length,loff_t * offset) { /* copy mux_buf to user space */ /* real transfer size is size_buf[mux_rd_cnt] * 256bit. * third parameter of copy_to_user() is the 'byte' number to transfer * so, it's calculated size_buf[mux_rd_cnt] * 32 */ unsigned int size; down(&muxfifo_read_sem); size = (*size_buf[mux_rd_cnt] << 5) + (enc_txmsg_size << 1); copy_to_user(buffer, mux_buf[mux_rd_cnt], size); /* multiplex ring buffer control */ if (!mux_ring_cnt && mux_rd_cnt <= mux_wr_cnt) { mux_rd_cnt ++; if (mux_rd_cnt == MAX_BUF_NUM) { mux_ring_cnt --; mux_rd_cnt = 0; } } else if (mux_ring_cnt) { mux_rd_cnt ++; if (mux_rd_cnt == MAX_BUF_NUM) { mux_ring_cnt --; mux_rd_cnt = 0; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -