From f8a9dc88eddf85404318da82720f05a162444163 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 Mar 2012 17:03:47 +0200 Subject: [PATCH] gfx: display: use regulator instead of gpio to power on/off display The platform code now abstracts the VLCM_DVDD voltage rail as a regulator, so switch to using the regulator framework instead of toggling the GPIO control directly. This allows usage counting and multiple users for the voltage rail. Signed-off-by: Jani Nikula Signed-off-by: Mika Westerberg Signed-off-by: Kirill A. Shutemov --- drivers/staging/mrst/drv/tc35876x-dsi-lvds.c | 66 +++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c index 6a6bbb4..b618ff9 100644 --- a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c +++ b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c @@ -28,11 +28,18 @@ #include "tc35876x-dsi-lvds.h" #include #include +#include #include static struct i2c_client *tc35876x_client; static struct i2c_client *cmi_lcd_i2c_client; +struct cmi_lcd_data { + struct regulator *regulator; + bool enabled; + struct mutex lock; /* for enabled */ +}; + #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) @@ -506,6 +513,8 @@ void tc35876x_brightness_control(struct drm_device *dev, int level) void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) { struct tc35876x_platform_data *pdata; + struct cmi_lcd_data *lcd_data = cmi_lcd_i2c_client ? + i2c_get_clientdata(cmi_lcd_i2c_client) : NULL; if (WARN(!tc35876x_client, "%s called before probe", __func__)) return; @@ -517,14 +526,22 @@ void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) if (pdata->gpio_panel_bl_en != -1) gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0); - if (pdata->gpio_panel_vadd != -1) - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0); + if (lcd_data && lcd_data->regulator) { + mutex_lock(&lcd_data->lock); + if (lcd_data->enabled) { + regulator_disable(lcd_data->regulator); + lcd_data->enabled = false; + } + mutex_unlock(&lcd_data->lock); + } } void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) { struct tc35876x_platform_data *pdata; struct drm_psb_private *dev_priv = dev->dev_private; + struct cmi_lcd_data *lcd_data = cmi_lcd_i2c_client ? + i2c_get_clientdata(cmi_lcd_i2c_client) : NULL; if (WARN(!tc35876x_client, "%s called before probe", __func__)) return; @@ -533,8 +550,13 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) pdata = dev_get_platdata(&tc35876x_client->dev); - if (pdata->gpio_panel_vadd != -1) { - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1); + if (lcd_data && lcd_data->regulator) { + mutex_lock(&lcd_data->lock); + if (!lcd_data->enabled) { + regulator_enable(lcd_data->regulator); + lcd_data->enabled = true; + } + mutex_unlock(&lcd_data->lock); msleep(260); } @@ -656,11 +678,6 @@ static int tc35876x_bridge_probe(struct i2c_client *client, gpio_direction_output(pdata->gpio_panel_bl_en, 0); } - if (pdata->gpio_panel_vadd != -1) { - gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd"); - gpio_direction_output(pdata->gpio_panel_vadd, 0); - } - tc35876x_client = client; return 0; @@ -678,9 +695,6 @@ static int tc35876x_bridge_remove(struct i2c_client *client) if (pdata->gpio_panel_bl_en != -1) gpio_free(pdata->gpio_panel_bl_en); - if (pdata->gpio_panel_vadd != -1) - gpio_free(pdata->gpio_panel_vadd); - tc35876x_client = NULL; return 0; @@ -705,6 +719,8 @@ static struct i2c_driver tc35876x_bridge_i2c_driver = { static int cmi_lcd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct cmi_lcd_data *lcd_data; + dev_info(&client->dev, "%s\n", __func__); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { @@ -713,6 +729,23 @@ static int cmi_lcd_i2c_probe(struct i2c_client *client, return -ENODEV; } + lcd_data = devm_kzalloc(&client->dev, sizeof(*lcd_data), GFP_KERNEL); + if (!lcd_data) { + dev_err(&client->dev, "out of memory\n"); + return -ENOMEM; + } + + lcd_data->regulator = regulator_get(&client->dev, "vlcm_dvdd"); + if (IS_ERR(lcd_data->regulator)) { + dev_err(&client->dev, "could not get regulator (%ld)\n", + PTR_ERR(lcd_data->regulator)); + lcd_data->regulator = NULL; + } + + mutex_init(&lcd_data->lock); + + i2c_set_clientdata(client, lcd_data); + cmi_lcd_i2c_client = client; return 0; @@ -720,8 +753,17 @@ static int cmi_lcd_i2c_probe(struct i2c_client *client, static int cmi_lcd_i2c_remove(struct i2c_client *client) { + struct cmi_lcd_data *lcd_data = i2c_get_clientdata(client); + dev_dbg(&client->dev, "%s\n", __func__); + if (lcd_data && lcd_data->regulator) { + if (lcd_data->enabled) + regulator_disable(lcd_data->regulator); + + regulator_put(lcd_data->regulator); + } + cmi_lcd_i2c_client = NULL; return 0; -- 2.7.4