]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00231266-3: adv7280_mipi_tvin add regulator support
authorAdrian Alonso <aalonso@freescale.com>
Thu, 25 Oct 2012 20:15:26 +0000 (15:15 -0500)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:40 +0000 (08:35 +0200)
* Add regulator support
  Set regulator voltage and enable them
  On remove callback disable regulators
* Add callbacks for target platform custom
  reset, power up/down and io pads configuration

Signed-off-by: Adrian Alonso <aalonso@freescale.com>
drivers/media/video/mxc/capture/adv7280_mipi_tvin.c

index 4310cb09bd932cbc33f40246b788502e22ab2f5f..06827ca243eaa51083b1b8e9ea1989c17988132f 100644 (file)
 #include <linux/types.h>
 #include <linux/device.h>
 #include <linux/i2c.h>
+#include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/fsl_devices.h>
+#include <linux/regulator/consumer.h>
 
 #define ADV7280_SAMPLE_SILICON         0x40
 #define ADV7280_PROD_SILICON           0x41
 #define ADV7280_NTSC_MODE_BIT          0x00 /* NTSC mode bit    */
 #define ADV7280_NTSC_4_43_MODE_BIT     0x10 /* NTSC 4.43 mode bit*/
 /** adv7280 voltages */
-#define ADV7280_VOLTAGE_ANALOG         2800000
-#define ADV7280_VOLTAGE_DIGITAL_CORE   1500000
+#define ADV7280_VOLTAGE_ANALOG         1800000
+#define ADV7280_VOLTAGE_DIGITAL_CORE   3300000
 #define ADV7280_VOLTAGE_DIGITAL_IO     1800000
 
+static struct regulator *dvddio_regulator;
+static struct regulator *dvdd_regulator;
+static struct regulator *avdd_regulator;
+static struct regulator *pvdd_regulator;
+
 struct reg_value {
        u8 reg;
        u8 value;
@@ -216,6 +223,104 @@ err:
        return ret;
 }
 
+static int adv7280_regulators_config(struct adv7280_chipset *adv7280)
+{
+       struct fsl_mxc_tvin_platform_data *pdata = adv7280->pdata;
+       int ret;
+
+       if (pdata->dvddio_reg) {
+               dvddio_regulator =
+                       regulator_get(adv7280->dev, pdata->dvddio_reg);
+               if (!IS_ERR(dvddio_regulator)) {
+                       ret = regulator_set_voltage(dvddio_regulator,
+                                       ADV7280_VOLTAGE_DIGITAL_CORE,
+                                       ADV7280_VOLTAGE_DIGITAL_CORE);
+                       if (ret < 0)
+                               goto dvddio_err;
+                       ret = regulator_enable(dvddio_regulator);
+                       if (ret != 0) {
+                               pr_err("%s: dvddio_reg set voltage error\n",
+                                               __func__);
+                               goto dvddio_err;
+                       }
+               } else
+                       dvddio_regulator = NULL;
+       }
+
+       if (pdata->dvdd_reg) {
+               dvdd_regulator = regulator_get(adv7280->dev, pdata->dvdd_reg);
+               if (!IS_ERR(dvdd_regulator)) {
+                       ret = regulator_set_voltage(dvdd_regulator,
+                                       ADV7280_VOLTAGE_DIGITAL_IO,
+                                       ADV7280_VOLTAGE_DIGITAL_IO);
+                       if (ret < 0)
+                               goto dvdd_err;
+                       ret = regulator_enable(dvdd_regulator);
+                       if (ret != 0) {
+                               pr_err("%s: dvdd_reg set voltage error\n",
+                                               __func__);
+                               goto dvdd_err;
+                       }
+               } else
+                       dvdd_regulator = NULL;
+       }
+
+       if (pdata->avdd_reg) {
+               avdd_regulator = regulator_get(adv7280->dev, pdata->avdd_reg);
+               if (!IS_ERR(avdd_regulator)) {
+                       ret = regulator_set_voltage(avdd_regulator,
+                                       ADV7280_VOLTAGE_ANALOG,
+                                       ADV7280_VOLTAGE_ANALOG);
+                       if (ret < 0)
+                               goto avdd_err;
+                       ret = regulator_enable(avdd_regulator);
+                       if (ret != 0) {
+                               pr_err("%s: avdd_reg set voltage error\n",
+                                               __func__);
+                               goto avdd_err;
+                       }
+               } else
+                       avdd_regulator = NULL;
+       }
+
+       if (pdata->pvdd_reg) {
+               pvdd_regulator = regulator_get(adv7280->dev, pdata->pvdd_reg);
+               if (!IS_ERR(pvdd_regulator)) {
+                       ret = regulator_set_voltage(pvdd_regulator,
+                                       ADV7280_VOLTAGE_DIGITAL_IO,
+                                       ADV7280_VOLTAGE_DIGITAL_IO);
+                       if (ret < 0)
+                               goto pvdd_err;
+                       ret = regulator_enable(pvdd_regulator);
+                       if (ret != 0) {
+                               pr_err("%s: pvdd_reg set voltage error\n",
+                                               __func__);
+                               goto pvdd_err;
+                       }
+               } else
+                       pvdd_regulator = NULL;
+       }
+
+       return 0;
+
+pvdd_err:
+       if (avdd_regulator) {
+               regulator_disable(avdd_regulator);
+               regulator_put(avdd_regulator);
+       }
+avdd_err:
+       if (dvdd_regulator) {
+               regulator_disable(dvdd_regulator);
+               regulator_put(dvdd_regulator);
+       }
+dvdd_err:
+       if (dvddio_regulator) {
+               regulator_disable(dvddio_regulator);
+               regulator_put(dvddio_regulator);
+       }
+dvddio_err:
+       return ret;
+}
 /*!
  * ADV7280 I2C probe function.
  * Function set in i2c_driver struct.
@@ -254,6 +359,20 @@ static int adv7280_i2c_probe(struct i2c_client *client,
                goto client_csi_tx_err;
        }
 
+       /* custom platform reset, powerup callbacks */
+       if (adv7280->pdata->io_init)
+               adv7280->pdata->io_init();
+
+       if (adv7280->pdata->reset)
+               adv7280->pdata->reset();
+
+       if (adv7280->pdata->pwdn)
+               adv7280->pdata->pwdn(0);
+       /* set regulators */
+       ret = adv7280_regulators_config(adv7280);
+       if (ret < 0)
+               goto err;
+
        ret = adv7280_read_reg(adv7280->client, ADV7280_IDENT);
        if (ret < 0) {
                pr_err("%s: read id error %x\n", __func__, ret);
@@ -284,6 +403,26 @@ static int adv7280_i2c_remove(struct i2c_client *i2c_client)
 {
        struct adv7280_chipset *adv7280 = i2c_get_clientdata(i2c_client);
 
+       if (dvddio_regulator) {
+               regulator_disable(dvddio_regulator);
+               regulator_put(dvddio_regulator);
+       }
+
+       if (dvdd_regulator) {
+               regulator_disable(dvdd_regulator);
+               regulator_put(dvdd_regulator);
+       }
+
+       if (avdd_regulator) {
+               regulator_disable(avdd_regulator);
+               regulator_put(avdd_regulator);
+       }
+
+       if (pvdd_regulator) {
+               regulator_disable(pvdd_regulator);
+               regulator_put(pvdd_regulator);
+       }
+
        i2c_unregister_device(adv7280->client_csi_tx);
        kfree(adv7280);
        return 0;