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 vbi_open(struct saa7146_dev *dev, struct file *file) { struct saa7146_fh *fh = file->private_data; u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1); int ret = 0; DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS); if (0 == ret) { DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n")); return -EBUSY; } /* adjust arbitrition control for video dma 3 */ arbtr_ctrl &= ~0x1f0000; arbtr_ctrl |= 0x1d0000; saa7146_write(dev, PCI_BT_V1, arbtr_ctrl); saa7146_write(dev, MC2, (MASK_04|MASK_20)); memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt)); fh->vbi_fmt.sampling_rate = 27000000; fh->vbi_fmt.offset = 248; /* todo */ fh->vbi_fmt.samples_per_line = vbi_pixel_to_capture; fh->vbi_fmt.sample_format = V4L2_PIX_FMT_GREY; fh->vbi_fmt.start[0] = 5; fh->vbi_fmt.count[0] = 16; fh->vbi_fmt.start[1] = 312; fh->vbi_fmt.count[1] = 16; videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct saa7146_buf), file); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; fh->vbi_read_timeout.data = (unsigned long)file; /* initialize the brs */ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19)); } else { saa7146_write(dev, BRS_CTRL, 0x00000001); if (0 != (ret = vbi_workaround(dev))) { DEB_VBI(("vbi workaround failed!\n")); /* return ret;*/ } } /* upload brs register */ saa7146_write(dev, MC2, (MASK_08|MASK_24)); 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 vbi_open(struct saa7146_dev *dev, struct file *file) { struct saa7146_fh *fh = file->private_data; struct saa7146_vv *vv = fh->dev->vv_data; u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1); int ret = 0; DEB_VBI("dev:%p, fh:%p\n", dev, fh); ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS); if (0 == ret) { DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n"); return -EBUSY; } /* adjust arbitrition control for video dma 3 */ arbtr_ctrl &= ~0x1f0000; arbtr_ctrl |= 0x1d0000; saa7146_write(dev, PCI_BT_V1, arbtr_ctrl); saa7146_write(dev, MC2, (MASK_04|MASK_20)); videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), file, &dev->v4l2_lock); vv->vbi_read_timeout.function = vbi_read_timeout; vv->vbi_read_timeout.data = (unsigned long)file; /* initialize the brs */ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19)); } else { saa7146_write(dev, BRS_CTRL, 0x00000001); if (0 != (ret = vbi_workaround(dev))) { DEB_VBI("vbi workaround failed!\n"); /* return ret;*/ } } /* upload brs register */ saa7146_write(dev, MC2, (MASK_08|MASK_24)); return 0; }