]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
media: video: tegra: imx132: edp support
authorCharlie Huang <chahuang@nvidia.com>
Wed, 5 Jun 2013 19:34:46 +0000 (12:34 -0700)
committerDan Willemsen <dwillemsen@nvidia.com>
Sat, 14 Sep 2013 20:34:06 +0000 (13:34 -0700)
support edp client on imx132.

bug 1299149

Change-Id: Iafa7bd1e749b73311a98e15ebba788d83951523a
Signed-off-by: Charlie Huang <chahuang@nvidia.com>
Reviewed-on: http://git-master/r/239822
(cherry picked from commit ace7e87d0db411479266492caf303f9057d29579)
Reviewed-on: http://git-master/r/250886
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Wei Chen (Camera) <wechen@nvidia.com>
Reviewed-by: David Wang (SW-TEGRA) <davidw@nvidia.com>
Reviewed-by: Sivaram Nair <sivaramn@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
drivers/media/video/tegra/imx091.c
drivers/media/video/tegra/imx132.c
include/media/imx132.h

index c1247a46bab13aaeccb76a9e736f927a9e639bc9..096f4717539e4859ceeac4d7e7fb40a5521179ce 100644 (file)
@@ -2238,8 +2238,7 @@ static int imx091_mode_wr_full(struct imx091_info *info, u32 mode_index)
 {
        int err;
 
-       /* the state num is temporary assigned, should be updated later as
-       per-mode basis */
+       /* request highest edp state */
        err = imx091_edp_req(info, 0);
        if (err) {
                dev_err(&info->i2c_client->dev,
index c885da3e63d9d9f14a390e72d6a6becfbe612f91..eece0e710080fa3d290e3be8239baabb57517a4c 100644 (file)
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/regulator/consumer.h>
-#include <media/imx132.h>
+#include <linux/edp.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
-#include <media/nvc.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <media/nvc.h>
+#include <media/imx132.h>
 #include "nvc_utilities.h"
 
 #ifdef CONFIG_DEBUG_FS
@@ -52,6 +53,8 @@ struct imx132_info {
        struct nvc_fuseid               fuse_id;
        struct i2c_client               *i2c_client;
        struct imx132_platform_data     *pdata;
+       struct edp_client               *edpc;
+       unsigned                        edp_state;
        atomic_t                        in_use;
        struct clk                      *mclk;
 #ifdef CONFIG_DEBUG_FS
@@ -454,6 +457,89 @@ imx132_write_table(struct i2c_client *client,
        return 0;
 }
 
+static void imx132_edp_lowest(struct imx132_info *info)
+{
+       if (!info->edpc)
+               return;
+
+       info->edp_state = info->edpc->num_states - 1;
+       dev_dbg(&info->i2c_client->dev, "%s %d\n", __func__, info->edp_state);
+       if (edp_update_client_request(info->edpc, info->edp_state, NULL)) {
+               dev_err(&info->i2c_client->dev, "THIS IS NOT LIKELY HAPPEN!\n");
+               dev_err(&info->i2c_client->dev,
+                       "UNABLE TO SET LOWEST EDP STATE!\n");
+       }
+}
+
+static void imx132_edp_throttle(unsigned int new_state, void *priv_data);
+
+static void imx132_edp_register(struct imx132_info *info)
+{
+       struct edp_manager *edp_manager;
+       struct edp_client *edpc = &info->pdata->edpc_config;
+       int ret;
+
+       info->edpc = NULL;
+       if (!edpc->num_states) {
+               dev_notice(&info->i2c_client->dev,
+                       "%s: NO edp states defined.\n", __func__);
+               return;
+       }
+
+       strncpy(edpc->name, "imx132", EDP_NAME_LEN - 1);
+       edpc->name[EDP_NAME_LEN - 1] = 0;
+       edpc->private_data = info;
+       edpc->throttle = imx132_edp_throttle;
+
+       dev_dbg(&info->i2c_client->dev, "%s: %s, e0 = %d, p %d\n",
+               __func__, edpc->name, edpc->e0_index, edpc->priority);
+       for (ret = 0; ret < edpc->num_states; ret++)
+               dev_dbg(&info->i2c_client->dev, "e%d = %d mA",
+                       ret - edpc->e0_index, edpc->states[ret]);
+
+       edp_manager = edp_get_manager("battery");
+       if (!edp_manager) {
+               dev_err(&info->i2c_client->dev,
+                       "unable to get edp manager: battery\n");
+               return;
+       }
+
+       ret = edp_register_client(edp_manager, edpc);
+       if (ret) {
+               dev_err(&info->i2c_client->dev,
+                       "unable to register edp client\n");
+               return;
+       }
+
+       info->edpc = edpc;
+       /* set to lowest state at init */
+       imx132_edp_lowest(info);
+}
+
+static int imx132_edp_req(struct imx132_info *info, unsigned new_state)
+{
+       unsigned approved;
+       int ret = 0;
+
+       if (!info->edpc)
+               return 0;
+
+       dev_dbg(&info->i2c_client->dev, "%s %d\n", __func__, new_state);
+       ret = edp_update_client_request(info->edpc, new_state, &approved);
+       if (ret) {
+               dev_err(&info->i2c_client->dev, "E state transition failed\n");
+               return ret;
+       }
+
+       if (approved > new_state) {
+               dev_err(&info->i2c_client->dev, "EDP no enough current\n");
+               return -ENODEV;
+       }
+
+       info->edp_state = approved;
+       return 0;
+}
+
 static int
 imx132_set_mode(struct imx132_info *info, struct imx132_mode *mode)
 {
@@ -476,6 +562,14 @@ imx132_set_mode(struct imx132_info *info, struct imx132_mode *mode)
                return -EINVAL;
        }
 
+       /* request highest edp state */
+       err = imx132_edp_req(info, 0);
+       if (err) {
+               dev_err(&info->i2c_client->dev,
+                       "%s: ERROR cannot set edp state! %d\n", __func__, err);
+               return err;
+       }
+
        /*
         * get a list of override regs for the asking frame length,
         * coarse integration time, and gain.
@@ -856,6 +950,12 @@ static int imx132_power_off(struct imx132_info *info)
        struct imx132_power_rail *pw = &info->power;
        unsigned int cam2_gpio = info->pdata->cam2_gpio;
 
+       if (!info->i2c_client->dev.of_node) {
+               if (info->pdata && info->pdata->power_off)
+                       info->pdata->power_off(&info->power);
+               goto imx132_pwroff_end;
+       }
+
        if (unlikely(WARN_ON(!pw || !pw->avdd || !pw->iovdd || !pw->dvdd)))
                return -EFAULT;
 
@@ -872,9 +972,18 @@ static int imx132_power_off(struct imx132_info *info)
                regulator_disable(imx132_ext_reg2);
        }
 
+imx132_pwroff_end:
+       imx132_edp_lowest(info);
        return 0;
 }
 
+static void imx132_edp_throttle(unsigned int new_state, void *priv_data)
+{
+       struct imx132_info *info = priv_data;
+
+       imx132_power_off(info);
+}
+
 static int
 imx132_open(struct inode *inode, struct file *file)
 {
@@ -921,12 +1030,9 @@ imx132_release(struct inode *inode, struct file *file)
 {
        struct imx132_info *info = file->private_data;
 
-       if (info->i2c_client->dev.of_node) {
-               imx132_power_off(info);
-       } else {
-               if (info->pdata && info->pdata->power_off)
-                       info->pdata->power_off(&info->power);
-       }
+       imx132_power_off(info);
+
+       imx132_mclk_disable(info);
 
        file->private_data = NULL;
 
@@ -1082,6 +1188,8 @@ imx132_probe(struct i2c_client *client,
 
        imx132_power_get(info);
 
+       imx132_edp_register(info);
+
        memcpy(&info->miscdev_info,
                &imx132_device,
                sizeof(struct miscdevice));
index 1c1a8000ec5a6f83481f79d3fdb975f9dfdf6b31..10fa70a0d85db31d41ffdb9bb28b769d94761872 100644 (file)
@@ -59,6 +59,7 @@ struct imx132_platform_data {
        unsigned int cam2_gpio;
        bool ext_reg;
        const char *mclk_name; /* NULL for default */
+       struct edp_client edpc_config;
        int (*power_on)(struct imx132_power_rail *pw);
        int (*power_off)(struct imx132_power_rail *pw);
 };