]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: i2c: ov9640: drop soc_camera code and switch to v4l2_async
authorPetr Cvek <petrcvekcz@gmail.com>
Thu, 13 Dec 2018 15:39:13 +0000 (10:39 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 16 Jan 2019 18:17:09 +0000 (13:17 -0500)
This patch removes the dependency on an obsoleted soc_camera from ov9640
driver and changes the code to be a standalone v4l2 async subdevice.
It also adds GPIO allocations for power and reset signals (as they are not
handled by soc_camera now).

The values for waiting on GPIOs (reset and power) settling down were taken
from the datasheet (> 1 ms after HW/SW reset). The upper limit was chosen
as an arbitrary value. Also one occurrence of mdelay() was changed to
msleep(). The delays were successfully tested on a real hardware.

The patch makes ov9640 sensor again compatible with the pxa_camera driver.

Signed-off-by: Petr Cvek <petrcvekcz@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/i2c/ov9640.c
drivers/media/i2c/ov9640.h

index eb91b8240083d8c3d600528c6372e19a34013e08..1f7cf01d037ff802a36d3ed2fbc542a1f3838220 100644 (file)
@@ -9,6 +9,7 @@
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
  *
  * Based on ov7670 and soc_camera_platform driver,
+ * transition from soc_camera to pxa_camera based on mt9m111
  *
  * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
  * Copyright (C) 2008 Magnus Damm
 #include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
-#include <media/soc_camera.h>
+#include <media/v4l2-async.h>
 #include <media/v4l2-clk.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+
+#include <linux/gpio/consumer.h>
 
 #include "ov9640.h"
 
@@ -323,11 +328,23 @@ static int ov9640_set_register(struct v4l2_subdev *sd,
 
 static int ov9640_s_power(struct v4l2_subdev *sd, int on)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
        struct ov9640_priv *priv = to_ov9640_sensor(sd);
-
-       return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
+       int ret = 0;
+
+       if (on) {
+               gpiod_set_value(priv->gpio_power, 1);
+               usleep_range(1000, 2000);
+               ret = v4l2_clk_enable(priv->clk);
+               usleep_range(1000, 2000);
+               gpiod_set_value(priv->gpio_reset, 0);
+       } else {
+               gpiod_set_value(priv->gpio_reset, 1);
+               usleep_range(1000, 2000);
+               v4l2_clk_disable(priv->clk);
+               usleep_range(1000, 2000);
+               gpiod_set_value(priv->gpio_power, 0);
+       }
+       return ret;
 }
 
 /* select nearest higher resolution for capture */
@@ -475,7 +492,7 @@ static int ov9640_prog_dflt(struct i2c_client *client)
        }
 
        /* wait for the changes to actually happen, 140ms are not enough yet */
-       mdelay(150);
+       msleep(150);
 
        return 0;
 }
@@ -630,14 +647,10 @@ static const struct v4l2_subdev_core_ops ov9640_core_ops = {
 static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
                                struct v4l2_mbus_config *cfg)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
-
        cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
                V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
                V4L2_MBUS_DATA_ACTIVE_HIGH;
        cfg->type = V4L2_MBUS_PARALLEL;
-       cfg->flags = soc_camera_apply_board_flags(ssdd, cfg);
 
        return 0;
 }
@@ -666,18 +679,27 @@ static int ov9640_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct ov9640_priv *priv;
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
        int ret;
 
-       if (!ssdd) {
-               dev_err(&client->dev, "Missing platform_data for driver\n");
-               return -EINVAL;
-       }
-
-       priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(&client->dev, sizeof(*priv),
+                           GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
+       priv->gpio_power = devm_gpiod_get(&client->dev, "Camera power",
+                                         GPIOD_OUT_LOW);
+       if (IS_ERR_OR_NULL(priv->gpio_power)) {
+               ret = PTR_ERR(priv->gpio_power);
+               return ret;
+       }
+
+       priv->gpio_reset = devm_gpiod_get(&client->dev, "Camera reset",
+                                         GPIOD_OUT_HIGH);
+       if (IS_ERR_OR_NULL(priv->gpio_reset)) {
+               ret = PTR_ERR(priv->gpio_reset);
+               return ret;
+       }
+
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
 
        v4l2_ctrl_handler_init(&priv->hdl, 2);
@@ -696,12 +718,20 @@ static int ov9640_probe(struct i2c_client *client,
        }
 
        ret = ov9640_video_probe(client);
-       if (ret) {
-               v4l2_clk_put(priv->clk);
-eclkget:
-               v4l2_ctrl_handler_free(&priv->hdl);
-       }
+       if (ret)
+               goto eprobe;
 
+       priv->subdev.dev = &client->dev;
+       ret = v4l2_async_register_subdev(&priv->subdev);
+       if (ret)
+               goto eprobe;
+
+       return 0;
+
+eprobe:
+       v4l2_clk_put(priv->clk);
+eclkget:
+       v4l2_ctrl_handler_free(&priv->hdl);
        return ret;
 }
 
@@ -711,7 +741,7 @@ static int ov9640_remove(struct i2c_client *client)
        struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
        v4l2_clk_put(priv->clk);
-       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_async_unregister_subdev(&priv->subdev);
        v4l2_ctrl_handler_free(&priv->hdl);
        return 0;
 }
index 65d13ff1753630eae190cc446e7e39bcbe0ed94a..be5e4b29ac69b40e33ee59b7e86eff56c8a42be7 100644 (file)
@@ -200,6 +200,8 @@ struct ov9640_priv {
        struct v4l2_subdev              subdev;
        struct v4l2_ctrl_handler        hdl;
        struct v4l2_clk                 *clk;
+       struct gpio_desc                *gpio_power;
+       struct gpio_desc                *gpio_reset;
 
        int                             model;
        int                             revision;