static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { struct stk1160 *dev = video_drvdata(file); struct vb2_queue *q = &dev->vb_vidq; if (vb2_is_busy(q)) return -EBUSY; /* Check device presence */ if (!dev->udev) return -ENODEV; /* We need to set this now, before we call stk1160_set_std */ dev->norm = norm; /* This is taken from saa7115 video decoder */ if (dev->norm & V4L2_STD_525_60) { dev->width = 720; dev->height = 480; } else if (dev->norm & V4L2_STD_625_50) { dev->width = 720; dev->height = 576; } else { stk1160_err("invalid standard\n"); return -EINVAL; } stk1160_set_std(dev); v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); return 0; }
/* * stk1160_i2c_register() * register i2c bus */ int stk1160_i2c_register(struct stk1160 *dev) { int rc; dev->i2c_adap = adap_template; dev->i2c_adap.dev.parent = dev->dev; strcpy(dev->i2c_adap.name, "stk1160"); dev->i2c_adap.algo_data = dev; i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); rc = i2c_add_adapter(&dev->i2c_adap); if (rc < 0) { stk1160_err("cannot add i2c adapter (%d)\n", rc); return rc; } dev->i2c_client = client_template; dev->i2c_client.adapter = &dev->i2c_adap; /* Set i2c clock divider device address */ stk1160_write_reg(dev, STK1160_SICTL_CD, 0x0f); /* ??? */ stk1160_write_reg(dev, STK1160_ASIC + 3, 0x00); return 0; }
int stk1160_video_register(struct stk1160 *dev) { int rc; /* Initialize video_device with a template structure */ dev->vdev = v4l_template; dev->vdev.debug = vidioc_debug; dev->vdev.queue = &dev->vb_vidq; /* * Provide mutexes for v4l2 core and for videobuf2 queue. * It will be used to protect *only* v4l2 ioctls. */ dev->vdev.lock = &dev->v4l_lock; dev->vdev.queue->lock = &dev->vb_queue_lock; /* This will be used to set video_device parent */ dev->vdev.v4l2_dev = &dev->v4l2_dev; set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); /* NTSC is default */ dev->norm = V4L2_STD_NTSC_M; dev->width = 720; dev->height = 480; /* set default format */ dev->fmt = &format[0]; stk1160_set_std(dev); v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); video_set_drvdata(&dev->vdev, dev); rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (rc < 0) { stk1160_err("video_register_device failed (%d)\n", rc); return rc; } v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(&dev->vdev)); return 0; }
static int stk1160_start_streaming(struct stk1160 *dev) { bool new_pkt_size; int rc = 0; int i; /* Check device presence */ if (!dev->udev) return -ENODEV; if (mutex_lock_interruptible(&dev->v4l_lock)) return -ERESTARTSYS; /* * For some reason it is mandatory to set alternate *first* * and only *then* initialize isoc urbs. * Someone please explain me why ;) */ new_pkt_size = stk1160_set_alternate(dev); /* * We (re)allocate isoc urbs if: * there is no allocated isoc urbs, OR * a new dev->max_pkt_size is detected */ if (!dev->isoc_ctl.num_bufs || new_pkt_size) { rc = stk1160_alloc_isoc(dev); if (rc < 0) goto out_stop_hw; } /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_KERNEL); if (rc) { stk1160_err("cannot submit urb[%d] (%d)\n", i, rc); goto out_uninit; } } /* Start saa711x */ v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); /* Start stk1160 */ stk1160_write_reg(dev, STK1160_DCTRL, 0xb3); stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); stk1160_dbg("streaming started\n"); mutex_unlock(&dev->v4l_lock); return 0; out_uninit: stk1160_uninit_isoc(dev); out_stop_hw: usb_set_interface(dev->udev, 0, 0); stk1160_clear_queue(dev); mutex_unlock(&dev->v4l_lock); return rc; }