static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; int err; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh)); if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_EE(("streaming capture is active\n")); return -EBUSY; } err = try_fmt(fh,f); if (0 != err) return err; fh->video_fmt = f->fmt.pix; DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat)); return 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh)); err = try_win(dev,&f->fmt.win); if (0 != err) return err; down(&dev->lock); fh->ov.win = f->fmt.win; fh->ov.nclips = f->fmt.win.clipcount; if (fh->ov.nclips > 16) fh->ov.nclips = 16; if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) { up(&dev->lock); return -EFAULT; } /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; up(&dev->lock); /* check if our current overlay is active */ if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); saa7146_start_preview(fh); } return 0; default: DEB_D(("unknown format type '%d'\n",f->type)); return -EINVAL; } }
static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; int found = 0; int err, i; DEB_EE(("VIDIOC_S_STD\n")); if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { DEB_D(("cannot change video standard while streaming capture is active\n")); return -EBUSY; } if ((vv->video_status & STATUS_OVERLAY) != 0) { vv->ov_suspend = vv->video_fh; err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ if (0 != err) { DEB_D(("suspending video failed. aborting\n")); return err; } } mutex_lock(&dev->lock); for (i = 0; i < dev->ext_vv_data->num_stds; i++) if (*id & dev->ext_vv_data->stds[i].id) break; if (i != dev->ext_vv_data->num_stds) { vv->standard = &dev->ext_vv_data->stds[i]; if (NULL != dev->ext_vv_data->std_callback) dev->ext_vv_data->std_callback(dev, vv->standard); found = 1; } mutex_unlock(&dev->lock); if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); vv->ov_suspend = NULL; } if (!found) { DEB_EE(("VIDIOC_S_STD: standard not found.\n")); return -EINVAL; } DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name)); return 0; }
int saa7146_unregister_extension(struct saa7146_extension* ext) { DEB_EE("ext:%p\n", ext); pr_info("unregister extension '%s'\n", ext->name); pci_unregister_driver(&ext->driver); return 0; }
int saa7146_start_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct v4l2_format fmt; int ret = 0, err = 0; DEB_EE("dev:%p, fh:%p\n", dev, fh); /* check if we have overlay information */ if (vv->ov.fh == NULL) { DEB_D("no overlay data available. try S_FMT first.\n"); return -EAGAIN; } /* check if streaming capture is running */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D("streaming capture is active\n"); return -EBUSY; } /* check if overlay is running */ if (IS_OVERLAY_ACTIVE(fh) != 0) { if (vv->video_fh == fh) { DEB_D("overlay is already active\n"); return 0; } DEB_D("overlay is already active in another open\n"); return -EBUSY; } if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { DEB_D("cannot get necessary overlay resources\n"); return -EBUSY; } fmt.fmt.win = vv->ov.win; err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt); if (0 != err) { saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); return -EBUSY; } vv->ov.win = fmt.fmt.win; DEB_D("%dx%d+%d+%d %s field=%s\n", vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]); if (0 != (ret = saa7146_enable_overlay(fh))) { DEB_D("enabling overlay failed: %d\n", ret); saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); return ret; } vv->video_status = STATUS_OVERLAY; vv->video_fh = fh; return 0; }
static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; struct saa7146_vv *vv = dev->vv_data; if (f->tuner) return -EINVAL; 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); /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); vv->vbi_fieldcount = 0; spin_unlock(&dev->slock); return 0; }
static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; struct saa7146_vv *vv = dev->vv_data; if (f->tuner) return -EINVAL; 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); tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); spin_lock(&dev->slock); vv->vbi_fieldcount = 0; spin_unlock(&dev->slock); return 0; }
int saa7146_unregister_extension(struct saa7146_extension* ext) { DEB_EE(("ext:%p\n",ext)); printk("saa7146: unregister extension '%s'.\n",ext->name); pci_unregister_driver(&ext->driver); return 0; }
int saa7146_stop_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); /* check if streaming capture is running */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("streaming capture is active.\n")); return -EBUSY; } /* check if overlay is running at all */ if ((vv->video_status & STATUS_OVERLAY) == 0) { DEB_D(("no active overlay.\n")); return 0; } if (vv->video_fh != fh) { DEB_D(("overlay is active, but in another open.\n")); return -EBUSY; } vv->video_status = 0; vv->video_fh = NULL; saa7146_disable_overlay(fh); saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); return 0; }
int saa7146_unregister_extension(struct saa7146_extension* ext) { DEB_EE(("ext:%p\n",ext)); ; pci_unregister_driver(&ext->driver); return 0; }
static int video_begin(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct saa7146_format *fmt = NULL; unsigned int resource; int ret = 0, err = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); if ((vv->video_status & STATUS_CAPTURE) != 0) { if (vv->video_fh == fh) { DEB_S(("already capturing.\n")); return 0; } DEB_S(("already capturing in another open.\n")); return -EBUSY; } if ((vv->video_status & STATUS_OVERLAY) != 0) { DEB_S(("warning: suspending overlay video for streaming capture.\n")); vv->ov_suspend = vv->video_fh; err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ if (0 != err) { DEB_D(("suspending video failed. aborting\n")); return err; } } fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); /* we need to have a valid format set here */ BUG_ON(NULL == fmt); if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; } else { resource = RESOURCE_DMA1_HPS; } ret = saa7146_res_get(fh, resource); if (0 == ret) { DEB_S(("cannot get capture resource %d\n",resource)); if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); vv->ov_suspend = NULL; } return -EBUSY; } /* clear out beginning of streaming bit (rps register 0)*/ saa7146_write(dev, MC2, MASK_27 ); /* enable rps0 irqs */ SAA7146_IER_ENABLE(dev, MASK_27); vv->video_fh = fh; vv->video_status = STATUS_CAPTURE; return 0; }
static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f) { struct saa7146_fh *fh = __fh; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; int err; DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh); err = vidioc_try_fmt_vid_overlay(file, fh, f); if (0 != err) return err; fh->ov.win = f->fmt.win; fh->ov.nclips = f->fmt.win.clipcount; if (fh->ov.nclips > 16) fh->ov.nclips = 16; if (copy_from_user(fh->ov.clips, f->fmt.win.clips, sizeof(struct v4l2_clip) * fh->ov.nclips)) { return -EFAULT; } /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; /* check if our current overlay is active */ if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); saa7146_start_preview(fh); } return 0; }
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); if (i->index >= MXB_INPUTS) return -EINVAL; memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); return 0; }
static int vidioc_s_input(struct file *file, void *fh, unsigned int input) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int err = 0; int i = 0; DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); if (input >= MXB_INPUTS) return -EINVAL; mxb->cur_input = input; saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); /* prepare switching of tea6415c and saa7111a; have a look at the 'background'-file for further informations */ switch (input) { case TUNER: i = SAA7115_COMPOSITE0; err = tea6415c_call(mxb, video, s_routing, 3, 17, 0); /* connect tuner-output always to multicable */ if (!err) err = tea6415c_call(mxb, video, s_routing, 3, 13, 0); break; case AUX3_YC: /* nothing to be done here. aux3_yc is directly connected to the saa711a */ i = SAA7115_SVIDEO1; break; case AUX3: /* nothing to be done here. aux3 is directly connected to the saa711a */ i = SAA7115_COMPOSITE1; break; case AUX1: i = SAA7115_COMPOSITE0; err = tea6415c_call(mxb, video, s_routing, 1, 17, 0); break; } if (err) return err; /* switch video in saa7111a */ if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0)) printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a.\n"); /* switch the audio-source only if necessary */ if (0 == mxb->cur_mute) tea6420_route_line(mxb, video_audio_connect[input]); return 0; }
static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; struct v4l2_window *win = &f->fmt.win; enum v4l2_field field; int maxw, maxh; DEB_EE("dev:%p\n", dev); if (NULL == vv->ov_fb.base) { DEB_D("no fb base set\n"); return -EINVAL; } if (NULL == vv->ov_fmt) { DEB_D("no fb fmt set\n"); return -EINVAL; } if (win->w.width < 48 || win->w.height < 32) { DEB_D("min width/height. (%d,%d)\n", win->w.width, win->w.height); return -EINVAL; } if (win->clipcount > 16) { DEB_D("clipcount too big\n"); return -EINVAL; } field = win->field; maxw = vv->standard->h_max_out; maxh = vv->standard->v_max_out; if (V4L2_FIELD_ANY == field) { field = (win->w.height > maxh / 2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; } switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: case V4L2_FIELD_ALTERNATE: maxh = maxh / 2; break; case V4L2_FIELD_INTERLACED: break; default: DEB_D("no known field mode '%d'\n", field); return -EINVAL; } win->field = field; if (win->w.width > maxw) win->w.width = maxw; if (win->w.height > maxh) win->w.height = maxh; return 0; }
void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr) { struct budget *budget = (struct budget*)dev->ext_priv; DEB_EE(("dev: %p, budget: %p\n",dev,budget)); if (*isr & MASK_10) tasklet_schedule (&budget->vpe_tasklet); }
static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; *i = mxb->cur_input; DEB_EE(("VIDIOC_G_INPUT %d.\n", *i)); return 0; }
static int video_end(struct saa7146_fh *fh, struct file *file) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct saa7146_format *fmt = NULL; unsigned long flags; unsigned int resource; u32 dmas = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { DEB_S(("not capturing.\n")); return 0; } if (vv->video_fh != fh) { DEB_S(("capturing, but in another open.\n")); return -EBUSY; } fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); /* we need to have a valid format set here */ BUG_ON(NULL == fmt); if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; dmas = MASK_22 | MASK_21 | MASK_20; } else { resource = RESOURCE_DMA1_HPS; dmas = MASK_22; } spin_lock_irqsave(&dev->slock,flags); /* disable rps0 */ saa7146_write(dev, MC1, MASK_28); /* disable rps0 irqs */ SAA7146_IER_DISABLE(dev, MASK_27); /* shut down all used video dma transfers */ saa7146_write(dev, MC1, dmas); spin_unlock_irqrestore(&dev->slock, flags); vv->video_fh = NULL; vv->video_status = 0; saa7146_res_free(fh, resource); if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); vv->ov_suspend = NULL; } return 0; }
static int try_win(struct saa7146_dev *dev, struct v4l2_window *win) { struct saa7146_vv *vv = dev->vv_data; enum v4l2_field field; int maxw, maxh; DEB_EE(("dev:%p\n",dev)); if (NULL == vv->ov_fb.base) { DEB_D(("no fb base set.\n")); return -EINVAL; } if (NULL == vv->ov_fmt) { DEB_D(("no fb fmt set.\n")); return -EINVAL; } if (win->w.width < 48 || win->w.height < 32) { DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height)); return -EINVAL; } if (win->clipcount > 16) { DEB_D(("clipcount too big.\n")); return -EINVAL; } field = win->field; maxw = vv->standard->h_max_out; maxh = vv->standard->v_max_out; if (V4L2_FIELD_ANY == field) { field = (win->w.height > maxh/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; } switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: case V4L2_FIELD_ALTERNATE: maxh = maxh / 2; break; case V4L2_FIELD_INTERLACED: break; default: { DEB_D(("no known field mode '%d'.\n",field)); return -EINVAL; } } win->field = field; if (win->w.width > maxw) win->w.width = maxw; if (win->w.height > maxh) win->w.height = maxh; return 0; }
static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { struct saa7146_fh *fh = __fh; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; int err; DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_EE(("streaming capture is active\n")); return -EBUSY; } err = vidioc_try_fmt_vid_cap(file, fh, f); if (0 != err) return err; fh->video_fmt = f->fmt.pix; DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat)); return 0; }
static long vidioc_default(struct file *file, void *fh, bool valid_prio, int cmd, void *arg) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; switch (cmd) { case MXB_S_AUDIO_CD: { int i = *(int *)arg; if (i < 0 || i >= MXB_AUDIOS) { DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i); return -EINVAL; } DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i); tea6420_route_cd(mxb, i); return 0; } case MXB_S_AUDIO_LINE: { int i = *(int *)arg; if (i < 0 || i >= MXB_AUDIOS) { DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n", i); return -EINVAL; } DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i); tea6420_route_line(mxb, i); return 0; } default: /* DEB2(pr_err("does not handle this ioctl\n")); */ return -ENOIOCTLCMD; } return 0; }
static int stop_ts_capture(struct budget *budget) { DEB_EE(("budget: %p\n",budget)); if (--budget->feeding) return budget->feeding; saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off IER_DISABLE(budget->dev, MASK_10); return 0; }
int saa7146_unregister_extension(struct saa7146_extension* ext) { DEB_EE(("ext:%p\n",ext)); #ifdef CONFIG_DEBUG_PRINTK printk("saa7146: unregister extension '%s'.\n",ext->name); #else ; #endif pci_unregister_driver(&ext->driver); return 0; }
void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) { DEB_EE(("dev:%p, buf:%p\n",dev,buf)); if (in_interrupt()) BUG(); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); buf->vb.state = STATE_NEEDS_INIT; }
int saa7146_register_extension(struct saa7146_extension* ext) { DEB_EE(("ext:%p\n",ext)); ext->driver.name = ext->name; ext->driver.id_table = ext->pci_tbl; ext->driver.probe = saa7146_init_one; ext->driver.remove = saa7146_remove_one; printk("saa7146: register extension '%s'.\n",ext->name); return pci_register_driver(&ext->driver); }
static int vidioc_s_input(struct file *file, void *fh, unsigned int input) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; int err = 0; int i = 0; DEB_EE("VIDIOC_S_INPUT %d\n", input); if (input >= MXB_INPUTS) return -EINVAL; mxb->cur_input = input; saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); switch (input) { case TUNER: i = SAA7115_COMPOSITE0; err = tea6415c_call(mxb, video, s_routing, 3, 17, 0); if (!err) err = tea6415c_call(mxb, video, s_routing, 3, 13, 0); break; case AUX3_YC: i = SAA7115_SVIDEO1; break; case AUX3: i = SAA7115_COMPOSITE1; break; case AUX1: i = SAA7115_COMPOSITE0; err = tea6415c_call(mxb, video, s_routing, 1, 17, 0); break; } if (err) return err; if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0)) pr_err("VIDIOC_S_INPUT: could not address saa7111a\n"); if (0 == mxb->cur_mute) tea6420_route_line(mxb, video_audio_connect[input]); return 0; }
static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; int status; DEB_EE(("budget: %p\n",budget)); spin_lock(&budget->feedlock); status = stop_ts_capture (budget); spin_unlock(&budget->feedlock); return status; }
void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, struct saa7146_buf *buf) { struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); DEB_EE(("dev:%p, buf:%p\n",dev,buf)); BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); videobuf_dma_unmap(q, dma); videobuf_dma_free(dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; }
void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state) { assert_spin_locked(&dev->slock); DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state)); DEB_EE(("q->curr:%p\n",q->curr)); BUG_ON(!q->curr); /* finish current buffer */ if (NULL == q->curr) { DEB_D(("aiii. no current buffer\n")); return; } q->curr->vb.state = state; do_gettimeofday(&q->curr->vb.ts); wake_up(&q->curr->vb.done); q->curr = NULL; }
static int vidioc_g_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; if (a->index > MXB_INPUTS) { DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); return -EINVAL; } DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); return 0; }
/* this function only gets called when the probing was successful */ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct mxb *mxb; DEB_EE(("dev:%p\n", dev)); saa7146_vv_init(dev, &vv_data); if (mxb_probe(dev)) { saa7146_vv_release(dev); return -1; } 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; vv_data.ops.vidioc_g_tuner = vidioc_g_tuner; 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_g_audio = vidioc_g_audio; vv_data.ops.vidioc_s_audio = vidioc_s_audio; #ifdef CONFIG_VIDEO_ADV_DEBUG vv_data.ops.vidioc_g_register = vidioc_g_register; vv_data.ops.vidioc_s_register = vidioc_s_register; #endif vv_data.ops.vidioc_default = vidioc_default; if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); saa7146_vv_release(dev); return -1; } /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ if (MXB_BOARD_CAN_DO_VBI(dev)) { if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); } } printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); mxb_num++; mxb_init_done(dev); return 0; }