📄 zoran_driver.c
字号:
vcap->channels = zr->card.inputs; vcap->audios = 0; down(&zr->resource_lock); vcap->maxwidth = BUZ_MAX_WIDTH; vcap->maxheight = BUZ_MAX_HEIGHT; vcap->minwidth = BUZ_MIN_WIDTH; vcap->minheight = BUZ_MIN_HEIGHT; up(&zr->resource_lock); return 0; } break; case VIDIOCGCHAN: { struct video_channel *vchan = arg; int channel = vchan->channel; dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n", ZR_DEVNAME(zr), vchan->channel); memset(vchan, 0, sizeof(struct video_channel)); if (channel > zr->card.inputs || channel < 0) { dprintk(1, KERN_ERR "%s: VIDIOCGCHAN on not existing channel %d\n", ZR_DEVNAME(zr), channel); return -EINVAL; } strcpy(vchan->name, zr->card.input[channel].name); vchan->tuners = 0; vchan->flags = 0; vchan->type = VIDEO_TYPE_CAMERA; down(&zr->resource_lock); vchan->norm = zr->norm; up(&zr->resource_lock); vchan->channel = channel; return 0; } break; /* 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 *vchan = arg; int res; dprintk(3, KERN_DEBUG "%s: VIDIOCSCHAN - channel=%d, norm=%d\n", ZR_DEVNAME(zr), vchan->channel, vchan->norm); down(&zr->resource_lock); if ((res = zoran_set_input(zr, vchan->channel))) goto schan_unlock_and_return; if ((res = zoran_set_norm(zr, vchan->norm))) goto schan_unlock_and_return; /* Make sure the changes come into effect */ res = wait_grab_pending(zr); schan_unlock_and_return: up(&zr->resource_lock); return res; } break; case VIDIOCGPICT: { struct video_picture *vpict = arg; dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr)); memset(vpict, 0, sizeof(struct video_picture)); down(&zr->resource_lock); vpict->hue = zr->hue; vpict->brightness = zr->brightness; vpict->contrast = zr->contrast; vpict->colour = zr->saturation; if (fh->overlay_settings.format) { vpict->depth = fh->overlay_settings.format->depth; vpict->palette = fh->overlay_settings.format->palette; } else { vpict->depth = 0; } up(&zr->resource_lock); return 0; } break; case VIDIOCSPICT: { struct video_picture *vpict = arg; int i; dprintk(3, KERN_DEBUG "%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n", ZR_DEVNAME(zr), vpict->brightness, vpict->hue, vpict->colour, vpict->contrast, vpict->depth, vpict->palette); for (i = 0; i < zoran_num_formats; i++) { const struct zoran_format *fmt = &zoran_formats[i]; if (fmt->palette != -1 && fmt->flags & ZORAN_FORMAT_OVERLAY && fmt->palette == vpict->palette && fmt->depth == vpict->depth) break; } if (i == zoran_num_formats) { dprintk(1, KERN_ERR "%s: VIDIOCSPICT - Invalid palette %d\n", ZR_DEVNAME(zr), vpict->palette); return -EINVAL; } down(&zr->resource_lock); decoder_command(zr, DECODER_SET_PICTURE, vpict); zr->hue = vpict->hue; zr->contrast = vpict->contrast; zr->saturation = vpict->colour; zr->brightness = vpict->brightness; fh->overlay_settings.format = &zoran_formats[i]; up(&zr->resource_lock); return 0; } break; case VIDIOCCAPTURE: { int *on = arg, res; dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n", ZR_DEVNAME(zr), *on); down(&zr->resource_lock); res = setup_overlay(file, *on); up(&zr->resource_lock); return res; } break; case VIDIOCGWIN: { struct video_window *vwin = arg; dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr)); memset(vwin, 0, sizeof(struct video_window)); down(&zr->resource_lock); vwin->x = fh->overlay_settings.x; vwin->y = fh->overlay_settings.y; vwin->width = fh->overlay_settings.width; vwin->height = fh->overlay_settings.height; up(&zr->resource_lock); vwin->clipcount = 0; return 0; } break; case VIDIOCSWIN: { struct video_window *vwin = arg; int res; dprintk(3, KERN_DEBUG "%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n", ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width, vwin->height, vwin->clipcount); down(&zr->resource_lock); res = setup_window(file, vwin->x, vwin->y, vwin->width, vwin->height, vwin->clips, vwin->clipcount, NULL); up(&zr->resource_lock); return res; } break; case VIDIOCGFBUF: { struct video_buffer *vbuf = arg; dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr)); down(&zr->resource_lock); *vbuf = zr->buffer; up(&zr->resource_lock); return 0; } break; case VIDIOCSFBUF: { struct video_buffer *vbuf = arg; int i, res = 0; dprintk(3, KERN_DEBUG "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n", ZR_DEVNAME(zr), vbuf->base, vbuf->width, vbuf->height, vbuf->depth, vbuf->bytesperline); for (i = 0; i < zoran_num_formats; i++) if (zoran_formats[i].depth == vbuf->depth) break; if (i == zoran_num_formats) { dprintk(1, KERN_ERR "%s: VIDIOCSFBUF - invalid fbuf depth %d\n", ZR_DEVNAME(zr), vbuf->depth); return -EINVAL; } down(&zr->resource_lock); res = setup_fbuffer(file, vbuf->base, &zoran_formats[i], vbuf->width, vbuf->height, vbuf->bytesperline); up(&zr->resource_lock); return res; } break; case VIDIOCSYNC: { int *frame = arg, res; dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n", ZR_DEVNAME(zr), *frame); down(&zr->resource_lock); res = v4l_sync(file, *frame); up(&zr->resource_lock); if (!res) zr->v4l_sync_tail++; return res; } break; case VIDIOCMCAPTURE: { struct video_mmap *vmap = arg; int res; dprintk(3, KERN_DEBUG "%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n", ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height, vmap->format); down(&zr->resource_lock); res = v4l_grab(file, vmap); up(&zr->resource_lock); return res; } break; case VIDIOCGMBUF: { struct video_mbuf *vmbuf = arg; int i, res = 0; dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr)); vmbuf->size = fh->v4l_buffers.num_buffers * fh->v4l_buffers.buffer_size; vmbuf->frames = fh->v4l_buffers.num_buffers; for (i = 0; i < vmbuf->frames; i++) { vmbuf->offsets[i] = i * fh->v4l_buffers.buffer_size; } down(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOCGMBUF - buffers already allocated\n", ZR_DEVNAME(zr)); res = -EINVAL; goto v4l1reqbuf_unlock_and_return; } if (v4l_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l1reqbuf_unlock_and_return; } /* The next mmap will map the V4L buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; v4l1reqbuf_unlock_and_return: up(&zr->resource_lock); return res; } break; case VIDIOCGUNIT: { struct video_unit *vunit = arg; dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr)); vunit->video = zr->video_dev->minor; vunit->vbi = VIDEO_NO_UNIT; vunit->radio = VIDEO_NO_UNIT; vunit->audio = VIDEO_NO_UNIT; vunit->teletext = VIDEO_NO_UNIT; return 0; } break; /* * RJ: In principal we could support subcaptures for V4L grabbing. * Not even the famous BTTV driver has them, however. * If there should be a strong demand, one could consider * to implement them. */ case VIDIOCGCAPTURE: { dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n", ZR_DEVNAME(zr)); return -EINVAL; } break; case VIDIOCSCAPTURE: { dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n", ZR_DEVNAME(zr)); return -EINVAL; } break; case BUZIOC_G_PARAMS: { struct zoran_params *bparams = arg; dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr)); memset(bparams, 0, sizeof(struct zoran_params)); bparams->major_version = MAJOR_VERSION; bparams->minor_version = MINOR_VERSION; down(&zr->resource_lock); bparams->norm = zr->norm; bparams->input = zr->input; bparams->decimation = fh->jpg_settings.decimation; bparams->HorDcm = fh->jpg_settings.HorDcm; bparams->VerDcm = fh->jpg_settings.VerDcm; bparams->TmpDcm = fh->jpg_settings.TmpDcm; bparams->field_per_buff = fh->jpg_settings.field_per_buff; bparams->img_x = fh->jpg_settings.img_x; bparams->img_y = fh->jpg_settings.img_y; bparams->img_width = fh->jpg_settings.img_width; bparams->img_height = fh->jpg_settings.img_height; bparams->odd_even = fh->jpg_settings.odd_even; bparams->quality = fh->jpg_settings.jpg_comp.quality; bparams->APPn = fh->jpg_settings.jpg_comp.APPn; bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len; memcpy(bparams->APP_data, fh->jpg_settings.jpg_comp.APP_data, sizeof(bparams->APP_data)); bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len; memcpy(bparams->COM_data, fh->jpg_settings.jpg_comp.COM_data, sizeof(bparams->COM_data)); bparams->jpeg_markers = fh->jpg_settings.jpg_comp.jpeg_markers; up(&zr->resource_lock); bparams->VFIFO_FB = 0; return 0; } break; case BUZIOC_S_PARAMS: { struct zoran_params *bparams = arg; int res = 0; dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr)); settings.decimation = bparams->decimation; settings.HorDcm = bparams->HorDcm; settings.VerDcm = bparams->VerDcm; settings.TmpDcm = bparams->TmpDcm; settings.field_per_buff = bparams->field_per_buff; settings.img_x = bparams->img_x; settings.img_y = bparams->img_y; settings.img_width = bparams->img_width; settings.img_height = bparams->img_height; settings.odd_even = bparams->odd_even; settings.jpg_comp.quality = bparams->quality; settings.jpg_comp.APPn = bparams->APPn; settings.jpg_comp.APP_len = bparams->APP_len; memcpy(settings.jpg_comp.APP_data, bparams->APP_data, sizeof(bparams->APP_data)); settings.jpg_comp.COM_len = bparams->COM_len; memcpy(settings.jpg_comp.COM_data, bparams->COM_data, sizeof(bparams->COM_data)); settings.jpg_comp.jpeg_markers = bparams->jpeg_markers; down(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { dprintk(1, KERN_ERR "%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n", ZR_DEVNAME(zr)); res = -EINVAL; goto sparams_unlock_and_return; } /* Check the params first before overwriting our * nternal values */ if (zoran_check_jpg_settings(zr, &settings)) { res = -EINVAL; goto sparams_unlock_and_return; } fh->jpg_settings = settings; sparams_unlock_and_return: up(&zr->resource_lock); return res; } break; case BUZIOC_REQBUFS: { struct zoran_requestbuffers *breq = arg; int res = 0; dprintk(3, KERN_DEBUG "%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n", ZR_DEVNAME(zr), breq->count, breq->size); /* Enforce reasonable lower and upper limits */ if (breq->count < 4) breq->count = 4; /* Could be choosen smaller */ if (breq->count > jpg_nbufs) breq->count = jpg_nbufs; breq->size = PAGE_ALIGN(breq->size); if (breq->size < 8192) breq->size = 8192; /* Arbitrary */ /* breq->size is limited by 1 page for the stat_com * tables to a Maximum of 2 MB */ if (breq->size > jpg_bufsize) breq->size = jpg_bufsize; if (fh->jpg_buffers.need_contiguous && breq->size > MAX_KMALLOC_MEM) breq->size = MAX_KMALLOC_MEM; down(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, KERN_ERR "%s: BUZIOC_REQBUFS - buffers allready allocated\n", ZR_DEVNAME(zr)); res = -EBUSY; goto jpgreqbuf_unlock_and_return; } fh->jpg_buffers.num_buffers = breq->count; fh->jpg_buffers.buffer_size = breq->size; if (jpg_fbuffer_alloc(file)) { res = -ENOMEM; goto jpgreqbuf_unlock_and_return; } /* The next mmap will map the MJPEG buffers - could * also be *_PLAY, but it doesn't matter here */ fh->map_mode = ZORAN_MAP_MODE_JPG_REC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -