[ARM] tegra: stingray: Add fixed regulator for panel enable
authorRebecca Schultz Zavin <rebecca@android.com>
Tue, 14 Dec 2010 20:02:54 +0000 (12:02 -0800)
committerRebecca Schultz Zavin <rebecca@android.com>
Wed, 15 Dec 2010 19:15:30 +0000 (11:15 -0800)
Due to a problem with the hardware design, a voltage divider
is created on the i2c bus when the panel is turned off.  This
can cause problems with other devices on that bus.  To work
around, a fixed regulator has been created representing the panel
power.  This regulator must be enabled when devices on that i2c
bus are in use, even if the panel is otherwise off.

Change-Id: I78d9a3b29e69c1cffd5e8df23025b186527f31b3
Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
arch/arm/mach-tegra/board-stingray-panel.c

index c67076feeff6633e69774a139a1f231591b6ab9b..250c3afd38096925b380fcb0585bc7207a7de262 100644 (file)
@@ -29,6 +29,8 @@
 #include <mach/fb.h>
 #include <mach/nvhost.h>
 #include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include "board.h"
 #include "board-stingray.h"
@@ -145,29 +147,64 @@ int __init board_lcd_manfid_init(char *s)
 }
 __setup("lcd_manfid=", board_lcd_manfid_init);
 
-static int stingray_panel_enable(void)
-{
-       struct i2c_adapter *adapter = NULL;
+/* Disgusting hack to deal with the fact that there are a set of pull down
+ * resistors on the panel end of the i2c bus.  These cause a voltage
+ * divider on the i2c bus which can cause these devices to fail to recognize
+ * their addresses when power to the display is cut.  This creates a dependency
+ * between these devices and the power to the panel.
+ */
+static struct regulator_consumer_supply stingray_panel_reg_consumer_supply[] = {
+       { .supply = "vdd_panel", .dev_name = NULL, },
+       { .supply = "vio", .dev_name = "0-0077" /* barometer */},
+       { .supply = "vio", .dev_name = "0-002c" /* lighting */},
+       { .supply = "vio", .dev_name = "0-005b" /* touch */},
+       { .supply = "vio", .dev_name = "0-004b" /* als */},
+};
 
-       if (!strncmp(lcd_manfid, "SHP", 3) || !strncmp(lcd_manfid, "AUO", 3)) {
-               adapter = i2c_get_adapter(0);
-               if (adapter)
-                       i2c_lock_adapter(adapter);
-       }
+static struct regulator_init_data stingray_panel_reg_initdata = {
+       .consumer_supplies = stingray_panel_reg_consumer_supply,
+       .num_consumer_supplies = ARRAY_SIZE(stingray_panel_reg_consumer_supply),
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+};
 
-       gpio_set_value(STINGRAY_LVDS_SHDN_B, 1);
+static struct fixed_voltage_config stingray_panel_reg_config = {
+       .supply_name            = "stingray_panel_reg",
+       .microvolts             = 5000000,
+       .gpio                   = STINGRAY_LVDS_SHDN_B,
+       .startup_delay          = 200000,
+       .enable_high            = 1,
+       .enabled_at_boot        = 1,
+       .init_data              = &stingray_panel_reg_initdata,
+};
 
-       if (adapter) {
-               msleep(200);
-               i2c_unlock_adapter(adapter);
-               i2c_put_adapter(adapter);
+static struct platform_device stingray_panel_reg_device = {
+       .name   = "reg-fixed-voltage",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &stingray_panel_reg_config,
+       },
+};
+
+static struct regulator *stingray_panel_regulator = NULL;
+static int stingray_panel_enable(void)
+{
+       if (IS_ERR_OR_NULL(stingray_panel_regulator)) {
+               stingray_panel_regulator = regulator_get(NULL, "vdd_panel");
+               if (IS_ERR_OR_NULL(stingray_panel_regulator)) {
+                       pr_err("%s: Could not get panel regulator\n", __func__);
+                       return PTR_ERR(stingray_panel_regulator);
+               }
        }
-       return 0;
+
+       return regulator_enable(stingray_panel_regulator);
 }
 
 static int stingray_panel_disable(void)
 {
-       gpio_set_value(STINGRAY_LVDS_SHDN_B, 0);
+       if (!IS_ERR_OR_NULL(stingray_panel_regulator))
+               regulator_disable(stingray_panel_regulator);
        return 0;
 }
 
@@ -353,9 +390,7 @@ int __init stingray_panel_init(void)
                        ARRAY_SIZE(stingray_i2c_bus1_led_info));
        }
 
-       tegra_gpio_enable(STINGRAY_LVDS_SHDN_B);
-       gpio_request(STINGRAY_LVDS_SHDN_B, "lvds_shdn_b");
-       gpio_direction_output(STINGRAY_LVDS_SHDN_B, 1);
+       platform_device_register(&stingray_panel_reg_device);
 
        stingray_hdmi_init();