static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct stk1160 *dev = video_drvdata(file); int rc; u8 val; switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: /* TODO: Support me please :-( */ return -EINVAL; case V4L2_CHIP_MATCH_I2C_DRIVER: v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* TODO: is this correct? */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; } /* Match host */ rc = stk1160_read_reg(dev, reg->reg, &val); reg->val = val; reg->size = 1; return rc; }
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; }
/* * vpif_log_status() - Status information * @file: file ptr * @priv: file handle * * Returns zero. */ static int vpif_log_status(struct file *filep, void *priv) { /* status for sub devices */ v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status); return 0; }
static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { struct smi2021 *smi2021 = video_drvdata(file); if (i >= smi2021->vid_input_count) return -EINVAL; v4l2_device_call_all(&smi2021->v4l2_dev, 0, video, s_routing, smi2021->vid_inputs[i].type, 0, 0); smi2021->cur_input = i; return 0; }
static int vidioc_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct stk1160 *dev = video_drvdata(file); switch (reg->match.type) { case V4L2_CHIP_MATCH_AC97: return -EINVAL; case V4L2_CHIP_MATCH_I2C_DRIVER: v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* TODO: is this correct? */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; } /* Match host */ return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val)); }
/* Must be called with v4l_lock hold */ static void stk1160_stop_hw(struct stk1160 *dev) { /* If the device is not physically present, there is nothing to do */ if (!dev->udev) return; /* set alternate 0 */ dev->alt = 0; stk1160_info("setting alternate %d\n", dev->alt); usb_set_interface(dev->udev, 0, 0); /* Stop stk1160 */ stk1160_write_reg(dev, STK1160_DCTRL, 0x00); stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); /* Stop saa711x */ v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 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 vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { struct smi2021 *smi2021 = video_drvdata(file); if (vb2_is_busy(&smi2021->vb2q)) return -EBUSY; smi2021->cur_norm = norm; if (norm & V4L2_STD_525_60) smi2021->cur_height = SMI2021_NTSC_LINES; else if (norm & V4L2_STD_625_50) smi2021->cur_height = SMI2021_PAL_LINES; else return -EINVAL; v4l2_device_call_all(&smi2021->v4l2_dev, 0, core, s_std, smi2021->cur_norm); return 0; }
static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) { struct stk1160 *dev = video_drvdata(file); v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); 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; }