static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { struct unicorn_fh *fh = priv; struct unicorn_dev *dev = fh->dev; int err; dprintk_video(1, dev->name, "%s(%d)\n", __func__, i); if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; } if (i > MAX_VIDEO_INPUT_ENTRY-1) { printk(KERN_INFO "%s() invalid input -EINVAL\n", __func__); return -EINVAL; } if(fh->channel > MAX_VID_CHANNEL_NUM) { printk(KERN_INFO "%s() invalid channel -EINVAL\n", __func__); return -EINVAL; } fh->input = i; return 0; }
int cx18_s_input(struct file *file, void *fh, unsigned int inp) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (inp < 0 || inp >= cx->nof_inputs) return -EINVAL; if (inp == cx->active_input) { CX18_DEBUG_INFO("Input unchanged\n"); return 0; } CX18_DEBUG_INFO("Changing input from %d to %d\n", cx->active_input, inp); cx->active_input = inp; /* Set the audio input to whatever is appropriate for the input type. */ cx->audio_input = cx->card->video_inputs[inp].audio_index; /* prevent others from messing with the streams until we're finished changing inputs. */ cx18_mute(cx); cx18_video_set_io(cx); cx18_audio_set_io(cx); cx18_unmute(cx); return 0; }
static int cx18_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; int w, h; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; ret = cx18_try_fmt_vid_cap(file, fh, fmt); if (ret) return ret; w = fmt->fmt.pix.width; h = fmt->fmt.pix.height; if (cx->params.width == w && cx->params.height == h) return 0; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; cx->params.width = w; cx->params.height = h; cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); return cx18_g_fmt_vid_cap(file, fh, fmt); }
/** * 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; }
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; }
static int vidioc_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct unicorn_fh *fh = priv; struct unicorn_dev *dev = (fh)->dev; int err; if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; } return v4l2_subdev_call(dev->sensor[fh->input], core, s_register, reg); }
static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; return cx18_av_cmd(cx, VIDIOC_S_CROP, crop); }
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 vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct unicorn_fh *fh = priv; struct unicorn_dev *dev = fh->dev; int err; if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; } return v4l2_subdev_call(dev->sensor[fh->input], core, s_ctrl, ctl); }
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; }
static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (vt->index != 0) return -EINVAL; /* Setting tuner can only set audio mode */ cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt); return 0; }
/** * 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; }
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (vf->tuner != 0) return -EINVAL; cx18_mute(cx); CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf); cx18_unmute(cx); return 0; }
static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; cx->vbi.sliced_in->service_set = 0; cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); return cx18_g_fmt_vbi_cap(file, fh, fmt); }
static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if (id->type == CX18_ENC_STREAM_TYPE_VBI && cx->vbi.sliced_in->service_set && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; cx->vbi.sliced_in->service_set = 0; cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); return cx18_g_fmt_vbi_cap(file, fh, fmt); }
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; }
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; ret = v4l2_prio_check(&cx->prio, &id->prio); if (ret) return ret; if ((*std & V4L2_STD_ALL) == 0) return -EINVAL; if (*std == cx->std) return 0; if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || atomic_read(&cx->ana_capturing) > 0) { /* Switching standard would turn off the radio or mess with already running streams, prevent that by returning EBUSY. */ return -EBUSY; } cx->std = *std; cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; cx->params.is_50hz = cx->is_50hz = !cx->is_60hz; cx->params.width = 720; cx->params.height = cx->is_50hz ? 576 : 480; cx->vbi.count = cx->is_50hz ? 18 : 12; cx->vbi.start[0] = cx->is_50hz ? 6 : 10; cx->vbi.start[1] = cx->is_50hz ? 318 : 273; cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284; CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long) cx->std); /* Tuner */ cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); return 0; }
int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) { struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; struct v4l2_control ctrl; ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { int i; int err = 0; for (i = 0; i < c->count; i++) { ctrl.id = c->controls[i].id; ctrl.value = c->controls[i].value; err = cx18_s_ctrl(cx, &ctrl); c->controls[i].value = ctrl.value; if (err) { c->error_idx = i; break; } } return err; } if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { static u32 freqs[3] = { 44100, 48000, 32000 }; struct cx18_api_func_private priv; struct cx2341x_mpeg_params p = cx->params; int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), c, VIDIOC_S_EXT_CTRLS); unsigned int idx; if (err) return err; if (p.video_encoding != cx->params.video_encoding) { int is_mpeg1 = p.video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; struct v4l2_mbus_framefmt fmt; /* fix videodecoder resolution */ fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1); fmt.height = cx->params.height; fmt.code = V4L2_MBUS_FMT_FIXED; v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt); } priv.cx = cx; priv.s = &cx->streams[id->type]; err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); if (!err && (cx->params.stream_vbi_fmt != p.stream_vbi_fmt || cx->params.stream_type != p.stream_type)) err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt, p.stream_type); cx->params = p; cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; idx = p.audio_properties & 0x03; /* The audio clock of the digitizer must match the codec sample rate otherwise you get some very strange effects. */ if (idx < ARRAY_SIZE(freqs)) cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); return err; } return -EINVAL; }
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct unicorn_fh *fh = priv; struct unicorn_dev *dev = ((struct unicorn_fh *)priv)->dev; int err; if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) { printk(KERN_INFO "%s()v4l2_prio_check fail \n", __func__); return err; } } dprintk_video(1, dev->name, "%s()\n", __func__); if(fh->input == MIRE_VIDEO_INPUT) { dprintk_video(1, dev->name, "%s() MIRE input selected\n", __func__); } else if(dev->sensor[fh->input]==NULL) { printk(KERN_INFO "%s() no device on this input %d \n", __func__,fh->input); return -EINVAL; } err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) { printk(KERN_WARNING "%s() vidioc_try_fmt_vid_cap fail\n", __func__); return err; } fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; if (fh->fmt->fourcc != V4L2_PIX_FMT_YUYV){ printk(KERN_INFO "%s() expected 0x%x \n", __func__,V4L2_PIX_FMT_YUYV); printk(KERN_INFO "%s()0x%x pixel format not supported \n", __func__,fh->fmt->fourcc); return -EINVAL; } if(fh->input == MIRE_VIDEO_INPUT) { err = 0; } else { err = v4l2_subdev_call(dev->sensor[fh->input], video, s_fmt, f); } fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; dprintk_video(1, dev->name, "%s() width=%d height=%d field=%d err=%d\n", __func__, fh->width, fh->height, fh->vidq.field, err); return err; }
static int vpif_s_input(struct file *file, void *priv, unsigned int index) { struct vpif_capture_config *config = vpif_dev->platform_data; struct vpif_capture_chan_config *chan_cfg; 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; struct vpif_subdev_info *subdev_info; int ret = 0, sd_index = 0; u32 input = 0, output = 0; chan_cfg = &config->chan_config[ch->channel_id]; 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; subdev_info = vpif_map_sub_device_to_input(ch, config, index, &sd_index); if (NULL == subdev_info) { vpif_dbg(1, debug, "couldn't lookup sub device for the input index\n"); return -EINVAL; } if (mutex_lock_interruptible(&common->lock)) return -ERESTARTSYS; /* first setup input path from sub device to vpif */ if (config->setup_input_path) { ret = config->setup_input_path(ch->channel_id, subdev_info->name); if (ret < 0) { vpif_dbg(1, debug, "couldn't setup input path for the" " sub device %s, for input index %d\n", subdev_info->name, index); goto exit; } } if (subdev_info->can_route) { input = subdev_info->input; output = subdev_info->output; ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing, input, output, 0); if (ret < 0) { vpif_dbg(1, debug, "Failed to set input\n"); goto exit; } } vid_ch->input_idx = index; ch->curr_subdev_info = subdev_info; ch->curr_sd_index = sd_index; /* copy interface parameters to vpif */ ch->vpifparams.iface = subdev_info->vpif_if; /* update tvnorms from the sub device input info */ ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; exit: mutex_unlock(&common->lock); return ret; }