Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191206094301.76368-1-linus.walleij@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

+51 -74
+18 -8
arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c
··· 6 6 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> 7 7 */ 8 8 9 - #include <linux/gpio.h> 10 - #include <linux/platform_data/tc35876x.h> 9 + #include <linux/gpio/machine.h> 11 10 #include <asm/intel-mid.h> 11 + 12 + static struct gpiod_lookup_table tc35876x_gpio_table = { 13 + .dev_id = "i2c_disp_brig", 14 + .table = { 15 + GPIO_LOOKUP("0000:00:0c.0", -1, "bridge-reset", GPIO_ACTIVE_HIGH), 16 + GPIO_LOOKUP("0000:00:0c.0", -1, "bl-en", GPIO_ACTIVE_HIGH), 17 + GPIO_LOOKUP("0000:00:0c.0", -1, "vadd", GPIO_ACTIVE_HIGH), 18 + { }, 19 + }, 20 + }; 12 21 13 22 /*tc35876x DSI_LVDS bridge chip and panel platform data*/ 14 23 static void *tc35876x_platform_data(void *data) 15 24 { 16 - static struct tc35876x_platform_data pdata; 25 + struct gpiod_lookup_table *table = &tc35876x_gpio_table; 26 + struct gpiod_lookup *lookup = table->table; 17 27 18 - /* gpio pins set to -1 will not be used by the driver */ 19 - pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN"); 20 - pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN"); 21 - pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3"); 28 + lookup[0].chip_hwnum = get_gpio_by_name("LCMB_RXEN"); 29 + lookup[1].chip_hwnum = get_gpio_by_name("6S6P_BL_EN"); 30 + lookup[2].chip_hwnum = get_gpio_by_name("EN_VREG_LCD_V3P3"); 31 + gpiod_add_lookup_table(table); 22 32 23 - return &pdata; 33 + return NULL; 24 34 } 25 35 26 36 static const struct devs_id tc35876x_dev_id __initconst = {
+33 -55
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
··· 25 25 #include <linux/delay.h> 26 26 #include <linux/kernel.h> 27 27 #include <linux/module.h> 28 - #include <linux/platform_data/tc35876x.h> 28 + #include <linux/gpio/consumer.h> 29 29 30 30 #include <asm/intel_scu_ipc.h> 31 31 ··· 36 36 37 37 static struct i2c_client *tc35876x_client; 38 38 static struct i2c_client *cmi_lcd_i2c_client; 39 + /* Panel GPIOs */ 40 + static struct gpio_desc *bridge_reset; 41 + static struct gpio_desc *bridge_bl_enable; 42 + static struct gpio_desc *backlight_voltage; 43 + 39 44 40 45 #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) 41 46 #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) ··· 321 316 322 317 void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state) 323 318 { 324 - struct tc35876x_platform_data *pdata; 325 - 326 319 if (WARN(!tc35876x_client, "%s called before probe", __func__)) 327 320 return; 328 321 329 322 dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state); 330 323 331 - pdata = dev_get_platdata(&tc35876x_client->dev); 332 - 333 - if (pdata->gpio_bridge_reset == -1) 324 + if (!bridge_reset) 334 325 return; 335 326 336 327 if (state) { 337 - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); 328 + gpiod_set_value_cansleep(bridge_reset, 0); 338 329 mdelay(10); 339 330 } else { 340 331 /* Pull MIPI Bridge reset pin to Low */ 341 - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); 332 + gpiod_set_value_cansleep(bridge_reset, 0); 342 333 mdelay(20); 343 334 /* Pull MIPI Bridge reset pin to High */ 344 - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1); 335 + gpiod_set_value_cansleep(bridge_reset, 1); 345 336 mdelay(40); 346 337 } 347 338 } ··· 511 510 512 511 void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) 513 512 { 514 - struct tc35876x_platform_data *pdata; 515 - 516 513 if (WARN(!tc35876x_client, "%s called before probe", __func__)) 517 514 return; 518 515 519 516 dev_dbg(&tc35876x_client->dev, "%s\n", __func__); 520 517 521 - pdata = dev_get_platdata(&tc35876x_client->dev); 518 + if (bridge_bl_enable) 519 + gpiod_set_value_cansleep(bridge_bl_enable, 0); 522 520 523 - if (pdata->gpio_panel_bl_en != -1) 524 - gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0); 525 - 526 - if (pdata->gpio_panel_vadd != -1) 527 - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0); 521 + if (backlight_voltage) 522 + gpiod_set_value_cansleep(backlight_voltage, 0); 528 523 } 529 524 530 525 void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) 531 526 { 532 - struct tc35876x_platform_data *pdata; 533 527 struct drm_psb_private *dev_priv = dev->dev_private; 534 528 535 529 if (WARN(!tc35876x_client, "%s called before probe", __func__)) ··· 532 536 533 537 dev_dbg(&tc35876x_client->dev, "%s\n", __func__); 534 538 535 - pdata = dev_get_platdata(&tc35876x_client->dev); 536 - 537 - if (pdata->gpio_panel_vadd != -1) { 538 - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1); 539 + if (backlight_voltage) { 540 + gpiod_set_value_cansleep(backlight_voltage, 1); 539 541 msleep(260); 540 542 } 541 543 ··· 565 571 "i2c write failed (%d)\n", ret); 566 572 } 567 573 568 - if (pdata->gpio_panel_bl_en != -1) 569 - gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1); 574 + if (bridge_bl_enable) 575 + gpiod_set_value_cansleep(bridge_bl_enable, 1); 570 576 571 577 tc35876x_brightness_control(dev, dev_priv->brightness_adjusted); 572 578 } ··· 629 635 static int tc35876x_bridge_probe(struct i2c_client *client, 630 636 const struct i2c_device_id *id) 631 637 { 632 - struct tc35876x_platform_data *pdata; 633 - 634 638 dev_info(&client->dev, "%s\n", __func__); 635 639 636 640 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ··· 637 645 return -ENODEV; 638 646 } 639 647 640 - pdata = dev_get_platdata(&client->dev); 641 - if (!pdata) { 642 - dev_err(&client->dev, "%s: no platform data\n", __func__); 643 - return -ENODEV; 644 - } 648 + bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW); 649 + if (IS_ERR(bridge_reset)) 650 + return PTR_ERR(bridge_reset); 651 + if (bridge_reset) 652 + gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset"); 645 653 646 - if (pdata->gpio_bridge_reset != -1) { 647 - gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset"); 648 - gpio_direction_output(pdata->gpio_bridge_reset, 0); 649 - } 654 + bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW); 655 + if (IS_ERR(bridge_bl_enable)) 656 + return PTR_ERR(bridge_bl_enable); 657 + if (bridge_bl_enable) 658 + gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en"); 650 659 651 - if (pdata->gpio_panel_bl_en != -1) { 652 - gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en"); 653 - gpio_direction_output(pdata->gpio_panel_bl_en, 0); 654 - } 655 - 656 - if (pdata->gpio_panel_vadd != -1) { 657 - gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd"); 658 - gpio_direction_output(pdata->gpio_panel_vadd, 0); 659 - } 660 + backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW); 661 + if (IS_ERR(backlight_voltage)) 662 + return PTR_ERR(backlight_voltage); 663 + if (backlight_voltage) 664 + gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd"); 660 665 661 666 tc35876x_client = client; 662 667 ··· 662 673 663 674 static int tc35876x_bridge_remove(struct i2c_client *client) 664 675 { 665 - struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev); 666 - 667 676 dev_dbg(&client->dev, "%s\n", __func__); 668 - 669 - if (pdata->gpio_bridge_reset != -1) 670 - gpio_free(pdata->gpio_bridge_reset); 671 - 672 - if (pdata->gpio_panel_bl_en != -1) 673 - gpio_free(pdata->gpio_panel_bl_en); 674 - 675 - if (pdata->gpio_panel_vadd != -1) 676 - gpio_free(pdata->gpio_panel_vadd); 677 677 678 678 tc35876x_client = NULL; 679 679
-11
include/linux/platform_data/tc35876x.h
··· 1 - 2 - #ifndef _TC35876X_H 3 - #define _TC35876X_H 4 - 5 - struct tc35876x_platform_data { 6 - int gpio_bridge_reset; 7 - int gpio_panel_bl_en; 8 - int gpio_panel_vadd; 9 - }; 10 - 11 - #endif /* _TC35876X_H */