static int vpif_update_std_info(struct channel_obj *ch) { struct video_obj *vid_ch = &ch->video; struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; const struct vpif_channel_config_params *config; int i; for (i = 0; i < vpif_ch_params_count; i++) { config = &ch_params[i]; if (config->hd_sd == 0) { vpif_dbg(2, debug, "SD format\n"); if (config->stdid & vid_ch->stdid) { memcpy(std_info, config, sizeof(*config)); break; } } else { vpif_dbg(2, debug, "HD format\n"); if (config->dv_preset == vid_ch->dv_preset) { memcpy(std_info, config, sizeof(*config)); break; } } } if (i == vpif_ch_params_count) { vpif_dbg(1, debug, "Format not found\n"); return -EINVAL; } return 0; }
/** * vpif_s_std() - set STD handler * @file: file ptr * @priv: file handle * @std_id: ptr to std id */ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; vpif_dbg(2, debug, "vpif_s_std\n"); if (common->started) { vpif_err("streaming in progress\n"); return -EBUSY; } if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; /* Call encoder subdevice function to set the standard */ if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; ch->video.stdid = *std_id; /* Get the information about the standard */ if (vpif_update_std_info(ch)) { ret = -EINVAL; vpif_err("Error getting the standard info\n"); goto s_std_exit; } /* Configure the default format information */ vpif_config_format(ch); /* set standard in the sub device */ ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, s_std, *std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); s_std_exit: mutex_unlock(&common->lock); return ret; }
/** * vpif_streamoff() - streamoff handler * @file: file ptr * @priv: file handle * @buftype: v4l2 buffer type */ static int vpif_streamoff(struct file *file, void *priv, enum v4l2_buf_type buftype) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret; vpif_dbg(2, debug, "vpif_streamoff\n"); if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { vpif_dbg(1, debug, "buffer type not supported\n"); return -EINVAL; } /* If io is allowed for this file handle, return error */ if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { vpif_dbg(1, debug, "io not allowed\n"); return -EACCES; } /* If streaming is not started, return error */ if (!common->started) { vpif_dbg(1, debug, "channel->started\n"); return -EINVAL; } if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; /* disable channel */ if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { enable_channel0(0); channel0_intr_enable(0); } else { enable_channel1(0); channel1_intr_enable(0); } common->started = 0; ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, s_stream, 0); if (ret && (ret != -ENOIOCTLCMD)) vpif_dbg(1, debug, "stream off failed in subdev\n"); mutex_unlock(&common->lock); return videobuf_streamoff(&common->buffer_queue); }
static int vpif_s_dv_preset(struct file *file, void *priv, struct v4l2_dv_preset *preset) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; if (common->started) { vpif_dbg(1, debug, "streaming in progress\n"); return -EBUSY; } if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } ret = v4l2_prio_check(&ch->prio, fh->prio); if (ret) return ret; fh->initialized = 1; if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; ch->video.dv_preset = preset->preset; ch->video.stdid = V4L2_STD_UNKNOWN; memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); if (vpif_update_std_info(ch)) { vpif_dbg(1, debug, "Error getting the standard info\n"); ret = -EINVAL; } else { vpif_config_format(ch); ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, s_dv_preset, preset); } mutex_unlock(&common->lock); return ret; }
/** * buffer_prepare : callback function for buffer prepare * @q : buffer queue ptr * @vb: ptr to video buffer * @field: field info * * This is the callback function for buffer prepare when videobuf_qbuf() * function is called. The buffer is prepared and user space virtual address * or user address is converted into physical address */ static int vpif_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { /* Get the file handle object and channel object */ struct vpif_fh *fh = q->priv_data; struct channel_obj *ch = fh->channel; struct common_obj *common; unsigned long addr; vpif_dbg(2, debug, "vpif_buffer_prepare\n"); common = &ch->common[VPIF_VIDEO_INDEX]; /* If buffer is not initialized, initialize it */ if (VIDEOBUF_NEEDS_INIT == vb->state) { vb->width = common->width; vb->height = common->height; vb->size = vb->width * vb->height; vb->field = field; } vb->state = VIDEOBUF_PREPARED; /** * if user pointer memory mechanism is used, get the physical * address of the buffer */ if (V4L2_MEMORY_USERPTR == common->memory) { if (0 == vb->baddr) { vpif_dbg(1, debug, "buffer address is 0\n"); return -EINVAL; } vb->boff = vpif_uservirt_to_phys(vb->baddr); if (!IS_ALIGNED(vb->boff, 8)) goto exit; } addr = vb->boff; if (q->streaming) { if (!IS_ALIGNED((addr + common->ytop_off), 8) || !IS_ALIGNED((addr + common->ybtm_off), 8) || !IS_ALIGNED((addr + common->ctop_off), 8) || !IS_ALIGNED((addr + common->cbtm_off), 8)) goto exit; } return 0; exit: vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n"); return -EINVAL; }
static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; vpif_dbg(2, debug, "vpif_s_std\n"); if (common->started) { vpif_err("streaming in progress\n"); return -EBUSY; } if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; ch->video.stdid = *std_id; ch->video.dv_preset = V4L2_DV_INVALID; memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); if (vpif_update_std_info(ch)) { vpif_err("Error getting the standard info\n"); return -EINVAL; } vpif_config_format(ch); ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, s_std, *std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); return ret; }
static int vpif_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbuf) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common; u8 index = 0; vpif_dbg(2, debug, "vpif_reqbufs\n"); if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type) return -EINVAL; index = VPIF_VIDEO_INDEX; common = &ch->common[index]; if (0 != common->io_usrs) return -EBUSY; videobuf_queue_dma_contig_init(&common->buffer_queue, &video_qops, NULL, &common->irqlock, reqbuf->type, common->fmt.fmt.pix.field, sizeof(struct videobuf_buffer), fh, &common->lock); fh->io_allowed[index] = 1; common->io_usrs = 1; common->memory = reqbuf->memory; INIT_LIST_HEAD(&common->dma_queue); return videobuf_reqbufs(&common->buffer_queue, reqbuf); }
/** * vpif_update_std_info() - update standard related info * @ch: ptr to channel object * * For a given standard selected by application, update values * in the device data structures */ static int vpif_update_std_info(struct channel_obj *ch) { struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct vpif_params *vpifparams = &ch->vpifparams; const struct vpif_channel_config_params *config; struct vpif_channel_config_params *std_info; struct video_obj *vid_ch = &ch->video; int index; vpif_dbg(2, debug, "vpif_update_std_info\n"); std_info = &vpifparams->std_info; for (index = 0; index < ARRAY_SIZE(ch_params); index++) { config = &ch_params[index]; if (config->stdid & vid_ch->stdid) { memcpy(std_info, config, sizeof(*config)); break; } } /* standard not found */ if (index == ARRAY_SIZE(ch_params)) return -EINVAL; common->fmt.fmt.pix.width = std_info->width; common->width = std_info->width; common->fmt.fmt.pix.height = std_info->height; common->height = std_info->height; common->fmt.fmt.pix.bytesperline = std_info->width; vpifparams->video_params.hpitch = std_info->width; vpifparams->video_params.storage_mode = std_info->frm_fmt; return 0; }
static int vpif_update_resolution(struct channel_obj *ch) { struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct video_obj *vid_ch = &ch->video; struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height) return -EINVAL; if (vid_ch->stdid || vid_ch->dv_preset) { if (vpif_update_std_info(ch)) return -EINVAL; } common->fmt.fmt.pix.width = std_info->width; common->fmt.fmt.pix.height = std_info->height; vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n", common->fmt.fmt.pix.width, common->fmt.fmt.pix.height); /* Set height and width paramateres */ common->height = std_info->height; common->width = std_info->width; return 0; }
static int vpif_open(struct file *filep) { struct vpif_capture_config *config = vpif_dev->platform_data; struct video_device *vdev = video_devdata(filep); struct common_obj *common; struct video_obj *vid_ch; struct channel_obj *ch; struct vpif_fh *fh; int i; vpif_dbg(2, debug, "vpif_open\n"); ch = video_get_drvdata(vdev); vid_ch = &ch->video; common = &ch->common[VPIF_VIDEO_INDEX]; if (NULL == ch->curr_subdev_info) { for (i = 0; i < config->subdev_count; i++) { if (vpif_obj.sd[i]) { ch->curr_subdev_info = &config->subdev_info[i]; vid_ch->input_idx = 0; break; } } if (i == config->subdev_count) { vpif_err("No sub device registered\n"); return -ENOENT; } } fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); if (NULL == fh) { vpif_err("unable to allocate memory for file handle object\n"); return -ENOMEM; } filep->private_data = fh; fh->channel = ch; fh->initialized = 0; if (!ch->initialized) { fh->initialized = 1; ch->initialized = 1; memset(&(ch->vpifparams), 0, sizeof(struct vpif_params)); } ch->usrs++; fh->io_allowed[VPIF_VIDEO_INDEX] = 0; fh->prio = V4L2_PRIORITY_UNSET; v4l2_prio_open(&ch->prio, &fh->prio); return 0; }
static int vpif_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct v4l2_pix_format *pixfmt; int ret = 0; vpif_dbg(2, debug, "VIDIOC_S_FMT\n"); /* If streaming is started, return error */ if (common->started) { vpif_dbg(1, debug, "Streaming is started\n"); return -EBUSY; } if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; pixfmt = &fmt->fmt.pix; /* Check for valid field format */ ret = vpif_check_format(ch, pixfmt, 0); if (ret) return ret; /* store the format in the channel object */ if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; common->fmt = *fmt; mutex_unlock(&common->lock); return 0; }
static int vpif_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *fmt) { struct vpif_fh *fh = priv; struct v4l2_pix_format *pixfmt; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } /* Check for the priority */ ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; } if (common->started) { vpif_dbg(1, debug, "Streaming in progress\n"); return -EBUSY; } pixfmt = &fmt->fmt.pix; /* Check for valid field format */ ret = vpif_check_format(ch, pixfmt); if (ret) return ret; /* store the pix format in the channel object */ common->fmt.fmt.pix = *pixfmt; /* store the format in the channel object */ if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; common->fmt = *fmt; mutex_unlock(&common->lock); return 0; }
/* * vpif_mmap: It is used to map kernel space buffers into user spaces */ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) { struct vpif_fh *fh = filep->private_data; struct channel_obj *ch = fh->channel; struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); vpif_dbg(2, debug, "vpif_mmap\n"); return videobuf_mmap_mapper(&common->buffer_queue, vma); }
/** * vpif_g_std() - get STD handler * @file: file ptr * @priv: file handle * @std_id: ptr to std id */ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; vpif_dbg(2, debug, "vpif_g_std\n"); *std = ch->video.stdid; return 0; }
/** * vpif_querybuf() - query buffer handler * @file: file ptr * @priv: file handle * @buf: v4l2 buffer structure ptr */ static int vpif_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_querybuf\n"); if (common->fmt.type != buf->type) return -EINVAL; if (common->memory != V4L2_MEMORY_MMAP) { vpif_dbg(1, debug, "Invalid memory\n"); return -EINVAL; } return videobuf_querybuf(&common->buffer_queue, buf); }
static int vpif_update_std_info(struct channel_obj *ch) { struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct vpif_params *vpifparams = &ch->vpifparams; const struct vpif_channel_config_params *config; struct vpif_channel_config_params *std_info = &vpifparams->std_info; struct video_obj *vid_ch = &ch->video; int index; vpif_dbg(2, debug, "vpif_update_std_info\n"); for (index = 0; index < vpif_ch_params_count; index++) { config = &ch_params[index]; if (config->hd_sd == 0) { vpif_dbg(2, debug, "SD format\n"); if (config->stdid & vid_ch->stdid) { memcpy(std_info, config, sizeof(*config)); break; } } else { vpif_dbg(2, debug, "HD format\n"); if (config->dv_preset == vid_ch->dv_preset) { memcpy(std_info, config, sizeof(*config)); break; } } } if (index == vpif_ch_params_count) return -EINVAL; common->fmt.fmt.pix.width = std_info->width; common->width = std_info->width; common->fmt.fmt.pix.height = std_info->height; common->height = std_info->height; common->fmt.fmt.pix.bytesperline = std_info->width; vpifparams->video_params.hpitch = std_info->width; vpifparams->video_params.storage_mode = std_info->frm_fmt; return 0; }
/** * vpif_dqbuf() - query buffer handler * @file: file ptr * @priv: file handle * @buf: v4l2 buffer structure ptr */ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_dqbuf\n"); return videobuf_dqbuf(&common->buffer_queue, buf, file->f_flags & O_NONBLOCK); }
static int vpif_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct v4l2_pix_format *pixfmt; int ret = 0; vpif_dbg(2, debug, "%s\n", __func__); if (common->started) { vpif_dbg(1, debug, "Streaming is started\n"); return -EBUSY; } if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { if (!fh->initialized) { vpif_dbg(1, debug, "Channel Busy\n"); return -EBUSY; } } ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; pixfmt = &fmt->fmt.pix; ret = vpif_check_format(ch, pixfmt, 0); if (ret) return ret; common->fmt = *fmt; return 0; }
static unsigned int vpif_poll(struct file *filep, poll_table * wait) { struct vpif_fh *fh = filep->private_data; struct channel_obj *channel = fh->channel; struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]); vpif_dbg(2, debug, "vpif_poll\n"); if (common->started) return videobuf_poll_stream(filep, &common->buffer_queue, wait); return 0; }
/** * vpif_querystd() - querystd handler * @file: file ptr * @priv: file handle * @std_id: ptr to std id * * This function is called to detect standard at the selected input */ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; vpif_dbg(2, debug, "vpif_querystd\n"); if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; /* Call querystd function of decoder device */ ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, querystd, std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); mutex_unlock(&common->lock); return ret; }
/* * vpif_g_chip_ident() - Identify the chip * @file: file ptr * @priv: file handle * @chip: chip identity * * Returns zero or -EINVAL if read operations fails. */ static int vpif_g_chip_ident(struct file *file, void *priv, struct v4l2_dbg_chip_ident *chip) { chip->ident = V4L2_IDENT_NONE; chip->revision = 0; if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { vpif_dbg(2, debug, "match_type is invalid.\n"); return -EINVAL; } return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, g_chip_ident, chip); }
/** * vpif_release : function to clean up file close * @filep: file pointer * * This function deletes buffer queue, frees the buffers and the vpfe file * handle */ static int vpif_release(struct file *filep) { struct vpif_fh *fh = filep->private_data; struct channel_obj *ch = fh->channel; struct common_obj *common; vpif_dbg(2, debug, "vpif_release\n"); common = &ch->common[VPIF_VIDEO_INDEX]; if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ common->io_usrs = 0; /* Disable channel as per its device type and channel id */ if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { enable_channel0(0); channel0_intr_enable(0); } if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || (2 == common->started)) { enable_channel1(0); channel1_intr_enable(0); } common->started = 0; /* Free buffers allocated */ videobuf_queue_cancel(&common->buffer_queue); videobuf_mmap_free(&common->buffer_queue); } /* Decrement channel usrs counter */ ch->usrs--; /* unlock mutex on channel object */ mutex_unlock(&common->lock); /* Close the priority */ v4l2_prio_close(&ch->prio, fh->prio); if (fh->initialized) ch->initialized = 0; filep->private_data = NULL; kfree(fh); return 0; }
/** * vpif_config_addr() - function to configure buffer address in vpif * @ch - channel ptr * @muxmode - channel mux mode */ static void vpif_config_addr(struct channel_obj *ch, int muxmode) { struct common_obj *common; vpif_dbg(2, debug, "vpif_config_addr\n"); common = &(ch->common[VPIF_VIDEO_INDEX]); if (VPIF_CHANNEL1_VIDEO == ch->channel_id) common->set_addr = ch1_set_videobuf_addr; else if (2 == muxmode) common->set_addr = ch0_set_videobuf_addr_yc_nmux; else common->set_addr = ch0_set_videobuf_addr; }
/** * vpif_map_sub_device_to_input() - Maps sub device to input * @ch - ptr to channel * @config - ptr to capture configuration * @input_index - Given input index from application * @sub_device_index - index into sd table * * lookup the sub device information for a given input index. * we report all the inputs to application. inputs table also * has sub device name for the each input */ static struct vpif_subdev_info *vpif_map_sub_device_to_input( struct channel_obj *ch, struct vpif_capture_config *vpif_cfg, int input_index, int *sub_device_index) { struct vpif_capture_chan_config *chan_cfg; struct vpif_subdev_info *subdev_info = NULL; const char *subdev_name = NULL; int i; vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n"); chan_cfg = &vpif_cfg->chan_config[ch->channel_id]; /** * search through the inputs to find the sub device supporting * the input */ for (i = 0; i < chan_cfg->input_count; i++) { /* For each sub device, loop through input */ if (i == input_index) { subdev_name = chan_cfg->inputs[i].subdev_name; break; } } /* if reached maximum. return null */ if (i == chan_cfg->input_count || (NULL == subdev_name)) return subdev_info; /* loop through the sub device list to get the sub device info */ for (i = 0; i < vpif_cfg->subdev_count; i++) { subdev_info = &vpif_cfg->subdev_info[i]; if (!strcmp(subdev_info->name, subdev_name)) break; } if (i == vpif_cfg->subdev_count) return subdev_info; /* check if the sub device is registered */ if (NULL == vpif_obj.sd[i]) return NULL; *sub_device_index = i; return subdev_info; }
/** * vpif_buffer_queue : Callback function to add buffer to DMA queue * @q: ptr to videobuf_queue * @vb: ptr to videobuf_buffer */ static void vpif_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { /* Get the file handle object and channel object */ struct vpif_fh *fh = q->priv_data; struct channel_obj *ch = fh->channel; struct common_obj *common; common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_buffer_queue\n"); /* add the buffer to the DMA queue */ list_add_tail(&vb->queue, &common->dma_queue); /* Change state of the buffer */ vb->state = VIDEOBUF_QUEUED; }
static int vpif_enum_output(struct file *file, void *fh, struct v4l2_output *output) { struct vpif_display_config *config = vpif_dev->platform_data; if (output->index >= config->output_count) { vpif_dbg(1, debug, "Invalid output index\n"); return -EINVAL; } strcpy(output->name, config->output[output->index]); output->type = V4L2_OUTPUT_TYPE_ANALOG; output->std = DM646X_V4L2_STD; return 0; }
static void vpif_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct vpif_fh *fh = q->priv_data; struct channel_obj *ch = fh->channel; struct common_obj *common; common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_buffer_queue\n"); list_add_tail(&vb->queue, &common->dma_queue); vb->state = VIDEOBUF_QUEUED; }
static struct vpif_subdev_info *vpif_map_sub_device_to_input( struct channel_obj *ch, struct vpif_capture_config *vpif_cfg, int input_index, int *sub_device_index) { struct vpif_capture_chan_config *chan_cfg; struct vpif_subdev_info *subdev_info = NULL; const char *subdev_name = NULL; int i; vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n"); chan_cfg = &vpif_cfg->chan_config[ch->channel_id]; for (i = 0; i < chan_cfg->input_count; i++) { if (i == input_index) { subdev_name = chan_cfg->inputs[i].subdev_name; break; } } if (i == chan_cfg->input_count || (NULL == subdev_name)) return subdev_info; for (i = 0; i < vpif_cfg->subdev_count; i++) { subdev_info = &vpif_cfg->subdev_info[i]; if (!strcmp(subdev_info->name, subdev_name)) break; } if (i == vpif_cfg->subdev_count) return subdev_info; if (NULL == vpif_obj.sd[i]) return NULL; *sub_device_index = i; return subdev_info; }
/** * vpif_s_dv_presets() - S_DV_PRESETS handler * @file: file ptr * @priv: file handle * @preset: input preset */ static int vpif_s_dv_preset(struct file *file, void *priv, struct v4l2_dv_preset *preset) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct video_obj *vid_ch = &ch->video; int ret = 0; if (common->started) { vpif_dbg(1, debug, "streaming in progress\n"); return -EBUSY; } ret = v4l2_prio_check(&ch->prio, fh->prio); if (ret != 0) return ret; fh->initialized = 1; /* Call encoder subdevice function to set the standard */ if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; ch->video.dv_preset = preset->preset; ch->video.stdid = V4L2_STD_UNKNOWN; memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); /* Get the information about the standard */ if (vpif_update_resolution(ch)) { ret = -EINVAL; } else { /* Configure the default format information */ vpif_config_format(ch); ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], video, s_dv_preset, preset); } mutex_unlock(&common->lock); return ret; }
static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; int ret = 0; vpif_dbg(2, debug, "vpif_querystd\n"); ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, querystd, std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); return ret; }