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

📄 fr400cc_vdc.c

📁 一个linux内核编程文件
💻 C
📖 第 1 页 / 共 3 页
字号:
		printk("VDC_RC:%08x\r\n", v);//gfliu 1125
	}
}

static void
vdc_conf_to_prm(struct fr400vdc_config *src, struct vdc_prm *dst)
{
	int *prm;

	prm = src->prm;
	dst->htc = prm[0];
	dst->hdc = prm[1];
	dst->hfp = prm[2];
	dst->hsc = prm[3];
	dst->hbp = prm[4];
	dst->hip = prm[10];

	dst->vtc = prm[5];
	dst->vdc = prm[6];
	dst->vfp = prm[7];
	dst->vsc = prm[8];
	dst->vbp = prm[9];
	dst->vip = prm[11];

	dst->rck = prm[12];

	dst->rddl = src->rddl;
	dst->hls = src->hls;
	dst->pal = src->pal;
	dst->cscv = src->cscv;
	dst->dbls = src->dbls;
	dst->r601 = src->r601;
	dst->tfop = src->tfop;
	dst->dsm = src->dsm;
	dst->dfp = src->dfp;
	dst->die = src->die;
	dst->enop = src->enop;
	dst->vsop = src->vsop;
	dst->hsop = src->hsop;
	dst->dsr = src->dsr;
	dst->csron = src->csron;
	dst->dpf = src->dpf;
	dst->dms = src->dms;
}

#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT

static int
diff_check_without_dms(struct vdc_prm *p)
{
	struct vdc_prm *s;

	if(vdc_cur_prm_set == 0) return 1; /* diff */
	s = &vdc_cur_prm;
	
	return (p->htc != s->htc || p->hdc != s->hdc ||
	   p->hfp != s->hfp || p->hsc != s->hsc || p->hbp != s->hbp ||
	   p->vtc != s->vtc || p->vdc != s->vdc ||
	   p->vfp != s->vfp || p->vsc != s->vsc || p->vbp != s->vbp ||
	   p->hip != s->hip || p->vip != s->vip ||
	   p->rck != s->rck || p->rddl != s->rddl ||
	   p->hls != s->hls ||
	   p->pal != s->pal ||
	   p->cscv != s->cscv ||
	   p->dbls != s->dbls ||
	   p->r601 != s->r601 ||
	   p->tfop != s->tfop ||
	   p->dsm != s->dsm ||
	   p->dfp != s->dfp ||
	   p->die != s->die ||
	   p->enop != s->enop ||
	   p->vsop != s->vsop ||
	   p->hsop != s->hsop ||
	   p->dsr != s->dsr ||
	   p->csron != s->csron ||
	   p->dpf != s->dpf);
}

#endif /* CONFIG_FR400CC_VDC_VSYNC_REPORT */

static void
vdc_go(int type) /* type 0:vdc , 1:vsync */
{
	struct vdc_prm prm;
#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	struct vdc_prm tmp;
#endif

	if(GO_STAT_CHK(type)) return; /* already */

	vdc_conf_to_prm(&vdc_config, &prm);

	switch(type){
	case 0:
#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
		if(GO_STAT_CHK(GO_STAT_TYPE_VSYNC) && 
		   diff_check_without_dms(&prm)){
			tmp = vdc_cur_prm;
			tmp.dms = 1; /* stop stat */
			vdc_prm_wrt(&tmp);
		}
#endif
		printk("now in vdc_go, before vdc_prm_wrt\r\n"); //gfliu 1125
		vdc_prm_wrt(&prm);
		printk("now in vdc_go, after vdc_prm_wrt\r\n"); //gfliu 1125
		break;

#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	case 1:
		if(! GO_STAT_CHK(GO_STAT_TYPE_VDC)){
			prm.dms = 2; /* free run stat */
			vdc_prm_wrt(&prm);
		}
		break;
#endif
	}
	GO_STAT_SET(type);
}

/**/

static void
dma_stop(void)
{
	unsigned v;

	v = dmac_reg_read(VDC_DMA_CH, CCTR);
#if 1
	v &= ~(CCTR_IE);
	dmac_reg_write(VDC_DMA_CH, CCTR, v);
	v &= ~(CCTR_ACT);
	dmac_reg_write(VDC_DMA_CH, CCTR, v);
#else
	v &= ~(CCTR_ACT | CCTR_IE);
	dmac_reg_write(VDC_DMA_CH, CCTR, v);
#endif

	/* fifo clear */
	v = dmac_reg_read(VDC_DMA_CH, CCTR);
	v |= CCTR_FC;
	dmac_reg_write(VDC_DMA_CH, CCTR, v);
	v &= ~CCTR_FC;
	dmac_reg_write(VDC_DMA_CH, CCTR, v);

	dmac_reg_write(VDC_DMA_CH, BCL, 0);
	dmac_reg_write(VDC_DMA_CH, CSTR, 0);
}

static void
vdc_real_stop(void)
{
	vdc_reset();
	dma_stop();
}

static void
vdc_stop2(int type) /* type 0:vdc , 1:vsync */
{
#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	struct vdc_prm prm;
#endif
	
	if(! GO_STAT_CHK(type)) return; /* already */

	switch(type){
	case 0:
#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
		if(GO_STAT_CHK(GO_STAT_TYPE_VSYNC)){
			prm = vdc_cur_prm;
			prm.dms = 2; /* free run stat */
			vdc_prm_wrt(&prm);
			break;
		}
#endif
		vdc_real_stop();
		break;
#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	case 1:
		if(! GO_STAT_CHK(GO_STAT_TYPE_VDC)){
			vdc_real_stop();
		}
		break;
#endif
	}
	GO_STAT_RESET(type);
}

static int vdc_dma_intr_cnt;
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
static int vdc_intr_cnt;
static int vdc_intr_cnt_vsync;
static int vdc_intr_cnt_under;
#endif

static int vdc_dfi; /* 0: top , 1: bottom */

static void
vdc_dma_interrupt(int ch, void *dev_id)
{
	int updt, ret_count;
#if 0
	printk("vdc_dma_intr\n");
#endif

#if UNDERRUN_NORESET
#ifdef DDDN
	ddd_add(in_blank ? ddd_DMA_I : ddd_DMA_H);
#endif
	if(in_blank) return;
#endif
	vdc_dma_intr_cnt++;

	ret_count = play_idx;

	updt = !Q_EMP;
	if(vdc_config.skipbf == 1){ /* skipbf:1 only, not 0,2 */
		 updt = (updt && (vdc_dfi == 1));
	}
	if(updt){
		play_idx = Q_RD;
		Q_INC_R;
	}

#if VDC_INTR_NEVER /* under flow err test */
	if(vdc_dma_intr_cnt >= 30){
		if(updt){
			frm_count++;
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
			wake_up_interruptible(&vdc_waitq);
#else
			wake_up(&vdc_waitq);
#endif
		}
		return;
	}
#endif

	if(Q_TERM(play_idx)){
		vdc_stop2(0);
		Q_CLR;
	}else{
		vdc_dfi = 1 - vdc_dfi_get();
			/* current --> set next field idx */
		dma_set_2d(ch, area_get(play_idx));
	}

	if(updt){
		if(! vdc_config.rd_count_buf_idx) ret_count = frm_count;
		rbuf_que_put(&rbuf_vdc, FR400CC_VDC_RTYPE_FRAME_FIN, ret_count);
		frm_count++;
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
		wake_up_interruptible(&vdc_waitq);
#else
		wake_up(&vdc_waitq);
#endif
	}
}

#if UNDERRUN_NORESET

static void
vdc_underrun_dma(void)
{
	int updt;

	updt = !Q_EMP;
	if(updt){
		play_idx = Q_RD;
		Q_INC_R;
	}
	if(Q_TERM(play_idx)){
		vdc_stop2(0);
		Q_CLR;
	}else{
		dma_set_2d(VDC_DMA_CH, area_get(play_idx));
	}
}

#endif /* UNDERRUN_NORESET */

#ifdef DBG_Dec16
static void
dump_dma(int id)
{
	static unsigned buf[10*8];
	static int bufcnt = 0;
	static int ch = VDC_DMA_CH;


	buf[bufcnt++] = id;
	buf[bufcnt++] = dmac_reg_read(ch, CCTR);
	buf[bufcnt++] = dmac_reg_read(ch, CSTR);
	buf[bufcnt++] = dmac_reg_read(ch, SBA);
	buf[bufcnt++] = dmac_reg_read(ch, DBA);
	buf[bufcnt++] = dmac_reg_read(ch, BCL);
	buf[bufcnt++] = dmac_reg_read(ch, APR);
	buf[bufcnt++] = dmac_reg_read(ch, PIX);
	buf[bufcnt++] = dmac_reg_read(ch, SIX);
	buf[bufcnt++] = 0; /* dummy */

	if(bufcnt >= 10*8){
	  int i, j, k;
	  k = 0;
	  for(j=0; j<8; j++){
	    for(i=0; i<10; i++){
	      printk("%08x\n", buf[k++]);
	    }
	    printk("--\n");
	  }
	  printk("===\n");
	  bufcnt = 0;
	}
}
#endif

static void
vdc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	extern void ack_mb93401(unsigned int irq);
	unsigned iqsr, vdc_pat, v;
	int vsync, underflow, dfi;

#if 0
	printk("vdc_intr irq=%d\n", irq);
#endif

#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
	vdc_intr_cnt++;
#endif

	if(irq != vdc_kirq){
		printk("vdc: not vdc interrupt irq=%d\n", irq);
		return;
	}
	iqsr = read_fr400cc_register(IQSRs[VDC_FR400CC_IRQ]);
	vdc_pat = (1<<0); /* I0 */
	if((iqsr & vdc_pat) == 0){
#if 0
		printk("vdc: unknown interrupt IQSR=%08x\n", iqsr);
#endif
		return;
	}

	v = read_fr400cc_register(VDC_RS);
#if 0
	printk("RS=%08x\n", v);
#endif
	vsync = (v >> 17) & 1;
	underflow = (v >> 18) & 1;
	dfi = (v >> 16) & 1;

#ifdef DDDN
	if(underflow){
		ddd_en = 1;
		ddd_add(ddd_ERR);
	}
	if(vsync){
		ddd_add(dfi==0 ? ddd_VT : ddd_VB);
	}
#endif

#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	if(GO_STAT_CHK(GO_STAT_TYPE_VSYNC) && vsync){
		rbuf_que_put(&rbuf_vsync, 
			     FR400CC_VDC_RTYPE_VSYNC,
			     dfi);
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
		wake_up_interruptible(&vdc_vsync_waitq);
#else
		wake_up(&vdc_vsync_waitq);
#endif
	}
#endif

#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
	if(vsync){
		vdc_intr_cnt_vsync++;
	}
#endif

	if(underflow){
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
		vdc_intr_cnt_under++;
#endif
		rbuf_que_put(&rbuf_vdc, FR400CC_VDC_RTYPE_ERR_UNDERFLOW, 0);

#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)

#if UNDERRUN_NORESET
		if(underrun_reset){
			vdc_start_inner(0, 1);
		}else{
			dma_stop();

#if 1 /* RGB */
			vdc_underrun_dma();
			if(vdc_config.dpf == 1){ /* RGB */
				in_blank = 1;
			}else{
				if(dfi == 0) in_blank = 1;
			}
#else /* RGB */
			vdc_underrun_dma();
#ifdef DBG_Dec16
			if(dfi == 0){
				in_dbg16 = 1;
				dump_dma(1);
			}
#else
			if(dfi == 0) in_blank = 1;
#endif

#endif /* ! RGB */
		}
#else
		vdc_start_inner(0, 1);
#endif
		wake_up_interruptible(&vdc_waitq);
#else
		wake_up(&vdc_waitq);
#endif
	}

#if UNDERRUN_NORESET
#if 1 /* RGB */
	if(vdc_config.dpf == 1){ /* RGB */
		if(in_blank > 0){
			vdc_underrun_dma();
			in_blank--;
		}
	}else{
		if(vsync && dfi == 0 && in_blank > 0){
			vdc_underrun_dma();
			in_blank--;
		}
	}
#else
	if(vsync && dfi == 0 && in_blank > 0){
		vdc_underrun_dma();
		in_blank--;
	}
#endif
#endif

#ifdef DBG_Dec16
	if(vsync && dfi == 0 && in_dbg16 > 0){
		dump_dma(2);
		in_dbg16 = 0;
	}
#endif

#ifdef DDDN
	if(ddd_en && vsync && dfi == 0){
		ddd_add(ddd_DIV);
		ddd_en = 0;
	}
#endif

	/*
	about RS
	31..19 : reserved
	18..17 : IT[1:0]   IT[1] underflow , IT[0] vsync
	16     : DFI       TOP/BOTTOM
	15..5  : reserved
	4      : DCSR      Cursor ON/OFF
	3..2   : reserved
	1..0   : DCM       mode disable/stop/freerun/transfer
	*/
	v &= 0x10013; /* 16/4/1..0 --> keep */
	write_fr400cc_register(VDC_RS, v);

	do{
		iqsr = read_fr400cc_register(IQSRs[VDC_FR400CC_IRQ]);
	}while(iqsr & vdc_pat);

	ack_mb93401(irq);
#if 0
	printk("vdc intr fin.\n");
#endif
}

/**/

static int irq_open_cnt = 0;
static int
irq_open(void)
{
	int retval;
	if(irq_open_cnt++ > 0) return 0;
	if((retval = request_irq(vdc_kirq, 
				 vdc_interrupt, 
				 SA_INTERRUPT | SA_SHIRQ,
				 "fr400cc_vdc", 
				 &vdc_count)) != 0){
		irq_open_cnt--;
	}
	return retval;
}
static void
irq_close(void)
{
	if(irq_open_cnt <= 0) return;
	if(--irq_open_cnt > 0) return;
	free_irq(vdc_kirq, &vdc_count);
}

static int dma_open_cnt = 0;
static int
dma_open(void)
{
	int retval;
	if(dma_open_cnt++ > 0) return 0;

	Q_CLR;
	if((retval = mb93401_dma_register(VDC_DMA_CH, 
					  "fr400cc_vdc_dma",
					  vdc_dma_interrupt, 
					  NULL)) < 0){
		dma_open_cnt--;
		return retval;
	}
	vdc_dma_intr_cnt = 0;
#if defined(CONFIG_MB93091_CB30) || defined(CONFIG_FR400PDK2_BOARD)
	vdc_intr_cnt = 0;
	vdc_intr_cnt_vsync = 0;
	vdc_intr_cnt_under = 0;
#endif
	dma_stop();
	return retval;
}

static int
dma_close(void)
{
	int retval;
	if(dma_open_cnt <= 0) return 0;
	if(--dma_open_cnt > 0) return 0;
	if((retval = mb93401_dma_unregister(VDC_DMA_CH)) < 0){
		dma_open_cnt++;
	}
	return retval;
}

static int
vdc_open(struct inode *inode, struct file *file)
{
	int retval;

	lock_kernel();
	if(vdc_count){
		unlock_kernel();
		return -EBUSY;
	}

#ifdef CONFIG_FR400CC_VDC_VSYNC_REPORT
	if(vdc_vsync_count <= 0){
		vdc_config = default_config;
	}
#else
	vdc_config = default_config;
#endif
	if((retval = dma_open()) < 0){
		unlock_kernel();
		return retval;
	}
	if((retval = irq_open()) != 0){
		printk("vdc: open, request_irq NG.\n");
		dma_close();
		unlock_kernel();
		return retval;
	}

	vdc_count++;
	unlock_kernel();
	return 0;
}


⌨️ 快捷键说明

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