Loading drivers/media/common/saa7146_fops.c +27 −0 Original line number Diff line number Diff line Loading @@ -429,8 +429,13 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) } } static const struct v4l2_ctrl_ops saa7146_ctrl_ops = { .s_ctrl = saa7146_s_ctrl, }; int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; struct saa7146_vv *vv; int err; Loading @@ -438,9 +443,28 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if (err) return err; v4l2_ctrl_handler_init(hdl, 6); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_CONTRAST, 0, 127, 1, 64); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_SATURATION, 0, 127, 1, 64); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); if (hdl->error) { err = hdl->error; v4l2_ctrl_handler_free(hdl); return err; } dev->v4l2_dev.ctrl_handler = hdl; vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); if (vv == NULL) { ERR("out of memory. aborting.\n"); v4l2_ctrl_handler_free(hdl); return -ENOMEM; } ext_vv->ops = saa7146_video_ioctl_ops; Loading @@ -463,6 +487,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if( NULL == vv->d_clipping.cpu_addr ) { ERR("out of memory. aborting.\n"); kfree(vv); v4l2_ctrl_handler_free(hdl); return -1; } memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); Loading @@ -486,6 +511,7 @@ int saa7146_vv_release(struct saa7146_dev* dev) v4l2_device_unregister(&dev->v4l2_dev); pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); v4l2_ctrl_handler_free(&dev->ctrl_handler); kfree(vv); dev->vv_data = NULL; dev->vv_callback = NULL; Loading Loading @@ -516,6 +542,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, This driver needs auditing so that this flag can be removed. */ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &dev->v4l2_lock; vfd->v4l2_dev = &dev->v4l2_dev; vfd->tvnorms = 0; for (i = 0; i < dev->ext_vv_data->num_stds; i++) vfd->tvnorms |= dev->ext_vv_data->stds[i].id; Loading drivers/media/common/saa7146_video.c +38 −172 Original line number Diff line number Diff line Loading @@ -201,65 +201,6 @@ int saa7146_stop_preview(struct saa7146_fh *fh) } EXPORT_SYMBOL_GPL(saa7146_stop_preview); /********************************************************************************/ /* device controls */ static struct v4l2_queryctrl controls[] = { { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", .minimum = 0, .maximum = 255, .step = 1, .default_value = 128, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_CONTRAST, .name = "Contrast", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_SATURATION, .name = "Saturation", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_VFLIP, .name = "Vertical Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, },{ .id = V4L2_CID_HFLIP, .name = "Horizontal Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, }, }; static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); #define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0) static struct v4l2_queryctrl* ctrl_by_id(int id) { int i; for (i = 0; i < NUM_CONTROLS; i++) if (controls[i].id == id) return controls+i; return NULL; } /********************************************************************************/ /* common pagetable functions */ Loading Loading @@ -510,12 +451,13 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability * strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->version = SAA7146_VERSION_CODE; cap->capabilities = cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities |= dev->ext_vv_data->capabilities; cap->device_caps |= dev->ext_vv_data->capabilities; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } Loading Loading @@ -579,135 +521,58 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd return 0; } static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) { const struct v4l2_queryctrl *ctrl; if ((c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) && (c->id < V4L2_CID_PRIVATE_BASE || c->id >= V4L2_CID_PRIVATE_LASTP1)) return -EINVAL; ctrl = ctrl_by_id(c->id); if (ctrl == NULL) return -EINVAL; DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id); *c = *ctrl; return 0; } static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_dev *dev = container_of(ctrl->handler, struct saa7146_dev, ctrl_handler); struct saa7146_vv *vv = dev->vv_data; const struct v4l2_queryctrl *ctrl; u32 value = 0; u32 val; ctrl = ctrl_by_id(c->id); if (NULL == ctrl) return -EINVAL; switch (c->id) { switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: value = saa7146_read(dev, BCS_CTRL); c->value = 0xff & (value >> 24); DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value); break; case V4L2_CID_CONTRAST: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 16); DEB_D("V4L2_CID_CONTRAST: %d\n", c->value); break; case V4L2_CID_SATURATION: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 0); DEB_D("V4L2_CID_SATURATION: %d\n", c->value); break; case V4L2_CID_VFLIP: c->value = vv->vflip; DEB_D("V4L2_CID_VFLIP: %d\n", c->value); break; case V4L2_CID_HFLIP: c->value = vv->hflip; DEB_D("V4L2_CID_HFLIP: %d\n", c->value); break; default: return -EINVAL; } return 0; } static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; const struct v4l2_queryctrl *ctrl; ctrl = ctrl_by_id(c->id); if (NULL == ctrl) { DEB_D("unknown control %d\n", c->id); return -EINVAL; } switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER: if (c->value < ctrl->minimum) c->value = ctrl->minimum; if (c->value > ctrl->maximum) c->value = ctrl->maximum; break; default: /* nothing */; } switch (c->id) { case V4L2_CID_BRIGHTNESS: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0x00ffffff; value |= (c->value << 24); saa7146_write(dev, BCS_CTRL, value); val = saa7146_read(dev, BCS_CTRL); val &= 0x00ffffff; val |= (ctrl->val << 24); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_CONTRAST: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0xff00ffff; value |= (c->value << 16); saa7146_write(dev, BCS_CTRL, value); case V4L2_CID_CONTRAST: val = saa7146_read(dev, BCS_CTRL); val &= 0xff00ffff; val |= (ctrl->val << 16); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_SATURATION: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0xffffff00; value |= (c->value << 0); saa7146_write(dev, BCS_CTRL, value); case V4L2_CID_SATURATION: val = saa7146_read(dev, BCS_CTRL); val &= 0xffffff00; val |= (ctrl->val << 0); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_HFLIP: /* fixme: we can support changing VFLIP and HFLIP here... */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D("V4L2_CID_HFLIP while active capture\n"); if ((vv->video_status & STATUS_CAPTURE)) return -EBUSY; } vv->hflip = c->value; vv->hflip = ctrl->val; break; case V4L2_CID_VFLIP: if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D("V4L2_CID_VFLIP while active capture\n"); if ((vv->video_status & STATUS_CAPTURE)) return -EBUSY; } vv->vflip = c->value; vv->vflip = ctrl->val; break; default: return -EINVAL; } if (IS_OVERLAY_ACTIVE(fh) != 0) { if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */ struct saa7146_fh *fh = vv->video_fh; saa7146_stop_preview(fh); saa7146_start_preview(fh); } Loading @@ -720,6 +585,8 @@ static int vidioc_g_parm(struct file *file, void *fh, struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; parm->parm.capture.readbuffers = 1; v4l2_video_std_frame_period(vv->standard->id, &parm->parm.capture.timeperframe); Loading Loading @@ -787,6 +654,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma } f->fmt.pix.field = field; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; if (f->fmt.pix.width > maxw) f->fmt.pix.width = maxw; if (f->fmt.pix.height > maxh) Loading Loading @@ -1141,9 +1009,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_parm = vidioc_g_parm, Loading Loading @@ -1338,6 +1203,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; fh->video_fmt.bytesperline = 0; fh->video_fmt.field = V4L2_FIELD_ANY; fh->video_fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; Loading drivers/media/video/mxb.c +85 −88 Original line number Diff line number Diff line Loading @@ -64,8 +64,8 @@ enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; /* this array holds the information, which port of the saa7146 each Loading @@ -90,6 +90,36 @@ struct mxb_routing { u32 output; }; /* these are the available audio sources, which can switched to the line- and cd-output individually */ static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { { .index = 0, .name = "Tuner", .capability = V4L2_AUDCAP_STEREO, } , { .index = 1, .name = "AUX1", .capability = V4L2_AUDCAP_STEREO, } , { .index = 2, .name = "AUX2", .capability = V4L2_AUDCAP_STEREO, } , { .index = 3, .name = "AUX3", .capability = V4L2_AUDCAP_STEREO, } , { .index = 4, .name = "Radio (X9)", .capability = V4L2_AUDCAP_STEREO, } , { .index = 5, .name = "CD-ROM (X10)", .capability = V4L2_AUDCAP_STEREO, } }; /* These are the necessary input-output-pins for bringing one audio source (see above) to the CD-output. Note that gain is set to 0 in this table. */ static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { Loading @@ -114,11 +144,6 @@ static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = { { { 6, 3 }, { 6, 2 } } /* Mute */ }; #define MAXCONTROLS 1 static struct v4l2_queryctrl mxb_controls[] = { { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 }, }; struct mxb { struct video_device *video_dev; Loading Loading @@ -168,16 +193,45 @@ static inline void tea6420_route_line(struct mxb *mxb, int idx) static struct saa7146_extension extension; static int mxb_s_ctrl(struct v4l2_ctrl *ctrl) { struct saa7146_dev *dev = container_of(ctrl->handler, struct saa7146_dev, ctrl_handler); struct mxb *mxb = dev->ext_priv; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: mxb->cur_mute = ctrl->val; /* switch the audio-source */ tea6420_route_line(mxb, ctrl->val ? 6 : video_audio_connect[mxb->cur_input]); break; default: return -EINVAL; } return 0; } static const struct v4l2_ctrl_ops mxb_ctrl_ops = { .s_ctrl = mxb_s_ctrl, }; static int mxb_probe(struct saa7146_dev *dev) { struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; struct mxb *mxb = NULL; v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); if (hdl->error) return hdl->error; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); if (mxb == NULL) { DEB_D("not enough kernel memory\n"); return -ENOMEM; } snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); Loading Loading @@ -385,69 +439,6 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) } */ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; int i; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == qc->id) { *qc = mxb_controls[i]; DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id); return 0; } } return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc); } static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int i; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == vc->id) break; } if (i < 0) return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc); if (vc->id == V4L2_CID_AUDIO_MUTE) { vc->value = mxb->cur_mute; DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); return 0; } DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); return 0; } static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int i = 0; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == vc->id) break; } if (i < 0) return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc); if (vc->id == V4L2_CID_AUDIO_MUTE) { mxb->cur_mute = vc->value; /* switch the audio-source */ tea6420_route_line(mxb, vc->value ? 6 : video_audio_connect[mxb->cur_input]); DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value); } return 0; } static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index); Loading Loading @@ -568,12 +559,8 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; if (mxb->cur_input) { DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", mxb->cur_input); if (f->tuner) return -EINVAL; } *f = mxb->cur_freq; DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency); Loading @@ -592,17 +579,16 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; if (mxb->cur_input) { DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input); return -EINVAL; } mxb->cur_freq = *f; DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency); /* tune in desired frequency */ tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); tuner_call(mxb, tuner, s_frequency, f); /* let the tuner subdev clamp the frequency to the tuner range */ tuner_call(mxb, tuner, g_frequency, f); mxb->cur_freq = *f; if (mxb->cur_input) return 0; /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); Loading @@ -612,6 +598,14 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency return 0; } static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) { if (a->index >= MXB_AUDIOS) return -EINVAL; *a = mxb_audios[a->index]; return 0; } static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; Loading @@ -629,8 +623,13 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; DEB_D("VIDIOC_S_AUDIO %d\n", a->index); if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) return 0; return -EINVAL; } #ifdef CONFIG_VIDEO_ADV_DEBUG Loading Loading @@ -709,9 +708,6 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data } mxb = (struct mxb *)dev->ext_priv; vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; vv_data.ops.vidioc_enum_input = vidioc_enum_input; vv_data.ops.vidioc_g_input = vidioc_g_input; vv_data.ops.vidioc_s_input = vidioc_s_input; Loading @@ -719,6 +715,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data vv_data.ops.vidioc_s_tuner = vidioc_s_tuner; vv_data.ops.vidioc_g_frequency = vidioc_g_frequency; vv_data.ops.vidioc_s_frequency = vidioc_s_frequency; vv_data.ops.vidioc_enumaudio = vidioc_enumaudio; vv_data.ops.vidioc_g_audio = vidioc_g_audio; vv_data.ops.vidioc_s_audio = vidioc_s_audio; #ifdef CONFIG_VIDEO_ADV_DEBUG Loading Loading @@ -836,7 +833,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_ext_vv vv_data = { .inputs = MXB_INPUTS, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, Loading drivers/media/video/mxb.h +0 −29 Original line number Diff line number Diff line Loading @@ -10,33 +10,4 @@ #define MXB_AUDIOS 6 /* these are the available audio sources, which can switched to the line- and cd-output individually */ static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { { .index = 0, .name = "Tuner", .capability = V4L2_AUDCAP_STEREO, } , { .index = 1, .name = "AUX1", .capability = V4L2_AUDCAP_STEREO, } , { .index = 2, .name = "AUX2", .capability = V4L2_AUDCAP_STEREO, } , { .index = 3, .name = "AUX3", .capability = V4L2_AUDCAP_STEREO, } , { .index = 4, .name = "Radio (X9)", .capability = V4L2_AUDCAP_STEREO, } , { .index = 5, .name = "CD-ROM (X10)", .capability = V4L2_AUDCAP_STEREO, } }; #endif include/media/saa7146.h +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/scatterlist.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <linux/vmalloc.h> /* for vmalloc() */ #include <linux/mm.h> /* for vmalloc_to_page() */ Loading Loading @@ -121,6 +122,7 @@ struct saa7146_dev struct list_head item; struct v4l2_device v4l2_dev; struct v4l2_ctrl_handler ctrl_handler; /* different device locks */ spinlock_t slock; Loading Loading
drivers/media/common/saa7146_fops.c +27 −0 Original line number Diff line number Diff line Loading @@ -429,8 +429,13 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) } } static const struct v4l2_ctrl_ops saa7146_ctrl_ops = { .s_ctrl = saa7146_s_ctrl, }; int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; struct saa7146_vv *vv; int err; Loading @@ -438,9 +443,28 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if (err) return err; v4l2_ctrl_handler_init(hdl, 6); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_CONTRAST, 0, 127, 1, 64); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_SATURATION, 0, 127, 1, 64); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); if (hdl->error) { err = hdl->error; v4l2_ctrl_handler_free(hdl); return err; } dev->v4l2_dev.ctrl_handler = hdl; vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); if (vv == NULL) { ERR("out of memory. aborting.\n"); v4l2_ctrl_handler_free(hdl); return -ENOMEM; } ext_vv->ops = saa7146_video_ioctl_ops; Loading @@ -463,6 +487,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if( NULL == vv->d_clipping.cpu_addr ) { ERR("out of memory. aborting.\n"); kfree(vv); v4l2_ctrl_handler_free(hdl); return -1; } memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); Loading @@ -486,6 +511,7 @@ int saa7146_vv_release(struct saa7146_dev* dev) v4l2_device_unregister(&dev->v4l2_dev); pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); v4l2_ctrl_handler_free(&dev->ctrl_handler); kfree(vv); dev->vv_data = NULL; dev->vv_callback = NULL; Loading Loading @@ -516,6 +542,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, This driver needs auditing so that this flag can be removed. */ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &dev->v4l2_lock; vfd->v4l2_dev = &dev->v4l2_dev; vfd->tvnorms = 0; for (i = 0; i < dev->ext_vv_data->num_stds; i++) vfd->tvnorms |= dev->ext_vv_data->stds[i].id; Loading
drivers/media/common/saa7146_video.c +38 −172 Original line number Diff line number Diff line Loading @@ -201,65 +201,6 @@ int saa7146_stop_preview(struct saa7146_fh *fh) } EXPORT_SYMBOL_GPL(saa7146_stop_preview); /********************************************************************************/ /* device controls */ static struct v4l2_queryctrl controls[] = { { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", .minimum = 0, .maximum = 255, .step = 1, .default_value = 128, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_CONTRAST, .name = "Contrast", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_SATURATION, .name = "Saturation", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_VFLIP, .name = "Vertical Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, },{ .id = V4L2_CID_HFLIP, .name = "Horizontal Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, }, }; static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); #define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0) static struct v4l2_queryctrl* ctrl_by_id(int id) { int i; for (i = 0; i < NUM_CONTROLS; i++) if (controls[i].id == id) return controls+i; return NULL; } /********************************************************************************/ /* common pagetable functions */ Loading Loading @@ -510,12 +451,13 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability * strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->version = SAA7146_VERSION_CODE; cap->capabilities = cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities |= dev->ext_vv_data->capabilities; cap->device_caps |= dev->ext_vv_data->capabilities; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } Loading Loading @@ -579,135 +521,58 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd return 0; } static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) { const struct v4l2_queryctrl *ctrl; if ((c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) && (c->id < V4L2_CID_PRIVATE_BASE || c->id >= V4L2_CID_PRIVATE_LASTP1)) return -EINVAL; ctrl = ctrl_by_id(c->id); if (ctrl == NULL) return -EINVAL; DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id); *c = *ctrl; return 0; } static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_dev *dev = container_of(ctrl->handler, struct saa7146_dev, ctrl_handler); struct saa7146_vv *vv = dev->vv_data; const struct v4l2_queryctrl *ctrl; u32 value = 0; u32 val; ctrl = ctrl_by_id(c->id); if (NULL == ctrl) return -EINVAL; switch (c->id) { switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: value = saa7146_read(dev, BCS_CTRL); c->value = 0xff & (value >> 24); DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value); break; case V4L2_CID_CONTRAST: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 16); DEB_D("V4L2_CID_CONTRAST: %d\n", c->value); break; case V4L2_CID_SATURATION: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 0); DEB_D("V4L2_CID_SATURATION: %d\n", c->value); break; case V4L2_CID_VFLIP: c->value = vv->vflip; DEB_D("V4L2_CID_VFLIP: %d\n", c->value); break; case V4L2_CID_HFLIP: c->value = vv->hflip; DEB_D("V4L2_CID_HFLIP: %d\n", c->value); break; default: return -EINVAL; } return 0; } static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; const struct v4l2_queryctrl *ctrl; ctrl = ctrl_by_id(c->id); if (NULL == ctrl) { DEB_D("unknown control %d\n", c->id); return -EINVAL; } switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER: if (c->value < ctrl->minimum) c->value = ctrl->minimum; if (c->value > ctrl->maximum) c->value = ctrl->maximum; break; default: /* nothing */; } switch (c->id) { case V4L2_CID_BRIGHTNESS: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0x00ffffff; value |= (c->value << 24); saa7146_write(dev, BCS_CTRL, value); val = saa7146_read(dev, BCS_CTRL); val &= 0x00ffffff; val |= (ctrl->val << 24); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_CONTRAST: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0xff00ffff; value |= (c->value << 16); saa7146_write(dev, BCS_CTRL, value); case V4L2_CID_CONTRAST: val = saa7146_read(dev, BCS_CTRL); val &= 0xff00ffff; val |= (ctrl->val << 16); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_SATURATION: { u32 value = saa7146_read(dev, BCS_CTRL); value &= 0xffffff00; value |= (c->value << 0); saa7146_write(dev, BCS_CTRL, value); case V4L2_CID_SATURATION: val = saa7146_read(dev, BCS_CTRL); val &= 0xffffff00; val |= (ctrl->val << 0); saa7146_write(dev, BCS_CTRL, val); saa7146_write(dev, MC2, MASK_22 | MASK_06); break; } case V4L2_CID_HFLIP: /* fixme: we can support changing VFLIP and HFLIP here... */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D("V4L2_CID_HFLIP while active capture\n"); if ((vv->video_status & STATUS_CAPTURE)) return -EBUSY; } vv->hflip = c->value; vv->hflip = ctrl->val; break; case V4L2_CID_VFLIP: if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D("V4L2_CID_VFLIP while active capture\n"); if ((vv->video_status & STATUS_CAPTURE)) return -EBUSY; } vv->vflip = c->value; vv->vflip = ctrl->val; break; default: return -EINVAL; } if (IS_OVERLAY_ACTIVE(fh) != 0) { if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */ struct saa7146_fh *fh = vv->video_fh; saa7146_stop_preview(fh); saa7146_start_preview(fh); } Loading @@ -720,6 +585,8 @@ static int vidioc_g_parm(struct file *file, void *fh, struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; parm->parm.capture.readbuffers = 1; v4l2_video_std_frame_period(vv->standard->id, &parm->parm.capture.timeperframe); Loading Loading @@ -787,6 +654,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma } f->fmt.pix.field = field; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; if (f->fmt.pix.width > maxw) f->fmt.pix.width = maxw; if (f->fmt.pix.height > maxh) Loading Loading @@ -1141,9 +1009,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_parm = vidioc_g_parm, Loading Loading @@ -1338,6 +1203,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; fh->video_fmt.bytesperline = 0; fh->video_fmt.field = V4L2_FIELD_ANY; fh->video_fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; Loading
drivers/media/video/mxb.c +85 −88 Original line number Diff line number Diff line Loading @@ -64,8 +64,8 @@ enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; /* this array holds the information, which port of the saa7146 each Loading @@ -90,6 +90,36 @@ struct mxb_routing { u32 output; }; /* these are the available audio sources, which can switched to the line- and cd-output individually */ static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { { .index = 0, .name = "Tuner", .capability = V4L2_AUDCAP_STEREO, } , { .index = 1, .name = "AUX1", .capability = V4L2_AUDCAP_STEREO, } , { .index = 2, .name = "AUX2", .capability = V4L2_AUDCAP_STEREO, } , { .index = 3, .name = "AUX3", .capability = V4L2_AUDCAP_STEREO, } , { .index = 4, .name = "Radio (X9)", .capability = V4L2_AUDCAP_STEREO, } , { .index = 5, .name = "CD-ROM (X10)", .capability = V4L2_AUDCAP_STEREO, } }; /* These are the necessary input-output-pins for bringing one audio source (see above) to the CD-output. Note that gain is set to 0 in this table. */ static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { Loading @@ -114,11 +144,6 @@ static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = { { { 6, 3 }, { 6, 2 } } /* Mute */ }; #define MAXCONTROLS 1 static struct v4l2_queryctrl mxb_controls[] = { { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 }, }; struct mxb { struct video_device *video_dev; Loading Loading @@ -168,16 +193,45 @@ static inline void tea6420_route_line(struct mxb *mxb, int idx) static struct saa7146_extension extension; static int mxb_s_ctrl(struct v4l2_ctrl *ctrl) { struct saa7146_dev *dev = container_of(ctrl->handler, struct saa7146_dev, ctrl_handler); struct mxb *mxb = dev->ext_priv; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: mxb->cur_mute = ctrl->val; /* switch the audio-source */ tea6420_route_line(mxb, ctrl->val ? 6 : video_audio_connect[mxb->cur_input]); break; default: return -EINVAL; } return 0; } static const struct v4l2_ctrl_ops mxb_ctrl_ops = { .s_ctrl = mxb_s_ctrl, }; static int mxb_probe(struct saa7146_dev *dev) { struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; struct mxb *mxb = NULL; v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); if (hdl->error) return hdl->error; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); if (mxb == NULL) { DEB_D("not enough kernel memory\n"); return -ENOMEM; } snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); Loading Loading @@ -385,69 +439,6 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) } */ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; int i; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == qc->id) { *qc = mxb_controls[i]; DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id); return 0; } } return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc); } static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int i; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == vc->id) break; } if (i < 0) return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc); if (vc->id == V4L2_CID_AUDIO_MUTE) { vc->value = mxb->cur_mute; DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); return 0; } DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); return 0; } static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int i = 0; for (i = MAXCONTROLS - 1; i >= 0; i--) { if (mxb_controls[i].id == vc->id) break; } if (i < 0) return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc); if (vc->id == V4L2_CID_AUDIO_MUTE) { mxb->cur_mute = vc->value; /* switch the audio-source */ tea6420_route_line(mxb, vc->value ? 6 : video_audio_connect[mxb->cur_input]); DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value); } return 0; } static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index); Loading Loading @@ -568,12 +559,8 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; if (mxb->cur_input) { DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", mxb->cur_input); if (f->tuner) return -EINVAL; } *f = mxb->cur_freq; DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency); Loading @@ -592,17 +579,16 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency if (V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; if (mxb->cur_input) { DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input); return -EINVAL; } mxb->cur_freq = *f; DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency); /* tune in desired frequency */ tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); tuner_call(mxb, tuner, s_frequency, f); /* let the tuner subdev clamp the frequency to the tuner range */ tuner_call(mxb, tuner, g_frequency, f); mxb->cur_freq = *f; if (mxb->cur_input) return 0; /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); Loading @@ -612,6 +598,14 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency return 0; } static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) { if (a->index >= MXB_AUDIOS) return -EINVAL; *a = mxb_audios[a->index]; return 0; } static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; Loading @@ -629,8 +623,13 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; DEB_D("VIDIOC_S_AUDIO %d\n", a->index); if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) return 0; return -EINVAL; } #ifdef CONFIG_VIDEO_ADV_DEBUG Loading Loading @@ -709,9 +708,6 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data } mxb = (struct mxb *)dev->ext_priv; vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; vv_data.ops.vidioc_enum_input = vidioc_enum_input; vv_data.ops.vidioc_g_input = vidioc_g_input; vv_data.ops.vidioc_s_input = vidioc_s_input; Loading @@ -719,6 +715,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data vv_data.ops.vidioc_s_tuner = vidioc_s_tuner; vv_data.ops.vidioc_g_frequency = vidioc_g_frequency; vv_data.ops.vidioc_s_frequency = vidioc_s_frequency; vv_data.ops.vidioc_enumaudio = vidioc_enumaudio; vv_data.ops.vidioc_g_audio = vidioc_g_audio; vv_data.ops.vidioc_s_audio = vidioc_s_audio; #ifdef CONFIG_VIDEO_ADV_DEBUG Loading Loading @@ -836,7 +833,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_ext_vv vv_data = { .inputs = MXB_INPUTS, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO, .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, Loading
drivers/media/video/mxb.h +0 −29 Original line number Diff line number Diff line Loading @@ -10,33 +10,4 @@ #define MXB_AUDIOS 6 /* these are the available audio sources, which can switched to the line- and cd-output individually */ static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { { .index = 0, .name = "Tuner", .capability = V4L2_AUDCAP_STEREO, } , { .index = 1, .name = "AUX1", .capability = V4L2_AUDCAP_STEREO, } , { .index = 2, .name = "AUX2", .capability = V4L2_AUDCAP_STEREO, } , { .index = 3, .name = "AUX3", .capability = V4L2_AUDCAP_STEREO, } , { .index = 4, .name = "Radio (X9)", .capability = V4L2_AUDCAP_STEREO, } , { .index = 5, .name = "CD-ROM (X10)", .capability = V4L2_AUDCAP_STEREO, } }; #endif
include/media/saa7146.h +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/scatterlist.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <linux/vmalloc.h> /* for vmalloc() */ #include <linux/mm.h> /* for vmalloc_to_page() */ Loading Loading @@ -121,6 +122,7 @@ struct saa7146_dev struct list_head item; struct v4l2_device v4l2_dev; struct v4l2_ctrl_handler ctrl_handler; /* different device locks */ spinlock_t slock; Loading