upstream: [media] V4L2: em28xx: register a V4L2 clock source
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Wed, 28 Aug 2013 13:28:28 +0000 (10:28 -0300)
committerChanho Park <chanho61.park@samsung.com>
Thu, 7 Aug 2014 05:26:42 +0000 (14:26 +0900)
Camera sensors usually require a master clock for data sampling. This patch
registers such a clock source for em28xx cameras. This fixes the currently
broken em28xx ov2640 camera support and can also be used by other camera
sensors.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/usb/em28xx/em28xx-camera.c
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx.h

index 0a94765..3abeac2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <media/soc_camera.h>
 #include <media/mt9v011.h>
+#include <media/v4l2-clk.h>
 #include <media/v4l2-common.h>
 
 #include "em28xx.h"
@@ -325,13 +326,24 @@ int em28xx_detect_sensor(struct em28xx *dev)
 
 int em28xx_init_camera(struct em28xx *dev)
 {
+       char clk_name[V4L2_SUBDEV_NAME_SIZE];
+       struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
+       struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
+       int ret = 0;
+
+       v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
+                         i2c_adapter_id(adap), client->addr);
+       dev->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL);
+       if (IS_ERR(dev->clk))
+               return PTR_ERR(dev->clk);
+
        switch (dev->em28xx_sensor) {
        case EM28XX_MT9V011:
        {
                struct mt9v011_platform_data pdata;
                struct i2c_board_info mt9v011_info = {
                        .type = "mt9v011",
-                       .addr = dev->i2c_client[dev->def_i2c_bus].addr,
+                       .addr = client->addr,
                        .platform_data = &pdata,
                };
 
@@ -352,10 +364,11 @@ int em28xx_init_camera(struct em28xx *dev)
                dev->sensor_xtal = 4300000;
                pdata.xtal = dev->sensor_xtal;
                if (NULL ==
-                   v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
-                                             &dev->i2c_adap[dev->def_i2c_bus],
-                                             &mt9v011_info, NULL))
-                       return -ENODEV;
+                   v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap,
+                                             &mt9v011_info, NULL)) {
+                       ret = -ENODEV;
+                       break;
+               }
                /* probably means GRGB 16 bit bayer */
                dev->vinmode = 0x0d;
                dev->vinctl = 0x00;
@@ -391,7 +404,7 @@ int em28xx_init_camera(struct em28xx *dev)
                struct i2c_board_info ov2640_info = {
                        .type = "ov2640",
                        .flags = I2C_CLIENT_SCCB,
-                       .addr = dev->i2c_client[dev->def_i2c_bus].addr,
+                       .addr = client->addr,
                        .platform_data = &camlink,
                };
                struct v4l2_mbus_framefmt fmt;
@@ -408,9 +421,12 @@ int em28xx_init_camera(struct em28xx *dev)
                dev->sensor_yres = 480;
 
                subdev =
-                    v4l2_i2c_new_subdev_board(&dev->v4l2_dev,
-                                              &dev->i2c_adap[dev->def_i2c_bus],
+                    v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap,
                                               &ov2640_info, NULL);
+               if (NULL == subdev) {
+                       ret = -ENODEV;
+                       break;
+               }
 
                fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
                fmt.width = 640;
@@ -427,9 +443,14 @@ int em28xx_init_camera(struct em28xx *dev)
        }
        case EM28XX_NOSENSOR:
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
-       return 0;
+       if (ret < 0) {
+               v4l2_clk_unregister_fixed(dev->clk);
+               dev->clk = NULL;
+       }
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(em28xx_init_camera);
index d9b874e..506d1fc 100644 (file)
@@ -36,6 +36,7 @@
 #include <media/tvaudio.h>
 #include <media/i2c-addr.h>
 #include <media/tveeprom.h>
+#include <media/v4l2-clk.h>
 #include <media/v4l2-common.h>
 
 #include "em28xx.h"
@@ -2850,6 +2851,8 @@ void em28xx_release_resources(struct em28xx *dev)
        if (dev->def_i2c_bus)
                em28xx_i2c_unregister(dev, 1);
        em28xx_i2c_unregister(dev, 0);
+       if (dev->clk)
+               v4l2_clk_unregister_fixed(dev->clk);
 
        usb_put_dev(dev->udev);
 
index 297b739..a997730 100644 (file)
@@ -551,6 +551,7 @@ struct em28xx {
 
        struct v4l2_device v4l2_dev;
        struct v4l2_ctrl_handler ctrl_handler;
+       struct v4l2_clk *clk;
        struct em28xx_board board;
 
        /* Webcam specific fields */