Commit cd6a1ca3 authored by Linus Walleij's avatar Linus Walleij

drm/gma500: Pass GPIO for Intel MID using descriptors

The GMA500 driver is using the legacy GPIO API to fetch
three optional display control GPIO lines from the SFI
description used by the Medfield platform.

Switch this over to use GPIO descriptors and delete the
custom platform data.

We create three new static locals in the tc35876x bridge
code but it is hardly any worse than the I2C client static
local already there: I tried first to move it to the DRM
driver state container but there are workarounds for
probe order in the code so I just stayed off it, as the
result is unpredictable.

People wanting to do a more throrugh and proper cleanup
of the GMA500 driver can work on top of this, I can't
solve much more since I don't have access to the hardware,
I can only attempt to tidy up my GPIO corner.

Cc: Daniel Stone <daniels@collabora.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191206094301.76368-1-linus.walleij@linaro.orgSigned-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 2840f1f0
...@@ -6,21 +6,31 @@ ...@@ -6,21 +6,31 @@
* Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
*/ */
#include <linux/gpio.h> #include <linux/gpio/machine.h>
#include <linux/platform_data/tc35876x.h>
#include <asm/intel-mid.h> #include <asm/intel-mid.h>
static struct gpiod_lookup_table tc35876x_gpio_table = {
.dev_id = "i2c_disp_brig",
.table = {
GPIO_LOOKUP("0000:00:0c.0", -1, "bridge-reset", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "bl-en", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("0000:00:0c.0", -1, "vadd", GPIO_ACTIVE_HIGH),
{ },
},
};
/*tc35876x DSI_LVDS bridge chip and panel platform data*/ /*tc35876x DSI_LVDS bridge chip and panel platform data*/
static void *tc35876x_platform_data(void *data) static void *tc35876x_platform_data(void *data)
{ {
static struct tc35876x_platform_data pdata; struct gpiod_lookup_table *table = &tc35876x_gpio_table;
struct gpiod_lookup *lookup = table->table;
/* gpio pins set to -1 will not be used by the driver */ lookup[0].chip_hwnum = get_gpio_by_name("LCMB_RXEN");
pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN"); lookup[1].chip_hwnum = get_gpio_by_name("6S6P_BL_EN");
pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN"); lookup[2].chip_hwnum = get_gpio_by_name("EN_VREG_LCD_V3P3");
pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3"); gpiod_add_lookup_table(table);
return &pdata; return NULL;
} }
static const struct devs_id tc35876x_dev_id __initconst = { static const struct devs_id tc35876x_dev_id __initconst = {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_data/tc35876x.h> #include <linux/gpio/consumer.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
...@@ -36,6 +36,11 @@ ...@@ -36,6 +36,11 @@
static struct i2c_client *tc35876x_client; static struct i2c_client *tc35876x_client;
static struct i2c_client *cmi_lcd_i2c_client; static struct i2c_client *cmi_lcd_i2c_client;
/* Panel GPIOs */
static struct gpio_desc *bridge_reset;
static struct gpio_desc *bridge_bl_enable;
static struct gpio_desc *backlight_voltage;
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
...@@ -316,27 +321,23 @@ static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value) ...@@ -316,27 +321,23 @@ static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state) void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
{ {
struct tc35876x_platform_data *pdata;
if (WARN(!tc35876x_client, "%s called before probe", __func__)) if (WARN(!tc35876x_client, "%s called before probe", __func__))
return; return;
dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state); dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
pdata = dev_get_platdata(&tc35876x_client->dev); if (!bridge_reset)
if (pdata->gpio_bridge_reset == -1)
return; return;
if (state) { if (state) {
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); gpiod_set_value_cansleep(bridge_reset, 0);
mdelay(10); mdelay(10);
} else { } else {
/* Pull MIPI Bridge reset pin to Low */ /* Pull MIPI Bridge reset pin to Low */
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); gpiod_set_value_cansleep(bridge_reset, 0);
mdelay(20); mdelay(20);
/* Pull MIPI Bridge reset pin to High */ /* Pull MIPI Bridge reset pin to High */
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1); gpiod_set_value_cansleep(bridge_reset, 1);
mdelay(40); mdelay(40);
} }
} }
...@@ -510,25 +511,20 @@ void tc35876x_brightness_control(struct drm_device *dev, int level) ...@@ -510,25 +511,20 @@ void tc35876x_brightness_control(struct drm_device *dev, int level)
void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
{ {
struct tc35876x_platform_data *pdata;
if (WARN(!tc35876x_client, "%s called before probe", __func__)) if (WARN(!tc35876x_client, "%s called before probe", __func__))
return; return;
dev_dbg(&tc35876x_client->dev, "%s\n", __func__); dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
pdata = dev_get_platdata(&tc35876x_client->dev); if (bridge_bl_enable)
gpiod_set_value_cansleep(bridge_bl_enable, 0);
if (pdata->gpio_panel_bl_en != -1)
gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
if (pdata->gpio_panel_vadd != -1) if (backlight_voltage)
gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0); gpiod_set_value_cansleep(backlight_voltage, 0);
} }
void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) 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 drm_psb_private *dev_priv = dev->dev_private;
if (WARN(!tc35876x_client, "%s called before probe", __func__)) if (WARN(!tc35876x_client, "%s called before probe", __func__))
...@@ -536,10 +532,8 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) ...@@ -536,10 +532,8 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
dev_dbg(&tc35876x_client->dev, "%s\n", __func__); dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
pdata = dev_get_platdata(&tc35876x_client->dev); if (backlight_voltage) {
gpiod_set_value_cansleep(backlight_voltage, 1);
if (pdata->gpio_panel_vadd != -1) {
gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
msleep(260); msleep(260);
} }
...@@ -571,8 +565,8 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) ...@@ -571,8 +565,8 @@ void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
"i2c write failed (%d)\n", ret); "i2c write failed (%d)\n", ret);
} }
if (pdata->gpio_panel_bl_en != -1) if (bridge_bl_enable)
gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1); gpiod_set_value_cansleep(bridge_bl_enable, 1);
tc35876x_brightness_control(dev, dev_priv->brightness_adjusted); tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
} }
...@@ -635,8 +629,6 @@ static int tc35876x_get_panel_info(struct drm_device *dev, int pipe, ...@@ -635,8 +629,6 @@ static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
static int tc35876x_bridge_probe(struct i2c_client *client, static int tc35876x_bridge_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct tc35876x_platform_data *pdata;
dev_info(&client->dev, "%s\n", __func__); dev_info(&client->dev, "%s\n", __func__);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
...@@ -645,26 +637,23 @@ static int tc35876x_bridge_probe(struct i2c_client *client, ...@@ -645,26 +637,23 @@ static int tc35876x_bridge_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
pdata = dev_get_platdata(&client->dev); bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW);
if (!pdata) { if (IS_ERR(bridge_reset))
dev_err(&client->dev, "%s: no platform data\n", __func__); return PTR_ERR(bridge_reset);
return -ENODEV; if (bridge_reset)
} gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
if (pdata->gpio_bridge_reset != -1) { bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW);
gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset"); if (IS_ERR(bridge_bl_enable))
gpio_direction_output(pdata->gpio_bridge_reset, 0); return PTR_ERR(bridge_bl_enable);
} if (bridge_bl_enable)
gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
if (pdata->gpio_panel_bl_en != -1) {
gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
gpio_direction_output(pdata->gpio_panel_bl_en, 0);
}
if (pdata->gpio_panel_vadd != -1) { backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW);
gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd"); if (IS_ERR(backlight_voltage))
gpio_direction_output(pdata->gpio_panel_vadd, 0); return PTR_ERR(backlight_voltage);
} if (backlight_voltage)
gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
tc35876x_client = client; tc35876x_client = client;
...@@ -673,19 +662,8 @@ static int tc35876x_bridge_probe(struct i2c_client *client, ...@@ -673,19 +662,8 @@ static int tc35876x_bridge_probe(struct i2c_client *client,
static int tc35876x_bridge_remove(struct i2c_client *client) static int tc35876x_bridge_remove(struct i2c_client *client)
{ {
struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
if (pdata->gpio_bridge_reset != -1)
gpio_free(pdata->gpio_bridge_reset);
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; tc35876x_client = NULL;
return 0; return 0;
......
#ifndef _TC35876X_H
#define _TC35876X_H
struct tc35876x_platform_data {
int gpio_bridge_reset;
int gpio_panel_bl_en;
int gpio_panel_vadd;
};
#endif /* _TC35876X_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment