V4L: omap camera builds again
[pandora-kernel.git] / drivers / media / video / omap / camera_core.c
index 66ccd80..ab91cc1 100644 (file)
  * History:
  *   27/03/05   Vladimir Barinov - Added support for power management
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ctype.h>
-#include <linux/pagemap.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/videodev.h>
-#include <linux/pci.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
 #include <linux/dma-mapping.h>
 #include <linux/fb.h>
 
+#include <media/v4l2-common.h>
+
 #include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
 
 #include "sensor_if.h"
 #include "camera_hw_if.h"
 #include "camera_core.h"
-struct camera_device *camera_dev;
-extern struct camera_sensor camera_sensor_if;
-extern struct camera_hardware camera_hardware_if;
+
+
+static struct camera_device *camera_dev;
 static void camera_core_sgdma_process(struct camera_device *cam);
 
 /* module parameters */
@@ -323,7 +307,7 @@ static void
 camera_core_vbq_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
        videobuf_waiton(vb, 0, 0);
-       videobuf_dma_pci_unmap(NULL, &vb->dma);
+       videobuf_dma_unmap(q, &vb->dma);
        videobuf_dma_free(&vb->dma);
 
        vb->state = STATE_NEEDS_INIT;
@@ -373,7 +357,7 @@ camera_core_vbq_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
        spin_unlock(&cam->img_lock);
 
        if (vb->state == STATE_NEEDS_INIT)
-               err = videobuf_iolock(NULL, vb, NULL);
+               err = videobuf_iolock(q, vb, NULL);
 
        if (!err)
                vb->state = STATE_PREPARED;
@@ -913,48 +897,40 @@ camera_core_open(struct inode *inode, struct file *file)
 }
 
 #ifdef CONFIG_PM
-static int camera_core_suspend(struct device *dev, u32 state, u32 level)
+static int camera_core_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct camera_device *cam = dev_get_drvdata(dev);
+       struct camera_device *cam = platform_get_drvdata(pdev);
        int ret = 0;
 
        spin_lock(&cam->img_lock);
-       switch (level) {
-       case SUSPEND_POWER_DOWN:
-               if (cam->active) {
-                       cam->cam_hardware->close(cam->hardware_data);
-               }
-               cam->cam_sensor->power_off(cam->sensor_data);
-               break;
+       if (cam->active) {
+               cam->cam_hardware->close(cam->hardware_data);
        }
-
+       cam->cam_sensor->power_off(cam->sensor_data);
        spin_unlock(&cam->img_lock);
+
        return ret;
 }
 
-static int camera_core_resume(struct device *dev, u32 level)
+static int camera_core_resume(struct platform_device *pdev)
 {
-       struct camera_device *cam = dev_get_drvdata(dev);
+       struct camera_device *cam = platform_get_drvdata(pdev);
        int ret = 0;
 
        spin_lock(&cam->img_lock);
-       switch (level) {
-       case RESUME_POWER_ON:
-               cam->cam_sensor->power_on(cam->sensor_data);
-               if (cam->active) {
-                       cam->capture_completed = 1;
-                       cam->cam_hardware->open(cam->hardware_data);
-                       cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
-
-                       cam->cam_sensor->configure(&cam->pix, cam->xclk,
-                               &cam->cparm.timeperframe, cam->sensor_data);
-
-                       camera_core_sgdma_process(cam);
-               }
-               break;
-       }
+       cam->cam_sensor->power_on(cam->sensor_data);
+       if (cam->active) {
+               cam->capture_completed = 1;
+               cam->cam_hardware->open(cam->hardware_data);
+               cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
 
+               cam->cam_sensor->configure(&cam->pix, cam->xclk,
+                                          &cam->cparm.timeperframe,
+                                          cam->sensor_data);
+               camera_core_sgdma_process(cam);
+       }
        spin_unlock(&cam->img_lock);
+       
        return ret;
 }
 #endif /* CONFIG_PM */
@@ -971,91 +947,29 @@ static struct file_operations camera_core_fops =
        .release                = camera_core_release,
 };
 
-static struct device_driver camera_core_driver = {
-       .name                   = CAM_NAME,
-       .bus                    = &platform_bus_type,
-       .probe                  = NULL,
-       .remove                 = NULL,
-#ifdef CONFIG_PM
-       .suspend                = camera_core_suspend,
-       .resume                 = camera_core_resume,
-#endif
-       .shutdown               = NULL,
-};
-
-static struct platform_device camera_core_device = {
-       .name   = CAM_NAME,
-       .dev    = {
-                       .release        = NULL,
-                 },
-       .id     = 0,
-};
-
-void
-camera_core_cleanup(void)
-{
-       struct camera_device *cam = camera_dev;
-       struct video_device *vfd;
-
-       if (!cam)
-               return;
-
-       vfd = cam->vfd;
-       if (vfd) {
-               if (vfd->minor == -1) {
-                       /* The device never got registered, so release the 
-                       ** video_device struct directly
-                       */
-                       video_device_release(vfd);
-               } else {
-                       /* The unregister function will release the video_device
-                       ** struct as well as unregistering it.
-                       */
-                       video_unregister_device(vfd);
-                       driver_unregister(&camera_core_driver);
-                       platform_device_unregister(&camera_core_device);
-               }
-               cam->vfd = NULL;
-       }
-       if (cam->overlay_base) {
-               dma_free_coherent(NULL, cam->overlay_size,
-                                       (void *)cam->overlay_base, 
-                                       cam->overlay_base_phys);
-               cam->overlay_base = 0;
-       }       
-       cam->overlay_base_phys = 0;
-
-       cam->cam_sensor->cleanup(cam->sensor_data);
-       cam->cam_hardware->cleanup(cam->hardware_data);
-       kfree(cam);
-       camera_dev = NULL;
-
-       return;
-}
-
-
-int __init 
-camera_core_init(void)
+static int __init camera_core_probe(struct platform_device *pdev)
 {
        struct camera_device *cam;
        struct video_device *vfd;
+       int     status;
 
-       cam = kmalloc(sizeof(struct camera_device), GFP_KERNEL);
+       cam = kzalloc(sizeof(struct camera_device), GFP_KERNEL);
        if (!cam) {
                printk(KERN_ERR CAM_NAME ": could not allocate memory\n");
-               goto init_error;
+               status = -ENOMEM;
+               goto err0;
        }
-       memset(cam, 0, sizeof(struct camera_device));
-       
+
        /* Save the pointer to camera device in a global variable */
        camera_dev = cam;
-
+       
        /* initialize the video_device struct */
        vfd = cam->vfd = video_device_alloc();
        if (!vfd) {
                printk(KERN_ERR CAM_NAME 
                        ": could not allocate video device struct\n");
-               goto init_error;
+               status = -ENOMEM;
+               goto err1;
        }
        
        vfd->release = video_device_release;
@@ -1086,7 +1000,8 @@ camera_core_init(void)
                if (!cam->overlay_base) {
                        printk(KERN_ERR CAM_NAME
                                ": cannot allocate overlay framebuffer\n");
-                       goto init_error;
+                       status = -ENOMEM;
+                       goto err2;
                }
        }
        memset((void*)cam->overlay_base, 0, cam->overlay_size);
@@ -1101,7 +1016,8 @@ camera_core_init(void)
        cam->hardware_data = cam->cam_hardware->init();
        if (!cam->hardware_data) {
                printk(KERN_ERR CAM_NAME ": cannot initialize interface hardware\n");
-               goto init_error;
+               status = -ENODEV;
+               goto err3;
        }
         
        /* initialize the spinlock used to serialize access to the image 
@@ -1125,7 +1041,8 @@ camera_core_init(void)
        if (!cam->sensor_data) {
                cam->cam_hardware->disable(cam->hardware_data);
                printk(KERN_ERR CAM_NAME ": cannot initialize sensor\n");
-               goto init_error;
+               status = -ENODEV;
+               goto err4;
        }
 
        printk(KERN_INFO CAM_NAME ": %s interface with %s sensor\n",
@@ -1150,40 +1067,120 @@ camera_core_init(void)
 
        /* Disable the Camera after detection */
        cam->cam_hardware->disable(cam->hardware_data);
-
-       dev_set_drvdata(&camera_core_device.dev, (void *)cam);
-       if (platform_device_register(&camera_core_device) < 0) {
-               printk(KERN_ERR CAM_NAME
-                       ": could not register platform_device\n");
-               goto init_error;
-       }
-
-       if (driver_register(&camera_core_driver) < 0) {
-               printk(KERN_ERR CAM_NAME
-                       ": could not register driver\n");
-               platform_device_unregister(&camera_core_device);
-               goto init_error;
-       }
+       
+       platform_set_drvdata(pdev, cam);
+       
        if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) {
                printk(KERN_ERR CAM_NAME 
                        ": could not register Video for Linux device\n");
-               platform_device_unregister(&camera_core_device);
-               driver_unregister(&camera_core_driver);
-               goto init_error;
+               status = -ENODEV;
+               goto err5;
        }
 
        printk(KERN_INFO CAM_NAME 
-               ": registered device video%d [v4l2]\n", vfd->minor);
+              ": registered device video%d [v4l2]\n", vfd->minor);
+
+       return 0;
+
+ err5:
+       cam->cam_sensor->cleanup(cam->sensor_data);
+ err4:
+       cam->cam_hardware->cleanup(cam->hardware_data);
+ err3:
+       dma_free_coherent(NULL, cam->overlay_size,
+                               (void *)cam->overlay_base, 
+                               cam->overlay_base_phys);
+       cam->overlay_base = 0;
+ err2:
+       video_device_release(vfd);
+ err1:
+       kfree(cam);
+       camera_dev = NULL;
+ err0:
+       return status;
+}
+
+static int camera_core_remove(struct platform_device *pdev)
+{
+       struct camera_device *cam = platform_get_drvdata(pdev);
+       struct video_device *vfd;
+
+       vfd = cam->vfd;
+       if (vfd) {
+               if (vfd->minor == -1) {
+                       /* The device never got registered, so release the 
+                       ** video_device struct directly
+                       */
+                       video_device_release(vfd);
+               } else {
+                       /* The unregister function will release the video_device
+                       ** struct as well as unregistering it.
+                       */
+                       video_unregister_device(vfd);
+               }
+               cam->vfd = NULL;
+       }
+       if (cam->overlay_base) {
+               dma_free_coherent(NULL, cam->overlay_size,
+                                       (void *)cam->overlay_base, 
+                                       cam->overlay_base_phys);
+               cam->overlay_base = 0;
+       }       
+       cam->overlay_base_phys = 0;
+
+       cam->cam_sensor->cleanup(cam->sensor_data);
+       cam->cam_hardware->cleanup(cam->hardware_data);
+       kfree(cam);
+       camera_dev = NULL;
+
        return 0;
+}
+
+static struct platform_driver camera_core_driver = {
+       .driver = {
+               .name           = CAM_NAME,
+               .owner          = THIS_MODULE,
+       },
+       .probe                  = camera_core_probe,
+       .remove                 = camera_core_remove,
+#ifdef CONFIG_PM
+       .suspend                = camera_core_suspend,
+       .resume                 = camera_core_resume,
+#endif
+};
 
-init_error:
-       camera_core_cleanup();
-       return -ENODEV;
+/* FIXME register omap16xx or omap24xx camera device in arch/arm/...
+ * system init code, with its resources and mux setup, NOT here.
+ * Then MODULE_ALIAS(CAM_NAME) so it hotplugs and coldplugs; this
+ * "legacy" driver style is trouble.
+ */
+static struct platform_device *cam;
+
+static void __exit
+camera_core_cleanup(void)
+{
+       platform_driver_unregister(&camera_core_driver);
+       platform_device_unregister(cam);
+}
+
+static char banner[] __initdata = KERN_INFO "OMAP Camera driver initialzing\n";
+
+static int __init
+camera_core_init(void)
+{
+
+       printk(banner);
+       platform_driver_register(&camera_core_driver);
+
+       cam = platform_device_register_simple(CAM_NAME, -1, NULL, 0);
+
+       return 0;
 }
 
 MODULE_AUTHOR("Texas Instruments.");
 MODULE_DESCRIPTION("OMAP Video for Linux camera driver");
 MODULE_LICENSE("GPL");
+
 module_param(video_nr, int, 0);
 MODULE_PARM_DESC(video_nr, 
                "Minor number for video device (-1 ==> auto assign)");
@@ -1194,4 +1191,3 @@ MODULE_PARM_DESC(capture_mem,
 module_init(camera_core_init);
 module_exit(camera_core_cleanup);
 
-