📄 buz.c
字号:
/* insert constant params */ params->major_version = MAJOR_VERSION; params->minor_version = MINOR_VERSION; /* Check input and norm */ if (params->input != 0 && params->input != 1) { err++; } if (params->norm != VIDEO_MODE_PAL && params->norm != VIDEO_MODE_NTSC) { err++; } /* Check decimation, set default values for decimation = 1, 2, 4 */ switch (params->decimation) { case 1: params->HorDcm = 1; params->VerDcm = 1; params->TmpDcm = 1; params->field_per_buff = 2; params->img_x = 0; params->img_y = 0; params->img_width = 720; params->img_height = tvnorms[params->norm].Ha / 2; break; case 2: params->HorDcm = 2; params->VerDcm = 1; params->TmpDcm = 2; params->field_per_buff = 1; params->img_x = 8; params->img_y = 0; params->img_width = 704; params->img_height = tvnorms[params->norm].Ha / 2; break; case 4: params->HorDcm = 4; params->VerDcm = 2; params->TmpDcm = 2; params->field_per_buff = 1; params->img_x = 8; params->img_y = 0; params->img_width = 704; params->img_height = tvnorms[params->norm].Ha / 2; break; case 0: /* We have to check the data the user has set */ if (params->HorDcm != 1 && params->HorDcm != 2 && params->HorDcm != 4) err0++; if (params->VerDcm != 1 && params->VerDcm != 2) err0++; if (params->TmpDcm != 1 && params->TmpDcm != 2) err0++; if (params->field_per_buff != 1 && params->field_per_buff != 2) err0++; if (params->img_x < 0) err0++; if (params->img_y < 0) err0++; if (params->img_width < 0) err0++; if (params->img_height < 0) err0++; if (params->img_x + params->img_width > 720) err0++; if (params->img_y + params->img_height > tvnorms[params->norm].Ha / 2) err0++; if (params->img_width % (16 * params->HorDcm) != 0) err0++; if (params->img_height % (8 * params->VerDcm) != 0) err0++; if (err0) { err++; } break; default: err++; break; } if (params->quality > 100) params->quality = 100; if (params->quality < 5) params->quality = 5; if (params->APPn < 0) params->APPn = 0; if (params->APPn > 15) params->APPn = 15; if (params->APP_len < 0) params->APP_len = 0; if (params->APP_len > 60) params->APP_len = 60; if (params->COM_len < 0) params->COM_len = 0; if (params->COM_len > 60) params->COM_len = 60; if (err) return -EINVAL; return 0;}static void zoran_open_init_params(struct zoran *zr){ int i; /* Per default, map the V4L Buffers */ zr->map_mjpeg_buffers = 0; /* User must explicitly set a window */ zr->window_set = 0; zr->window.x = 0; zr->window.y = 0; zr->window.width = 0; zr->window.height = 0; zr->window.chromakey = 0; zr->window.flags = 0; zr->window.clips = NULL; zr->window.clipcount = 0; zr->video_interlace = 0; zr->v4l_memgrab_active = 0; zr->v4l_overlay_active = 0; zr->v4l_grab_frame = NO_GRAB_ACTIVE; zr->v4l_grab_seq = 0; zr->gwidth = 0; zr->gheight = 0; zr->gformat = 0; zr->gbpl = 0; /* DMA ring stuff for V4L */ zr->v4l_pend_tail = 0; zr->v4l_pend_head = 0; for (i = 0; i < v4l_nbufs; i++) { zr->v4l_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ } /* Set necessary params and call zoran_check_params to set the defaults */ zr->params.decimation = 1; zr->params.quality = 50; /* default compression factor 8 */ zr->params.odd_even = 1; zr->params.APPn = 0; zr->params.APP_len = 0; /* No APPn marker */ for (i = 0; i < 60; i++) zr->params.APP_data[i] = 0; zr->params.COM_len = 0; /* No COM marker */ for (i = 0; i < 60; i++) zr->params.COM_data[i] = 0; zr->params.VFIFO_FB = 0; memset(zr->params.reserved, 0, sizeof(zr->params.reserved)); zr->params.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; i = zoran_check_params(zr, &zr->params); if (i) printk(KERN_ERR "%s: zoran_open_init_params internal error\n", zr->name);}/* * Open a buz card. Right now the flags stuff is just playing */static int zoran_open(struct video_device *dev, int flags){ struct zoran *zr = (struct zoran *) dev; DEBUG(printk(KERN_INFO ": zoran_open\n")); switch (flags) { case 0: if (zr->user) return -EBUSY; zr->user++; if (v4l_fbuffer_alloc(zr) < 0) { zr->user--; return -ENOMEM; } /* default setup */ zoran_open_init_params(zr); zr36057_enable_jpg(zr, BUZ_MODE_IDLE); btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts btor(ZR36057_ICR_IntPinEn, ZR36057_ICR); break; default: return -EBUSY; } MOD_INC_USE_COUNT; return 0;}static void zoran_close(struct video_device *dev){ struct zoran *zr = (struct zoran *) dev; DEBUG(printk(KERN_INFO ": zoran_close\n")); /* disable interrupts */ btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); /* wake up sleeping beauties */ wake_up_interruptible(&zr->v4l_capq); wake_up_interruptible(&zr->jpg_capq); zr36057_enable_jpg(zr, BUZ_MODE_IDLE); zr36057_set_memgrab(zr, 0); if (zr->v4l_overlay_active) zr36057_overlay(zr, 0); zr->user--; v4l_fbuffer_free(zr); jpg_fbuffer_free(zr); zr->jpg_nbufs = 0; MOD_DEC_USE_COUNT; DEBUG(printk(KERN_INFO ": zoran_close done\n"));}static long zoran_read(struct video_device *dev, char *buf, unsigned long count, int nonblock){ return -EINVAL;}static long zoran_write(struct video_device *dev, const char *buf, unsigned long count, int nonblock){ return -EINVAL;}/* * ioctl routine */static int zoran_ioctl(struct video_device *dev, unsigned int cmd, void *arg){ struct zoran *zr = (struct zoran *) dev; switch (cmd) { case VIDIOCGCAP: { struct video_capability b; IOCTL_DEBUG(printk("buz ioctl VIDIOCGCAP\n")); strncpy(b.name, zr->video_dev.name, sizeof(b.name)); b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | VID_TYPE_SCALES; /* theoretically we could also flag VID_TYPE_SUBCAPTURE but this is not even implemented in the BTTV driver */ b.channels = 2; /* composite, svhs */ b.audios = 0; b.maxwidth = BUZ_MAX_WIDTH; b.maxheight = BUZ_MAX_HEIGHT; b.minwidth = BUZ_MIN_WIDTH; b.minheight = BUZ_MIN_HEIGHT; if (copy_to_user(arg, &b, sizeof(b))) { return -EFAULT; } return 0; } case VIDIOCGCHAN: { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) { return -EFAULT; } IOCTL_DEBUG(printk("buz ioctl VIDIOCGCHAN for channel %d\n", v.channel)); switch (v.channel) { case 0: strcpy(v.name, "Composite"); break; case 1: strcpy(v.name, "SVHS"); break; default: return -EINVAL; } v.tuners = 0; v.flags = 0; v.type = VIDEO_TYPE_CAMERA; v.norm = zr->params.norm; if (copy_to_user(arg, &v, sizeof(v))) { return -EFAULT; } return 0; } /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." * ^^^^^^^ * The famos BTTV driver has it implemented with a struct video_channel argument * and we follow it for compatibility reasons * * BTW: this is the only way the user can set the norm! */ case VIDIOCSCHAN: { struct video_channel v; int input; int on, res; if (copy_from_user(&v, arg, sizeof(v))) { return -EFAULT; } IOCTL_DEBUG(printk("buz ioctl VIDIOCSCHAN: channel=%d, norm=%d\n", v.channel, v.norm)); switch (v.channel) { case 0: input = 3; break; case 1: input = 7; break; default: return -EINVAL; } if (v.norm != VIDEO_MODE_PAL && v.norm != VIDEO_MODE_NTSC) { return -EINVAL; } zr->params.norm = v.norm; zr->params.input = v.channel; /* We switch overlay off and on since a change in the norm needs different VFE settings */ on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; if (on) zr36057_overlay(zr, 0); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); if (on) zr36057_overlay(zr, 1); /* Make sure the changes come into effect */ res = wait_grab_pending(zr); if (res) return res; return 0; } case VIDIOCGTUNER: case VIDIOCSTUNER: return -EINVAL; case VIDIOCGPICT: { struct video_picture p = zr->picture; IOCTL_DEBUG(printk("buz ioctl VIDIOCGPICT\n")); p.depth = zr->buffer.depth; switch (zr->buffer.depth) { case 15: p.palette = VIDEO_PALETTE_RGB555; break; case 16: p.palette = VIDEO_PALETTE_RGB565; break; case 24: p.palette = VIDEO_PALETTE_RGB24; break; case 32: p.palette = VIDEO_PALETTE_RGB32; break; } if (copy_to_user(arg, &p, sizeof(p))) { return -EFAULT; } return 0; } case VIDIOCSPICT: { struct video_picture p; if (copy_from_user(&p, arg, sizeof(p))) { return -EFAULT; } i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); IOCTL_DEBUG(printk("buz ioctl VIDIOCSPICT bri=%d hue=%d col=%d con=%d dep=%d pal=%d\n", p.brightness, p.hue, p.colour, p.contrast, p.depth, p.palette)); /* The depth and palette values have no meaning to us, should we return -EINVAL if they don't fit ? */ zr->picture = p; return 0; } case VIDIOCCAPTURE: { int v, res; if (copy_from_user(&v, arg, sizeof(v))) { return -EFAULT; } IOCTL_DEBUG(printk("buz ioctl VIDIOCCAPTURE: %d\n", v)); /* If there is nothing to do, return immediatly */ if ((v && zr->v4l_overlay_active) || (!v && !zr->v4l_overlay_active)) return 0; if (v == 0) { zr->v4l_overlay_active = 0; if (!zr->v4l_memgrab_active) zr36057_overlay(zr, 0); /* When a grab is running, the video simply won't be switched on any more */ } else { if (!zr->buffer_set || !zr->window_set) { return -EINVAL; } zr->v4l_overlay_active = 1; if (!zr->v4l_memgrab_active) zr36057_overlay(zr, 1); /* When a grab is running, the video will be switched on when grab is finished */ } /* Make sure the changes come into effect */ res = wait_grab_pending(zr); if (res) return res; return 0; } case VIDIOCGWIN: { IOCTL_DEBUG(printk("buz ioctl VIDIOCGWIN\n")); if (copy_to_user(arg, &zr->window, sizeof(zr->window))) { return -EFAULT; } return 0; } case VIDIOCSWIN: { struct video_clip *vcp; struct video_window vw; int on, end, res; if (copy_from_user(&vw, arg, sizeof(vw))) { return -EFAULT; } IOCTL_DEBUG(printk("buz ioctl VIDIOCSWIN: x=%d y=%d w=%d h=%d clipcount=%d\n", vw.x, vw.y, vw.width, vw.height, vw.clipcount)); if (!zr->buffer_set) { return -EINVAL; } /* * The video front end needs 4-byte alinged line sizes, we correct that * silently here if necessary */ if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { end = (vw.x + vw.width) & ~1; /* round down */ vw.x = (vw.x + 1) & ~1; /* round up */ vw.width = end - vw.x; } if (zr->buffer.depth == 24) { end = (vw.x + vw.wid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -