]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/media/i2c/mt9p031.c
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[mirror_ubuntu-bionic-kernel.git] / drivers / media / i2c / mt9p031.c
index 28cf95b372854f532bd619d558c5a3fbbcbd0cfb..4734836fe5a410c8cf4249d9c455f5ceaf4b627c 100644 (file)
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
-#include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 
 #include <media/mt9p031.h>
-#include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
 #include <media/v4l2-subdev.h>
 
 #include "aptina-pll.h"
@@ -124,9 +125,7 @@ struct mt9p031 {
        int power_count;
 
        struct clk *clk;
-       struct regulator *vaa;
-       struct regulator *vdd;
-       struct regulator *vdd_io;
+       struct regulator_bulk_data regulators[3];
 
        enum mt9p031_model model;
        struct aptina_pll pll;
@@ -271,23 +270,26 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031)
 
 static int mt9p031_power_on(struct mt9p031 *mt9p031)
 {
+       int ret;
+
        /* Ensure RESET_BAR is low */
-       if (mt9p031->reset != -1) {
+       if (gpio_is_valid(mt9p031->reset)) {
                gpio_set_value(mt9p031->reset, 0);
                usleep_range(1000, 2000);
        }
 
        /* Bring up the supplies */
-       regulator_enable(mt9p031->vdd);
-       regulator_enable(mt9p031->vdd_io);
-       regulator_enable(mt9p031->vaa);
+       ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators),
+                                  mt9p031->regulators);
+       if (ret < 0)
+               return ret;
 
        /* Emable clock */
        if (mt9p031->clk)
                clk_prepare_enable(mt9p031->clk);
 
        /* Now RESET_BAR must be high */
-       if (mt9p031->reset != -1) {
+       if (gpio_is_valid(mt9p031->reset)) {
                gpio_set_value(mt9p031->reset, 1);
                usleep_range(1000, 2000);
        }
@@ -297,14 +299,13 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031)
 
 static void mt9p031_power_off(struct mt9p031 *mt9p031)
 {
-       if (mt9p031->reset != -1) {
+       if (gpio_is_valid(mt9p031->reset)) {
                gpio_set_value(mt9p031->reset, 0);
                usleep_range(1000, 2000);
        }
 
-       regulator_disable(mt9p031->vaa);
-       regulator_disable(mt9p031->vdd_io);
-       regulator_disable(mt9p031->vdd);
+       regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators),
+                              mt9p031->regulators);
 
        if (mt9p031->clk)
                clk_disable_unprepare(mt9p031->clk);
@@ -849,18 +850,18 @@ static int mt9p031_registered(struct v4l2_subdev *subdev)
 
        /* Read out the chip version register */
        data = mt9p031_read(client, MT9P031_CHIP_VERSION);
+       mt9p031_power_off(mt9p031);
+
        if (data != MT9P031_CHIP_VERSION_VALUE) {
                dev_err(&client->dev, "MT9P031 not detected, wrong version "
                        "0x%04x\n", data);
                return -ENODEV;
        }
 
-       mt9p031_power_off(mt9p031);
-
        dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
                 client->addr);
 
-       return ret;
+       return 0;
 }
 
 static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
@@ -928,10 +929,36 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
  * Driver initialization and probing
  */
 
+static struct mt9p031_platform_data *
+mt9p031_get_pdata(struct i2c_client *client)
+{
+       struct mt9p031_platform_data *pdata;
+       struct device_node *np;
+
+       if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+               return client->dev.platform_data;
+
+       np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL);
+       if (!np)
+               return NULL;
+
+       pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               goto done;
+
+       pdata->reset = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
+       of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq);
+       of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
+
+done:
+       of_node_put(np);
+       return pdata;
+}
+
 static int mt9p031_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
-       struct mt9p031_platform_data *pdata = client->dev.platform_data;
+       struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client);
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct mt9p031 *mt9p031;
        unsigned int i;
@@ -958,14 +985,14 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->model = did->driver_data;
        mt9p031->reset = -1;
 
-       mt9p031->vaa = devm_regulator_get(&client->dev, "vaa");
-       mt9p031->vdd = devm_regulator_get(&client->dev, "vdd");
-       mt9p031->vdd_io = devm_regulator_get(&client->dev, "vdd_io");
+       mt9p031->regulators[0].supply = "vdd";
+       mt9p031->regulators[1].supply = "vdd_io";
+       mt9p031->regulators[2].supply = "vaa";
 
-       if (IS_ERR(mt9p031->vaa) || IS_ERR(mt9p031->vdd) ||
-           IS_ERR(mt9p031->vdd_io)) {
+       ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators);
+       if (ret < 0) {
                dev_err(&client->dev, "Unable to get regulators\n");
-               return -ENODEV;
+               return ret;
        }
 
        v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
@@ -1031,7 +1058,7 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->format.field = V4L2_FIELD_NONE;
        mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
 
-       if (pdata->reset != -1) {
+       if (gpio_is_valid(pdata->reset)) {
                ret = devm_gpio_request_one(&client->dev, pdata->reset,
                                            GPIOF_OUT_INIT_LOW, "mt9p031_rst");
                if (ret < 0)
@@ -1070,8 +1097,18 @@ static const struct i2c_device_id mt9p031_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mt9p031_id);
 
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id mt9p031_of_match[] = {
+       { .compatible = "aptina,mt9p031", },
+       { .compatible = "aptina,mt9p031m", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt9p031_of_match);
+#endif
+
 static struct i2c_driver mt9p031_i2c_driver = {
        .driver = {
+               .of_match_table = of_match_ptr(mt9p031_of_match),
                .name = "mt9p031",
        },
        .probe          = mt9p031_probe,