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

📄 buz.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* if window has more than half of active height,	   switch on interlacing - we want the full information */	zr->video_interlace = (video_height > Ha / 2);/**** zr36057 ****/	/* horizontal */	VidWinWid = video_width;	X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa;	We = (VidWinWid * 64) / X;	HorDcm = 64 - X;	hcrop1 = 2 * ((tvn->Wa - We) / 4);	hcrop2 = tvn->Wa - We - hcrop1;	HStart = tvn->HStart | 1;	HEnd = HStart + tvn->Wa - 1;	HStart += hcrop1;	HEnd -= hcrop2;	reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)	    | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);	reg |= ZR36057_VFEHCR_HSPol;	btwrite(reg, ZR36057_VFEHCR);	/* Vertical */	DispMode = !zr->video_interlace;	VidWinHt = DispMode ? video_height : video_height / 2;	Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha;	He = (VidWinHt * 64) / Y;	VerDcm = 64 - Y;	vcrop1 = (tvn->Ha / 2 - He) / 2;	vcrop2 = tvn->Ha / 2 - He - vcrop1;	VStart = tvn->VStart;	VEnd = VStart + tvn->Ha / 2 - 1;	VStart += vcrop1;	VEnd -= vcrop2;	reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)	    | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);	reg |= ZR36057_VFEVCR_VSPol;	btwrite(reg, ZR36057_VFEVCR);	/* scaler and pixel format */	reg = 0			// ZR36057_VFESPFR_ExtFl /* Trying to live without ExtFl */	     | (HorDcm << ZR36057_VFESPFR_HorDcm)	    | (VerDcm << ZR36057_VFESPFR_VerDcm)	    | (DispMode << ZR36057_VFESPFR_DispMode)	    | ZR36057_VFESPFR_LittleEndian;	/* RJ: I don't know, why the following has to be the opposite	   of the corresponding ZR36060 setting, but only this way	   we get the correct colors when uncompressing to the screen  */	reg |= ZR36057_VFESPFR_VCLKPol;	/* RJ: Don't know if that is needed for NTSC also */	reg |= ZR36057_VFESPFR_TopField;	switch (video_format) {	case VIDEO_PALETTE_YUV422:		reg |= ZR36057_VFESPFR_YUV422;		break;	case VIDEO_PALETTE_RGB555:		reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif;		break;	case VIDEO_PALETTE_RGB565:		reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif;		break;	case VIDEO_PALETTE_RGB24:		reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24;		break;	case VIDEO_PALETTE_RGB32:		reg |= ZR36057_VFESPFR_RGB888;		break;	default:		printk(KERN_INFO "%s: Unknown color_fmt=%x\n", zr->name, video_format);		return;	}	if (HorDcm >= 48) {		reg |= 3 << ZR36057_VFESPFR_HFilter;	/* 5 tap filter */	} else if (HorDcm >= 32) {		reg |= 2 << ZR36057_VFESPFR_HFilter;	/* 4 tap filter */	} else if (HorDcm >= 16) {		reg |= 1 << ZR36057_VFESPFR_HFilter;	/* 3 tap filter */	}	btwrite(reg, ZR36057_VFESPFR);	/* display configuration */	reg = (16 << ZR36057_VDCR_MinPix)	    | (VidWinHt << ZR36057_VDCR_VidWinHt)	    | (VidWinWid << ZR36057_VDCR_VidWinWid);	if (triton)		reg &= ~ZR36057_VDCR_Triton;	else		reg |= ZR36057_VDCR_Triton;	btwrite(reg, ZR36057_VDCR);	/* Write overlay clipping mask data, but don't enable overlay clipping */	/* RJ: since this makes only sense on the screen, we use 	   zr->window.width instead of video_width */	mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;	reg = virt_to_bus(zr->overlay_mask);	btwrite(reg, ZR36057_MMTR);	reg = virt_to_bus(zr->overlay_mask + mask_line_size);	btwrite(reg, ZR36057_MMBR);	reg = mask_line_size - (zr->window.width + 31) / 32;	if (DispMode == 0)		reg += mask_line_size;	reg <<= ZR36057_OCR_MaskStride;	btwrite(reg, ZR36057_OCR);}/* * Switch overlay on or off */static void zr36057_overlay(struct zoran *zr, int on){	int fmt, bpp;	u32 reg;	if (on) {		/* do the necessary settings ... */		btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);	/* switch it off first */		switch (zr->buffer.depth) {		case 15:			fmt = VIDEO_PALETTE_RGB555;			bpp = 2;			break;		case 16:			fmt = VIDEO_PALETTE_RGB565;			bpp = 2;			break;		case 24:			fmt = VIDEO_PALETTE_RGB24;			bpp = 3;			break;		case 32:			fmt = VIDEO_PALETTE_RGB32;			bpp = 4;			break;		default:			fmt = 0;			bpp = 0;		}		zr36057_set_vfe(zr, zr->window.width, zr->window.height, fmt);		/* Start and length of each line MUST be 4-byte aligned.		   This should be allready checked before the call to this routine.		   All error messages are internal driver checking only! */		/* video display top and bottom registers */		reg = (u32) zr->buffer.base		    + zr->window.x * bpp		    + zr->window.y * zr->buffer.bytesperline;		btwrite(reg, ZR36057_VDTR);		if (reg & 3)			printk(KERN_ERR "%s: zr36057_overlay: video_address not aligned\n", zr->name);		if (zr->video_interlace)			reg += zr->buffer.bytesperline;		btwrite(reg, ZR36057_VDBR);		/* video stride, status, and frame grab register */		reg = zr->buffer.bytesperline - zr->window.width * bpp;		if (zr->video_interlace)			reg += zr->buffer.bytesperline;		if (reg & 3)			printk(KERN_ERR "%s: zr36057_overlay: video_stride not aligned\n", zr->name);		reg = (reg << ZR36057_VSSFGR_DispStride);		reg |= ZR36057_VSSFGR_VidOvf;	/* clear overflow status */		btwrite(reg, ZR36057_VSSFGR);		/* Set overlay clipping */		if (zr->window.clipcount)			btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);		/* ... and switch it on */		btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);	} else {		/* Switch it off */		btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);	}}/* * The overlay mask has one bit for each pixel on a scan line, *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. */static void write_overlay_mask(struct zoran *zr, struct video_clip *vp, int count){	unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;	u32 *mask;	int x, y, width, height;	unsigned i, j, k;	u32 reg;	/* fill mask with one bits */	memset(zr->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);	reg = 0;	for (i = 0; i < count; ++i) {		/* pick up local copy of clip */		x = vp[i].x;		y = vp[i].y;		width = vp[i].width;		height = vp[i].height;		/* trim clips that extend beyond the window */		if (x < 0) {			width += x;			x = 0;		}		if (y < 0) {			height += y;			y = 0;		}		if (x + width > zr->window.width) {			width = zr->window.width - x;		}		if (y + height > zr->window.height) {			height = zr->window.height - y;		}		/* ignore degenerate clips */		if (height <= 0) {			continue;		}		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(ZR36057_ICR_GIRQ0, ZR36057_ICR);		/* enable SnapShot */		btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);		/* Set zr36057 video front end  and enable video */#ifdef XAWTV_HACK		zr36057_set_vfe(zr, zr->gwidth > 720 ? 720 : zr->gwidth, zr->gheight, zr->gformat);#else		zr36057_set_vfe(zr, zr->gwidth, zr->gheight, zr->gformat);#endif		zr->v4l_memgrab_active = 1;	} else {		zr->v4l_memgrab_active = 0;		/* switch off VSync interrupts */		btand(~ZR36057_ICR_GIRQ0, ZR36057_ICR);		/* 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 her, 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)		return -EINVAL;	/* Check size and format of the grab wanted */	if (mp->height < BUZ_MIN_HEIGHT || mp->width < BUZ_MIN_WIDTH)		return -EINVAL;	if (mp->height > BUZ_MAX_HEIGHT || mp->width > BUZ_MAX_WIDTH)		return -EINVAL;	bpp = format2bpp(mp->format);	if (bpp == 0)		return -EINVAL;	/* Check against available buffer size */	if (mp->height * mp->width * bpp > v4l_bufsize)		return -EINVAL;	/* The video front end needs 4-byte alinged line sizes */	if ((bpp == 2 && (mp->width & 1)) || (bpp == 3 && (mp->width & 3)))		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);	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) {		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) {//		printk(KERN_ERR "%s: v4l_sync: Trying to sync on a buffer which was not queued?\n", zr->name);		return -EINVAL;	}	/* 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;	u32 ct=0;	while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {		ct++;		if(ct>100000)		{			printk(KERN_ERR "%s: timeout on post office.\n", zr->name);			return -1;		}		/* wait for something to happen */	}	if ((por & ZR36057_POR_POPen) != 0) {		printk(KERN_WARNING "%s: pop pending %08x\n", zr->name, por);		return -1;	}	if ((por & (ZR36057_POR_POTime | ZR36057_POR_POPen)) != 0) {		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;	post_office_wait(zr);	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;	post_office_wait(zr);	por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);	btwrite(por, ZR36057_POR);	if (post_office_wait(zr) < 0) {		return -1;	}

⌨️ 快捷键说明

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