* - Support for control ioctls
*/
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
-#include <linux/version.h>
#include <media/v4l2-common.h>
#include <linux/io.h>
#include <media/davinci/vpfe_capture.h>
int vpfe_probed;
/* name of ccdc device */
char name[32];
- /* for storing mem maps for CCDC */
- int ccdc_addr_size;
- void *__iomem ccdc_addr;
};
/* data structures */
BUG_ON(!dev->hw_ops.set_image_window);
BUG_ON(!dev->hw_ops.get_image_window);
BUG_ON(!dev->hw_ops.get_line_length);
- BUG_ON(!dev->hw_ops.setfbaddr);
BUG_ON(!dev->hw_ops.getfid);
mutex_lock(&ccdc_lock);
* walk through it during vpfe probe
*/
printk(KERN_ERR "vpfe capture not initialized\n");
- ret = -1;
+ ret = -EFAULT;
goto unlock;
}
if (strcmp(dev->name, ccdc_cfg->name)) {
/* ignore this ccdc */
- ret = -1;
+ ret = -EINVAL;
goto unlock;
}
if (ccdc_dev) {
printk(KERN_ERR "ccdc already registered\n");
- ret = -1;
+ ret = -EINVAL;
goto unlock;
}
ccdc_dev = dev;
- dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr,
- ccdc_cfg->ccdc_addr_size);
unlock:
mutex_unlock(&ccdc_lock);
return ret;
frame_format = ccdc_dev->hw_ops.get_frame_format();
if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
- free_irq(IRQ_VDINT1, vpfe_dev);
+ free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
}
static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
buf, file->f_flags & O_NONBLOCK);
}
+static int vpfe_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qctrl)
+{
+ struct vpfe_device *vpfe_dev = video_drvdata(file);
+ struct vpfe_subdev_info *sdinfo;
+
+ sdinfo = vpfe_dev->current_subdev;
+
+ return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+ core, queryctrl, qctrl);
+
+}
+
+static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
+{
+ struct vpfe_device *vpfe_dev = video_drvdata(file);
+ struct vpfe_subdev_info *sdinfo;
+
+ sdinfo = vpfe_dev->current_subdev;
+
+ return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+ core, g_ctrl, ctrl);
+}
+
+static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
+{
+ struct vpfe_device *vpfe_dev = video_drvdata(file);
+ struct vpfe_subdev_info *sdinfo;
+
+ sdinfo = vpfe_dev->current_subdev;
+
+ return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
+ core, s_ctrl, ctrl);
+}
+
/*
* vpfe_calculate_offsets : This function calculates buffers offset
* for top and bottom field
.vidioc_querystd = vpfe_querystd,
.vidioc_s_std = vpfe_s_std,
.vidioc_g_std = vpfe_g_std,
+ .vidioc_queryctrl = vpfe_queryctrl,
+ .vidioc_g_ctrl = vpfe_g_ctrl,
+ .vidioc_s_ctrl = vpfe_s_ctrl,
.vidioc_reqbufs = vpfe_reqbufs,
.vidioc_querybuf = vpfe_querybuf,
.vidioc_qbuf = vpfe_qbuf,
return vpfe_dev;
}
-static void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
-{
- struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
-
- clk_disable(vpfe_cfg->vpssclk);
- clk_put(vpfe_cfg->vpssclk);
- clk_disable(vpfe_cfg->slaveclk);
- clk_put(vpfe_cfg->slaveclk);
- v4l2_info(vpfe_dev->pdev->driver,
- "vpfe vpss master & slave clocks disabled\n");
-}
-
-static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
-{
- struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
- int ret = -ENOENT;
-
- vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master");
- if (NULL == vpfe_cfg->vpssclk) {
- v4l2_err(vpfe_dev->pdev->driver, "No clock defined for"
- "vpss_master\n");
- return ret;
- }
-
- if (clk_enable(vpfe_cfg->vpssclk)) {
- v4l2_err(vpfe_dev->pdev->driver,
- "vpfe vpss master clock not enabled\n");
- goto out;
- }
- v4l2_info(vpfe_dev->pdev->driver,
- "vpfe vpss master clock enabled\n");
-
- vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave");
- if (NULL == vpfe_cfg->slaveclk) {
- v4l2_err(vpfe_dev->pdev->driver,
- "No clock defined for vpss slave\n");
- goto out;
- }
-
- if (clk_enable(vpfe_cfg->slaveclk)) {
- v4l2_err(vpfe_dev->pdev->driver,
- "vpfe vpss slave clock not enabled\n");
- goto out;
- }
- v4l2_info(vpfe_dev->pdev->driver, "vpfe vpss slave clock enabled\n");
- return 0;
-out:
- if (vpfe_cfg->vpssclk)
- clk_put(vpfe_cfg->vpssclk);
- if (vpfe_cfg->slaveclk)
- clk_put(vpfe_cfg->slaveclk);
-
- return -1;
-}
-
/*
* vpfe_probe : This function creates device entries by register
* itself to the V4L2 driver and initializes fields of each
if (NULL == pdev->dev.platform_data) {
v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
- ret = -ENOENT;
+ ret = -ENODEV;
goto probe_free_dev_mem;
}
goto probe_free_dev_mem;
}
- /* enable vpss clocks */
- ret = vpfe_enable_clock(vpfe_dev);
- if (ret)
- goto probe_free_dev_mem;
-
mutex_lock(&ccdc_lock);
/* Allocate memory for ccdc configuration */
ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
if (NULL == ccdc_cfg) {
v4l2_err(pdev->dev.driver,
"Memory allocation failed for ccdc_cfg\n");
- goto probe_disable_clock;
+ goto probe_free_dev_mem;
}
strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
if (!res1) {
v4l2_err(pdev->dev.driver,
"Unable to get interrupt for VINT0\n");
- ret = -ENOENT;
- goto probe_disable_clock;
+ ret = -ENODEV;
+ goto probe_free_ccdc_cfg_mem;
}
vpfe_dev->ccdc_irq0 = res1->start;
/* Get VINT1 irq resource */
- res1 = platform_get_resource(pdev,
- IORESOURCE_IRQ, 1);
+ res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (!res1) {
v4l2_err(pdev->dev.driver,
"Unable to get interrupt for VINT1\n");
- ret = -ENOENT;
- goto probe_disable_clock;
+ ret = -ENODEV;
+ goto probe_free_ccdc_cfg_mem;
}
vpfe_dev->ccdc_irq1 = res1->start;
- /* Get address base of CCDC */
- res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res1) {
- v4l2_err(pdev->dev.driver,
- "Unable to get register address map\n");
- ret = -ENOENT;
- goto probe_disable_clock;
- }
-
- ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1;
- if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size,
- pdev->dev.driver->name)) {
- v4l2_err(pdev->dev.driver,
- "Failed request_mem_region for ccdc base\n");
- ret = -ENXIO;
- goto probe_disable_clock;
- }
- ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start,
- ccdc_cfg->ccdc_addr_size);
- if (!ccdc_cfg->ccdc_addr) {
- v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n");
- ret = -ENXIO;
- goto probe_out_release_mem1;
- }
-
ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
"vpfe_capture0", vpfe_dev);
if (0 != ret) {
v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");
- goto probe_out_unmap1;
+ goto probe_free_ccdc_cfg_mem;
}
/* Allocate memory for video device */
vfd = video_device_alloc();
if (NULL == vfd) {
ret = -ENOMEM;
- v4l2_err(pdev->dev.driver,
- "Unable to alloc video device\n");
+ v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");
goto probe_out_release_irq;
}
vfd->release = video_device_release;
vfd->fops = &vpfe_fops;
vfd->ioctl_ops = &vpfe_ioctl_ops;
- vfd->minor = -1;
vfd->tvnorms = 0;
vfd->current_norm = V4L2_STD_PAL;
vfd->v4l2_dev = &vpfe_dev->v4l2_dev;
platform_set_drvdata(pdev, vpfe_dev);
/* set driver private data */
video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
- i2c_adap = i2c_get_adapter(1);
- vpfe_cfg = pdev->dev.platform_data;
+ i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);
num_subdevs = vpfe_cfg->num_subdevs;
vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
GFP_KERNEL);
probe_out_v4l2_unregister:
v4l2_device_unregister(&vpfe_dev->v4l2_dev);
probe_out_video_release:
- if (vpfe_dev->video_dev->minor == -1)
+ if (!video_is_registered(vpfe_dev->video_dev))
video_device_release(vpfe_dev->video_dev);
probe_out_release_irq:
free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
-probe_out_unmap1:
- iounmap(ccdc_cfg->ccdc_addr);
-probe_out_release_mem1:
- release_mem_region(res1->start, res1->end - res1->start + 1);
-probe_disable_clock:
- vpfe_disable_clock(vpfe_dev);
+probe_free_ccdc_cfg_mem:
mutex_unlock(&ccdc_lock);
kfree(ccdc_cfg);
probe_free_dev_mem:
/*
* vpfe_remove : It un-register device from V4L2 driver
*/
-static int vpfe_remove(struct platform_device *pdev)
+static int __devexit vpfe_remove(struct platform_device *pdev)
{
struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
- struct resource *res;
v4l2_info(pdev->dev.driver, "vpfe_remove\n");
kfree(vpfe_dev->sd);
v4l2_device_unregister(&vpfe_dev->v4l2_dev);
video_unregister_device(vpfe_dev->video_dev);
- mutex_lock(&ccdc_lock);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res->end - res->start + 1);
- iounmap(ccdc_cfg->ccdc_addr);
- mutex_unlock(&ccdc_lock);
- vpfe_disable_clock(vpfe_dev);
kfree(vpfe_dev);
kfree(ccdc_cfg);
return 0;
return -1;
}
-static struct dev_pm_ops vpfe_dev_pm_ops = {
+static const struct dev_pm_ops vpfe_dev_pm_ops = {
.suspend = vpfe_suspend,
.resume = vpfe_resume,
};