ivtv-ioctl.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,920 行 · 第 1/4 页
C
1,920 行
}static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt){ return ivtv_g_fmt_vbi_cap(file, fh, fmt);}static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt){ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; if (id->type == IVTV_DEC_STREAM_TYPE_VBI) return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt); /* set sliced VBI capture format */ vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; vbifmt->reserved[0] = 0; vbifmt->reserved[1] = 0; if (vbifmt->service_set) ivtv_expand_service_set(vbifmt, itv->is_50hz); check_service_set(vbifmt, itv->is_50hz); vbifmt->service_set = ivtv_get_service_set(vbifmt); return 0;}static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv_open_id *id = fh; s32 w = fmt->fmt.pix.width; s32 h = fmt->fmt.pix.height; int field = fmt->fmt.pix.field; int ret = ivtv_g_fmt_vid_out(file, fh, fmt); w = min(w, 720); w = max(w, 2); /* Why can the height be 576 even when the output is NTSC? Internally the buffers of the PVR350 are always set to 720x576. The decoded video frame will always be placed in the top left corner of this buffer. For any video which is not 720x576, the buffer will then be cropped to remove the unused right and lower areas, with the remaining image being scaled by the hardware to fit the display area. The video can be scaled both up and down, so a 720x480 video can be displayed full-screen on PAL and a 720x576 video can be displayed without cropping on NTSC. Note that the scaling only occurs on the video stream, the osd resolution is locked to the broadcast standard and not scaled. Thanks to Ian Armstrong for this explanation. */ h = min(h, 576); h = max(h, 2); if (id->type == IVTV_DEC_STREAM_TYPE_YUV) fmt->fmt.pix.field = field; fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; return ret;}static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; u32 chromakey = fmt->fmt.win.chromakey; u8 global_alpha = fmt->fmt.win.global_alpha; if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; ivtv_g_fmt_vid_out_overlay(file, fh, fmt); fmt->fmt.win.chromakey = chromakey; fmt->fmt.win.global_alpha = global_alpha; return 0;}static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt){ return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);}static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct cx2341x_mpeg_params *p = &itv->params; int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; if (ret) return ret; if (p->width == w && p->height == h) return 0; if (atomic_read(&itv->capturing) > 0) return -EBUSY; p->width = w; p->height = h; if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) fmt->fmt.pix.width /= 2; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); return ivtv_g_fmt_vid_cap(file, fh, fmt);}static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) return -EBUSY; itv->vbi.sliced_in->service_set = 0; itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); return ivtv_g_fmt_vbi_cap(file, fh, fmt);}static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt){ struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt); if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) return ret; check_service_set(vbifmt, itv->is_50hz); if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) return -EBUSY; itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); return 0;}static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; int ret = ivtv_try_fmt_vid_out(file, fh, fmt); if (ret) return ret; if (id->type != IVTV_DEC_STREAM_TYPE_YUV) return 0; /* Return now if we already have some frame data */ if (yi->stream_size) return -EBUSY; yi->v4l2_src_w = fmt->fmt.pix.width; yi->v4l2_src_h = fmt->fmt.pix.height; switch (fmt->fmt.pix.field) { case V4L2_FIELD_NONE: yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; break; case V4L2_FIELD_ANY: yi->lace_mode = IVTV_YUV_MODE_AUTO; break; case V4L2_FIELD_INTERLACED_BT: yi->lace_mode = IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; break; case V4L2_FIELD_INTERLACED_TB: default: yi->lace_mode = IVTV_YUV_MODE_INTERLACED; break; } yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) itv->dma_data_req_size = 1080 * ((yi->v4l2_src_h + 31) & ~31); return 0;}static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt); if (ret == 0) { itv->osd_chroma_key = fmt->fmt.win.chromakey; itv->osd_global_alpha = fmt->fmt.win.global_alpha; ivtv_set_osd_alpha(itv); } return ret;}static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; chip->ident = V4L2_IDENT_NONE; chip->revision = 0; if (chip->match_type == V4L2_CHIP_MATCH_HOST) { if (v4l2_chip_match_host(chip->match_type, chip->match_chip)) chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; return 0; } if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) return ivtv_i2c_id(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip); if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR) return ivtv_call_i2c_client(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip); return -EINVAL;}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg){ struct v4l2_register *regs = arg; unsigned long flags; volatile u8 __iomem *reg_start; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) reg_start = itv->reg_mem - IVTV_REG_OFFSET; else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE) reg_start = itv->enc_mem; else return -EINVAL; spin_lock_irqsave(&ivtv_cards_lock, flags); if (cmd == VIDIOC_DBG_G_REGISTER) regs->val = readl(regs->reg + reg_start); else writel(regs->val, regs->reg + reg_start); spin_unlock_irqrestore(&ivtv_cards_lock, flags); return 0;}static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg); return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg);}static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg); return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);}#endifstatic int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; *p = v4l2_prio_max(&itv->prio); return 0;}static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; return v4l2_prio_change(&itv->prio, &id->prio, prio);}static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev)); vcap->version = IVTV_DRIVER_VERSION; /* version */ vcap->capabilities = itv->v4l2_cap; /* capabilities */ return 0;}static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; return ivtv_get_audio_input(itv, vin->index, vin);}static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; vin->index = itv->audio_input; return ivtv_get_audio_input(itv, vin->index, vin);}static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; if (vout->index >= itv->nof_audio_inputs) return -EINVAL; itv->audio_input = vout->index; ivtv_audio_set_io(itv); return 0;}static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; /* set it to defaults from our table */ return ivtv_get_audio_output(itv, vin->index, vin);}static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; vin->index = 0; return ivtv_get_audio_output(itv, vin->index, vin);}static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; return ivtv_get_audio_output(itv, vout->index, vout);}static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; /* set it to defaults from our table */ return ivtv_get_input(itv, vin->index, vin);}static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; return ivtv_get_output(itv, vout->index, vout);}static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; int streamtype; streamtype = id->type; if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; cropcap->bounds.top = cropcap->bounds.left = 0; cropcap->bounds.width = 720; if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { cropcap->bounds.height = itv->is_50hz ? 576 : 480; cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { if (yi->track_osd) { cropcap->bounds.width = yi->osd_full_w; cropcap->bounds.height = yi->osd_full_h; } else { cropcap->bounds.width = 720; cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; } cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; } else { cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; } cropcap->defrect = cropcap->bounds; return 0;}static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; int streamtype; streamtype = id->type; if (ivtv_debug & IVTV_DBGFLG_IOCTL) { printk(KERN_INFO "ivtv%d ioctl: ", itv->num); /* Should be replaced */ /* v4l_printk_ioctl(VIDIOC_S_CROP); */ } if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { yi->main_rect = crop->c; return 0; } else { if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { itv->main_rect = crop->c; return 0; } } return -EINVAL; } return -EINVAL;}static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop){ struct ivtv_open_id *id = fh; struct ivtv *itv = id->itv; struct yuv_playback_info *yi = &itv->yuv_info; int streamtype; streamtype = id->type; if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) crop->c = yi->main_rect; else crop->c = itv->main_rect; return 0; } return -EINVAL;}static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt){ static struct v4l2_fmtdesc formats[] = { { 0, 0, 0, "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } }, { 1, 0, V4L2_FMT_FLAG_COMPRESSED, "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 } } }; enum v4l2_buf_type type = fmt->type; if (fmt->index > 1) return -EINVAL; *fmt = formats[fmt->index]; fmt->type = type; return 0;}static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt){ struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; static struct v4l2_fmtdesc formats[] = { { 0, 0, 0, "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 } },
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?