📄 buz.c
字号:
u32 reg; zr36060_reset(zr); mdelay(10); reg = (0 << 7) /* Load=0 */ |(1 << 0); /* SynRst=1 */ zr36060_write_8(zr, 0x000, reg); zr36060_set_jpg(zr, mode); zr36060_set_video(zr, mode); zr36060_set_jpg_SOF(zr); zr36060_set_jpg_SOS(zr); zr36060_set_jpg_DRI(zr); zr36060_set_jpg_DQT(zr); zr36060_set_jpg_DHT(zr); zr36060_set_jpg_APP(zr); zr36060_set_jpg_COM(zr); reg = (1 << 7) /* Load=1 */ |(0 << 0); /* SynRst=0 */ zr36060_write_8(zr, 0x000, reg); /* wait for codec to unbusy */ for (i = 0; i < 1000; ++i) { reg = zr36060_read_8(zr, 0x001); if ((reg & (1 << 7)) == 0) { DEBUG(printk(KERN_DEBUG "060: loaded, loops=%u\n", i)); return; } udelay(1000); } printk(KERN_INFO "060: stuck busy, statux=%02x\n", reg);}static void zr36057_set_jpg(struct zoran *zr, enum zoran_codec_mode mode){ struct tvnorm *tvn; u32 reg; int i; tvn = &tvnorms[zr->params.norm]; /* assert P_Reset */ btwrite(0, ZR36057_JPC); /* re-initialize DMA ring stuff */ zr->jpg_que_head = 0; zr->jpg_dma_head = 0; zr->jpg_dma_tail = 0; zr->jpg_que_tail = 0; zr->jpg_seq_num = 0; for (i = 0; i < BUZ_NUM_STAT_COM; ++i) { zr->stat_com[i] = 1; /* mark as unavailable to zr36057 */ } for (i = 0; i < zr->jpg_nbufs; i++) { zr->jpg_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ } /* MJPEG compression mode */ switch (mode) { case BUZ_MODE_MOTION_COMPRESS: default: reg = ZR36057_JMC_MJPGCmpMode; break; case BUZ_MODE_MOTION_DECOMPRESS: reg = ZR36057_JMC_MJPGExpMode; reg |= ZR36057_JMC_SyncMstr; /* RJ: The following is experimental - improves the output to screen */ if (zr->params.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; break; case BUZ_MODE_STILL_COMPRESS: reg = ZR36057_JMC_JPGCmpMode; break; case BUZ_MODE_STILL_DECOMPRESS: reg = ZR36057_JMC_JPGExpMode; break; } reg |= ZR36057_JMC_JPG; if (zr->params.field_per_buff == 1) reg |= ZR36057_JMC_Fld_per_buff; btwrite(reg, ZR36057_JMC); /* vertical */ btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR); reg = (6 << ZR36057_VSP_VsyncSize) | (tvn->Ht << ZR36057_VSP_FrmTot); btwrite(reg, ZR36057_VSP); reg = ((zr->params.img_y + tvn->VStart) << ZR36057_FVAP_NAY) | (zr->params.img_height << ZR36057_FVAP_PAY); btwrite(reg, ZR36057_FVAP); /* horizontal */ btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); reg = ((tvn->Wt - 100) << ZR36057_HSP_HsyncStart) | (tvn->Wt << ZR36057_HSP_LineTot); btwrite(reg, ZR36057_HSP); reg = ((zr->params.img_x + tvn->HStart) << ZR36057_FHAP_NAX) | (zr->params.img_width << ZR36057_FHAP_PAX); btwrite(reg, ZR36057_FHAP); /* field process parameters */ if (zr->params.odd_even) reg = ZR36057_FPP_Odd_Even; else reg = 0; btwrite(reg, ZR36057_FPP); /* Set proper VCLK Polarity, else colors will be wrong during playback */ btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR); /* code base address and FIFO threshold */ reg = virt_to_bus(zr->stat_com); btwrite(reg, ZR36057_JCBA); reg = 0x50; btwrite(reg, ZR36057_JCFT); /* JPEG codec guest ID */ reg = (1 << ZR36057_JCGI_JPEGuestID) | (0 << ZR36057_JCGI_JPEGuestReg); btwrite(reg, ZR36057_JCGI); /* Code transfer guest ID */ reg = (0 << ZR36057_MCTCR_CodGuestID) | (3 << ZR36057_MCTCR_CodGuestReg); reg |= ZR36057_MCTCR_CFlush; btwrite(reg, ZR36057_MCTCR); /* deassert P_Reset */ btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC);}static void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode){ static int zero = 0; static int one = 1; switch (mode) { case BUZ_MODE_MOTION_COMPRESS: zr36060_set_cap(zr, mode); zr36057_set_jpg(zr, mode); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); /* deassert P_Reset, assert Code transfer enable */ btwrite(IRQ_MASK, ZR36057_ISR); btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); break; case BUZ_MODE_MOTION_DECOMPRESS: i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &zero); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &one); zr36060_set_cap(zr, mode); zr36057_set_jpg(zr, mode); /* deassert P_Reset, assert Code transfer enable */ btwrite(IRQ_MASK, ZR36057_ISR); btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); break; case BUZ_MODE_IDLE: default: /* shut down processing */ btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC); btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC); btand(~ZR36057_JMC_Go_en, ZR36057_JMC); btwrite(0, ZR36057_ISR); zr36060_reset(zr); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); break; } zr->codec_mode = mode;}/* * Queue a MJPEG buffer for capture/playback */static int jpg_qbuf(struct zoran *zr, int frame, enum zoran_codec_mode mode){ unsigned long flags; int res; /* Check if buffers are allocated */ if (!zr->jpg_buffers_allocated) { printk(KERN_ERR "%s: jpg_qbuf: buffers not yet allocated\n", zr->name); return -ENOMEM; } /* Does the user want to stop streaming? */ if (frame < 0) { if (zr->codec_mode == mode) { zr36057_enable_jpg(zr, BUZ_MODE_IDLE); return 0; } else { printk(KERN_ERR "%s: jpg_qbuf - stop streaming but not in streaming mode\n", zr->name); return -EINVAL; } } /* No grabbing outside the buffer range! */ if (frame >= zr->jpg_nbufs) { printk(KERN_ERR "%s: jpg_qbuf: buffer %d out of range\n", zr->name, frame); return -EINVAL; } /* what is the codec mode right now? */ if (zr->codec_mode == BUZ_MODE_IDLE) { /* Ok load up the zr36060 and go */ zr36057_enable_jpg(zr, mode); } else if (zr->codec_mode != mode) { /* wrong codec mode active - invalid */ printk(KERN_ERR "%s: jpg_qbuf - codec in wrong mode\n", zr->name); return -EINVAL; } spin_lock_irqsave(&zr->lock, flags); /* make sure a grab isn't going on currently with this buffer */ switch (zr->jpg_gbuf[frame].state) { default: case BUZ_STATE_DMA: case BUZ_STATE_PEND: case BUZ_STATE_DONE: res = -EBUSY; /* what are you doing? */ break; case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least one more pend[] entry */ zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = frame; zr->jpg_gbuf[frame].state = BUZ_STATE_PEND; zoran_feed_stat_com(zr); res = 0; break; } spin_unlock_irqrestore(&zr->lock, flags); /* Start the zr36060 when the first frame is queued */ if (zr->jpg_que_head == 1) { btor(ZR36057_JMC_Go_en, ZR36057_JMC); btwrite(ZR36057_JPC_P_Reset | ZR36057_JPC_CodTrnsEn | ZR36057_JPC_Active, ZR36057_JPC); } return res;}/* * Sync on a MJPEG buffer */static int jpg_sync(struct zoran *zr, struct zoran_sync *bs){ unsigned long flags; int frame; if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { return -EINVAL; } while (zr->jpg_que_tail == zr->jpg_dma_tail) { interruptible_sleep_on(&zr->jpg_capq); if (signal_pending(current)) return -ERESTARTSYS; } spin_lock_irqsave(&zr->lock, flags); frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME]; /* buffer should now be in BUZ_STATE_DONE */ if (zr->jpg_gbuf[frame].state != BUZ_STATE_DONE) printk(KERN_ERR "%s: jpg_sync - internal error\n", zr->name); *bs = zr->jpg_gbuf[frame].bs; zr->jpg_gbuf[frame].state = BUZ_STATE_USER; spin_unlock_irqrestore(&zr->lock, flags); return 0;}/* when this is called the spinlock must be held */static void zoran_feed_stat_com(struct zoran *zr){ /* move frames from pending queue to DMA */ int frame, i, max_stat_com; max_stat_com = (zr->params.TmpDcm == 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1); while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com && zr->jpg_dma_head != zr->jpg_que_head) { frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME]; if (zr->params.TmpDcm == 1) { /* fill 1 stat_com entry */ i = zr->jpg_dma_head & BUZ_MASK_STAT_COM; zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; } else { /* fill 2 stat_com entries */ i = (zr->jpg_dma_head & 1) * 2; zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; zr->stat_com[i + 1] = zr->jpg_gbuf[frame].frag_tab_bus; } zr->jpg_gbuf[frame].state = BUZ_STATE_DMA; zr->jpg_dma_head++; }}/* when this is called the spinlock must be held */static void zoran_reap_stat_com(struct zoran *zr){ /* move frames from DMA queue to done queue */ int i; u32 stat_com; unsigned int seq; unsigned int dif; int frame; struct zoran_gbuffer *gbuf; /* In motion decompress we don't have a hardware frame counter, we just count the interrupts here */ if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) zr->jpg_seq_num++; while (zr->jpg_dma_tail != zr->jpg_dma_head) { if (zr->params.TmpDcm == 1) i = zr->jpg_dma_tail & BUZ_MASK_STAT_COM; else i = (zr->jpg_dma_tail & 1) * 2 + 1; stat_com = zr->stat_com[i]; if ((stat_com & 1) == 0) { return; } frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; gbuf = &zr->jpg_gbuf[frame]; get_fast_time(&gbuf->bs.timestamp); if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { gbuf->bs.length = (stat_com & 0x7fffff) >> 1; /* update sequence number with the help of the counter in stat_com */ seq = stat_com >> 24; dif = (seq - zr->jpg_seq_num) & 0xff; zr->jpg_seq_num += dif; } else { gbuf->bs.length = 0; } gbuf->bs.seq = zr->params.TmpDcm == 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num; gbuf->state = BUZ_STATE_DONE; zr->jpg_dma_tail++; }}static void zoran_irq(int irq, void *dev_id, struct pt_regs *regs){ u32 stat, astat; int count; struct zoran *zr; unsigned long flags; zr = (struct zoran *) dev_id; count = 0; spin_lock_irqsave(&zr->lock, flags); while (1) { /* get/clear interrupt status bits */ stat = btread(ZR36057_ISR); astat = stat & IRQ_MASK; if (!astat) { break; } btwrite(astat, ZR36057_ISR); IDEBUG(printk(BUZ_DEBUG "-%u: astat %08x stat %08x\n", zr->id, astat, stat));#if (IRQ_MASK & ZR36057_ISR_GIRQ0) if (astat & ZR36057_ISR_GIRQ0) { /* Interrupts may still happen when zr->v4l_memgrab_active is switched off. We simply ignore them */ if (zr->v4l_memgrab_active) {/* A lot more checks should be here ... */ if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) printk(KERN_WARNING "%s: BuzIRQ with SnapShot off ???\n", zr->name); if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { /* There is a grab on a frame going on, check if it has finished */ if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { /* it is finished, notify the user */ zr->v4l_gbuf[zr->v4l_grab_frame].state = BUZ_STATE_DONE; zr->v4l_grab_frame = NO_GRAB_ACTIVE; zr->v4l_grab_seq++; zr->v4l_pend_tail++; } } if (zr->v4l_grab_frame == NO_GRAB_ACTIVE) wake_up_interruptible(&zr->v4l_capq); /* Check if there is another grab queued */ if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && zr->v4l_pend_tail != zr->v4l_pend_head) { int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; u32 reg; zr->v4l_grab_frame = frame; /* Set zr36057 video front end and enable video */ /* Buffer address */ reg = zr->v4l_gbuf[frame].fbuffer_bus; btwrite(reg, ZR36057_VDTR); if (zr->video_interlace) reg += zr->gbpl; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */#ifdef XAWTV_HACK reg = (zr->gwidth > 720) ? ((zr->gwidth & ~3) - 720) * zr->gbpl / zr->gwidth : 0;#else reg = 0;#endif if (zr->video_interlace) reg += zr->gbpl; reg = (reg << ZR36057_VSSFGR_DispStride); reg |= ZR36057_VSSFGR_VidOvf; reg |= ZR36057_VSSFGR_SnapShot; reg |= ZR36057_VSSFGR_FrameGrab; btwrite(reg, ZR36057_VSSFGR); btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); } } }#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ0) */#if (IRQ_MASK & ZR36057_ISR_GIRQ1) if (astat & ZR36057_ISR_GIRQ1) { unsigned csr = zr36060_read_8(zr, 0x001); unsigned isr = zr36060_read_8(zr, 0x008); IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_GIRQ1 60_code=%02x 60_intr=%02x\n", zr->name, csr, isr)); btand(~ZR36057_ICR_GIRQ1, ZR36057_ICR); zoran_reap_stat_com(zr); zoran_feed_stat_com(zr); }#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ1) */#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) if (astat & ZR36057_ISR_CodRepIRQ) { IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", zr->name)); btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); }#endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) if ((astat & ZR36057_ISR_JPEGRepIRQ) && (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { zoran_reap_stat_com(zr); zoran_feed_stat_com(zr); wake_up_interruptible(&zr->jpg_capq); }#endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ count++; if (count > 10) { printk(KERN_WARNING "%s: irq loop %d\n", zr->name, count); if (count > 20) { btwrite(0, ZR36057_ICR); printk(KERN_ERR "%s: IRQ lockup, cleared int mask\n", zr->name); break; } } } spin_unlock_irqrestore(&zr->lock, flags);}/* Check a zoran_params struct for correctness, insert default params */static int zoran_check_params(struct zoran *zr, struct zoran_params *params){ int err = 0, err0 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -