📄 at2041_inf.c
字号:
demux_wr_cnt = 0; } } else if (demux_ring_cnt && (demux_wr_cnt < demux_rd_cnt)) { demux_wr_cnt ++; } //printk ("down:%d %d %d\n", demux_ring_cnt, demux_wr_cnt, demux_rd_cnt); return 0;}static int at2041_open(struct inode* inode, struct file* filp){ printk("the AT2041 Open!!!\n"); MOD_INC_USE_COUNT; return 0;}static int at2041_release(struct inode* inode, struct file* filp){ printk("the AT2041 Release!!!\n"); MOD_DEC_USE_COUNT; return 0;}/* the AT2041 file operations */static struct file_operations at2041_fops = { read: muxfifo_read, write: demuxfifo_write, ioctl: at2041_ioctl, open: at2041_open, release: at2041_release,};static void at2041_interrupt_handle(int irq, void *dev_id, struct pt_regs * regs){ _SET_REG_STR_ set_reg_st={0,0,{0,0,0,0,0,0}}; unsigned int tx_data=0; unsigned int stat_data=0; unsigned int data_size = 0; #if 0 int tmp=0; unsigned short temp; unsigned char picture_type[]={'I', 'P', 'B'};#endif int break_value=0; int count = 0; unsigned int mux_data; unsigned short mux_tmp[2]; unsigned short mux_swap[2]; unsigned short fifo_dat[4]; unsigned short id_conf = RxID(GID_ENC_VIDEO, 0x00, 0x01, R_FLAG); do { stat_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_STATUS_REG)); count ++; udelay(10); } while ((stat_data & 0x100) && (count < 1000)); //printk("stat_data_%d : 0x%04x\n", count, stat_data); udelay(10); if (count < 1000) { /* data read from Tx_FIFO of the AT2041 */ //tx_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_TX_FIFO)); tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[0]=(tx_data&0xFFFF); fifo_dat[1]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); //printk("fifo_dat : 0x%04x, 0x%04x\n", fifo_dat[0], fifo_dat[1]); } #if 1 if (fifo_dat[0] ==id_conf) /*RESOLUTION*/ { tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[0]=(tx_data&0xFFFF);fifo_dat[1]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); if (fifo_dat[0]==480) { PAL_NTSC=NTSC; printk ("## NTSC INPUT VIDEO DETECTEDT ##\n"); } else { PAL_NTSC=PAL; printk ("## PAL INPUT VIDEO DETECTEDT ##\n"); } /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); /* acknowledge for data ready message */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=id_conf; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); }#endif /* check whether first tx message is 'data ready message' * or 'data request message' */ if ((fifo_dat[0] & 0x0001) == 0x0000) /*Message*/ { // read data from tx_fifo /* check tx fifo empty */ do { stat_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_STATUS_REG)); count ++; udelay(10); } while ((stat_data & 0x100) && (count < 1000)); //printk("Message : %d, 0x%04x\n", count, stat_data); udelay(10); if (count < 1000) { /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[2]=(tx_data&0xFFFF); fifo_dat[3]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); //printk("Message : 0x%04x, 0x%04x\n", fifo_dat[2], fifo_dat[3]); } /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); } else if (fifo_dat[0] == 0x8803) /*Encoding*/ { // read message from tx_fifo : data ready message(Encoder) /* if first tx message is 'data ready message', * read three tx message sequentially. * the contents of second tx_message are 'data type', 'channel ID', * 'skip', 'loss' and 'output buffer full', etc. */ /* read the second parameter of Tx_FIFO */ mux_buf[mux_wr_cnt][0] = fifo_dat[1]; //printk( "[ch:%d]", (mux_buf[mux_wr_cnt][0] >> 4) & 0xf); //printk( "[%c]", picture_type[((mux_buf[mux_wr_cnt][0] >> 12) & 0x3)-1]); //printk( "[type:%d]", mux_buf[mux_wr_cnt][0] & 0xf); do { stat_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_STATUS_REG)); count ++; udelay(10); } while ((stat_data & 0x100) && (count < 1000)); if (count < 1000) { /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[2]=(tx_data&0xFFFF); fifo_dat[3]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); } /* read the third parameter of Tx_FIFO */ /* the contents of the third tx_message are 'output data size' */ mux_buf[mux_wr_cnt][1] = fifo_dat[2]; //printk( "[size:%08d]\n", (((mux_buf[mux_wr_cnt][1] &0xffff) << 4) + enc_txmsg_size)*2); /* read the fourth parameter of Tx_FIFO */ /* the contents of the fourth tx_message are 'reserved' */ mux_buf[mux_wr_cnt][2] = fifo_dat[3]; /* calculate data size to transfer */ *size_buf[mux_wr_cnt] = mux_buf[mux_wr_cnt][1]; data_size = ((*size_buf[mux_wr_cnt] & 0xffff) << 4) + enc_txmsg_size; /* data read from multiplex FIFO of the AT2041 */ /* write multiplex data from the AT2041 to d/d's buffer */ for (ii = enc_txmsg_size; ii < data_size; ii+=2) /*data size is short type*/ { mux_data= *((unsigned int *)((unsigned int)fifo_reg + AT2041_MUX_FIFO)); mux_tmp[0]=(mux_data&0xFFFF); mux_tmp[1]=((mux_data>>AT2041_DAT_SHIFT)&0xFFFF); mux_swap[0]= (((mux_tmp[0]<<8)&0xFF00) | ((mux_tmp[0]>>8)&0x00FF)); mux_swap[1]= (((mux_tmp[1]<<8)&0xFF00) | ((mux_tmp[1]>>8)&0x00FF)); mux_buf[mux_wr_cnt][ii]=mux_swap[0]; mux_buf[mux_wr_cnt][ii+1]=mux_swap[1]; } up(&muxfifo_read_sem); /* multiplex ring buffer control */ if (!mux_ring_cnt) { mux_wr_cnt ++; if (mux_wr_cnt == MAX_BUF_NUM) { mux_ring_cnt ++; mux_wr_cnt = 0; } } else if (mux_ring_cnt && mux_wr_cnt < mux_rd_cnt) { mux_wr_cnt ++; } else { //printk("!!![MUX][%02d][%02d][%02d]\n", mux_wr_cnt, mux_rd_cnt, mux_ring_cnt); } if (mux_ring_cnt && mux_wr_cnt == mux_rd_cnt) { mux_full = 1; //printk("!!!!!!!! MUX FULL !!!!!!!!!\n"); } /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); /* acknowledge for data ready message */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8803; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); } /*Encoding*/ else if (fifo_dat[0] == 0x9003) /*Decoding*/ { /* data write to de-multiplex FIFO of the AT2041 */ // read message from txfifo : data request(Decoding) if (!demux_ring_cnt && (demux_wr_cnt == demux_rd_cnt)) { #if 0 /* check tx fifo empty */ do { stat_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_STATUS_REG)); count ++; udelay(10); } while ((stat_data & 0x100) && (count < 1000)); if (count < 1000) { /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[2]=(tx_data&0xFFFF); fifo_dat[3]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); } #endif demux_empty=1; /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); /* acknowledge for data ready message */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x9003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); //printk ("[RETURN : %d %d %d]\n", demux_ring_cnt, demux_wr_cnt, demux_rd_cnt); return ; } /* check tx fifo empty */ #if 0 do { stat_data = *((unsigned short *)((unsigned int)fifo_reg + AT2041_STATUS_REG)); count ++; udelay(10); } while ((stat_data & 0x100) && (count < 1000)); if (count < 1000) { /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned int *)((unsigned int)fifo_reg + AT2041_TX_FIFO));udelay(10); fifo_dat[2]=(tx_data&0xFFFF); fifo_dat[3]=((tx_data>>AT2041_DAT_SHIFT)&0xFFFF); } #endif /* write de-multiplex data from d/d's buffer to the AT2041 */ for (ii = 0; ii < (demux_size_buf[demux_rd_cnt] + 256)/2; ii +=2) { /*data size is short type*/ mux_tmp[0]=demux_buf[demux_rd_cnt][ii]; mux_tmp[1]=demux_buf[demux_rd_cnt][ii+1]; mux_swap[0]= (((mux_tmp[0]<<8)&0xFF00) | ((mux_tmp[0]>>8)&0x00FF)); mux_swap[1]= (((mux_tmp[1]<<8)&0xFF00) | ((mux_tmp[1]>>8)&0x00FF));#if 0 if (ii < 2) { //printk("%04x_%04x ", mux_swap[0], mux_swap[1]); if (mux_swap[1]==0x01e0) break_value=1; else break_value=0; } else if (ii < 4) { //printk("%04x_%04x\n", mux_swap[0], mux_swap[1]); if (break_value) break; }#endif set_reg_st.cmd_num=1;set_reg_st.addr=AT2041_DEMUX_FIFO_ADDR; set_reg_st.value[0]=mux_swap[0];set_reg_st.value[1]=mux_swap[1]; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); } up(&demuxfifo_write_sem); /* de-multiplex ring buffer control */ //if (!demux_ring_cnt && demux_rd_cnt <= demux_wr_cnt) if (!demux_ring_cnt && demux_rd_cnt < demux_wr_cnt) { demux_rd_cnt ++; if (demux_rd_cnt == MAX_BUF_NUM) { demux_ring_cnt --; demux_rd_cnt = 0; } } else if (demux_ring_cnt) { demux_rd_cnt ++; if (demux_rd_cnt == MAX_BUF_NUM) { demux_ring_cnt --; demux_rd_cnt = 0; } } /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); /* acknowledge for data ready message */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x9003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); //printk ("up:%d %d %d\n", demux_ring_cnt, demux_wr_cnt, demux_rd_cnt); } /*Decoding*/ else { printk ("\n[ISR_ELSE : 0x%04x, 0x%04x, 0x%04x]\n", stat_data, fifo_dat[0], fifo_dat[1]); /* TxACK command */ set_reg_st.cmd_num=0;set_reg_st.addr=AT2041_RX_FIFO_ADDR; set_reg_st.value[0]=0x8003; do_mw32 ( (_SET_REG_STR_ ) set_reg_st); } return ;}int at2041_init_module(void){ int ret, kk; printk ("## BWSCON : 0x%08x ##\n" , rBWSCON); /*BWSCON : 0x48000000*/ (unsigned int *)fifo_reg = (unsigned int *)ioremap(AT2042_BASE, AT2042_REMAP_SIZE); printk("init_at2042 0x%x ==> 0x%x\n", (unsigned int)fifo_reg, (unsigned int)fifo_reg+AT2042_REMAP_SIZE); ret = register_chrdev(AT2041_MAJOR, "at2042", &at2041_fops); init_MUTEX_LOCKED(&muxfifo_read_sem); sema_init(&demuxfifo_write_sem, MAX_BUF_NUM); if (ret < 0) { printk("at2042: at2042 register failed\n"); return ret; } /* mux_buf & demux_buf allocation */ for (kk = 0; kk < MAX_BUF_NUM; kk ++){ if (!(mux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE + (enc_txmsg_size << 1), GFP_KERNEL))) { printk("AT2041 : mux_buf kmalloc failed...\n"); return -ENOMEM; } if (!(demux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE, GFP_KERNEL))) { printk("AT2041 : demux_buf kmalloc failed...\n"); return -ENOMEM; } if (!(size_buf[kk] = (unsigned short *) vmalloc(sizeof(unsigned short)))) { printk("AT2041 : size_buf kmalloc failed...\n"); return -ENOMEM; } } printk("the AT2041 driver initialized...\n"); #if 0 //printk ("__nWAIT_REENABLE__\n");printk ("__nWAIT_REENABLE__\n");/*HJT*/ //rBWSCON |= (0x5<<8); printk ("__nWAIT_DISABLE__\n");printk ("__nWAIT_DISABLE__\n");/*HJT*/ rBWSCON &= ~(0x4<<8); printk ("__Tacc_control__\n");printk ("__Tacc_control__\n");/*HJT*/ rBANKCON2 |= (0x7<<8); /*14CLK*/#endif /* Enable interrupts for EINT0/GPF0 */ /*HJT*/ printk ("__INTERRUPT_AVAILABLE__\n"); /*HJT*/ //rEXTINT0 = 0x22222244; // EINT[7:0] /*AT2042 Falling Edge Triggered*/ /*HJT*/ rEXTINT0 = 0x22222444; // EINT[7:0] /*AT2042 Rising Edge Triggered*/ /*HJT*/ //rINTMSK &= ~0x00000001; //Intservice MASK ==> AVAILABLE /*HJT*/ rSRCPND |= 0x00000004; //Intservice requested /*HJT*/ //rINTMSK |=0x00000004; //Intservice MASK ==> MASKED /*HJT*/ rINTMSK &= ~0x00000004; //Intservice MASK ==> AVAILABLE /*HJT*/ /* AT2041_IRQ = 25, Fast interrupt, No interrupt sharing */ //printk ("0x%x : 0x%x\n", SA_INTERRUPT, SA_SHIRQ); if(request_irq(IRQ_EINT2, at2041_interrupt_handle, SA_INTERRUPT, "at2042", NULL)) //if(request_irq(IRQ_EINT2, at2041_interrupt_handle, SA_SHIRQ, "at2042", NULL)) //if(request_irq(IRQ_EINT2, at2041_interrupt_handle, 0, "at2042", NULL)) { printk("at2042 : cannot register IRQ %d\n", IRQ_EINT2); return -EIO; } printk("at2042 : register IRQ %d\n", IRQ_EINT2); return 0;}void at2041_cleanup_module(void){ volatile int ret; free_irq(IRQ_EINT2, NULL); ret = unregister_chrdev(AT2041_MAJOR, "at2042"); if (ret < 0) { printk("at2042: at2042 unregister failed\n"); return; } for (ii = 0; ii < MAX_BUF_NUM; ii ++) { kfree(mux_buf[ii]); kfree(demux_buf[ii]); vfree(size_buf[ii]); } printk("at2042: at2042 unloaded\n"); iounmap((void *)fifo_reg); return;}module_init(at2041_init_module);module_exit(at2041_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -