📄 zr36067.c
字号:
} if (width <= 0) { continue; } /* apply clip for each scan line */ for (j = 0; j < height; ++j) { /* reset bit for each pixel */ /* this can be optimized later if need be */ mask = zr->overlay_mask + (y + j) * mask_line_size; for (k = 0; k < width; ++k) { mask[(x + k) / 32] &= ~((u32) 1 << (x + k) % 32); } } }}/* Enable/Disable uncompressed memory grabbing of the 36057 */static void zr36057_set_memgrab(struct zoran *zr, int mode){ if (mode) { if (btread(ZR36057_VSSFGR) & (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab)) printk(KERN_WARNING "%s: zr36057_set_memgrab_on with SnapShot or FrameGrab on ???\n", zr->name); /* switch on VSync interrupts */ btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts btor(cardvsync[zr->card], ZR36057_ICR); // SW /* enable SnapShot */ btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); /* Set zr36057 video front end and enable video */ zr36057_set_vfe(zr, zr->gwidth, zr->gheight, zr->gformat); zr->v4l_memgrab_active = 1; } else { zr->v4l_memgrab_active = 0; /* switch off VSync interrupts */ //btand(~ZR36057_ICR_GIRQ1, ZR36057_ICR); // SW /* reenable grabbing to screen if it was running */ if (zr->v4l_overlay_active) { zr36057_overlay(zr, 1); } else { btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); } }}static int wait_grab_pending(struct zoran *zr){ unsigned long flags; /* wait until all pending grabs are finished */ if (!zr->v4l_memgrab_active) return 0; while (zr->v4l_pend_tail != zr->v4l_pend_head) { interruptible_sleep_on(&zr->v4l_capq); if (signal_pending(current)) return -ERESTARTSYS; } spin_lock_irqsave(&zr->lock, flags); zr36057_set_memgrab(zr, 0); spin_unlock_irqrestore(&zr->lock, flags); return 0;}/* * V4L Buffer grabbing */static int v4l_grab(struct zoran *zr, struct video_mmap *mp){ unsigned long flags; int res, bpp; /* * There is a long list of limitations to what is allowed to be grabbed * We don't output error messages here, since some programs (e.g. xawtv) * just try several settings to find out what is valid or not. */ /* No grabbing outside the buffer range! */ if (mp->frame >= v4l_nbufs || mp->frame < 0) { DEBUG2(printk (KERN_ERR "%s: Can not grab frame %d\n", zr->name, mp->frame)); return -EINVAL; } /* Check size and format of the grab wanted */ if (mp->height < BUZ_MIN_HEIGHT || mp->width < BUZ_MIN_WIDTH || mp->height > BUZ_MAX_HEIGHT || mp->width > BUZ_MAX_WIDTH) { DEBUG2(printk (KERN_ERR "%s: Wrong frame size.\n", zr->name)); return -EINVAL; } bpp = format2bpp(mp->format); if (bpp == 0) { DEBUG2(printk (KERN_ERR "%s: Wrong bytes-per-pixel format\n", zr->name)); return -EINVAL; } /* Check against available buffer size */ if (mp->height * mp->width * bpp > v4l_bufsize) { DEBUG2(printk (KERN_ERR "%s: Video buffer size is too small\n", zr->name)); return -EINVAL; } /* The video front end needs 4-byte alinged line sizes */ if ((bpp == 2 && (mp->width & 1)) || (bpp == 3 && (mp->width & 3))) { DEBUG2(printk (KERN_ERR "%s: Wrong frame alingment\n", zr->name)); return -EINVAL; } /* * To minimize the time spent in the IRQ routine, we avoid setting up * the video front end there. * If this grab has different parameters from a running streaming capture * we stop the streaming capture and start it over again. */ if (zr->v4l_memgrab_active && (zr->gwidth != mp->width || zr->gheight != mp->height || zr->gformat != mp->format)) { res = wait_grab_pending(zr); if (res) return res; } zr->gwidth = mp->width; zr->gheight = mp->height; zr->gformat = mp->format; zr->gbpl = bpp * zr->gwidth; spin_lock_irqsave(&zr->lock, flags); /* make sure a grab isn't going on currently with this buffer */ switch (zr->v4l_gbuf[mp->frame].state) { default: case BUZ_STATE_PEND: res = -EBUSY; /* what are you doing? */ break; case BUZ_STATE_USER: case BUZ_STATE_DONE: /* since there is at least one unused buffer there's room for at least one more pend[] entry */ zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = mp->frame; zr->v4l_gbuf[mp->frame].state = BUZ_STATE_PEND; res = 0; break; } /* put the 36057 into frame grabbing mode */ if (!res && !zr->v4l_memgrab_active) zr36057_set_memgrab(zr, 1); spin_unlock_irqrestore(&zr->lock, flags); //DEBUG2(printk(KERN_INFO "%s: Frame grab 3...\n", zr->name)); return res;}/* * Sync on a V4L buffer */static int v4l_sync(struct zoran *zr, int frame){ unsigned long flags; /* check passed-in frame number */ if (frame >= v4l_nbufs || frame < 0) { DEBUG1(printk(KERN_ERR "%s: v4l_sync: frame %d is invalid\n", zr->name, frame)); return -EINVAL; } /* Check if is buffer was queued at all */ if (zr->v4l_gbuf[frame].state == BUZ_STATE_USER) { DEBUG1(printk(KERN_ERR "%s: v4l_sync: Attempt to sync on a buffer which was not queued?\n", zr->name)); return -EPROTO; } /* wait on this buffer to get ready */ while (zr->v4l_gbuf[frame].state == BUZ_STATE_PEND) { interruptible_sleep_on(&zr->v4l_capq); if (signal_pending(current)) return -ERESTARTSYS; } /* buffer should now be in BUZ_STATE_DONE */ if (zr->v4l_gbuf[frame].state != BUZ_STATE_DONE) printk(KERN_ERR "%s: v4l_sync - internal error\n", zr->name); /* Check if streaming capture has finished */ spin_lock_irqsave(&zr->lock, flags); if (zr->v4l_pend_tail == zr->v4l_pend_head) zr36057_set_memgrab(zr, 0); spin_unlock_irqrestore(&zr->lock, flags); return 0;}/***************************************************************************** * * * Set up the Buz-specific MJPEG part * * * *****************************************************************************//*Wait til post office is no longer busy */static int post_office_wait(struct zoran *zr){ u32 por;// while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) { while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) { /* wait for something to happen */ } if ((por & ZR36057_POR_POTime) && zr->card != LML33 && zr->card != BUZ) { /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */ printk(KERN_WARNING "%s: pop timeout %08x\n", zr->name, por); return -1; } return 0;}static int post_office_write(struct zoran *zr, unsigned guest, unsigned reg, unsigned value){ u32 por; por = ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16) | (value & 0xFF); btwrite(por, ZR36057_POR); return post_office_wait(zr);}static int post_office_read(struct zoran *zr, unsigned guest, unsigned reg){ u32 por; por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16); btwrite(por, ZR36057_POR); if (post_office_wait(zr) < 0) { return -1; } return btread(ZR36057_POR) & 0xFF;}static int zr36060_write_8(struct zoran *zr, unsigned reg, unsigned val){ if (post_office_wait(zr) || post_office_write(zr, 0, 1, reg >> 8) || post_office_write(zr, 0, 2, reg)) { return -1; } return post_office_write(zr, 0, 3, val);}static int zr36060_write_16(struct zoran *zr, unsigned reg, unsigned val){ if (zr36060_write_8(zr, reg + 0, val >> 8)) { return -1; } return zr36060_write_8(zr, reg + 1, val >> 0);}static int zr36060_write_24(struct zoran *zr, unsigned reg, unsigned val){ if (zr36060_write_8(zr, reg + 0, val >> 16)) { return -1; } return zr36060_write_16(zr, reg + 1, val >> 0);}static int zr36060_write_32(struct zoran *zr, unsigned reg, unsigned val){ if (zr36060_write_16(zr, reg + 0, val >> 16)) { return -1; } return zr36060_write_16(zr, reg + 2, val >> 0);}static u32 zr36060_read_8(struct zoran *zr, unsigned reg){ if (post_office_wait(zr) || post_office_write(zr, 0, 1, reg >> 8) || post_office_write(zr, 0, 2, reg)) { return -1; } return post_office_read(zr, 0, 3) & 0xFF;}/* ----------------------------------------------------------------------- */static void GPIO(struct zoran *zr, unsigned bit, unsigned value){ u32 reg; u32 mask; mask = 1 << (24 + bit); reg = btread(ZR36057_GPPGCR1) & ~mask; if (value) { reg |= mask; } btwrite(reg, ZR36057_GPPGCR1); udelay(1);}static void zr36060_sleep(struct zoran *zr, int sleep){ switch (zr->card) { case DC10: case DC10plus: GPIO(zr, 3, !sleep); break; case BUZ: case LML33: GPIO(zr, 1, !sleep); break; default: break; } if (!sleep) udelay(500); else udelay(2);}static int zr36060_reset(struct zoran *zr){ switch (zr->card) { case DC10: case DC10plus: zr36060_sleep(zr, 0); GPIO(zr, 0, 0); udelay(2); GPIO(zr, 0, 1); udelay(2); break; case LML33: case BUZ: zr36060_sleep(zr, 0); post_office_write(zr, 3, 0, 0); udelay(2); default: } return 0;}static void set_frame(struct zoran *zr, int val){ switch (zr->card) { case DC10: case DC10plus: GPIO(zr, 6, val); break; case LML33: case BUZ: GPIO(zr, 3, val); break; default: break; }}static void set_videobus_dir(struct zoran *zr, int val){ switch (zr->card) { case DC10: case DC10plus: GPIO(zr, 1, val); break; case LML33: if (lml33dpath == 0) GPIO(zr, 5, val); else GPIO(zr, 5, 1); break; case BUZ: default: break; }}static void set_videobus_enable(struct zoran *zr, int val){ switch (zr->card) { case LML33: GPIO(zr, 7, val); break; case DC10: case DC10plus: case BUZ: default: break; }}static void zr36060_set_jpg(struct zoran *zr, enum zoran_codec_mode mode){ struct tvnorm *tvn; u32 reg; int size, blocks; reg = (1 << 0) /* CodeMstr */ |(0 << 2) /* CFIS=0 */ |(0 << 6) /* Endian=0 */ |(0 << 7); /* Code16=0 */ zr36060_write_8(zr, 0x002, reg); switch (mode) { case BUZ_MODE_MOTION_DECOMPRESS: case BUZ_MODE_STILL_DECOMPRESS: reg = 0x00; /* Codec mode = decompression */ break; case BUZ_MODE_MOTION_COMPRESS: case BUZ_MODE_STILL_COMPRESS: default: reg = 0xa4; /* Codec mode = compression with variable scale factor */ break; } zr36060_write_8(zr, 0x003, reg); reg = 0x00; /* reserved, mbz */ zr36060_write_8(zr, 0x004, reg); /* code volume */ /* Target field size in pixels: */ tvn = zr->timing; size = (tvn->Ha / 2) * (tvn->Wa) / (zr->params.HorDcm) / (zr->params.VerDcm); blocks = size / 64; /* Target compressed field size in bits: */ size = size * 16; /* uncompressed size in bits */ size = size * zr->params.quality / 400; /* quality = 100 is a compression ratio 1:4 */ /* Lower limit (arbitrary, 1 KB) */ if (size < 8192) size = 8192; /* Upper limit: 6/8 of the code buffers */ if (size * zr->params.field_per_buff > zr->jpg_bufsize * 6) size = zr->jpg_bufsize * 6 / zr->params.field_per_buff; reg = size * 4 / blocks; if (reg > 0xf0) reg = 0xf0; /* 480 bits/block, does 0xff represents unlimited? */ zr36060_write_8(zr, 0x005, reg); /* JPEG markers */ reg = (zr->params.jpeg_markers) & 0x38; /* DRI, DQT, DHT */ if (zr->params.COM_len) reg |= JPEG_MARKER_COM; if (zr->params.APP_len) reg |= JPEG_MARKER_APP; zr36060_write_8(zr, 0x006, reg); if (zr->card != LML33 && zr->card != BUZ) { reg = (0 << 3) /* EOAV=0 */ |(0 << 2) /* EOI=0 */ |(0 << 1) /* END=0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -