From a7c7402f68cf97c9a021466c04029f039f9f4f27 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:03 -0300 Subject: V4L/DVB (7169): Add chip IDs for Micron mt9m001 and mt9v022 CMOS cameras Add V4L2_IDENT chip IDs for mt9m001 and mt9v022 cameras, will be used by future patches, primarily to implement the g_chip_ident ioctl. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-chip-ident.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/media') diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 032bb75f69c..0ea0bd85c03 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -153,6 +153,12 @@ enum { V4L2_IDENT_MSP4428G = 44287, V4L2_IDENT_MSP4448G = 44487, V4L2_IDENT_MSP4458G = 44587, + + /* Micron CMOS sensor chips: 45000-45099 */ + V4L2_IDENT_MT9M001C12ST = 45000, + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; #endif -- cgit v1.2.3-70-g09d2 From e55222ef27a2390d8abce27a3ce2d4c719ad5f1b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:03 -0300 Subject: V4L/DVB (7170): soc_camera V4L2 driver for directly-connected SoC-based cameras This driver provides an interface between platform-specific camera busses and camera devices. It should be used if the camera is connected not over a "proper" bus like PCI or USB, but over a special bus, like, for example, the Quick Capture interface on PXA270 SoCs. Later it should also be used for i.MX31 SoCs from Freescale. It can handle multiple cameras and / or multiple busses, which can be used, e.g., in stereo-vision applications. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 9 + drivers/media/video/Makefile | 2 + drivers/media/video/soc_camera.c | 973 +++++++++++++++++++++++++++++++++++++++ include/media/soc_camera.h | 147 ++++++ 4 files changed, 1131 insertions(+) create mode 100644 drivers/media/video/soc_camera.c create mode 100644 include/media/soc_camera.h (limited to 'include/media') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 1832966f53f..5d3fbd969b6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -836,4 +836,13 @@ config USB_STKWEBCAM endif # V4L_USB_DRIVERS +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_DMA_SG + help + SoC Camera is a common API to several cameras, not connecting + over a bus like PCI or USB. For example some i2c camera connected + directly to the data bus of an SoC. + endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 6f1ef09df1d..cf5e990a47b 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -136,5 +136,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c new file mode 100644 index 00000000000..904e9dfc1a8 --- /dev/null +++ b/drivers/media/video/soc_camera.c @@ -0,0 +1,973 @@ +/* + * camera image capture (abstract) bus driver + * + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This driver provides an interface between platform-specific camera + * busses and camera devices. It should be used if the camera is + * connected not over a "proper" bus like PCI or USB, but over a + * special bus, like, for example, the Quick Capture interface on PXA270 + * SoCs. Later it should also be used for i.MX31 SoCs from Freescale. + * It can handle multiple cameras and / or multiple busses, which can + * be used, e.g., in stereo-vision applications. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static LIST_HEAD(hosts); +static LIST_HEAD(devices); +static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(video_lock); + +const static struct soc_camera_data_format* +format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < icd->ops->num_formats; i++) + if (icd->ops->formats[i].fourcc == fourcc) + return icd->ops->formats + i; + return NULL; +} + +static int soc_camera_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + enum v4l2_field field; + const struct soc_camera_data_format *fmt; + int ret; + + WARN_ON(priv != file->private_data); + + fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!fmt) { + dev_dbg(&icd->dev, "invalid format 0x%08x\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { + field = V4L2_FIELD_NONE; + } else if (V4L2_FIELD_NONE != field) { + dev_err(&icd->dev, "Field type invalid.\n"); + return -EINVAL; + } + + /* limit to host capabilities */ + ret = ici->try_fmt_cap(ici, f); + + /* limit to sensor capabilities */ + if (!ret) + ret = icd->ops->try_fmt_cap(icd, f); + + /* calculate missing fields */ + f->fmt.pix.field = field; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return ret; +} + +static int soc_camera_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Camera"); + + return 0; +} + +static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + + return 0; +} + +static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) +{ + return 0; +} + +static int soc_camera_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + int ret; + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory); + + ret = videobuf_reqbufs(&icf->vb_vidq, p); + if (ret < 0) + return ret; + + return ici->reqbufs(icf, p); + + return ret; +} + +static int soc_camera_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_querybuf(&icf->vb_vidq, p); +} + +static int soc_camera_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_qbuf(&icf->vb_vidq, p); +} + +static int soc_camera_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); +} + +static int soc_camera_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct soc_camera_device *icd = container_of(vdev->dev, + struct soc_camera_device, dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct soc_camera_file *icf; + int ret; + + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + + icf->icd = icd; + + if (!try_module_get(icd->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); + ret = -EINVAL; + goto emgd; + } + + if (!try_module_get(ici->owner)) { + dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + ret = -EINVAL; + goto emgi; + } + + file->private_data = icf; + dev_dbg(&icd->dev, "camera device open\n"); + + /* We must pass NULL as dev pointer, then all pci_* dma operations + * transform to normal dma_* ones. Do we need an irqlock? */ + videobuf_queue_pci_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + ici->msize, icd); + + return 0; + +emgi: + module_put(icd->ops->owner); +emgd: + vfree(icf); + return ret; +} + +static int soc_camera_close(struct inode *inode, struct file *file) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct video_device *vdev = icd->vdev; + + module_put(icd->ops->owner); + module_put(ici->owner); + vfree(file->private_data); + + dev_dbg(vdev->dev, "camera device close\n"); + + return 0; +} + +static int soc_camera_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct video_device *vdev = icd->vdev; + int err = -EINVAL; + + dev_err(vdev->dev, "camera device read not implemented\n"); + + return err; +} + +static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int err; + + dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + + err = videobuf_mmap_mapper(&icf->vb_vidq, vma); + + dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, + err); + + return err; +} + +static unsigned int soc_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (list_empty(&icf->vb_vidq.stream)) { + dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); + return POLLERR; + } + + return ici->poll(file, pt); +} + + +static struct file_operations soc_camera_fops = { + .owner = THIS_MODULE, + .open = soc_camera_open, + .release = soc_camera_close, + .ioctl = video_ioctl2, + .read = soc_camera_read, + .mmap = soc_camera_mmap, + .poll = soc_camera_poll, + .llseek = no_llseek, +}; + + +static int soc_camera_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + struct v4l2_rect rect; + const static struct soc_camera_data_format *data_fmt; + + WARN_ON(priv != file->private_data); + + data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!data_fmt) + return -EINVAL; + + /* cached_datawidth may be further adjusted by the ici */ + icd->cached_datawidth = data_fmt->depth; + + ret = soc_camera_try_fmt_cap(file, icf, f); + if (ret < 0) + return ret; + + rect.left = icd->x_current; + rect.top = icd->y_current; + rect.width = f->fmt.pix.width; + rect.height = f->fmt.pix.height; + ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + + if (!ret) { + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); + + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + } + + return ret; +} + +static int soc_camera_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + const struct soc_camera_data_format *format; + + WARN_ON(priv != file->private_data); + + if (f->index >= icd->ops->num_formats) + return -EINVAL; + + format = &icd->ops->formats[f->index]; + + strlcpy(f->description, format->name, sizeof(f->description)); + f->pixelformat = format->fourcc; + return 0; +} + +static int soc_camera_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + f->fmt.pix.width = icd->width; + f->fmt.pix.height = icd->height; + f->fmt.pix.field = icf->vb_vidq.field; + f->fmt.pix.pixelformat = icd->current_fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * icd->current_fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", + icd->current_fmt->fourcc); + return 0; +} + +static int soc_camera_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); + return ici->querycap(ici, cap); +} + +static int soc_camera_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + icd->ops->start_capture(icd); + + /* This calls buf_queue from host driver's videobuf_queue_ops */ + return videobuf_streamon(&icf->vb_vidq); +} + +static int soc_camera_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop capture */ + videobuf_streamoff(&icf->vb_vidq); + + icd->ops->stop_capture(icd); + + return 0; +} + +static int soc_camera_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int i; + + WARN_ON(priv != file->private_data); + + if (!qc->id) + return -EINVAL; + + for (i = 0; i < icd->ops->num_controls; i++) + if (qc->id == icd->ops->controls[i].id) { + memcpy(qc, &(icd->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + +static int soc_camera_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (icd->gain == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->gain; + return 0; + case V4L2_CID_EXPOSURE: + if (icd->exposure == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->exposure; + return 0; + } + + if (icd->ops->get_control) + return icd->ops->get_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + if (icd->ops->set_control) + return icd->ops->set_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->bounds.left = icd->x_min; + a->bounds.top = icd->y_min; + a->bounds.width = icd->width_max; + a->bounds.height = icd->height_max; + a->defrect.left = icd->x_min; + a->defrect.top = icd->y_min; + a->defrect.width = 640; + a->defrect.height = 480; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int soc_camera_g_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c.left = icd->x_current; + a->c.top = icd->y_current; + a->c.width = icd->width; + a->c.height = icd->height; + + return 0; +} + +static int soc_camera_s_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + ret = ici->set_capture_format(icd, 0, &a->c); + if (!ret) { + icd->width = a->c.width; + icd->height = a->c.height; + icd->x_current = a->c.left; + icd->y_current = a->c.top; + } + + return ret; +} + +static int soc_camera_g_chip_ident(struct file *file, void *fh, + struct v4l2_chip_ident *id) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_chip_id) + return -EINVAL; + + return icd->ops->get_chip_id(icd, id); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int soc_camera_g_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_register) + return -EINVAL; + + return icd->ops->get_register(icd, reg); +} + +static int soc_camera_s_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->set_register) + return -EINVAL; + + return icd->ops->set_register(icd, reg); +} +#endif + +static int device_register_link(struct soc_camera_device *icd) +{ + int ret = device_register(&icd->dev); + + if (ret < 0) { + /* Prevent calling device_unregister() */ + icd->dev.parent = NULL; + dev_err(&icd->dev, "Cannot register device: %d\n", ret); + /* Even if probe() was unsuccessful for all registered drivers, + * device_register() returns 0, and we add the link, just to + * document this camera's control device */ + } else if (icd->control) + /* Have to sysfs_remove_link() before device_unregister()? */ + if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, + "control")) + dev_warn(&icd->dev, + "Failed creating the control symlink\n"); + return ret; +} + +/* So far this function cannot fail */ +static void scan_add_host(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_for_each_entry(icd, &devices, list) { + if (icd->iface == ici->nr) { + icd->dev.parent = &ici->dev; + device_register_link(icd); + } + } + + mutex_unlock(&list_lock); +} + +/* return: 0 if no match found or a match found and + * device_register() successful, error code otherwise */ +static int scan_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici; + int ret = 0; + + mutex_lock(&list_lock); + + list_add_tail(&icd->list, &devices); + + /* Watch out for class_for_each_device / class_find_device API by + * Dave Young */ + list_for_each_entry(ici, &hosts, list) { + if (icd->iface == ici->nr) { + ret = 1; + icd->dev.parent = &ici->dev; + break; + } + } + + mutex_unlock(&list_lock); + + if (ret) + ret = device_register_link(icd); + + return ret; +} + +static int soc_camera_probe(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (!icd->probe) + return -ENODEV; + + ret = ici->add(icd); + if (ret < 0) + return ret; + + ret = icd->probe(icd); + if (ret < 0) + ici->remove(icd); + else { + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : + (unsigned short)~0; + } + + return ret; +} + +/* This is called on device_unregister, which only means we have to disconnect + * from the host, but not remove ourselves from the device list */ +static int soc_camera_remove(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (icd->remove) + icd->remove(icd); + + ici->remove(icd); + + return 0; +} + +static struct bus_type soc_camera_bus_type = { + .name = "soc-camera", + .probe = soc_camera_probe, + .remove = soc_camera_remove, +}; + +static struct device_driver ic_drv = { + .name = "camera", + .bus = &soc_camera_bus_type, + .owner = THIS_MODULE, +}; + +/* + * Image capture host - this is a host device, not a bus device, so, + * no bus reference, no probing. + */ +static struct class soc_camera_host_class = { + .owner = THIS_MODULE, + .name = "camera_host", +}; + +static void dummy_release(struct device *dev) +{ +} + +int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +{ + int ret; + struct soc_camera_host *ix; + + if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + return -EINVAL; + + /* Number might be equal to the platform device ID */ + sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); + ici->dev.class = &soc_camera_host_class; + + mutex_lock(&list_lock); + list_for_each_entry(ix, &hosts, list) { + if (ix->nr == ici->nr) { + mutex_unlock(&list_lock); + return -EBUSY; + } + } + + list_add_tail(&ici->list, &hosts); + mutex_unlock(&list_lock); + + ici->owner = owner; + ici->dev.release = dummy_release; + + ret = device_register(&ici->dev); + + if (ret) + goto edevr; + + scan_add_host(ici); + + return 0; + +edevr: + mutex_lock(&list_lock); + list_del(&ici->list); + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(soc_camera_host_register); + +/* Unregister all clients! */ +void soc_camera_host_unregister(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_del(&ici->list); + + list_for_each_entry(icd, &devices, list) { + if (icd->dev.parent == &ici->dev) { + device_unregister(&icd->dev); + /* Not before device_unregister(), .remove + * needs parent to call ici->remove() */ + icd->dev.parent = NULL; + memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); + } + } + + mutex_unlock(&list_lock); + + device_unregister(&ici->dev); +} +EXPORT_SYMBOL(soc_camera_host_unregister); + +/* Image capture device */ +int soc_camera_device_register(struct soc_camera_device *icd) +{ + struct soc_camera_device *ix; + int num = -1, i; + + if (!icd) + return -EINVAL; + + for (i = 0; i < 256 && num < 0; i++) { + num = i; + list_for_each_entry(ix, &devices, list) { + if (ix->iface == icd->iface && ix->devnum == i) { + num = -1; + break; + } + } + } + + if (num < 0) + /* ok, we have 256 cameras on this host... + * man, stay reasonable... */ + return -ENOMEM; + + icd->devnum = num; + icd->dev.bus = &soc_camera_bus_type; + snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id), + "%u-%u", icd->iface, icd->devnum); + + icd->dev.release = dummy_release; + + if (icd->ops->get_datawidth) + icd->cached_datawidth = icd->ops->get_datawidth(icd); + + return scan_add_device(icd); +} +EXPORT_SYMBOL(soc_camera_device_register); + +void soc_camera_device_unregister(struct soc_camera_device *icd) +{ + mutex_lock(&list_lock); + list_del(&icd->list); + + /* The bus->remove will be eventually called */ + if (icd->dev.parent) + device_unregister(&icd->dev); + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(soc_camera_device_unregister); + +int soc_camera_video_start(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int err = -ENOMEM; + struct video_device *vdev; + + if (!icd->dev.parent) + return -ENODEV; + + vdev = video_device_alloc(); + if (!vdev) + goto evidallocd; + dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + + strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); + /* Maybe better &ici->dev */ + vdev->dev = &icd->dev; + vdev->type = VID_TYPE_CAPTURE; + vdev->current_norm = V4L2_STD_UNKNOWN; + vdev->fops = &soc_camera_fops; + vdev->release = video_device_release; + vdev->minor = -1; + vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->vidioc_querycap = soc_camera_querycap; + vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap; + vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap; + vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap; + vdev->vidioc_enum_input = soc_camera_enum_input; + vdev->vidioc_g_input = soc_camera_g_input; + vdev->vidioc_s_input = soc_camera_s_input; + vdev->vidioc_s_std = soc_camera_s_std; + vdev->vidioc_reqbufs = soc_camera_reqbufs; + vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap; + vdev->vidioc_querybuf = soc_camera_querybuf; + vdev->vidioc_qbuf = soc_camera_qbuf; + vdev->vidioc_dqbuf = soc_camera_dqbuf; + vdev->vidioc_streamon = soc_camera_streamon; + vdev->vidioc_streamoff = soc_camera_streamoff; + vdev->vidioc_queryctrl = soc_camera_queryctrl; + vdev->vidioc_g_ctrl = soc_camera_g_ctrl; + vdev->vidioc_s_ctrl = soc_camera_s_ctrl; + vdev->vidioc_cropcap = soc_camera_cropcap; + vdev->vidioc_g_crop = soc_camera_g_crop; + vdev->vidioc_s_crop = soc_camera_s_crop; + vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident; +#ifdef CONFIG_VIDEO_ADV_DEBUG + vdev->vidioc_g_register = soc_camera_g_register; + vdev->vidioc_s_register = soc_camera_s_register; +#endif + + icd->current_fmt = &icd->ops->formats[0]; + + err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); + if (err < 0) { + dev_err(vdev->dev, "video_register_device failed\n"); + goto evidregd; + } + icd->vdev = vdev; + + return 0; + +evidregd: + video_device_release(vdev); +evidallocd: + return err; +} +EXPORT_SYMBOL(soc_camera_video_start); + +void soc_camera_video_stop(struct soc_camera_device *icd) +{ + struct video_device *vdev = icd->vdev; + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (!icd->dev.parent || !vdev) + return; + + mutex_lock(&video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&video_lock); +} +EXPORT_SYMBOL(soc_camera_video_stop); + +static int __init soc_camera_init(void) +{ + int ret = bus_register(&soc_camera_bus_type); + if (ret) + return ret; + ret = driver_register(&ic_drv); + if (ret) + goto edrvr; + ret = class_register(&soc_camera_host_class); + if (ret) + goto eclr; + + return 0; + +eclr: + driver_unregister(&ic_drv); +edrvr: + bus_unregister(&soc_camera_bus_type); + return ret; +} + +static void __exit soc_camera_exit(void) +{ + class_unregister(&soc_camera_host_class); + driver_unregister(&ic_drv); + bus_unregister(&soc_camera_bus_type); +} + +module_init(soc_camera_init); +module_exit(soc_camera_exit); + +MODULE_DESCRIPTION("Image capture bus driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL"); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h new file mode 100644 index 00000000000..69aba7188e4 --- /dev/null +++ b/include/media/soc_camera.h @@ -0,0 +1,147 @@ +/* + * camera image capture (abstract) bus driver header + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef SOC_CAMERA_H +#define SOC_CAMERA_H + +#include +#include + +struct soc_camera_device { + struct list_head list; + struct device dev; + struct device *control; + unsigned short width; /* Current window */ + unsigned short height; /* sizes */ + unsigned short x_min; /* Camera capabilities */ + unsigned short y_min; + unsigned short x_current; /* Current window location */ + unsigned short y_current; + unsigned short width_min; + unsigned short width_max; + unsigned short height_min; + unsigned short height_max; + unsigned short y_skip_top; /* Lines to skip at the top */ + unsigned short gain; + unsigned short exposure; + unsigned char iface; /* Host number */ + unsigned char devnum; /* Device number per host */ + unsigned char cached_datawidth; /* See comment in .c */ + struct soc_camera_ops *ops; + struct video_device *vdev; + const struct soc_camera_data_format *current_fmt; + int (*probe)(struct soc_camera_device *icd); + void (*remove)(struct soc_camera_device *icd); + struct module *owner; +}; + +struct soc_camera_file { + struct soc_camera_device *icd; + struct videobuf_queue vb_vidq; +}; + +struct soc_camera_host { + struct list_head list; + struct device dev; + unsigned char nr; /* Host number */ + size_t msize; + struct videobuf_queue_ops *vbq_ops; + struct module *owner; + void *priv; + char *drv_name; + int (*add)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); + int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + unsigned int (*poll)(struct file *, poll_table *); +}; + +struct soc_camera_link { + /* Camera bus id, used to match a camera and a bus */ + int bus_id; + /* GPIO number to switch between 8 and 10 bit modes */ + unsigned int gpio; +}; + +static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) +{ + return container_of(dev, struct soc_camera_device, dev); +} + +static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) +{ + return container_of(dev, struct soc_camera_host, dev); +} + +extern int soc_camera_host_register(struct soc_camera_host *ici, + struct module *owner); +extern void soc_camera_host_unregister(struct soc_camera_host *ici); +extern int soc_camera_device_register(struct soc_camera_device *icd); +extern void soc_camera_device_unregister(struct soc_camera_device *icd); + +extern int soc_camera_video_start(struct soc_camera_device *icd); +extern void soc_camera_video_stop(struct soc_camera_device *icd); + +struct soc_camera_data_format { + char *name; + unsigned int depth; + __u32 fourcc; + enum v4l2_colorspace colorspace; +}; + +struct soc_camera_ops { + struct module *owner; + int (*init)(struct soc_camera_device *); + int (*release)(struct soc_camera_device *); + int (*start_capture)(struct soc_camera_device *); + int (*stop_capture)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *, unsigned int); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*get_chip_id)(struct soc_camera_device *, + struct v4l2_chip_ident *); +#ifdef CONFIG_VIDEO_ADV_DEBUG + int (*get_register)(struct soc_camera_device *, struct v4l2_register *); + int (*set_register)(struct soc_camera_device *, struct v4l2_register *); +#endif + const struct soc_camera_data_format *formats; + int num_formats; + int (*get_control)(struct soc_camera_device *, struct v4l2_control *); + int (*set_control)(struct soc_camera_device *, struct v4l2_control *); + const struct v4l2_queryctrl *controls; + int num_controls; + unsigned int(*get_datawidth)(struct soc_camera_device *icd); +}; + +static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( + struct soc_camera_ops *ops, int id) +{ + int i; + + for (i = 0; i < ops->num_controls; i++) + if (ops->controls[i].id == id) + return &ops->controls[i]; + + return NULL; +} + +#define IS_MASTER (1<<0) +#define IS_HSYNC_ACTIVE_HIGH (1<<1) +#define IS_VSYNC_ACTIVE_HIGH (1<<2) +#define IS_DATAWIDTH_8 (1<<3) +#define IS_DATAWIDTH_9 (1<<4) +#define IS_DATAWIDTH_10 (1<<5) +#define IS_PCLK_SAMPLE_RISING (1<<6) + +#endif -- cgit v1.2.3-70-g09d2 From 0705135e59f8503e4dade4b3580fed77b1743b7c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:42:13 -0300 Subject: V4L/DVB (7237): Convert videobuf-dma-sg to generic DMA API videobuf-dma-sg does not need to depend on PCI. Switch it to using generic DMA API, convert all affected drivers, relax Kconfig restriction, improve compile-time type checking, fix some Coding Style violations while at it. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 2 +- drivers/media/common/saa7146_vbi.c | 4 +- drivers/media/common/saa7146_video.c | 4 +- drivers/media/video/bt8xx/bttv-driver.c | 16 ++-- drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx23885/cx23885-video.c | 4 +- drivers/media/video/cx88/cx88-alsa.c | 8 +- drivers/media/video/cx88/cx88-blackbird.c | 4 +- drivers/media/video/cx88/cx88-dvb.c | 4 +- drivers/media/video/cx88/cx88-video.c | 8 +- drivers/media/video/saa7134/saa7134-alsa.c | 10 +-- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 4 +- drivers/media/video/saa7134/saa7134-video.c | 8 +- drivers/media/video/soc_camera.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 117 +++++++++++++------------- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-dma-sg.h | 14 +-- 18 files changed, 109 insertions(+), 108 deletions(-) (limited to 'include/media') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index a8650458744..b9b38d9ff65 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -160,7 +160,7 @@ config VIDEOBUF_GEN tristate config VIDEOBUF_DMA_SG - depends on PCI || ARCH_PXA + depends on HAS_DMA select VIDEOBUF_GEN tristate diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index bfbd5a841eb..74e2b56ecb5 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) fh->vbi_fmt.start[1] = 312; fh->vbi_fmt.count[1] = 16; - videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops, - dev->pci, &dev->slock, + 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), diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 66fdbd0e6a6..3cbc6ebbe64 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; - videobuf_queue_pci_init(&fh->video_q, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->video_q, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7146_buf), diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index fcf8f2d208a..af2c0c99418 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); @@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) mutex_lock(&fh->cap.vb_lock); if (on) { fh->ov.tvnorm = btv->tvnorm; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); } else { @@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - new = videobuf_pci_alloc(sizeof(*new)); + new = videobuf_sg_alloc(sizeof(*new)); new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv, fh, new); @@ -3184,7 +3184,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) /* need to capture a new frame */ if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) goto err; - fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); + fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize); if (NULL == fh->cap.read_buf) goto err; fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; @@ -3251,14 +3251,14 @@ static int bttv_open(struct inode *inode, struct file *file) fh->ov.setup_ok = 0; v4l2_prio_open(&btv->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &bttv_video_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer), fh); - videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops, - btv->c.pci, &btv->s_lock, + videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops, + &btv->c.pci->dev, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index ed465c007ce..6c21779852f 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -349,7 +349,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) /* dvb stuff */ printk("%s: cx23885 based dvb card\n", dev->name); - videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock, + videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx23885_buffer), port); err = dvb_register(port); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index d3c4d2c5cbe..45bf2146a19 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 316b106c351..2f5a4a4ba40 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_pci_dma_unmap(chip->pci, chip->dma_risc); + videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); btcx_riscmem_free(chip->pci,&chip->buf->risc); kfree(chip->buf); @@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, BUG_ON(!chip->dma_size); BUG_ON(chip->num_periods & (chip->num_periods-1)); - buf = videobuf_pci_alloc(sizeof(*buf)); + buf = videobuf_sg_alloc(sizeof(*buf)); if (NULL == buf) return -ENOMEM; @@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, buf->vb.height = chip->num_periods; buf->vb.size = chip->dma_size; - dma=videobuf_to_dma(&buf->vb); + dma = videobuf_to_dma(&buf->vb); videobuf_dma_init(dma); ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); if (ret < 0) goto error; - ret = videobuf_pci_dma_map(chip->pci,dma); + ret = videobuf_sg_dma_map(&chip->pci->dev, dma); if (ret < 0) goto error; diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index c3726907452..d582395805d 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1087,8 +1087,8 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 7586fe31f64..fa21666966e 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -744,8 +744,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 8b293a3357b..c30356bb35e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -776,14 +776,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), fh); - videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct cx88_buffer), diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 505bc0a478a..048081be91f 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, /* release the old buffer */ if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } @@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, return err; } - if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) { + if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { dsp_buffer_free(dev); return err; } if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, dev->dmasound.dma.sglen, 0))) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); return err; } @@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) if (substream->runtime->dma_area) { saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); - videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma); + videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); dsp_buffer_free(dev); substream->runtime->dma_area = NULL; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index b55df4877af..eabc67d03b2 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -899,8 +899,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; dev->dvb.name = dev->name; - videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 40d4a66b77f..e002be568c2 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev) printk(KERN_INFO "%s: registered device video%d [mpeg]\n", dev->name,dev->empress_dev->minor & 0x1f); - videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 5385026a85e..ecc5243da57 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1350,14 +1350,14 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 576; v4l2_prio_open(&dev->prio,&fh->prio); - videobuf_queue_pci_init(&fh->cap, &video_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->cap, &video_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7134_buf), fh); - videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops, - dev->pci, &dev->slock, + videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops, + &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct saa7134_buf), diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 904e9dfc1a8..c947525c3f2 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -210,7 +210,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* We must pass NULL as dev pointer, then all pci_* dma operations * transform to normal dma_* ones. Do we need an irqlock? */ - videobuf_queue_pci_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, ici->msize, icd); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 7008afabe92..6141a13bfc9 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ static int debug; module_param(debug, int, 0644); -MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); +MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); @@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); return &mem->dma; } @@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dma->direction = direction; switch (dma->direction) { - case PCI_DMA_FROMDEVICE: rw = READ; break; - case PCI_DMA_TODEVICE: rw = WRITE; break; - default: BUG(); + case DMA_FROM_DEVICE: + rw = READ; + break; + case DMA_TO_DEVICE: + rw = WRITE; + break; + default: + BUG(); } first = (data & PAGE_MASK) >> PAGE_SHIFT; @@ -216,10 +221,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, return 0; } -int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -245,7 +248,7 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return -ENOMEM; } if (!dma->bus_addr) { - dma->sglen = pci_map_sg(dev,dma->sglist, + dma->sglen = dma_map_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); if (0 == dma->sglen) { printk(KERN_WARNING @@ -259,14 +262,12 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma) return 0; } -int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma) +int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { - void *dev=q->dev; - - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(!dma->sglen); - pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); return 0; } @@ -274,11 +275,11 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) { void *dev=q->dev; - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); if (!dma->sglen) return 0; - pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction); + dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); kfree(dma->sglist); dma->sglist = NULL; @@ -306,28 +307,28 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) if (dma->bus_addr) { dma->bus_addr = 0; } - dma->direction = PCI_DMA_NONE; + dma->direction = DMA_NONE; return 0; } /* --------------------------------------------------------------------- */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_map(&q,dma)); + return videobuf_dma_map(&q, dma); } -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { struct videobuf_queue q; - q.dev=pci; + q.dev = dev; - return (videobuf_dma_unmap(&q,dma)); + return videobuf_dma_unmap(&q, dma); } /* --------------------------------------------------------------------- */ @@ -347,7 +348,7 @@ videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; struct videobuf_queue *q = map->q; - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; int i; dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, @@ -409,18 +410,18 @@ static struct vm_operations_struct videobuf_vm_ops = }; /* --------------------------------------------------------------------- - * PCI handlers for the generic methods + * SG handlers for the generic methods */ /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_buffer *vb; vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); @@ -443,10 +444,10 @@ static int __videobuf_iolock (struct videobuf_queue* q, { int err,pages; dma_addr_t bus; - struct videbuf_pci_sg_memory *mem=vb->priv; + struct videobuf_dma_sg_memory *mem = vb->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); switch (vb->memory) { case V4L2_MEMORY_MMAP: @@ -455,14 +456,14 @@ static int __videobuf_iolock (struct videobuf_queue* q, /* no userspace addr -- kernel bounce buffer */ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; err = videobuf_dma_init_kernel( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, pages ); if (0 != err) return err; } else if (vb->memory == V4L2_MEMORY_USERPTR) { /* dma directly to userspace */ err = videobuf_dma_init_user( &mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr,vb->bsize ); if (0 != err) return err; @@ -473,7 +474,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, locking inversion, so don't take it here */ err = videobuf_dma_init_user_locked(&mem->dma, - PCI_DMA_FROMDEVICE, + DMA_FROM_DEVICE, vb->baddr, vb->bsize); if (0 != err) return err; @@ -490,7 +491,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, */ bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff; pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE, + err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE, bus, pages); if (0 != err) return err; @@ -498,7 +499,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, default: BUG(); } - err = videobuf_dma_map(q,&mem->dma); + err = videobuf_dma_map(q, &mem->dma); if (0 != err) return err; @@ -508,8 +509,8 @@ static int __videobuf_iolock (struct videobuf_queue* q, static int __videobuf_sync(struct videobuf_queue *q, struct videobuf_buffer *buf) { - struct videbuf_pci_sg_memory *mem=buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); return videobuf_dma_sync(q,&mem->dma); @@ -532,7 +533,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { - struct videbuf_pci_sg_memory *mem; + struct videobuf_dma_sg_memory *mem; struct videobuf_mapping *map; unsigned int first,last,size,i; int retval; @@ -552,7 +553,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, if (NULL == q->bufs[first]) continue; mem=q->bufs[first]->priv; - BUG_ON (!mem); + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) @@ -615,8 +616,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, char __user *data, size_t count, int nonblocking ) { - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); /* copy to userspace */ @@ -634,8 +635,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, int vbihack, int nonblocking ) { unsigned int *fc; - struct videbuf_pci_sg_memory *mem=q->read_buf->priv; - BUG_ON (!mem); + struct videobuf_dma_sg_memory *mem = q->read_buf->priv; + BUG_ON(!mem); MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); if (vbihack) { @@ -658,7 +659,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, return count; } -static struct videobuf_qtype_ops pci_ops = { +static struct videobuf_qtype_ops sg_ops = { .magic = MAGIC_QTYPE_OPS, .alloc = __videobuf_alloc, @@ -670,21 +671,21 @@ static struct videobuf_qtype_ops pci_ops = { .copy_stream = __videobuf_copy_stream, }; -void *videobuf_pci_alloc (size_t size) +void *videobuf_sg_alloc(size_t size) { struct videobuf_queue q; /* Required to make generic handler to call __videobuf_alloc */ - q.int_ops=&pci_ops; + q.int_ops = &sg_ops; - q.msize=size; + q.msize = size; - return videobuf_alloc (&q); + return videobuf_alloc(&q); } -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -692,7 +693,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, void *priv) { videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, - priv, &pci_ops); + priv, &sg_ops); } /* --------------------------------------------------------------------- */ @@ -709,11 +710,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync); EXPORT_SYMBOL_GPL(videobuf_dma_unmap); EXPORT_SYMBOL_GPL(videobuf_dma_free); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_map); -EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap); -EXPORT_SYMBOL_GPL(videobuf_pci_alloc); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); +EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); +EXPORT_SYMBOL_GPL(videobuf_sg_alloc); -EXPORT_SYMBOL_GPL(videobuf_queue_pci_init); +EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); /* * Local variables: diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 3de3c892017..4a2508dfa0e 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -102,7 +102,7 @@ static struct vm_operations_struct videobuf_vm_ops = /* Allocated area consists on 3 parts: struct video_buffer struct _buffer (cx88_buffer, saa7134_buf, ...) - struct videobuf_pci_sg_memory + struct videobuf_dma_sg_memory */ static void *__videobuf_alloc(size_t size) diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 38105031db2..b6ab08045de 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -1,5 +1,5 @@ /* - * helper functions for PCI DMA video4linux capture buffers + * helper functions for SG DMA video4linux capture buffers * * The functions expect the hardware being able to scatter gatter * (i.e. the buffers are not linear in physical memory, but fragmented @@ -81,7 +81,7 @@ struct videobuf_dmabuf { int direction; }; -struct videbuf_pci_sg_memory +struct videobuf_dma_sg_memory { u32 magic; @@ -103,11 +103,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); -void *videobuf_pci_alloc (size_t size); +void *videobuf_sg_alloc(size_t size); -void videobuf_queue_pci_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue* q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, @@ -117,6 +117,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q, /*FIXME: these variants are used only on *-alsa code, where videobuf is * used without queue */ -int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma); -int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma); +int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); +int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); -- cgit v1.2.3-70-g09d2 From 9dc4e48fbea5412127ce2eb30d688c4fc55f5565 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:45:32 -0300 Subject: V4L/DVB (7276): soc-camera: deactivate cameras when not used Only attach cameras to the host interface for probing, then detach until open. This allows platforms with several cameras on an interface, physically supporting only one camera, to handle multiple cameras and activate them selectively after initial probing. The first attach during probe is needed to activate the host interface to be able to physically communicate with cameras. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 52 ++++++++++++++++++++++++++++++---------- include/media/soc_camera.h | 2 ++ 2 files changed, 41 insertions(+), 13 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index c947525c3f2..322f837bcfe 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -179,11 +179,9 @@ static int soc_camera_dqbuf(struct file *file, void *priv, static int soc_camera_open(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct soc_camera_device *icd = container_of(vdev->dev, - struct soc_camera_device, dev); - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); + struct video_device *vdev; + struct soc_camera_device *icd; + struct soc_camera_host *ici; struct soc_camera_file *icf; int ret; @@ -191,7 +189,12 @@ static int soc_camera_open(struct inode *inode, struct file *file) if (!icf) return -ENOMEM; - icf->icd = icd; + /* Protect against icd->remove() until we module_get() both drivers. */ + mutex_lock(&video_lock); + + vdev = video_devdata(file); + icd = container_of(vdev->dev, struct soc_camera_device, dev); + ici = to_soc_camera_host(icd->dev.parent); if (!try_module_get(icd->ops->owner)) { dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); @@ -205,6 +208,22 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgi; } + icd->use_count++; + + icf->icd = icd; + + /* Now we really have to activate the camera */ + if (icd->use_count == 1) { + ret = ici->add(icd); + if (ret < 0) { + dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); + icd->use_count--; + goto eiciadd; + } + } + + mutex_unlock(&video_lock); + file->private_data = icf; dev_dbg(&icd->dev, "camera device open\n"); @@ -216,9 +235,13 @@ static int soc_camera_open(struct inode *inode, struct file *file) return 0; + /* All errors are entered with the video_lock held */ +eiciadd: + module_put(ici->owner); emgi: module_put(icd->ops->owner); emgd: + mutex_unlock(&video_lock); vfree(icf); return ret; } @@ -230,8 +253,14 @@ static int soc_camera_close(struct inode *inode, struct file *file) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct video_device *vdev = icd->vdev; + mutex_lock(&video_lock); + icd->use_count--; + if (!icd->use_count) + ici->remove(icd); module_put(icd->ops->owner); module_put(ici->owner); + mutex_unlock(&video_lock); + vfree(file->private_data); dev_dbg(vdev->dev, "camera device close\n"); @@ -673,14 +702,14 @@ static int soc_camera_probe(struct device *dev) if (!icd->probe) return -ENODEV; + /* We only call ->add() here to activate and probe the camera. + * We shall ->remove() and deactivate it immediately afterwards. */ ret = ici->add(icd); if (ret < 0) return ret; ret = icd->probe(icd); - if (ret < 0) - ici->remove(icd); - else { + if (ret >= 0) { const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); @@ -689,6 +718,7 @@ static int soc_camera_probe(struct device *dev) icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; } + ici->remove(icd); return ret; } @@ -698,14 +728,10 @@ static int soc_camera_probe(struct device *dev) static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); if (icd->remove) icd->remove(icd); - ici->remove(icd); - return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 69aba7188e4..c886b1e6487 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -41,6 +41,8 @@ struct soc_camera_device { int (*probe)(struct soc_camera_device *icd); void (*remove)(struct soc_camera_device *icd); struct module *owner; + /* soc_camera.c private count. Only accessed with video_lock held */ + int use_count; }; struct soc_camera_file { -- cgit v1.2.3-70-g09d2 From ad5f2e859d76dccb7eb1aa942171b1a32211efc2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 7 Mar 2008 21:57:18 -0300 Subject: V4L/DVB (7336): soc-camera: streamline hardware parameter negotiation Improve hardware parameter negotiation between the camera host driver and camera drivers. Parameters like horizontal and vertical synchronisation, pixel clock polarity shall be set depending on capabilities of the parties. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 77 +++++++++++-------- drivers/media/video/mt9v022.c | 129 +++++++++++++++++++------------- drivers/media/video/pxa_camera.c | 156 ++++++++++++++++++++++++++++----------- drivers/media/video/soc_camera.c | 49 ++++++------ include/media/soc_camera.h | 52 +++++++++---- 5 files changed, 301 insertions(+), 162 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 4ad834326fa..acb5454b57e 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -210,40 +210,64 @@ static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) #endif } -static int mt9m001_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +static int bus_switch_possible(struct mt9m001 *mt9m001) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + return gpio_is_valid(mt9m001->switch_gpio); +#else + return 0; +#endif +} + +static int mt9m001_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | - IS_DATAWIDTH_8); + unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; - const u16 hblank = 9, vblank = 25; - /* MT9M001 has all capture_format parameters fixed */ - if (!(flags & IS_MASTER) || - !(flags & IS_PCLK_SAMPLE_RISING) || - !(flags & IS_HSYNC_ACTIVE_HIGH) || - !(flags & IS_VSYNC_ACTIVE_HIGH)) - return -EINVAL; - - /* Only one width bit may be set */ - if (!is_power_of_2(width_flag)) - return -EINVAL; + /* Flags validity verified in test_bus_param */ - if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || - (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || - (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || + (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || + (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == IS_DATAWIDTH_9) + if (width_flag == SOCAM_DATAWIDTH_9) return -EINVAL; ret = bus_switch_act(mt9m001, - width_flag == IS_DATAWIDTH_8); + width_flag == SOCAM_DATAWIDTH_8); if (ret < 0) return ret; - mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; } + return 0; +} + +static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + unsigned int width_flag = SOCAM_DATAWIDTH_10; + + if (bus_switch_possible(mt9m001)) + width_flag |= SOCAM_DATAWIDTH_8; + + /* MT9M001 has all capture_format parameters fixed */ + return SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_MASTER | + width_flag; +} + +static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + int ret; + const u16 hblank = 9, vblank = 25; + /* Blanking and start values - default... */ ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); if (ret >= 0) @@ -348,12 +372,6 @@ static int mt9m001_set_register(struct soc_camera_device *icd, } #endif -static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) -{ - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - return mt9m001->datawidth; -} - const struct v4l2_queryctrl mt9m001_controls[] = { { .id = V4L2_CID_VFLIP, @@ -401,11 +419,12 @@ static struct soc_camera_ops mt9m001_ops = { .release = mt9m001_release, .start_capture = mt9m001_start_capture, .stop_capture = mt9m001_stop_capture, - .set_capture_format = mt9m001_set_capture_format, + .set_fmt_cap = mt9m001_set_fmt_cap, .try_fmt_cap = mt9m001_try_fmt_cap, + .set_bus_param = mt9m001_set_bus_param, + .query_bus_param = mt9m001_query_bus_param, .formats = NULL, /* Filled in later depending on the */ .num_formats = 0, /* camera type and data widths */ - .get_datawidth = mt9m001_get_datawidth, .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), .get_control = mt9m001_get_control, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index d677344d233..a2f161dcc72 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -241,19 +241,89 @@ static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) #endif } -static int mt9v022_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +static int bus_switch_possible(struct mt9v022 *mt9v022) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + return gpio_is_valid(mt9v022->switch_gpio); +#else + return 0; +#endif +} + +static int mt9v022_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | - IS_DATAWIDTH_8); - u16 pixclk = 0; + unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; + u16 pixclk = 0; /* Only one width bit may be set */ if (!is_power_of_2(width_flag)) return -EINVAL; + if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || + (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || + (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == SOCAM_DATAWIDTH_9) + return -EINVAL; + + ret = bus_switch_act(mt9v022, + width_flag == SOCAM_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; + } + + if (flags & SOCAM_PCLK_SAMPLE_RISING) + pixclk |= 0x10; + + if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH)) + pixclk |= 0x1; + + if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH)) + pixclk |= 0x2; + + ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + if (ret < 0) + return ret; + + if (!(flags & SOCAM_MASTER)) + mt9v022->chip_control &= ~0x8; + + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + pixclk, mt9v022->chip_control); + + return 0; +} + +static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + unsigned int width_flag = SOCAM_DATAWIDTH_10; + + if (bus_switch_possible(mt9v022)) + width_flag |= SOCAM_DATAWIDTH_8; + + return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_MASTER | SOCAM_SLAVE | + width_flag; +} + +static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + int ret; + /* The caller provides a supported format, as verified per call to * icd->try_fmt_cap(), datawidth is from our supported format list */ switch (pixfmt) { @@ -308,44 +378,6 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd, dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); - if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || - (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || - (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == IS_DATAWIDTH_9) - return -EINVAL; - - ret = bus_switch_act(mt9v022, - width_flag == IS_DATAWIDTH_8); - if (ret < 0) - return ret; - - mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; - } - - if (flags & IS_PCLK_SAMPLE_RISING) - pixclk |= 0x10; - - if (!(flags & IS_HSYNC_ACTIVE_HIGH)) - pixclk |= 0x1; - - if (!(flags & IS_VSYNC_ACTIVE_HIGH)) - pixclk |= 0x2; - - ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); - if (ret < 0) - return ret; - - if (!(flags & IS_MASTER)) - mt9v022->chip_control &= ~0x8; - - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); - if (ret < 0) - return ret; - - dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", - pixclk, mt9v022->chip_control); - return 0; } @@ -420,12 +452,6 @@ static int mt9v022_set_register(struct soc_camera_device *icd, } #endif -static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) -{ - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - return mt9v022->datawidth; -} - const struct v4l2_queryctrl mt9v022_controls[] = { { .id = V4L2_CID_VFLIP, @@ -491,11 +517,12 @@ static struct soc_camera_ops mt9v022_ops = { .release = mt9v022_release, .start_capture = mt9v022_start_capture, .stop_capture = mt9v022_stop_capture, - .set_capture_format = mt9v022_set_capture_format, + .set_fmt_cap = mt9v022_set_fmt_cap, .try_fmt_cap = mt9v022_try_fmt_cap, + .set_bus_param = mt9v022_set_bus_param, + .query_bus_param = mt9v022_query_bus_param, .formats = NULL, /* Filled in later depending on the */ .num_formats = 0, /* sensor type and data widths */ - .get_datawidth = mt9v022_get_datawidth, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), .get_control = mt9v022_get_control, diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a34a193249f..4756699d16a 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -581,64 +581,109 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } -static int pxa_camera_set_capture_format(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int test_platform_param(struct pxa_camera_dev *pcdev, + unsigned char buswidth, unsigned long *flags) { - struct soc_camera_host *ici = - to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; - unsigned int datawidth = 0, dw, bpp; - u32 cicr0, cicr4 = 0; - int ret; + /* + * Platform specified synchronization and pixel clock polarities are + * only a recommendation and are only used during probing. The PXA270 + * quick capture interface supports both. + */ + *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? + SOCAM_MASTER : SOCAM_SLAVE) | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_PCLK_SAMPLE_FALLING; /* If requested data width is supported by the platform, use it */ - switch (icd->cached_datawidth) { + switch (buswidth) { case 10: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) - datawidth = IS_DATAWIDTH_10; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_10; break; case 9: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) - datawidth = IS_DATAWIDTH_9; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_9; break; case 8: - if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) - datawidth = IS_DATAWIDTH_8; + if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_8; } - if (!datawidth) + + return 0; +} + +static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long dw, bpp, bus_flags, camera_flags, common_flags; + u32 cicr0, cicr4 = 0; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) return -EINVAL; - ret = icd->ops->set_capture_format(icd, pixfmt, rect, - datawidth | - (pcdev->platform_flags & PXA_CAMERA_MASTER ? - IS_MASTER : 0) | - (pcdev->platform_flags & PXA_CAMERA_HSP ? - 0 : IS_HSYNC_ACTIVE_HIGH) | - (pcdev->platform_flags & PXA_CAMERA_VSP ? - 0 : IS_VSYNC_ACTIVE_HIGH) | - (pcdev->platform_flags & PXA_CAMERA_PCP ? - 0 : IS_PCLK_SAMPLE_RISING)); + /* Make choises, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (pcdev->platform_flags & PXA_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) return ret; /* Datawidth is now guaranteed to be equal to one of the three values. * We fix bit-per-pixel equal to data-width... */ - switch (datawidth) { - case IS_DATAWIDTH_10: - icd->cached_datawidth = 10; + switch (common_flags & SOCAM_DATAWIDTH_MASK) { + case SOCAM_DATAWIDTH_10: + icd->buswidth = 10; dw = 4; bpp = 0x40; break; - case IS_DATAWIDTH_9: - icd->cached_datawidth = 9; + case SOCAM_DATAWIDTH_9: + icd->buswidth = 9; dw = 3; bpp = 0x20; break; default: /* Actually it can only be 8 now, * default is just to silence compiler warnings */ - case IS_DATAWIDTH_8: - icd->cached_datawidth = 8; + case SOCAM_DATAWIDTH_8: + icd->buswidth = 8; dw = 2; bpp = 0; } @@ -647,19 +692,19 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, cicr4 |= CICR4_PCLK_EN; if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) cicr4 |= CICR4_MCLK_EN; - if (pcdev->platform_flags & PXA_CAMERA_PCP) + if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) cicr4 |= CICR4_PCP; - if (pcdev->platform_flags & PXA_CAMERA_HSP) + if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) cicr4 |= CICR4_HSP; - if (pcdev->platform_flags & PXA_CAMERA_VSP) + if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) cicr4 |= CICR4_VSP; cicr0 = CICR0; if (cicr0 & CICR0_ENB) CICR0 = cicr0 & ~CICR0_ENB; - CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; + CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; CICR2 = 0; - CICR3 = CICR3_LPF_VAL(rect->height - 1) | + CICR3 = CICR3_LPF_VAL(icd->height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); CICR4 = mclk_get_divisor(pcdev) | cicr4; @@ -671,7 +716,29 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, return 0; } -static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, +static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long bus_flags, camera_flags; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; +} + +static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + return icd->ops->set_fmt_cap(icd, pixfmt, rect); +} + +static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, struct v4l2_format *f) { /* limit to pxa hardware capabilities */ @@ -685,7 +752,8 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, f->fmt.pix.width = 2048; f->fmt.pix.width &= ~0x01; - return 0; + /* limit to sensor capabilities */ + return icd->ops->try_fmt_cap(icd, f); } static int pxa_camera_reqbufs(struct soc_camera_file *icf, @@ -742,11 +810,13 @@ static struct soc_camera_host pxa_soc_camera_host = { .add = pxa_camera_add_device, .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .set_capture_format = pxa_camera_set_capture_format, + .set_fmt_cap = pxa_camera_set_fmt_cap, .try_fmt_cap = pxa_camera_try_fmt_cap, .reqbufs = pxa_camera_reqbufs, .poll = pxa_camera_poll, .querycap = pxa_camera_querycap, + .try_bus_param = pxa_camera_try_bus_param, + .set_bus_param = pxa_camera_set_bus_param, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -782,8 +852,8 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->pdata = pdev->dev.platform_data; pcdev->platform_flags = pcdev->pdata->flags; - if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | - PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { + if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { /* Platform hasn't set available data widths. This is bad. * Warn and use a default. */ dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 322f837bcfe..bd8677cb1ca 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -75,12 +75,13 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, return -EINVAL; } - /* limit to host capabilities */ - ret = ici->try_fmt_cap(ici, f); + /* test physical bus parameters */ + ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); + if (ret) + return ret; - /* limit to sensor capabilities */ - if (!ret) - ret = icd->ops->try_fmt_cap(icd, f); + /* limit format to hardware capabilities */ + ret = ici->try_fmt_cap(icd, f); /* calculate missing fields */ f->fmt.pix.field = field; @@ -344,8 +345,8 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, if (!data_fmt) return -EINVAL; - /* cached_datawidth may be further adjusted by the ici */ - icd->cached_datawidth = data_fmt->depth; + /* buswidth may be further adjusted by the ici */ + icd->buswidth = data_fmt->depth; ret = soc_camera_try_fmt_cap(file, icf, f); if (ret < 0) @@ -355,22 +356,23 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, rect.top = icd->y_current; rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; - ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + if (ret < 0) + return ret; - if (!ret) { - icd->current_fmt = data_fmt; - icd->width = rect.width; - icd->height = rect.height; - icf->vb_vidq.field = f->fmt.pix.field; - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) - dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", - f->type); - - dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->width, icd->height); - } + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); - return ret; + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + + /* set physical bus parameters */ + return ici->set_bus_param(icd, f->fmt.pix.pixelformat); } static int soc_camera_enum_fmt_cap(struct file *file, void *priv, @@ -577,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ici->set_capture_format(icd, 0, &a->c); + ret = ici->set_fmt_cap(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -860,9 +862,6 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->dev.release = dummy_release; - if (icd->ops->get_datawidth) - icd->cached_datawidth = icd->ops->get_datawidth(icd); - return scan_add_device(icd); } EXPORT_SYMBOL(soc_camera_device_register); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index c886b1e6487..3e48e435b21 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -34,7 +34,7 @@ struct soc_camera_device { unsigned short exposure; unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ - unsigned char cached_datawidth; /* See comment in .c */ + unsigned char buswidth; /* See comment in .c */ struct soc_camera_ops *ops; struct video_device *vdev; const struct soc_camera_data_format *current_fmt; @@ -61,11 +61,13 @@ struct soc_camera_host { char *drv_name; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); - int (*set_capture_format)(struct soc_camera_device *, __u32, - struct v4l2_rect *); - int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*set_fmt_cap)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + int (*try_bus_param)(struct soc_camera_device *, __u32); + int (*set_bus_param)(struct soc_camera_device *, __u32); unsigned int (*poll)(struct file *, poll_table *); }; @@ -108,9 +110,11 @@ struct soc_camera_ops { int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); int (*stop_capture)(struct soc_camera_device *); - int (*set_capture_format)(struct soc_camera_device *, __u32, - struct v4l2_rect *, unsigned int); + int (*set_fmt_cap)(struct soc_camera_device *, __u32, + struct v4l2_rect *); int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + unsigned long (*query_bus_param)(struct soc_camera_device *); + int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, struct v4l2_chip_ident *); #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -123,7 +127,6 @@ struct soc_camera_ops { int (*set_control)(struct soc_camera_device *, struct v4l2_control *); const struct v4l2_queryctrl *controls; int num_controls; - unsigned int(*get_datawidth)(struct soc_camera_device *icd); }; static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( @@ -138,12 +141,33 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( return NULL; } -#define IS_MASTER (1<<0) -#define IS_HSYNC_ACTIVE_HIGH (1<<1) -#define IS_VSYNC_ACTIVE_HIGH (1<<2) -#define IS_DATAWIDTH_8 (1<<3) -#define IS_DATAWIDTH_9 (1<<4) -#define IS_DATAWIDTH_10 (1<<5) -#define IS_PCLK_SAMPLE_RISING (1<<6) +#define SOCAM_MASTER (1 << 0) +#define SOCAM_SLAVE (1 << 1) +#define SOCAM_HSYNC_ACTIVE_HIGH (1 << 2) +#define SOCAM_HSYNC_ACTIVE_LOW (1 << 3) +#define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4) +#define SOCAM_VSYNC_ACTIVE_LOW (1 << 5) +#define SOCAM_DATAWIDTH_8 (1 << 6) +#define SOCAM_DATAWIDTH_9 (1 << 7) +#define SOCAM_DATAWIDTH_10 (1 << 8) +#define SOCAM_PCLK_SAMPLE_RISING (1 << 9) +#define SOCAM_PCLK_SAMPLE_FALLING (1 << 10) + +#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \ + SOCAM_DATAWIDTH_10) + +static inline unsigned long soc_camera_bus_param_compatible( + unsigned long camera_flags, unsigned long bus_flags) +{ + unsigned long common_flags, hsync, vsync, pclk; + + common_flags = camera_flags & bus_flags; + + hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW); + vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW); + pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING); + + return (!hsync || !vsync || !pclk) ? 0 : common_flags; +} #endif -- cgit v1.2.3-70-g09d2 From 62325497db6ef3b13cae41d5038e2693997d7d3e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:52 -0300 Subject: V4L/DVB (7347): tuner-simple: add basic support for digital tuning of hybrid devices Add entry points used for digital tuning via the dvb_frontend. Share state data between multiple instances of the driver for hybrid tuners. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 156 ++++++++++++++++++++++++++++++++++--- include/media/tuner-types.h | 14 +++- 2 files changed, 156 insertions(+), 14 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index ee5ef860700..d6d922c32bc 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -88,14 +88,20 @@ MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 +static DEFINE_MUTEX(tuner_simple_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); + struct tuner_simple_priv { u16 last_div; + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; unsigned int type; struct tunertype *tun; u32 frequency; + u32 bandwidth; }; /* ---------------------------------------------------------------------- */ @@ -188,6 +194,9 @@ static inline char *tuner_param_name(enum param_type type) case TUNER_PARAM_TYPE_NTSC: name = "ntsc"; break; + case TUNER_PARAM_TYPE_DIGITAL: + name = "digital"; + break; default: name = "unknown"; break; @@ -687,14 +696,118 @@ static int simple_set_params(struct dvb_frontend *fe, priv->frequency = params->frequency * 62500; break; } + priv->bandwidth = 0; return ret; } +static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, + const struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + struct tunertype *tun = priv->tun; + static struct tuner_params *t_params; + u8 config, cb; + u32 div; + int ret, frequency = params->frequency / 62500; + + t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL); + ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb); + if (ret < 0) + return ret; + + div = ((frequency + t_params->iffreq) * 62500 + offset + + tun->stepsize/2) / tun->stepsize; + + buf[0] = div >> 8; + buf[1] = div & 0xff; + buf[2] = config; + buf[3] = cb; + + tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", + tun->name, div, buf[0], buf[1], buf[2], buf[3]); + + /* calculate the frequency we set it to */ + return (div * tun->stepsize) - t_params->iffreq; +} + +static int simple_dvb_calc_regs(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + u8 *buf, int buf_len) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int ret; + u32 frequency; + + if (buf_len < 5) + return -EINVAL; + + ret = simple_dvb_configure(fe, buf+1, params); + if (ret < 0) + return ret; + else + frequency = ret; + + buf[0] = priv->i2c_props.addr; + + priv->frequency = frequency; + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? + params->u.ofdm.bandwidth : 0; + + return 5; +} + +static int simple_dvb_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u32 prev_freq, prev_bw; + int ret; + u8 buf[5]; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + prev_freq = priv->frequency; + prev_bw = priv->bandwidth; + + ret = simple_dvb_calc_regs(fe, params, buf, 5); + if (ret != 5) + goto fail; + + /* put analog demod in standby when tuning digital */ + if (fe->ops.analog_ops.standby) + fe->ops.analog_ops.standby(fe); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* buf[0] contains the i2c address, but * + * we already have it in i2c_props.addr */ + ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4); + if (ret != 4) + goto fail; + + return 0; +fail: + /* calc_regs sets frequency and bandwidth. if we failed, unset them */ + priv->frequency = prev_freq; + priv->bandwidth = prev_bw; + + return ret; +} static int simple_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + struct tuner_simple_priv *priv = fe->tuner_priv; + + mutex_lock(&tuner_simple_list_mutex); + + if (priv) + hybrid_tuner_release_state(priv); + + mutex_unlock(&tuner_simple_list_mutex); + fe->tuner_priv = NULL; return 0; @@ -707,10 +820,20 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency) return 0; } +static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + static struct dvb_tuner_ops simple_tuner_ops = { .set_analog_params = simple_set_params, + .set_params = simple_dvb_set_params, + .calc_regs = simple_dvb_calc_regs, .release = simple_release, .get_frequency = simple_get_frequency, + .get_bandwidth = simple_get_bandwidth, .get_status = simple_get_status, .get_rf_strength = simple_get_rf_strength, }; @@ -721,6 +844,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, unsigned int type) { struct tuner_simple_priv *priv = NULL; + int instance; if (type >= tuner_count) { printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", @@ -728,22 +852,34 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, return NULL; } - priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); - if (priv == NULL) + mutex_lock(&tuner_simple_list_mutex); + + instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv, + hybrid_tuner_instance_list, + i2c_adap, i2c_addr, + "tuner-simple"); + switch (instance) { + case 0: + mutex_unlock(&tuner_simple_list_mutex); return NULL; - fe->tuner_priv = priv; + break; + case 1: + fe->tuner_priv = priv; - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; - priv->i2c_props.name = "tuner-simple"; + priv->type = type; + priv->tun = &tuners[type]; + break; + default: + fe->tuner_priv = priv; + break; + } - priv->type = type; - priv->tun = &tuners[type]; + mutex_unlock(&tuner_simple_list_mutex); memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", priv->type, priv->tun->name); + tuner_info("type set to %d (%s)\n", type, priv->tun->name); strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, sizeof(fe->ops.tuner_ops.info.name)); diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index b201371416a..4b5e5cf780c 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -6,10 +6,11 @@ #define __TUNER_TYPES_H__ enum param_type { - TUNER_PARAM_TYPE_RADIO, \ - TUNER_PARAM_TYPE_PAL, \ - TUNER_PARAM_TYPE_SECAM, \ - TUNER_PARAM_TYPE_NTSC + TUNER_PARAM_TYPE_RADIO, + TUNER_PARAM_TYPE_PAL, + TUNER_PARAM_TYPE_SECAM, + TUNER_PARAM_TYPE_NTSC, + TUNER_PARAM_TYPE_DIGITAL, }; struct tuner_range { @@ -105,6 +106,7 @@ struct tuner_params { the SECAM-L/L' standards. Range: -16:+15 */ signed int default_top_secam_high:5; + u16 iffreq; unsigned int count; struct tuner_range *ranges; @@ -114,6 +116,10 @@ struct tunertype { char *name; unsigned int count; struct tuner_params *params; + + u16 min; + u16 max; + u16 stepsize; }; extern struct tunertype tuners[]; -- cgit v1.2.3-70-g09d2 From 6f4a57292f4f0a0fef5e4e39cb394fedcf2acf9f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:53 -0300 Subject: V4L/DVB (7351): tuner-simple: add init and sleep methods taken from dvb-pll Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 48 ++++++++++++++++++++++++++++++++++++++ drivers/media/video/tuner-types.c | 25 ++++++++++++++++++++ include/media/tuner-types.h | 3 +++ 3 files changed, 76 insertions(+) (limited to 'include/media') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3ec76391a60..3a27d4a8ce3 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -810,6 +810,52 @@ fail: return ret; } +static int simple_init(struct dvb_frontend *fe) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + if (priv->tun->initdata) { + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = tuner_i2c_xfer_send(&priv->i2c_props, + priv->tun->initdata + 1, + priv->tun->initdata[0]); + if (ret != priv->tun->initdata[0]) + return ret; + } + + return 0; +} + +static int simple_sleep(struct dvb_frontend *fe) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + if (priv->i2c_props.adap == NULL) + return -EINVAL; + + if (priv->tun->sleepdata) { + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = tuner_i2c_xfer_send(&priv->i2c_props, + priv->tun->sleepdata + 1, + priv->tun->sleepdata[0]); + if (ret != priv->tun->sleepdata[0]) + return ret; + } + + return 0; +} + static int simple_release(struct dvb_frontend *fe) { struct tuner_simple_priv *priv = fe->tuner_priv; @@ -841,6 +887,8 @@ static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) } static struct dvb_tuner_ops simple_tuner_ops = { + .init = simple_init, + .sleep = simple_sleep, .set_analog_params = simple_set_params, .set_params = simple_dvb_set_params, .calc_regs = simple_dvb_calc_regs, diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 8b53d0d05b2..13c76a57d8e 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -35,6 +35,27 @@ * based on the video standard in use. */ +/* The following was taken from dvb-pll.c: */ + +/* Set AGC TOP value to 103 dBuV: + * 0x80 = Control Byte + * 0x40 = 250 uA charge pump (irrelevant) + * 0x18 = Aux Byte to follow + * 0x06 = 64.5 kHz divider (irrelevant) + * 0x01 = Disable Vt (aka sleep) + * + * 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) + * 0x50 = AGC Take over point = 103 dBuV + */ +static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; + +/* 0x04 = 166.67 kHz divider + * + * 0x80 = AGC Time constant 50ms Iagc = 9 uA + * 0x20 = AGC Take over point = 112 dBuV + */ +static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 }; + /* 0-9 */ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ @@ -1425,6 +1446,7 @@ struct tunertype tuners[] = { .min = 16 * 57.00, .max = 16 * 863.00, .stepsize = 62500, + .initdata = tua603x_agc103, }, [TUNER_TENA_9533_DI] = { /* Philips PAL */ .name = "Tena TNF9533-D/IF/TNF9533-B/DF", @@ -1439,6 +1461,8 @@ struct tunertype tuners[] = { .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), + .initdata = tua603x_agc112, + .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */ .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ @@ -1447,6 +1471,7 @@ struct tunertype tuners[] = { .min = 16 * 54.00, .max = 16 * 863.00, .stepsize = 62500, + .initdata = tua603x_agc103, }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 4b5e5cf780c..fda12093cab 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -120,6 +120,9 @@ struct tunertype { u16 min; u16 max; u16 stepsize; + + u8 *initdata; + u8 *sleepdata; }; extern struct tunertype tuners[]; -- cgit v1.2.3-70-g09d2 From 23a88108cf6d5fa8073a3b2af804fff7305e86e3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:53 -0300 Subject: V4L/DVB (7352): tuner-simple: enable digital tuning support for Philips FMD1216ME Enable digital tuning support within tuner-simple. This will allow for a single tuner module to manage the hardware, without having dvb-pll loaded. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-simple.c | 18 ++++++++++++++++++ drivers/media/video/tuner-types.c | 18 ++++++++++++++++++ include/media/tuner-types.h | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'include/media') diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3a27d4a8ce3..b6587300bb8 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -714,6 +714,22 @@ static int simple_set_params(struct dvb_frontend *fe, return ret; } +static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, + const struct dvb_frontend_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_PHILIPS_FMD1216ME_MK3: + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && + params->frequency >= 158870000) + buf[3] |= 0x08; + break; + default: + break; + } +} + static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { @@ -737,6 +753,8 @@ static int simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, buf[2] = config; buf[3] = cb; + simple_set_dvb(fe, buf, params); + tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", tun->name, div, buf[0], buf[1], buf[2], buf[3]); diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 13c76a57d8e..f2e6630731b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -923,6 +923,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { { 16 * 999.99 , 0x86, 0x54, }, }; +static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = { + { 16 * 143.87 /*MHz*/, 0xbc, 0x41 }, + { 16 * 158.87 /*MHz*/, 0xf4, 0x41 }, + { 16 * 329.87 /*MHz*/, 0xbc, 0x42 }, + { 16 * 441.87 /*MHz*/, 0xf4, 0x42 }, + { 16 * 625.87 /*MHz*/, 0xbc, 0x44 }, + { 16 * 803.87 /*MHz*/, 0xf4, 0x44 }, + { 16 * 999.99 , 0xfc, 0x44 }, +}; static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { { @@ -936,6 +945,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { .port2_invert_for_secam_lc = 1, .port1_set_for_fm_mono = 1, }, + { + .type = TUNER_PARAM_TYPE_DIGITAL, + .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges), + .iffreq = 16 * 36.125, /*MHz*/ + }, }; @@ -1461,6 +1476,9 @@ struct tunertype tuners[] = { .name = "Philips FMD1216ME MK3 Hybrid Tuner", .params = tuner_philips_fmd1216me_mk3_params, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), + .min = 16 * 50.87, + .max = 16 * 858.00, + .stepsize = 166667, .initdata = tua603x_agc112, .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index fda12093cab..ab03c534420 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -119,7 +119,7 @@ struct tunertype { u16 min; u16 max; - u16 stepsize; + u32 stepsize; u8 *initdata; u8 *sleepdata; -- cgit v1.2.3-70-g09d2 From 7f0dd17913eda77961fc8213b64cb8af4a155d3e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:01 -0300 Subject: V4L/DVB (7372): cx88: Add IR support for Pixelview MPEG 8000GT Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 45 +++++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 7 ++++++ include/media/ir-common.h | 1 + 3 files changed, 53 insertions(+) (limited to 'include/media') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 107565c4727..35793185630 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_pixelview); +/* + Mauro Carvalho Chehab + present on PV MPEG 8000GT + */ +IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { + [0x3c] = KEY_PAUSE, /* Timeshift */ + [0x12] = KEY_POWER, + + [0x3d] = KEY_1, + [0x38] = KEY_2, + [0x18] = KEY_3, + [0x35] = KEY_4, + [0x39] = KEY_5, + [0x15] = KEY_6, + [0x36] = KEY_7, + [0x3a] = KEY_8, + [0x1e] = KEY_9, + [0x3e] = KEY_0, + + [0x1c] = KEY_AGAIN, /* LOOP */ + [0x3f] = KEY_MEDIA, /* Source */ + [0x1f] = KEY_LAST, /* +100 */ + [0x1b] = KEY_MUTE, + + [0x17] = KEY_CHANNELDOWN, + [0x16] = KEY_CHANNELUP, + [0x10] = KEY_VOLUMEUP, + [0x14] = KEY_VOLUMEDOWN, + [0x13] = KEY_ZOOM, + + [0x19] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x1a] = KEY_SEARCH, /* scan */ + + [0x37] = KEY_REWIND, /* << */ + [0x32] = KEY_RECORD, /* o (red) */ + [0x33] = KEY_FORWARD, /* >> */ + [0x11] = KEY_STOP, /* square */ + [0x3b] = KEY_PLAY, /* > */ + [0x30] = KEY_PLAYPAUSE, /* || */ + + [0x31] = KEY_TV, + [0x34] = KEY_RADIO, +}; +EXPORT_SYMBOL_GPL(ir_codes_pixelview_new); + IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [ 0x00 ] = KEY_0, [ 0x01 ] = KEY_1, diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index d2e42c77b5a..6b25b8c9bb6 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; + case CX88_BOARD_PROLINK_PV_8000GT: + ir_codes = ir_codes_pixelview_new; + ir->gpio_addr = MO_GP1_IO; + ir->mask_keycode = 0x3f; + ir->mask_keyup = 0x80; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_KWORLD_LTV883: ir_codes = ir_codes_pixelview; ir->gpio_addr = MO_GP1_IO; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index a4274203f25..20f1afe2140 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; -- cgit v1.2.3-70-g09d2 From e9bcf6675d6da1a1e9925b2bdfc21f8d2330a1c5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Apr 2008 14:46:02 -0300 Subject: V4L/DVB (7376): Improve compile-time type-checking in videobuf Make the dev member of the struct videobuf_queue of type "struct device *" to avoid future problems. Also change the prototype of the videobuf_queue_core_init() function. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 +- include/media/videobuf-core.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 5ea635fac23..137a1ff4a14 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -120,7 +120,7 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 99033945cde..fcdffdd6330 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -151,7 +151,7 @@ struct videobuf_qtype_ops { struct videobuf_queue { struct mutex vb_lock; spinlock_t *irqlock; - void *dev; /* on pci, points to struct pci_dev */ + struct device *dev; enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ @@ -185,7 +185,7 @@ void *videobuf_alloc(struct videobuf_queue* q); void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, - void *dev, + struct device *dev, spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, -- cgit v1.2.3-70-g09d2 From ab8b870e430d3e2cfb299f81e0ae0aef7fe5bfda Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:46:05 -0300 Subject: V4L/DVB (7381): tuner: rename TUNER_PHILIPS_ATSC to TUNER_PHILIPS_FCV1236D TUNER_PHILIPS_ATSC is an ambiguous name for a tuner. Rename it to TUNER_PHILIPS_FCV1236D to be more descriptive. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 4 ++-- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/tuner-simple.c | 6 +++--- drivers/media/video/tuner-types.c | 4 ++-- include/media/tuner.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 22c2708e42a..4a82cd2dd66 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2327,7 +2327,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2966,7 +2966,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DVICO_FUSIONHDTV_2] = { .name = "DViCO FusionHDTV 2", .tuner = 0, - .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */ + .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .video_inputs = 3, diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index aae7753fef1..94aed008f83 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -331,7 +331,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Kworld USB2800", .is_em2800 = 1, .vchannels = 3, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA7113, .input = { { diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 17f461a78f1..c33ba35a4dd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -185,7 +185,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .shortname = "oa2", .client_modules.lst = pvr2_client_onair_usb2, .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), - .default_tuner_type = TUNER_PHILIPS_ATSC, + .default_tuner_type = TUNER_PHILIPS_FCV1236D, .flag_has_analogtuner = !0, .flag_has_composite = !0, .flag_has_svideo = !0, diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6fde042ee31..55b056bc4e6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3333,7 +3333,7 @@ struct saa7134_board saa7134_boards[] = { /* Juan Pablo Sormani */ .name = "Encore ENLTV-FM", .audio_clock = 0x00200000, - .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_type = TUNER_PHILIPS_FCV1236D, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 07007d67d45..273030bda6d 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -284,7 +284,7 @@ static void simple_set_rf_input(struct dvb_frontend *fe, break; } break; - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: switch (rf) { case 1: *cb |= 0x01; @@ -356,7 +356,7 @@ static int simple_std_setup(struct dvb_frontend *fe, } break; - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: /* 0x00 -> ATSC antenna input 1 */ /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ @@ -766,7 +766,7 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, buf[3] |= 1 << 3; break; case TUNER_PHILIPS_TUV1236D: - case TUNER_PHILIPS_ATSC: + case TUNER_PHILIPS_FCV1236D: { unsigned int new_rf; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index ad16bc25197..10dddca8b5d 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -615,7 +615,7 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { }, }; -/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */ +/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */ static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = { { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, }, @@ -1434,7 +1434,7 @@ struct tunertype tuners[] = { .params = tuner_philips_pal_mk_params, .count = ARRAY_SIZE(tuner_philips_pal_mk_params), }, - [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ + [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */ .name = "Philips FCV1236D ATSC/NTSC dual in", .params = tuner_philips_fcv1236d_params, .count = ARRAY_SIZE(tuner_philips_fcv1236d_params), diff --git a/include/media/tuner.h b/include/media/tuner.h index 1bf24a6ed8f..77068fcc86b 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -78,7 +78,7 @@ #define TUNER_HITACHI_NTSC 40 #define TUNER_PHILIPS_PAL_MK 41 -#define TUNER_PHILIPS_ATSC 42 +#define TUNER_PHILIPS_FCV1236D 42 #define TUNER_PHILIPS_FM1236_MK3 43 #define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */ -- cgit v1.2.3-70-g09d2 From 26f1b942156766c6ff1a70fb2ac463c6fce31309 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 24 Mar 2008 12:18:36 -0300 Subject: V4L/DVB (7406): soc-camera: improve separation between soc_camera_ops and soc_camera_device In case of muliple cameras, handled by the same driver, they can support Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 24 ++++++++++++------------ drivers/media/video/mt9v022.c | 26 ++++++++++++-------------- drivers/media/video/soc_camera.c | 20 ++++++++++---------- include/media/soc_camera.h | 8 ++++---- 4 files changed, 38 insertions(+), 40 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index acb5454b57e..2ea133e8a62 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -410,11 +410,15 @@ const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); -static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); +static int mt9m001_video_probe(struct soc_camera_device *); +static void mt9m001_video_remove(struct soc_camera_device *); +static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); +static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9m001_ops = { .owner = THIS_MODULE, + .probe = mt9m001_video_probe, + .remove = mt9m001_video_remove, .init = mt9m001_init, .release = mt9m001_release, .start_capture = mt9m001_start_capture, @@ -423,8 +427,6 @@ static struct soc_camera_ops mt9m001_ops = { .try_fmt_cap = mt9m001_try_fmt_cap, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, - .formats = NULL, /* Filled in later depending on the */ - .num_formats = 0, /* camera type and data widths */ .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), .get_control = mt9m001_get_control, @@ -573,19 +575,19 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8411: case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; - mt9m001_ops.formats = mt9m001_colour_formats; + icd->formats = mt9m001_colour_formats; if (mt9m001->client->dev.platform_data) - mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats); else - mt9m001_ops.num_formats = 1; + icd->num_formats = 1; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; - mt9m001_ops.formats = mt9m001_monochrome_formats; + icd->formats = mt9m001_monochrome_formats; if (mt9m001->client->dev.platform_data) - mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); + icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); else - mt9m001_ops.num_formats = 1; + icd->num_formats = 1; break; default: ret = -ENODEV; @@ -646,8 +648,6 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd = &mt9m001->icd; - icd->probe = mt9m001_video_probe; - icd->remove = mt9m001_video_remove; icd->ops = &mt9m001_ops; icd->control = &client->dev; icd->x_min = 20; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index a2f161dcc72..d4b9e274434 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -506,13 +506,15 @@ const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl); -static int mt9v022_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl); +static int mt9v022_video_probe(struct soc_camera_device *); +static void mt9v022_video_remove(struct soc_camera_device *); +static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); +static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9v022_ops = { .owner = THIS_MODULE, + .probe = mt9v022_video_probe, + .remove = mt9v022_video_remove, .init = mt9v022_init, .release = mt9v022_release, .start_capture = mt9v022_start_capture, @@ -521,8 +523,6 @@ static struct soc_camera_ops mt9v022_ops = { .try_fmt_cap = mt9v022_try_fmt_cap, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, - .formats = NULL, /* Filled in later depending on the */ - .num_formats = 0, /* sensor type and data widths */ .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), .get_control = mt9v022_get_control, @@ -705,19 +705,19 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) !strcmp("color", sensor_type))) { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; - mt9v022_ops.formats = mt9v022_colour_formats; + icd->formats = mt9v022_colour_formats; if (mt9v022->client->dev.platform_data) - mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_colour_formats); + icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats); else - mt9v022_ops.num_formats = 1; + icd->num_formats = 1; } else { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; - mt9v022_ops.formats = mt9v022_monochrome_formats; + icd->formats = mt9v022_monochrome_formats; if (mt9v022->client->dev.platform_data) - mt9v022_ops.num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); + icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); else - mt9v022_ops.num_formats = 1; + icd->num_formats = 1; } if (ret >= 0) @@ -773,8 +773,6 @@ static int mt9v022_probe(struct i2c_client *client) i2c_set_clientdata(client, mt9v022); icd = &mt9v022->icd; - icd->probe = mt9v022_video_probe; - icd->remove = mt9v022_video_remove; icd->ops = &mt9v022_ops; icd->control = &client->dev; icd->x_min = 1; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 91e1ab36fe5..4af38d444e0 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -38,9 +38,9 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) { unsigned int i; - for (i = 0; i < icd->ops->num_formats; i++) - if (icd->ops->formats[i].fourcc == fourcc) - return icd->ops->formats + i; + for (i = 0; i < icd->num_formats; i++) + if (icd->formats[i].fourcc == fourcc) + return icd->formats + i; return NULL; } @@ -384,10 +384,10 @@ static int soc_camera_enum_fmt_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - if (f->index >= icd->ops->num_formats) + if (f->index >= icd->num_formats) return -EINVAL; - format = &icd->ops->formats[f->index]; + format = &icd->formats[f->index]; strlcpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; @@ -701,7 +701,7 @@ static int soc_camera_probe(struct device *dev) to_soc_camera_host(icd->dev.parent); int ret; - if (!icd->probe) + if (!icd->ops->probe) return -ENODEV; /* We only call ->add() here to activate and probe the camera. @@ -710,7 +710,7 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) return ret; - ret = icd->probe(icd); + ret = icd->ops->probe(icd); if (ret >= 0) { const struct v4l2_queryctrl *qctrl; @@ -731,8 +731,8 @@ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - if (icd->remove) - icd->remove(icd); + if (icd->ops->remove) + icd->ops->remove(icd); return 0; } @@ -928,7 +928,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev->vidioc_s_register = soc_camera_s_register; #endif - icd->current_fmt = &icd->ops->formats[0]; + icd->current_fmt = &icd->formats[0]; err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); if (err < 0) { diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 3e48e435b21..7a2fa3ed849 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -38,8 +38,8 @@ struct soc_camera_device { struct soc_camera_ops *ops; struct video_device *vdev; const struct soc_camera_data_format *current_fmt; - int (*probe)(struct soc_camera_device *icd); - void (*remove)(struct soc_camera_device *icd); + const struct soc_camera_data_format *formats; + int num_formats; struct module *owner; /* soc_camera.c private count. Only accessed with video_lock held */ int use_count; @@ -106,6 +106,8 @@ struct soc_camera_data_format { struct soc_camera_ops { struct module *owner; + int (*probe)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); int (*init)(struct soc_camera_device *); int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); @@ -121,8 +123,6 @@ struct soc_camera_ops { int (*get_register)(struct soc_camera_device *, struct v4l2_register *); int (*set_register)(struct soc_camera_device *, struct v4l2_register *); #endif - const struct soc_camera_data_format *formats; - int num_formats; int (*get_control)(struct soc_camera_device *, struct v4l2_control *); int (*set_control)(struct soc_camera_device *, struct v4l2_control *); const struct v4l2_queryctrl *controls; -- cgit v1.2.3-70-g09d2 From 137d1cb19d9da163ce6cb57a6fa1e6a3468af6a4 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 2 Apr 2008 18:10:59 -0300 Subject: V4L/DVB (7493): videobuf: Avoid deadlock with QBUF and bring up to spec for empty queue Add a waitqueue to wait on when there are no buffers in the buffer queue. DQBUF waits on this queue without holding vb_lock to allow a QBUF to happen. Once a buffer has been queued we recheck that the queue is still streaming and wait on the new buffer's waitqueue while holding the vb_lock. The driver should come along in a timely manner and put the buffer into its next state finishing the DQBUF. By implementing this waitqueue it also brings the videobuf DQBUF up to spec and it now blocks on O_NONBLOCK even when no buffers have been queued via QBUF: "By default VIDIOC_DQBUF blocks when no buffer is in the outgoing queue." - V4L2 spec Signed-off-by: Brandon Philips CC: Trent Piepho CC: Carl Karsten CC: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 96 +++++++++++++++++++++++++++++-------- include/media/videobuf-core.h | 2 + 2 files changed, 78 insertions(+), 20 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 1ba3aaa29dd..3ab556093ca 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -141,6 +141,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, BUG_ON(!q->int_ops); mutex_init(&q->vb_lock); + init_waitqueue_head(&q->wait); INIT_LIST_HEAD(&q->stream); } @@ -188,6 +189,10 @@ void videobuf_queue_cancel(struct videobuf_queue *q) unsigned long flags = 0; int i; + q->streaming = 0; + q->reading = 0; + wake_up_interruptible_sync(&q->wait); + /* remove queued buffers from list */ if (q->irqlock) spin_lock_irqsave(q->irqlock, flags); @@ -565,6 +570,7 @@ int videobuf_qbuf(struct videobuf_queue *q, } dprintk(1, "qbuf: succeded\n"); retval = 0; + wake_up_interruptible_sync(&q->wait); done: mutex_unlock(&q->vb_lock); @@ -575,37 +581,88 @@ int videobuf_qbuf(struct videobuf_queue *q, return retval; } -int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking) + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) { - struct videobuf_buffer *buf; int retval; - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - mutex_lock(&q->vb_lock); - retval = -EBUSY; - if (q->reading) { - dprintk(1, "dqbuf: Reading running...\n"); - goto done; - } - retval = -EINVAL; - if (b->type != q->type) { - dprintk(1, "dqbuf: Wrong type.\n"); +checks: + if (!q->streaming) { + dprintk(1, "next_buffer: Not streaming\n"); + retval = -EINVAL; goto done; } + if (list_empty(&q->stream)) { - dprintk(1, "dqbuf: stream running\n"); - goto done; + if (noblock) { + retval = -EAGAIN; + dprintk(2, "next_buffer: no buffers to dequeue\n"); + goto done; + } else { + dprintk(2, "next_buffer: waiting on buffer\n"); + + /* Drop lock to avoid deadlock with qbuf */ + mutex_unlock(&q->vb_lock); + + /* Checking list_empty and streaming is safe without + * locks because we goto checks to validate while + * holding locks before proceeding */ + retval = wait_event_interruptible(q->wait, + !list_empty(&q->stream) || !q->streaming); + mutex_lock(&q->vb_lock); + + if (retval) + goto done; + + goto checks; + } } + + retval = 0; + +done: + return retval; +} + + +/* Locking: Caller holds q->vb_lock */ +static int stream_next_buffer(struct videobuf_queue *q, + struct videobuf_buffer **vb, int nonblocking) +{ + int retval; + struct videobuf_buffer *buf = NULL; + + retval = stream_next_buffer_check_queue(q, nonblocking); + if (retval) + goto done; + buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - mutex_unlock(&q->vb_lock); retval = videobuf_waiton(buf, nonblocking, 1); + if (retval < 0) + goto done; + + *vb = buf; +done: + return retval; +} + +int videobuf_dqbuf(struct videobuf_queue *q, + struct v4l2_buffer *b, int nonblocking) +{ + struct videobuf_buffer *buf = NULL; + int retval; + + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + mutex_lock(&q->vb_lock); + + retval = stream_next_buffer(q, &buf, nonblocking); if (retval < 0) { - dprintk(1, "dqbuf: waiton returned %d\n", retval); + dprintk(1, "dqbuf: next_buffer error: %i\n", retval); goto done; } + switch (buf->state) { case VIDEOBUF_ERROR: dprintk(1, "dqbuf: state is error\n"); @@ -654,6 +711,7 @@ int videobuf_streamon(struct videobuf_queue *q) if (q->irqlock) spin_unlock_irqrestore(q->irqlock, flags); + wake_up_interruptible_sync(&q->wait); done: mutex_unlock(&q->vb_lock); return retval; @@ -666,7 +724,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q) return -EINVAL; videobuf_queue_cancel(q); - q->streaming = 0; return 0; } @@ -869,7 +926,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) q->bufs[i] = NULL; } q->read_buf = NULL; - q->reading = 0; } diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index fcdffdd6330..377a6c6e931 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -153,6 +153,8 @@ struct videobuf_queue { spinlock_t *irqlock; struct device *dev; + wait_queue_head_t wait; /* wait if queue is empty */ + enum v4l2_buf_type type; unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */ unsigned int msize; -- cgit v1.2.3-70-g09d2 From b8d9904c3525c0a149976ffaad48fcb03e8703f7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 4 Apr 2008 13:41:25 -0300 Subject: V4L/DVB (7500): soc-camera: extract function pointers from host object into operations Function pointers and the driver owner are not expected to change throughout soc-camera host's life. Extract them into an operations struct. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 27 ++++++++++++++++----------- drivers/media/video/soc_camera.c | 37 ++++++++++++++++++------------------- include/media/soc_camera.h | 9 ++++++--- 3 files changed, 40 insertions(+), 33 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 4756699d16a..9758f7eb593 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -803,20 +803,25 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, return 0; } -/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host_ops pxa_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, + .set_fmt_cap = pxa_camera_set_fmt_cap, + .try_fmt_cap = pxa_camera_try_fmt_cap, + .reqbufs = pxa_camera_reqbufs, + .poll = pxa_camera_poll, + .querycap = pxa_camera_querycap, + .try_bus_param = pxa_camera_try_bus_param, + .set_bus_param = pxa_camera_set_bus_param, +}; + +/* Should be allocated dynamically too, but we have only one. */ static struct soc_camera_host pxa_soc_camera_host = { .drv_name = PXA_CAM_DRV_NAME, .vbq_ops = &pxa_videobuf_ops, - .add = pxa_camera_add_device, - .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .set_fmt_cap = pxa_camera_set_fmt_cap, - .try_fmt_cap = pxa_camera_try_fmt_cap, - .reqbufs = pxa_camera_reqbufs, - .poll = pxa_camera_poll, - .querycap = pxa_camera_querycap, - .try_bus_param = pxa_camera_try_bus_param, - .set_bus_param = pxa_camera_set_bus_param, + .ops = &pxa_soc_camera_host_ops, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -912,7 +917,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pxa_soc_camera_host.priv = pcdev; pxa_soc_camera_host.dev.parent = &pdev->dev; pxa_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE); + err = soc_camera_host_register(&pxa_soc_camera_host); if (err) goto exit_free_irq; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 4af38d444e0..43c8110599e 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -76,12 +76,12 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, } /* test physical bus parameters */ - ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); + ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat); if (ret) return ret; /* limit format to hardware capabilities */ - ret = ici->try_fmt_cap(icd, f); + ret = ici->ops->try_fmt_cap(icd, f); /* calculate missing fields */ f->fmt.pix.field = field; @@ -143,7 +143,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, if (ret < 0) return ret; - return ici->reqbufs(icf, p); + return ici->ops->reqbufs(icf, p); return ret; } @@ -203,7 +203,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgd; } - if (!try_module_get(ici->owner)) { + if (!try_module_get(ici->ops->owner)) { dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); ret = -EINVAL; goto emgi; @@ -215,7 +215,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); icd->use_count--; @@ -238,7 +238,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: - module_put(ici->owner); + module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); emgd: @@ -257,9 +257,9 @@ static int soc_camera_close(struct inode *inode, struct file *file) mutex_lock(&video_lock); icd->use_count--; if (!icd->use_count) - ici->remove(icd); + ici->ops->remove(icd); module_put(icd->ops->owner); - module_put(ici->owner); + module_put(ici->ops->owner); mutex_unlock(&video_lock); vfree(file->private_data); @@ -312,7 +312,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return POLLERR; } - return ici->poll(file, pt); + return ici->ops->poll(file, pt); } @@ -356,7 +356,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, rect.top = icd->y_current; rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; - ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); if (ret < 0) return ret; @@ -372,7 +372,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - return ici->set_bus_param(icd, f->fmt.pix.pixelformat); + return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); } static int soc_camera_enum_fmt_cap(struct file *file, void *priv, @@ -426,7 +426,7 @@ static int soc_camera_querycap(struct file *file, void *priv, WARN_ON(priv != file->private_data); strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); - return ici->querycap(ici, cap); + return ici->ops->querycap(ici, cap); } static int soc_camera_streamon(struct file *file, void *priv, @@ -579,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ici->set_fmt_cap(icd, 0, &a->c); + ret = ici->ops->set_fmt_cap(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -706,7 +706,7 @@ static int soc_camera_probe(struct device *dev) /* We only call ->add() here to activate and probe the camera. * We shall ->remove() and deactivate it immediately afterwards. */ - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) return ret; @@ -720,7 +720,7 @@ static int soc_camera_probe(struct device *dev) icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; } - ici->remove(icd); + ici->ops->remove(icd); return ret; } @@ -762,12 +762,12 @@ static void dummy_release(struct device *dev) { } -int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +int soc_camera_host_register(struct soc_camera_host *ici) { int ret; struct soc_camera_host *ix; - if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove) return -EINVAL; /* Number might be equal to the platform device ID */ @@ -785,7 +785,6 @@ int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); - ici->owner = owner; ici->dev.release = dummy_release; ret = device_register(&ici->dev); @@ -819,7 +818,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) if (icd->dev.parent == &ici->dev) { device_unregister(&icd->dev); /* Not before device_unregister(), .remove - * needs parent to call ici->remove() */ + * needs parent to call ici->ops->remove() */ icd->dev.parent = NULL; memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 7a2fa3ed849..80e1193c07d 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -56,9 +56,13 @@ struct soc_camera_host { unsigned char nr; /* Host number */ size_t msize; struct videobuf_queue_ops *vbq_ops; - struct module *owner; void *priv; char *drv_name; + struct soc_camera_host_ops *ops; +}; + +struct soc_camera_host_ops { + struct module *owner; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); int (*set_fmt_cap)(struct soc_camera_device *, __u32, @@ -88,8 +92,7 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) return container_of(dev, struct soc_camera_host, dev); } -extern int soc_camera_host_register(struct soc_camera_host *ici, - struct module *owner); +extern int soc_camera_host_register(struct soc_camera_host *ici); extern void soc_camera_host_unregister(struct soc_camera_host *ici); extern int soc_camera_device_register(struct soc_camera_device *icd); extern void soc_camera_device_unregister(struct soc_camera_device *icd); -- cgit v1.2.3-70-g09d2 From 1a0063a9852380190a7172c1a1cb79e934b06cd4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 4 Apr 2008 13:46:34 -0300 Subject: V4L/DVB (7501): soc-camera: use a spinlock for videobuffer queue All drivers should provide a spinlock to be used in videobuf operations. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 10 +++++++++ drivers/media/video/soc_camera.c | 46 +++++++++++++++++++++++++++++++++++----- include/media/soc_camera.h | 3 +++ 3 files changed, 54 insertions(+), 5 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 9758f7eb593..bef3c9c7902 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -803,6 +803,15 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, return 0; } +static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icf->icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + return &pcdev->lock; +} + static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .owner = THIS_MODULE, .add = pxa_camera_add_device, @@ -814,6 +823,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .querycap = pxa_camera_querycap, .try_bus_param = pxa_camera_try_bus_param, .set_bus_param = pxa_camera_set_bus_param, + .spinlock_alloc = pxa_camera_spinlock_alloc, }; /* Should be allocated dynamically too, but we have only one. */ diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43c8110599e..1e921578804 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) struct soc_camera_device *icd; struct soc_camera_host *ici; struct soc_camera_file *icf; + spinlock_t *lock; int ret; icf = vmalloc(sizeof(*icf)); @@ -209,10 +210,16 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgi; } - icd->use_count++; - icf->icd = icd; + icf->lock = ici->ops->spinlock_alloc(icf); + if (!icf->lock) { + ret = -ENOMEM; + goto esla; + } + + icd->use_count++; + /* Now we really have to activate the camera */ if (icd->use_count == 1) { ret = ici->ops->add(icd); @@ -229,8 +236,8 @@ static int soc_camera_open(struct inode *inode, struct file *file) dev_dbg(&icd->dev, "camera device open\n"); /* We must pass NULL as dev pointer, then all pci_* dma operations - * transform to normal dma_* ones. Do we need an irqlock? */ - videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + * transform to normal dma_* ones. */ + videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, ici->msize, icd); @@ -238,6 +245,11 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: + lock = icf->lock; + icf->lock = NULL; + if (ici->ops->spinlock_free) + ici->ops->spinlock_free(lock); +esla: module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); @@ -253,16 +265,20 @@ static int soc_camera_close(struct inode *inode, struct file *file) struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct video_device *vdev = icd->vdev; + spinlock_t *lock = icf->lock; mutex_lock(&video_lock); icd->use_count--; if (!icd->use_count) ici->ops->remove(icd); + icf->lock = NULL; + if (ici->ops->spinlock_free) + ici->ops->spinlock_free(lock); module_put(icd->ops->owner); module_put(ici->ops->owner); mutex_unlock(&video_lock); - vfree(file->private_data); + vfree(icf); dev_dbg(vdev->dev, "camera device close\n"); @@ -762,6 +778,21 @@ static void dummy_release(struct device *dev) { } +static spinlock_t *spinlock_alloc(struct soc_camera_file *icf) +{ + spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL); + + if (lock) + spin_lock_init(lock); + + return lock; +} + +static void spinlock_free(spinlock_t *lock) +{ + kfree(lock); +} + int soc_camera_host_register(struct soc_camera_host *ici) { int ret; @@ -792,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (ret) goto edevr; + if (!ici->ops->spinlock_alloc) { + ici->ops->spinlock_alloc = spinlock_alloc; + ici->ops->spinlock_free = spinlock_free; + } + scan_add_host(ici); return 0; diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 80e1193c07d..6a8c8be7a1a 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -48,6 +48,7 @@ struct soc_camera_device { struct soc_camera_file { struct soc_camera_device *icd; struct videobuf_queue vb_vidq; + spinlock_t *lock; }; struct soc_camera_host { @@ -73,6 +74,8 @@ struct soc_camera_host_ops { int (*try_bus_param)(struct soc_camera_device *, __u32); int (*set_bus_param)(struct soc_camera_device *, __u32); unsigned int (*poll)(struct file *, poll_table *); + spinlock_t* (*spinlock_alloc)(struct soc_camera_file *); + void (*spinlock_free)(spinlock_t *); }; struct soc_camera_link { -- cgit v1.2.3-70-g09d2 From ba928034df7e8b603152c896a2f84f9b12e8c290 Mon Sep 17 00:00:00 2001 From: Dâniel Fraga Date: Tue, 8 Apr 2008 19:56:44 -0300 Subject: V4L/DVB (7506): Powercolor Real Angel 330 (remote control support) The attached patch adds complete remote control support for Powercolor Real Angel 330. Signed-off-by: Daniel Fraga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 43 +++++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 6 +++++ include/media/ir-common.h | 1 + 3 files changed, 50 insertions(+) (limited to 'include/media') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 35793185630..c5d10bdf428 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2084,3 +2084,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { [0x50] = KEY_BLUE, }; EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce); + +/* + * Remote control for Powercolor Real Angel 330 + * Daniel Fraga + */ +IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { + [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_DIGITS, /* single, double, tripple digit */ + [0x29] = KEY_PREVIOUS, /* previous channel */ + [0x12] = KEY_BRIGHTNESSUP, + [0x13] = KEY_BRIGHTNESSDOWN, + [0x2b] = KEY_MODE, /* stereo/mono */ + [0x2c] = KEY_TEXT, /* teletext */ + [0x20] = KEY_UP, /* channel up */ + [0x21] = KEY_DOWN, /* channel down */ + [0x10] = KEY_RIGHT, /* volume up */ + [0x11] = KEY_LEFT, /* volume down */ + [0x0d] = KEY_MUTE, + [0x1f] = KEY_RECORD, + [0x17] = KEY_PLAY, + [0x16] = KEY_PAUSE, + [0x0b] = KEY_STOP, + [0x27] = KEY_FASTFORWARD, + [0x26] = KEY_REWIND, + [0x1e] = KEY_SEARCH, /* autoscan */ + [0x0e] = KEY_SHUFFLE, /* snapshot */ + [0x2d] = KEY_SETUP, + [0x0f] = KEY_SCREEN, /* full screen */ + [0x14] = KEY_RADIO, /* FM radio */ + [0x25] = KEY_POWER, /* power */ +}; +EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6b25b8c9bb6..53526d997a4 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -317,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir_type = IR_TYPE_RC5; ir->sampling = 1; break; + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + ir_codes = ir_codes_powercolor_real_angel; + ir->gpio_addr = MO_GP2_IO; + ir->mask_keycode = 0x7e; + ir->polling = 100; /* ms */ + break; } if (NULL == ir_codes) { diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 20f1afe2140..75a3482866f 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -144,6 +144,7 @@ extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3-70-g09d2 From 78e92006f410a4044f8c1760c25ac9d11d259aa2 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 9 Apr 2008 19:13:13 -0300 Subject: V4L/DVB (7538): Adds selectable adapter numbers as per module option The adapter_nr module options can be used to allocate static adapter numbers on a driver level. It avoids problems with changing DVB apapter numbers after warm/cold boot or device unplugging and repluging. Each driver holds DVB_MAX_ADAPTER long array of the preferred order of adapter numbers. options dvb-usb-dib0700 adapter_nr=7,6,5,4,3,2,1,0 would result in a reversed allocation of adapter numbers. With adapter_nr=2,5 it tries first to get adapter number 2 and 5. If both are already in use it will allocate the lowest free adapter number. Signed-off-by: Janne Grunau Acked-by: Hermann Pitton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop.c | 8 +++-- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 7 +++- drivers/media/dvb/cinergyT2/cinergyT2.c | 7 +++- drivers/media/dvb/dvb-core/dvbdev.c | 41 +++++++++++++++++------ drivers/media/dvb/dvb-core/dvbdev.h | 13 ++++++- drivers/media/dvb/dvb-usb/a800.c | 6 +++- drivers/media/dvb/dvb-usb/af9005.c | 5 ++- drivers/media/dvb/dvb-usb/au6610.c | 6 +++- drivers/media/dvb/dvb-usb/cxusb.c | 29 +++++++++++----- drivers/media/dvb/dvb-usb/dib0700_core.c | 5 ++- drivers/media/dvb/dvb-usb/dibusb-mb.c | 14 +++++--- drivers/media/dvb/dvb-usb/dibusb-mc.c | 5 ++- drivers/media/dvb/dvb-usb/digitv.c | 8 +++-- drivers/media/dvb/dvb-usb/dtt200u.c | 17 +++++++--- drivers/media/dvb/dvb-usb/dvb-usb-common.h | 3 +- drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | 9 ++--- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 16 +++++---- drivers/media/dvb/dvb-usb/dvb-usb.h | 5 ++- drivers/media/dvb/dvb-usb/gl861.c | 6 +++- drivers/media/dvb/dvb-usb/gp8psk.c | 5 ++- drivers/media/dvb/dvb-usb/m920x.c | 22 +++++++----- drivers/media/dvb/dvb-usb/nova-t-usb2.c | 5 ++- drivers/media/dvb/dvb-usb/opera1.c | 6 +++- drivers/media/dvb/dvb-usb/ttusb2.c | 8 +++-- drivers/media/dvb/dvb-usb/umt-010.c | 5 ++- drivers/media/dvb/dvb-usb/vp702x.c | 5 ++- drivers/media/dvb/dvb-usb/vp7045.c | 6 +++- drivers/media/dvb/pluto2/pluto2.c | 5 ++- drivers/media/dvb/ttpci/av7110.c | 4 ++- drivers/media/dvb/ttpci/budget-core.c | 7 ++-- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 8 +++-- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 6 +++- drivers/media/video/cx23885/cx23885-dvb.c | 4 ++- drivers/media/video/cx88/cx88-dvb.c | 5 ++- drivers/media/video/saa7134/saa7134-dvb.c | 5 ++- drivers/media/video/videobuf-dvb.c | 6 ++-- include/media/videobuf-dvb.h | 3 +- 37 files changed, 242 insertions(+), 83 deletions(-) (limited to 'include/media') diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 205146c2412..5f79c8dc383 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS); #undef DEBSTATUS +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* global zero for ibi values */ flexcop_ibi_value ibi_zero; @@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) static int flexcop_dvb_init(struct flexcop_device *fc) { - int ret; - if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) { + int ret = dvb_register_adapter(&fc->dvb_adapter, + "FlexCop Digital TV device", fc->owner, + fc->dev, adapter_nr); + if (ret < 0) { err("error registering DVB adapter"); return ret; } diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index a39439b5f04..6afbfbbef0c 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -40,6 +40,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk( args... ) \ do { \ if (debug) printk(KERN_DEBUG args); \ @@ -717,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) { int result; - if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) { + result = dvb_register_adapter(&card->dvb_adapter, card->card_name, + THIS_MODULE, &card->bt->dev->dev, + adapter_nr); + if (result < 0) { printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result); return result; } diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 29b2459e0b2..f5010e8671b 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -58,6 +58,8 @@ static int debug; module_param_named(debug, debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(level, args...) \ do { \ if ((debug & level)) { \ @@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf, return -ENOMEM; } - if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) { + err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, + THIS_MODULE, &cinergyt2->udev->dev, + adapter_nr); + if (err < 0) { kfree(cinergyt2); return err; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 0a2897bc987..8b56d929f7f 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -49,7 +49,6 @@ static const char * const dnames[] = { "net", "osd" }; -#define DVB_MAX_ADAPTERS 8 #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) @@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_unregister_device); +static int dvbdev_check_free_adapter_num(int num) +{ + struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { + struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); + if (adap->num == num) + return 0; + } + return 1; +} static int dvbdev_get_free_adapter_num (void) { int num = 0; while (num < DVB_MAX_ADAPTERS) { - struct dvb_adapter *adap; - list_for_each_entry(adap, &dvb_adapter_list, list_head) - if (adap->num == num) - goto skip; - return num; -skip: + if (dvbdev_check_free_adapter_num(num)) + return num; num++; } @@ -281,13 +287,28 @@ skip: } -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device) +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums) { - int num; + int i, num; mutex_lock(&dvbdev_register_lock); - if ((num = dvbdev_get_free_adapter_num ()) < 0) { + for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { + num = adapter_nums[i]; + if (num >= 0 && num < DVB_MAX_ADAPTERS) { + /* use the one the driver asked for */ + if (dvbdev_check_free_adapter_num(num)) + break; + } else { + num = dvbdev_get_free_adapter_num(); + break; + } + num = -1; + } + + if (num < 0) { mutex_unlock(&dvbdev_register_lock); return -ENFILE; } diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 6dff10ebf47..5f9a737c6de 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -31,6 +31,10 @@ #define DVB_MAJOR 212 +#define DVB_MAX_ADAPTERS 8 + +#define DVB_UNSET (-1) + #define DVB_DEVICE_VIDEO 0 #define DVB_DEVICE_AUDIO 1 #define DVB_DEVICE_SEC 2 @@ -41,6 +45,11 @@ #define DVB_DEVICE_NET 7 #define DVB_DEVICE_OSD 8 +#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ + static short adapter_nr[] = \ + {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ + module_param_array(adapter_nr, short, NULL, 0444); \ + MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") struct dvb_adapter { int num; @@ -78,7 +87,9 @@ struct dvb_device { }; -extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device); +extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums); extern int dvb_unregister_adapter (struct dvb_adapter *adap); extern int dvb_register_device (struct dvb_adapter *adap, diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index a6c5f19f680..dc8c8784caa 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c @@ -18,6 +18,9 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(debug,0x01,args) static int a800_power_ctrl(struct dvb_usb_device *d, int onoff) @@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties; static int a800_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &a800_properties, + THIS_MODULE, NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index e7f76f515b4..cfe71feefca 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c @@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0; module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* remote control decoder */ int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event, int *state); @@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties; static int af9005_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL); + return dvb_usb_device_init(intf, &af9005_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id af9005_usb_table[] = { diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c index f3ff8131469..2ccb90fa60c 100644 --- a/drivers/media/dvb/dvb-usb/au6610.c +++ b/drivers/media/dvb/dvb-usb/au6610.c @@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug; module_param_named(debug, dvb_usb_au6610_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf, if (intf->num_altsetting < AU6610_ALTSETTING_COUNT) return -ENODEV; - if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); if (alt == NULL) { diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 4e5118dfe2e..c4b00660c65 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -40,6 +40,9 @@ static int dvb_usb_cxusb_debug; module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) #define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ dprintk(dvb_usb_cxusb_debug,0x01,args) @@ -723,16 +726,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) { + if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, + &cxusb_bluebird_nano2_needsfirmware_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; - } return -EINVAL; } diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 4b3836e63be..595a04696c8 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -17,6 +17,8 @@ int dvb_usb_dib0700_ir_proto = 1; module_param(dvb_usb_dib0700_ir_proto, int, 0644); MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* expecting rx buffer: request data[0] data[1] ... data[2] */ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) { @@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf, struct dvb_usb_device *dev; for (i = 0; i < dib0700_device_count; i++) - if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0) + if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, + &dev, adapter_nr) == 0) { dib0700_rc_setup(dev); return 0; diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 043cadae085..eeef50bff4f 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -14,6 +14,8 @@ */ #include "dibusb.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) { struct dvb_usb_adapter *adap = fe->dvb->priv; @@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties; static int dibusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -EINVAL; diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index e7ea3e753d6..059cec95531 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -14,13 +14,16 @@ */ #include "dibusb.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* USB Driver stuff */ static struct dvb_usb_device_properties dibusb_mc_properties; static int dibusb_mc_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE, + NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 3acbda4aa27..b545cf3eab2 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -20,6 +20,9 @@ static int dvb_usb_digitv_debug; module_param_named(debug,dvb_usb_digitv_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args) static int digitv_ctrl_msg(struct dvb_usb_device *d, @@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dvb_usb_device *d; - int ret; - if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { + int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { u8 b[4] = { 0 }; if (d != NULL) { /* do that only when the firmware is loaded */ diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index d86cf9bee91..81a6cbf6016 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug; module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) { u8 b = SET_INIT; @@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties; static int dtt200u_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &dtt200u_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -ENODEV; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h index 35ab68f6dcf..6b7b2a89242 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h @@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap); extern int dvb_usb_i2c_init(struct dvb_usb_device *); extern int dvb_usb_i2c_exit(struct dvb_usb_device *); -extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap); +extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, + short *adapter_nums); extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap); extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap); extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index 4561a672da9..ce8cd0c5d83 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) return dvb_usb_ctrl_feed(dvbdmxfeed,0); } -int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap) +int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) { - int ret; + int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name, + adap->dev->owner, &adap->dev->udev->dev, + adapter_nums); - if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name, - adap->dev->owner, &adap->dev->udev->dev)) < 0) { + if (ret < 0) { deb_info("dvb_register_adapter failed: error %d", ret); goto err; } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index cdd717c3fe4..e331db8c77b 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage; module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); -static int dvb_usb_adapter_init(struct dvb_usb_device *d) +static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) { struct dvb_usb_adapter *adap; int ret,n; @@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d) } if ((ret = dvb_usb_adapter_stream_init(adap)) || - (ret = dvb_usb_adapter_dvb_init(adap)) || + (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) || (ret = dvb_usb_adapter_frontend_init(adap))) { return ret; } @@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d) return 0; } -static int dvb_usb_init(struct dvb_usb_device *d) +static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums) { int ret = 0; @@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d) dvb_usb_device_power_ctrl(d, 1); if ((ret = dvb_usb_i2c_init(d)) || - (ret = dvb_usb_adapter_init(d))) { + (ret = dvb_usb_adapter_init(d, adapter_nums))) { dvb_usb_exit(d); return ret; } @@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff) /* * USB */ -int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties - *props, struct module *owner,struct dvb_usb_device **du) +int dvb_usb_device_init(struct usb_interface *intf, + struct dvb_usb_device_properties *props, + struct module *owner, struct dvb_usb_device **du, + short *adapter_nums) { struct usb_device *udev = interface_to_usbdev(intf); struct dvb_usb_device *d = NULL; @@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper if (du != NULL) *du = d; - ret = dvb_usb_init(d); + ret = dvb_usb_init(d, adapter_nums); if (ret == 0) info("%s successfully initialized and connected.",desc->name); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index d1b3c7b81ff..b1de0f7e26e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -372,7 +372,10 @@ struct dvb_usb_device { void *priv; }; -extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **); +extern int dvb_usb_device_init(struct usb_interface *, + struct dvb_usb_device_properties *, + struct module *, struct dvb_usb_device **, + short *adapter_nums); extern void dvb_usb_device_exit(struct usb_interface *); /* the generic read/write method for device control */ diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c index 6b99d9f4d5b..0a8ac64a4e3 100644 --- a/drivers/media/dvb/dvb-usb/gl861.c +++ b/drivers/media/dvb/dvb-usb/gl861.c @@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug; module_param_named(debug,dvb_usb_gl861_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf, if (intf->num_altsetting < 2) return -ENODEV; - if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d, + adapter_nr); + if (ret == 0) { alt = usb_altnum_to_altsetting(intf, 0); if (alt == NULL) { diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index 83e8535014c..9a942afaf0a 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug; module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = 0,try = 0; @@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf, { int ret; struct usb_device *udev = interface_to_usbdev(intf); - ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); + ret = dvb_usb_device_init(intf, &gp8psk_properties, + THIS_MODULE, NULL, adapter_nr); if (ret == 0) { info("found Genpix USB device pID = %x (hex)", le16_to_cpu(udev->descriptor.idProduct)); diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 29ec2b96774..a12e6f784fd 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug; module_param_named(debug,dvb_usb_m920x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid); static inline int m920x_read(struct usb_device *udev, u8 request, u16 value, @@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf, * multi-tuner device */ - if ((ret = dvb_usb_device_init(intf, &megasky_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &megasky_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { rc_init_seq = megasky_rc_init; goto found; } - if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { /* No remote control, so no rc_init_seq */ goto found; } /* This configures both tuners on the TV Walker Twin */ - if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { rc_init_seq = tvwalkertwin_rc_init; goto found; } - if ((ret = dvb_usb_device_init(intf, &dposh_properties, - THIS_MODULE, &d)) == 0) { + ret = dvb_usb_device_init(intf, &dposh_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { /* Remote controller not supported yet. */ goto found; } diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index badc468170e..07fb843c7c2 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -15,6 +15,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_rc(args...) dprintk(debug,0x01,args) #define deb_ee(args...) dprintk(debug,0x02,args) @@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties; static int nova_t_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &nova_t_properties, + THIS_MODULE, NULL, adapter_nr); } /* do not change the order of the ID table */ diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 302cc67407c..0eef5fe094e 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, u8 * data, u16 len, int flags) { @@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf, return -EINVAL; } - if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0) + if (0 != dvb_usb_device_init(intf, &opera1_properties, + THIS_MODULE, NULL, adapter_nr)) return -EINVAL; return 0; } diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index 0eb33378254..706687c7850 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug; module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct ttusb2_state { u8 id; }; @@ -181,8 +183,10 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400; static int ttusb2_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf, &ttusb2_properties, THIS_MODULE, NULL) == 0 || - dvb_usb_device_init(intf, &ttusb2_properties_s2400, THIS_MODULE, NULL) == 0) + if (0 == dvb_usb_device_init(intf, &ttusb2_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, + THIS_MODULE, NULL, adapter_nr)) return 0; return -ENODEV; } diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index 0dcab3d4e23..9e7653bb3b6 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c @@ -13,6 +13,8 @@ #include "mt352.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static int umt_mt352_demod_init(struct dvb_frontend *fe) { static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; @@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties; static int umt_probe(struct usb_interface *intf, const struct usb_device_id *id) { - if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0) + if (0 == dvb_usb_device_init(intf, &umt_properties, + THIS_MODULE, NULL, adapter_nr)) return 0; return -EINVAL; } diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index e553c139ac4..986fff9a5ba 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug; module_param_named(debug,dvb_usb_vp702x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + struct vp702x_state { int pid_filter_count; int pid_filter_can_bypass; @@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties; static int vp702x_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &vp702x_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id vp702x_usb_table [] = { diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index c172babf59b..acb345504e0 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -18,6 +18,9 @@ static int dvb_usb_vp7045_debug; module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) @@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties; static int vp7045_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL); + return dvb_usb_device_init(intf, &vp7045_properties, + THIS_MODULE, NULL, adapter_nr); } static struct usb_device_id vp7045_usb_table [] = { diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 08a2599ed74..960ed5763ae 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -39,6 +39,8 @@ #include "dvbdev.h" #include "tda1004x.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define DRIVER_NAME "pluto2" #define REG_PIDn(n) ((n) << 2) /* PID n pattern registers */ @@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, goto err_pluto_hw_exit; /* dvb */ - ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev); + ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, + THIS_MODULE, &pdev->dev, adapter_nr); if (ret < 0) goto err_i2c_del_adapter; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 78919b9e14d..747e7f1a626 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: module_param(tv_standard, int, 0444); MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + static void restart_feeds(struct av7110 *av7110); static int av7110_num; @@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, goto err_kfree_0; ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, - THIS_MODULE, &dev->pci->dev); + THIS_MODULE, &dev->pci->dev, adapter_nr); if (ret < 0) goto err_put_firmware_1; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 06bbce42fcd..18cac4b12ab 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444); MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /**************************************************************************** * TT budget / WinTV Nova ****************************************************************************/ @@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, budget->buffer_width, budget->buffer_height); printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); - if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) { + ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, + owner, &budget->dev->pci->dev, adapter_nr); + if (ret < 0) return ret; - } /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 317eccbe5c6..46dc4a3fcb6 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -56,10 +56,11 @@ */ static int debug; - module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0) #define ISO_BUF_COUNT 4 @@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i mutex_unlock(&ttusb->semi2c); - if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) { + result = dvb_register_adapter(&ttusb->adapter, + "Technotrend/Hauppauge Nova-USB", + THIS_MODULE, &udev->dev, adapter_nr); + if (result < 0) { ttusb_free_iso_urbs(ttusb); kfree(ttusb); return result; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 95110c48331..42eee04daa5 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); module_param(enable_rc, int, 0644); MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk if (debug) printk #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB" @@ -1437,7 +1439,9 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) dprintk("%s\n", __func__); if ((result = dvb_register_adapter(&dec->adapter, - dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) { + dec->model_name, THIS_MODULE, + &dec->udev->dev, + adapter_nr)) < 0) { printk("%s: dvb_register_adapter failed: error %d\n", __func__, result); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 74baa28d16a..1a720abbd06 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -54,6 +54,8 @@ static unsigned int alt_tuner; module_param(alt_tuner, int, 0644); MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* ------------------------------------------------------------------ */ static int dvb_buf_setup(struct videobuf_queue *q, @@ -333,7 +335,7 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ return videobuf_dvb_register(&port->dvb, THIS_MODULE, port, - &dev->pci->dev); + &dev->pci->dev, adapter_nr); } int cx23885_dvb_register(struct cx23885_tsport *port) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index e83d9869e68..fda7334d934 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -58,6 +58,8 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(level,fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) @@ -862,7 +864,8 @@ static int dvb_register(struct cx8802_dev *dev) cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); + return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr); } /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e5c3569dd2c..73154c1a023 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -65,6 +65,8 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off)."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk(fmt, arg...) do { if (debug) \ printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0) @@ -1257,7 +1259,8 @@ static int dvb_init(struct saa7134_dev *dev) } /* register everything else */ - ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); + ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, + adapter_nr); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 4ba8b7db7fd..0f8542a4c71 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -138,14 +138,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) int videobuf_dvb_register(struct videobuf_dvb *dvb, struct module *module, void *adapter_priv, - struct device *device) + struct device *device, + short *adapter_nr) { int result; mutex_init(&dvb->lock); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device); + result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device, + adapter_nr); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", dvb->name, result); diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h index 8233cafdeef..b7774869632 100644 --- a/include/media/videobuf-dvb.h +++ b/include/media/videobuf-dvb.h @@ -27,7 +27,8 @@ struct videobuf_dvb { int videobuf_dvb_register(struct videobuf_dvb *dvb, struct module *module, void *adapter_priv, - struct device *device); + struct device *device, + short *adapter_nr); void videobuf_dvb_unregister(struct videobuf_dvb *dvb); /* -- cgit v1.2.3-70-g09d2 From a9dbbeb7d615761a82fcd4f00ec290a07be7d8a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 14:59:29 -0300 Subject: V4L/DVB (7554): videobuf-dma-sg: Remove unused flag Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 4 ---- include/media/videobuf-dma-sg.h | 3 --- 2 files changed, 7 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 440c1a8e9c1..c0b7902862e 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -162,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", data,size,dma->nr_pages); - dma->varea = (void *) data; - - err = get_user_pages(current,current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ @@ -300,7 +297,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) vfree(dma->vmalloc); dma->vmalloc = NULL; - dma->varea = NULL; if (dma->bus_addr) { dma->bus_addr = 0; diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index b6ab08045de..be8da269ee3 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -68,9 +68,6 @@ struct videobuf_dmabuf { /* for kernel buffers */ void *vmalloc; - /* Stores the userspace pointer to vmalloc area */ - void *varea; - /* for overlay buffers (pci-pci dma) */ dma_addr_t bus_addr; -- cgit v1.2.3-70-g09d2 From 59d3448995a4c0ca98cbe82f6dac9460323377c1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Apr 2008 15:10:00 -0300 Subject: V4L/DVB (7566): videobuf-dvb: allow its usage with videobuf-vmalloc videobuf-dvb were still using a function that were videobuf-dma-sg dependent. This patch creates a generic handler for this function. This way, videobuf-dvb can now work with all videobuf implementations. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 7 +++++++ drivers/media/video/videobuf-dma-sg.c | 11 +++++++++++ drivers/media/video/videobuf-dvb.c | 10 ++++++---- drivers/media/video/videobuf-vmalloc.c | 1 + include/media/videobuf-core.h | 18 ++++++++++-------- include/media/videobuf-vmalloc.h | 4 ++++ 6 files changed, 39 insertions(+), 12 deletions(-) (limited to 'include/media') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 848a2d0e123..fc51e4918bb 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -94,6 +94,13 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, return CALL(q, iolock, q, vb, fbuf); } +void *videobuf_queue_to_vmalloc (struct videobuf_queue *q, + struct videobuf_buffer *buf) +{ + return CALL(q, vmalloc, buf); +} +EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); + /* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index c0b7902862e..03a7b946bd5 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -432,6 +432,16 @@ static void *__videobuf_alloc(size_t size) return vb; } +static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) +{ + struct videobuf_dma_sg_memory *mem = buf->priv; + BUG_ON(!mem); + + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); + + return mem->dma.vmalloc; +} + static int __videobuf_iolock (struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) @@ -677,6 +687,7 @@ static struct videobuf_qtype_ops sg_ops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, + .vmalloc = __videobuf_to_vmalloc, }; void *videobuf_sg_alloc(size_t size) diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0f8542a4c71..6e4d73ec685 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -20,9 +20,10 @@ #include #include #include + #include -#include +#include #include /* ------------------------------------------------------------------ */ @@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data) struct videobuf_buffer *buf; unsigned long flags; int err; - struct videobuf_dmabuf *dma; + void *outp; dprintk("dvb thread started\n"); set_freezable(); @@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data) try_to_freeze(); /* feed buffer data to demux */ - dma=videobuf_to_dma(buf); + outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf); + if (buf->state == VIDEOBUF_DONE) - dvb_dmx_swfilter(&dvb->demux, dma->vmalloc, + dvb_dmx_swfilter(&dvb->demux, outp, buf->size); /* requeue buffer */ diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index d68d0273807..c91e1d8e380 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -387,6 +387,7 @@ static struct videobuf_qtype_ops qops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, + .vmalloc = videobuf_to_vmalloc, }; void videobuf_queue_vmalloc_init(struct videobuf_queue* q, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 377a6c6e931..5b39a22533f 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -13,6 +13,9 @@ * the Free Software Foundation; either version 2 */ +#ifndef _VIDEOBUF_CORE_H +#define _VIDEOBUF_CORE_H + #include #ifdef CONFIG_VIDEO_V4L1_COMPAT #include @@ -123,7 +126,8 @@ struct videobuf_queue_ops { struct videobuf_qtype_ops { u32 magic; - void* (*alloc) (size_t size); + void *(*alloc) (size_t size); + void *(*vmalloc) (struct videobuf_buffer *buf); int (*iolock) (struct videobuf_queue* q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); @@ -185,6 +189,10 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, void *videobuf_alloc(struct videobuf_queue* q); +/* Used on videobuf-dvb */ +void *videobuf_queue_to_vmalloc (struct videobuf_queue* q, + struct videobuf_buffer *buf); + void videobuf_queue_core_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, struct device *dev, @@ -233,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q); int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma); -/* --------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index ec63ab0fab9..aed39460c15 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -12,6 +12,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 */ +#ifndef _VIDEOBUF_VMALLOC_H +#define _VIDEOBUF_VMALLOC_H #include @@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, void *videobuf_to_vmalloc (struct videobuf_buffer *buf); void videobuf_vmalloc_free (struct videobuf_buffer *buf); + +#endif -- cgit v1.2.3-70-g09d2 From 130ca945d83637046bde4943629f011e22831fd3 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 10 Apr 2008 01:18:56 -0300 Subject: V4L/DVB (7665): videodev: Add default vidioc handler Added default vidioc handler for other private ioctls Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videodev.c | 7 +++++++ include/media/v4l2-dev.h | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'include/media') diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index effcd2ae415..31e8af0ba27 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1861,6 +1861,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } + default: + { + if (!vfd->vidioc_default) + break; + ret = vfd->vidioc_default(file, fh, cmd, arg); + break; + } } /* switch */ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index f2114459995..a807d2f86ee 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -318,6 +318,10 @@ struct video_device int (*vidioc_g_chip_ident) (struct file *file, void *fh, struct v4l2_chip_ident *chip); + /* For other private ioctls */ + int (*vidioc_default) (struct file *file, void *fh, + int cmd, void *arg); + #ifdef OBSOLETE_OWNER /* to be removed soon */ /* obsolete -- fops->owner is used instead */ -- cgit v1.2.3-70-g09d2 From b34dddbe4b88bf59e7607d1fc504eee43570c6a4 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Wed, 23 Apr 2008 14:09:08 -0300 Subject: V4L/DVB (7677): saa7134: Add/fix Beholder entries Beholder TV/FM tuners: Changes: Add support Beholder Columbus PCMCIA card. Add key map for remote control of Beholder Columbus PCMCIA card. Fix gpiomask for all Beholder tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 4 +- drivers/media/common/ir-keymaps.c | 70 +++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 80 ++++++++++++++++++++++++++--- drivers/media/video/saa7134/saa7134-input.c | 13 ++++- include/media/ir-common.h | 1 + 5 files changed, 157 insertions(+), 11 deletions(-) (limited to 'include/media') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index fe925b335c9..44d84dd15ad 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -25,8 +25,8 @@ 24 -> KNC One TV-Station DVR [1894:a006] 25 -> ASUS TV-FM 7133 [1043:4843] 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b] - 27 -> Manli MuchTV M-TV002/Behold TV 403 FM - 28 -> Manli MuchTV M-TV001/Behold TV 401 + 27 -> Manli MuchTV M-TV002 + 28 -> Manli MuchTV M-TV001 29 -> Nagase Sangyo TransGear 3000TV [1461:050c] 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4] 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 65f810cde60..a3485817e46 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2043,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_behold); +/* Beholder Intl. Ltd. 2008 + * Dmitry Belimov d.belimov@google.com + * Keytable is used by BeholdTV Columbus + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { + + /* 0x13 0x11 0x1C 0x12 * + * Mute Source TV/FM Power * + * */ + + [0x13] = KEY_MUTE, + [0x11] = KEY_PROPS, + [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ + [0x12] = KEY_POWER, + + /* 0x01 0x02 0x03 0x0D * + * 1 2 3 Stereo * + * * + * 0x04 0x05 0x06 0x19 * + * 4 5 6 Snapshot * + * * + * 0x07 0x08 0x09 0x10 * + * 7 8 9 Zoom * + * */ + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x0D] = KEY_SETUP, /* Setup key */ + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x10] = KEY_ZOOM, + + /* 0x0A 0x00 0x0B 0x0C * + * RECALL 0 ChannelUp VolumeUp * + * */ + [0x0A] = KEY_AGAIN, + [0x00] = KEY_0, + [0x0B] = KEY_CHANNELUP, + [0x0C] = KEY_VOLUMEUP, + + /* 0x1B 0x1D 0x15 0x18 * + * Timeshift Record ChannelDown VolumeDown * + * */ + + [0x1B] = KEY_REWIND, + [0x1D] = KEY_RECORD, + [0x15] = KEY_CHANNELDOWN, + [0x18] = KEY_VOLUMEDOWN, + + /* 0x0E 0x1E 0x0F 0x1A * + * Stop Pause Previouse Next * + * */ + + [0x0E] = KEY_STOP, + [0x1E] = KEY_PAUSE, + [0x0F] = KEY_PREVIOUS, + [0x1A] = KEY_NEXT, + +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_columbus); + /* * Remote control for the Genius TVGO A11MCE * Adrian Pardini diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 82fe19c3b1d..98375955a84 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -30,6 +30,7 @@ #include "tuner-xc2028.h" #include #include +#include "tea5767.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -1049,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV002] = { /* Ognjen Nastic */ - .name = "Manli MuchTV M-TV002/Behold TV 403 FM", + .name = "Manli MuchTV M-TV002", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -1076,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV001] = { /* Ognjen Nastic UNTESTED */ - .name = "Manli MuchTV M-TV001/Behold TV 401", + .name = "Manli MuchTV M-TV001", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -2198,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_409FM] = { /* , Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -2205,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3576,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_401] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 401", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3602,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_403] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3624,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_403FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3650,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_405] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3657,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3674,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_405FM] = { /* Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3681,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3701,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_407] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3708,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3728,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_407FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3735,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3760,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3767,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3783,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_505FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 505 FM/RDS", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3790,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3814,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_507_9FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3821,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3841,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV Columbus TVFM", .audio_clock = 0x00187de7, .tuner_type = TUNER_ALPS_TSBE5_PAL, @@ -3848,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x000A8004, .inputs = {{ .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, - },{ + .gpio = 0x000A8004, + }, { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ + .gpio = 0x000A8000, + }, { .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, + .gpio = 0x000A8000, + } }, .radio = { .name = name_radio, .amux = LINE2, + .gpio = 0x000A8000, }, }, [SAA7134_BOARD_BEHOLD_607_9FM] = { @@ -5471,7 +5510,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_CARDBUS: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: case SAA7134_BOARD_AVERMEDIA_M115: - case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: case SAA7134_BOARD_AVERMEDIA_A16D: /* power-down tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); @@ -5482,6 +5520,18 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(10); break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0); + msleep(10); + /* power-up tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004); + msleep(10); + /* remote via GPIO */ + dev->has_remote = SAA7134_REMOTE_GPIO; + break; case SAA7134_BOARD_RTD_VFG7350: /* @@ -5770,6 +5820,20 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + { + struct v4l2_priv_tun_config tea5767_cfg; + struct tea5767_ctrl ctl; + + dev->i2c_client.addr = 0xC0; + /* set TEA5767(analog FM) defines */ + memset(&ctl, 0, sizeof(ctl)); + ctl.xtal_freq = TEA5767_HIGH_LO_13MHz; + tea5767_cfg.tuner = TUNER_TEA5767; + tea5767_cfg.priv = &ctl; + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg); + } + break; } if (dev->tuner_type == TUNER_XC2028) { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 65f8e594d6f..767ff30832f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: + ir_codes = ir_codes_manli; + mask_keycode = 0x001f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_BEHOLD_401: case SAA7134_BOARD_BEHOLD_403: @@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: ir_codes = ir_codes_manli; - mask_keycode = 0x001f00; + mask_keycode = 0x003f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + ir_codes = ir_codes_behold_columbus; + mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 75a3482866f..bfee8be5d63 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; -- cgit v1.2.3-70-g09d2