diff options
Diffstat (limited to 'drivers/media/pci/saa7164/saa7164-encoder.c')
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-encoder.c | 653 |
1 files changed, 175 insertions, 478 deletions
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 4434e0f28c26..1b184c39ba97 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -25,6 +25,18 @@ #define ENCODER_MIN_BITRATE 1000000 #define ENCODER_DEF_BITRATE 5000000 +/* + * This is a dummy non-zero value for the sizeimage field of v4l2_pix_format. + * It is not actually used for anything since this driver does not support + * stream I/O, only read(), and because this driver produces an MPEG stream + * and not discrete frames. But the V4L2 spec doesn't allow for this value + * to be 0, so set it to 0x10000 instead. + * + * If we ever change this driver to support stream I/O, then this field + * will be the size of the streaming buffers. + */ +#define SAA7164_SIZEIMAGE (0x10000) + static struct saa7164_tvnorm saa7164_tvnorms[] = { { .name = "NTSC-M", @@ -35,24 +47,6 @@ static struct saa7164_tvnorm saa7164_tvnorms[] = { } }; -static const u32 saa7164_v4l2_ctrls[] = { - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_AUDIO_VOLUME, - V4L2_CID_SHARPNESS, - V4L2_CID_MPEG_STREAM_TYPE, - V4L2_CID_MPEG_VIDEO_ASPECT, - V4L2_CID_MPEG_VIDEO_B_FRAMES, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, - V4L2_CID_MPEG_AUDIO_MUTE, - V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - V4L2_CID_MPEG_VIDEO_BITRATE, - V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, - 0 -}; - /* Take the encoder configuration form the port struct and * flush it to the hardware. */ @@ -211,10 +205,8 @@ static int saa7164_encoder_initialize(struct saa7164_port *port) } /* -- V4L2 --------------------------------------------------------- */ -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) +int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; unsigned int i; @@ -240,22 +232,33 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + return saa7164_s_std(fh->port, id); +} + +int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id) +{ *id = port->std; return 0; } -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { - int n; + struct saa7164_encoder_fh *fh = file->private_data; + + return saa7164_g_std(fh->port, id); +} - char *inputs[] = { "tuner", "composite", "svideo", "aux", - "composite 2", "svideo 2", "aux 2" }; +int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i) +{ + static const char * const inputs[] = { + "tuner", "composite", "svideo", "aux", + "composite 2", "svideo 2", "aux 2" + }; + int n; if (i->index >= 7) return -EINVAL; @@ -273,10 +276,8 @@ static int vidioc_enum_input(struct file *file, void *priv, return 0; } -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +int saa7164_g_input(struct saa7164_port *port, unsigned int *i) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; if (saa7164_api_get_videomux(port) != SAA_OK) @@ -289,10 +290,15 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) return 0; } -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + + return saa7164_g_input(fh->port, i); +} + +int saa7164_s_input(struct saa7164_port *port, unsigned int i) +{ struct saa7164_dev *dev = port->dev; dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i); @@ -308,8 +314,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct saa7164_encoder_fh *fh = file->private_data; + + return saa7164_s_input(fh->port, i); +} + +int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct saa7164_encoder_fh *fh = file->private_data; struct saa7164_port *port = fh->port; @@ -319,38 +331,45 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; strcpy(t->name, "tuner"); - t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; + t->rangelow = SAA7164_TV_MIN_FREQ; + t->rangehigh = SAA7164_TV_MAX_FREQ; dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type); return 0; } -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *t) +int saa7164_s_tuner(struct file *file, void *priv, + const struct v4l2_tuner *t) { + if (0 != t->index) + return -EINVAL; + /* Update the A/V core */ return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) +int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + if (f->tuner) + return -EINVAL; - f->type = V4L2_TUNER_ANALOG_TV; f->frequency = port->freq; - return 0; } -static int vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; + + return saa7164_g_frequency(fh->port, f); +} + +int saa7164_s_frequency(struct saa7164_port *port, + const struct v4l2_frequency *f) +{ struct saa7164_dev *dev = port->dev; struct saa7164_port *tsport; struct dvb_frontend *fe; @@ -370,16 +389,13 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->tuner != 0) return -EINVAL; - if (f->type != V4L2_TUNER_ANALOG_TV) - return -EINVAL; - - port->freq = f->frequency; + port->freq = clamp(f->frequency, + SAA7164_TV_MIN_FREQ, SAA7164_TV_MAX_FREQ); /* Update the hardware */ if (port->nr == SAA7164_PORT_ENC1) tsport = &dev->ports[SAA7164_PORT_TS1]; - else - if (port->nr == SAA7164_PORT_ENC2) + else if (port->nr == SAA7164_PORT_ENC2) tsport = &dev->ports[SAA7164_PORT_TS2]; else BUG(); @@ -396,253 +412,54 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) +static int vidioc_s_frequency(struct file *file, void *priv, + const struct v4l2_frequency *f) { struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { - case V4L2_CID_BRIGHTNESS: - ctl->value = port->ctl_brightness; - break; - case V4L2_CID_CONTRAST: - ctl->value = port->ctl_contrast; - break; - case V4L2_CID_SATURATION: - ctl->value = port->ctl_saturation; - break; - case V4L2_CID_HUE: - ctl->value = port->ctl_hue; - break; - case V4L2_CID_SHARPNESS: - ctl->value = port->ctl_sharpness; - break; - case V4L2_CID_AUDIO_VOLUME: - ctl->value = port->ctl_volume; - break; - default: - return -EINVAL; - } - return 0; + return saa7164_s_frequency(fh->port, f); } -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) +static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl) { - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; + struct saa7164_port *port = + container_of(ctrl->handler, struct saa7164_port, ctrl_handler); + struct saa7164_encoder_params *params = &port->encoder_params; int ret = 0; - dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__, - ctl->id, ctl->value); - - switch (ctl->id) { + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_brightness = ctl->value; - saa7164_api_set_usercontrol(port, - PU_BRIGHTNESS_CONTROL); - } else - ret = -EINVAL; + port->ctl_brightness = ctrl->val; + saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL); break; case V4L2_CID_CONTRAST: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_contrast = ctl->value; - saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL); - } else - ret = -EINVAL; + port->ctl_contrast = ctrl->val; + saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL); break; case V4L2_CID_SATURATION: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_saturation = ctl->value; - saa7164_api_set_usercontrol(port, - PU_SATURATION_CONTROL); - } else - ret = -EINVAL; + port->ctl_saturation = ctrl->val; + saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL); break; case V4L2_CID_HUE: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_hue = ctl->value; - saa7164_api_set_usercontrol(port, PU_HUE_CONTROL); - } else - ret = -EINVAL; + port->ctl_hue = ctrl->val; + saa7164_api_set_usercontrol(port, PU_HUE_CONTROL); break; case V4L2_CID_SHARPNESS: - if ((ctl->value >= 0) && (ctl->value <= 255)) { - port->ctl_sharpness = ctl->value; - saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL); - } else - ret = -EINVAL; + port->ctl_sharpness = ctrl->val; + saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL); break; case V4L2_CID_AUDIO_VOLUME: - if ((ctl->value >= -83) && (ctl->value <= 24)) { - port->ctl_volume = ctl->value; - saa7164_api_set_audio_volume(port, port->ctl_volume); - } else - ret = -EINVAL; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int saa7164_get_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_encoder_params *params = &port->encoder_params; - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctrl->value = params->bitrate; - break; - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = params->stream_type; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - ctrl->value = params->ctl_mute; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctrl->value = params->ctl_aspect; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctrl->value = params->bitrate_mode; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - ctrl->value = params->refdist; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - ctrl->value = params->bitrate_peak; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - ctrl->value = params->gop_size; - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_get_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - -static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) -{ - int ret = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_MPEG_VIDEO_BITRATE: - if ((ctrl->value >= ENCODER_MIN_BITRATE) && - (ctrl->value <= ENCODER_MAX_BITRATE)) - ret = 0; + port->ctl_volume = ctrl->val; + saa7164_api_set_audio_volume(port, port->ctl_volume); break; - case V4L2_CID_MPEG_STREAM_TYPE: - if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) || - (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)) - ret = 0; - break; - case V4L2_CID_MPEG_AUDIO_MUTE: - if ((ctrl->value >= 0) && - (ctrl->value <= 1)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) && - (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - if ((ctrl->value >= 0) && - (ctrl->value <= 255)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) || - (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - if ((ctrl->value >= 1) && - (ctrl->value <= 3)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - if ((ctrl->value >= ENCODER_MIN_BITRATE) && - (ctrl->value <= ENCODER_MAX_BITRATE)) - ret = 0; - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int vidioc_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - } - - return -EINVAL; -} - -static int saa7164_set_ctrl(struct saa7164_port *port, - struct v4l2_ext_control *ctrl) -{ - struct saa7164_encoder_params *params = &port->encoder_params; - int ret = 0; - - switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_BITRATE: - params->bitrate = ctrl->value; + params->bitrate = ctrl->val; break; case V4L2_CID_MPEG_STREAM_TYPE: - params->stream_type = ctrl->value; + params->stream_type = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_MUTE: - params->ctl_mute = ctrl->value; + params->ctl_mute = ctrl->val; ret = saa7164_api_audio_mute(port, params->ctl_mute); if (ret != SAA_OK) { printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, @@ -651,7 +468,7 @@ static int saa7164_set_ctrl(struct saa7164_port *port, } break; case V4L2_CID_MPEG_VIDEO_ASPECT: - params->ctl_aspect = ctrl->value; + params->ctl_aspect = ctrl->val; ret = saa7164_api_set_aspect_ratio(port); if (ret != SAA_OK) { printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, @@ -660,55 +477,24 @@ static int saa7164_set_ctrl(struct saa7164_port *port, } break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - params->bitrate_mode = ctrl->value; + params->bitrate_mode = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_B_FRAMES: - params->refdist = ctrl->value; + params->refdist = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - params->bitrate_peak = ctrl->value; + params->bitrate_peak = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - params->gop_size = ctrl->value; + params->gop_size = ctrl->val; break; default: - return -EINVAL; + ret = -EINVAL; } - /* TODO: Update the hardware */ - return ret; } -static int vidioc_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = saa7164_try_ctrl(ctrl, 0); - if (err) { - ctrls->error_idx = i; - break; - } - err = saa7164_set_ctrl(port, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -745,145 +531,22 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, +static int vidioc_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7164_encoder_fh *fh = file->private_data; struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; + f->fmt.pix.sizeimage = SAA7164_SIZEIMAGE; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.width = port->width; f->fmt.pix.height = port->height; - - dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n", - port->width, port->height); - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n", - port->width, port->height); return 0; } -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct saa7164_encoder_fh *fh = file->private_data; - struct saa7164_port *port = fh->port; - struct saa7164_dev *dev = port->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - port->ts_packet_size * port->ts_packet_count; - f->fmt.pix.colorspace = 0; - - dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); - - return 0; -} - -static int fill_queryctrl(struct saa7164_encoder_params *params, - struct v4l2_queryctrl *c) -{ - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128); - case V4L2_CID_SHARPNESS: - return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8); - case V4L2_CID_MPEG_AUDIO_MUTE: - return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(c, -83, 24, 1, 20); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(c, - ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, - 100000, ENCODER_DEF_BITRATE); - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, - 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS); - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_ASPECT_1x1, - V4L2_MPEG_VIDEO_ASPECT_221x100, - 1, V4L2_MPEG_VIDEO_ASPECT_4x3); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(c, 1, 255, 1, 15); - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, - 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - return v4l2_ctrl_query_fill(c, - 1, 3, 1, 1); - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - return v4l2_ctrl_query_fill(c, - ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, - 100000, ENCODER_DEF_BITRATE); - default: - return -EINVAL; - } -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - struct saa7164_encoder_fh *fh = priv; - struct saa7164_port *port = fh->port; - int i, next; - u32 id = c->id; - - memset(c, 0, sizeof(*c)); - - next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); - c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; - - for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) { - if (next) { - if (c->id < saa7164_v4l2_ctrls[i]) - c->id = saa7164_v4l2_ctrls[i]; - else - continue; - } - - if (c->id == saa7164_v4l2_ctrls[i]) - return fill_queryctrl(&port->encoder_params, c); - - if (c->id < saa7164_v4l2_ctrls[i]) - break; - } - - return -EINVAL; -} - static int saa7164_encoder_stop_port(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; @@ -1084,8 +747,10 @@ static int fops_open(struct file *file) if (NULL == fh) return -ENOMEM; - file->private_data = fh; fh->port = port; + v4l2_fh_init(&fh->fh, video_devdata(file)); + v4l2_fh_add(&fh->fh); + file->private_data = fh; return 0; } @@ -1106,7 +771,8 @@ static int fops_release(struct file *file) } } - file->private_data = NULL; + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); kfree(fh); return 0; @@ -1250,10 +916,11 @@ err: static unsigned int fops_poll(struct file *file, poll_table *wait) { + unsigned long req_events = poll_requested_events(wait); struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; - unsigned int mask = 0; + unsigned int mask = v4l2_ctrl_poll(file, wait); port->last_poll_msecs_diff = port->last_poll_msecs; port->last_poll_msecs = jiffies_to_msecs(jiffies); @@ -1263,26 +930,18 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) - return -EIO; + if (!(req_events & (POLLIN | POLLRDNORM))) + return mask; if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { if (saa7164_encoder_initialize(port) < 0) - return -EINVAL; + return mask | POLLERR; saa7164_encoder_start_streaming(port); msleep(200); } } - /* blocking wait for buffer */ - if ((file->f_flags & O_NONBLOCK) == 0) { - if (wait_event_interruptible(port->wait_read, - saa7164_enc_next_buf(port))) { - return -ERESTARTSYS; - } - } - /* Pull the first buffer from the used list */ if (!list_empty(&port->list_buf_used.list)) mask |= POLLIN | POLLRDNORM; @@ -1290,6 +949,10 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) return mask; } +static const struct v4l2_ctrl_ops saa7164_ctrl_ops = { + .s_ctrl = saa7164_s_ctrl, +}; + static const struct v4l2_file_operations mpeg_fops = { .owner = THIS_MODULE, .open = fops_open, @@ -1302,24 +965,21 @@ static const struct v4l2_file_operations mpeg_fops = { static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, + .vidioc_enum_input = saa7164_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_tuner = saa7164_g_tuner, + .vidioc_s_tuner = saa7164_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, - .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_fmt_vid_cap, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static struct video_device saa7164_mpeg_template = { @@ -1357,6 +1017,7 @@ static struct video_device *saa7164_encoder_alloc( int saa7164_encoder_register(struct saa7164_port *port) { struct saa7164_dev *dev = port->dev; + struct v4l2_ctrl_handler *hdl = &port->ctrl_handler; int result = -ENODEV; dprintk(DBGLVL_ENC, "%s()\n", __func__); @@ -1381,19 +1042,52 @@ int saa7164_encoder_register(struct saa7164_port *port) port->video_format = EU_VIDEO_FORMAT_MPEG_2; port->audio_format = 0; port->video_resolution = 0; - port->ctl_brightness = 127; - port->ctl_contrast = 66; - port->ctl_hue = 128; - port->ctl_saturation = 62; - port->ctl_sharpness = 8; - port->encoder_params.bitrate = ENCODER_DEF_BITRATE; - port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE; - port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; - port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS; - port->encoder_params.ctl_mute = 0; - port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; - port->encoder_params.refdist = 1; - port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE; + port->freq = SAA7164_TV_MIN_FREQ; + + v4l2_ctrl_handler_init(hdl, 14); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 66); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 62); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_HUE, 0, 255, 1, 128); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_SHARPNESS, 0x0, 0x0f, 1, 8); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_AUDIO_MUTE, 0x0, 0x01, 1, 0); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_AUDIO_VOLUME, -83, 24, 1, 20); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE, + ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, + 100000, ENCODER_DEF_BITRATE); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_MPEG_VIDEO_ASPECT_221x100, 0, + V4L2_MPEG_VIDEO_ASPECT_4x3); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, 15); + v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_B_FRAMES, 1, 3, 1, 1); + v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE, + 100000, ENCODER_DEF_BITRATE); + if (hdl->error) { + result = hdl->error; + goto failed; + } + port->std = V4L2_STD_NTSC_M; if (port->encodernorm.id & V4L2_STD_525_60) @@ -1412,6 +1106,8 @@ int saa7164_encoder_register(struct saa7164_port *port) goto failed; } + port->v4l_device->ctrl_handler = hdl; + v4l2_ctrl_handler_setup(hdl); video_set_drvdata(port->v4l_device, port); result = video_register_device(port->v4l_device, VFL_TYPE_GRABBER, -1); @@ -1466,6 +1162,7 @@ void saa7164_encoder_unregister(struct saa7164_port *port) port->v4l_device = NULL; } + v4l2_ctrl_handler_free(&port->ctrl_handler); dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); } |