diff --git a/include/linux/msm_gpio.h b/include/linux/msm_gpio.h index 31ed14f..f8e62ac 100644 --- a/include/linux/msm_gpio.h +++ b/include/linux/msm_gpio.h @@ -24,6 +24,8 @@ * This shim preserves the legacy integer-GPIO calling convention for * out-of-tree drivers that have not yet migrated to the descriptor API. * + * fwnode_gpiod_get_index() does not mutate the fwnode; the non-const + * signature is a kernel API oversight. * The cast to (struct fwnode_handle *) drops the const qualifier that * of_fwnode_handle() preserves from its const device_node argument. * fwnode_gpiod_get_index() does not mutate the fwnode; the non-const diff --git a/msm/dp/dp_gpio_hpd.c b/msm/dp/dp_gpio_hpd.c index e51224d..af4b4c7 100644 --- a/msm/dp/dp_gpio_hpd.c +++ b/msm/dp/dp_gpio_hpd.c @@ -223,7 +223,7 @@ struct dp_hpd *dp_gpio_hpd_get(struct device *dev, const char *hpd_gpio_name = "qcom,dp-hpd-gpio"; struct dp_gpio_hpd_private *gpio_hpd; struct dp_pinctrl pinctrl = {0}; - unsigned int gpio; + struct gpio_desc *gpiod; if (!dev || !cb) { DP_ERR("invalid device\n"); @@ -231,10 +231,10 @@ struct dp_hpd *dp_gpio_hpd_get(struct device *dev, goto error; } - gpio = of_get_named_gpio(dev->of_node, hpd_gpio_name, 0); - if (!gpio_is_valid(gpio)) { + gpiod = devm_gpiod_get(dev, "qcom,dp-hpd", GPIOD_IN); + if (IS_ERR(gpiod)) { DP_DEBUG("%s gpio not specified\n", hpd_gpio_name); - rc = -EINVAL; + rc = PTR_ERR(gpiod); goto error; } @@ -258,22 +258,14 @@ struct dp_hpd *dp_gpio_hpd_get(struct device *dev, } } - gpio_hpd->gpio_cfg.gpio = gpio; + gpio_hpd->gpio_cfg.gpio = desc_to_gpio(gpiod); strscpy(gpio_hpd->gpio_cfg.gpio_name, hpd_gpio_name, sizeof(gpio_hpd->gpio_cfg.gpio_name)); gpio_hpd->gpio_cfg.value = 0; - rc = gpio_request(gpio_hpd->gpio_cfg.gpio, - gpio_hpd->gpio_cfg.gpio_name); - if (rc) { - DP_ERR("%s: failed to request gpio\n", hpd_gpio_name); - goto gpio_error; - } - gpio_direction_input(gpio_hpd->gpio_cfg.gpio); - gpio_hpd->dev = dev; gpio_hpd->cb = cb; - gpio_hpd->irq = gpio_to_irq(gpio_hpd->gpio_cfg.gpio); + gpio_hpd->irq = gpiod_to_irq(gpiod); INIT_DELAYED_WORK(&gpio_hpd->work, dp_gpio_hpd_work); gpio_hpd->base.simulate_connect = dp_gpio_hpd_simulate_connect; diff --git a/msm/dp/dp_lphw_hpd.c b/msm/dp/dp_lphw_hpd.c index b0e9a6b..86c4594 100644 --- a/msm/dp/dp_lphw_hpd.c +++ b/msm/dp/dp_lphw_hpd.c @@ -350,7 +350,7 @@ struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser, int rc = 0; const char *hpd_gpio_name = "qcom,dp-hpd-gpio"; struct dp_lphw_hpd_private *lphw_hpd = NULL; - unsigned int gpio; + struct gpio_desc *gpiod; if (!dev || !parser || !cb) { DP_ERR("invalid device\n"); @@ -358,10 +358,10 @@ struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser, goto error; } - gpio = of_get_named_gpio(dev->of_node, hpd_gpio_name, 0); - if (!gpio_is_valid(gpio)) { + gpiod = devm_gpiod_get(dev, "qcom,dp-hpd", GPIOD_IN); + if (IS_ERR(gpiod)) { DP_DEBUG("%s gpio not specified\n", hpd_gpio_name); - rc = -EINVAL; + rc = PTR_ERR(gpiod); goto error; } @@ -371,22 +371,14 @@ struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser, goto error; } - lphw_hpd->gpio_cfg.gpio = gpio; + lphw_hpd->gpio_cfg.gpio = desc_to_gpio(gpiod); strscpy(lphw_hpd->gpio_cfg.gpio_name, hpd_gpio_name, sizeof(lphw_hpd->gpio_cfg.gpio_name)); lphw_hpd->gpio_cfg.value = 0; - rc = gpio_request(lphw_hpd->gpio_cfg.gpio, - lphw_hpd->gpio_cfg.gpio_name); - if (rc) { - DP_ERR("%s: failed to request gpio\n", hpd_gpio_name); - goto gpio_error; - } - gpio_direction_input(lphw_hpd->gpio_cfg.gpio); - lphw_hpd->dev = dev; lphw_hpd->cb = cb; - lphw_hpd->irq = gpio_to_irq(lphw_hpd->gpio_cfg.gpio); + lphw_hpd->irq = gpiod_to_irq(gpiod); rc = dp_lphw_hpd_create_workqueue(lphw_hpd); if (rc) { diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 4bc63eb..c85d946 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -711,8 +712,16 @@ static void dsi_display_parse_te_data(struct dsi_display *display) return; } - display->disp_te_gpio = of_get_named_gpio(dev->of_node, - "qcom,platform-te-gpio", 0); + display->disp_te_gpiod = devm_gpiod_get(dev, "qcom,platform-te", + GPIOD_IN); + if (IS_ERR(display->disp_te_gpiod)) { + DSI_DEBUG("te gpio not specified, rc=%ld\n", + PTR_ERR(display->disp_te_gpiod)); + display->disp_te_gpiod = NULL; + display->disp_te_gpio = -EINVAL; + } else { + display->disp_te_gpio = desc_to_gpio(display->disp_te_gpiod); + } if (display->fw) rc = dsi_parser_read_u32(display->parser_node, @@ -6041,6 +6050,7 @@ static int dsi_display_get_io_resources(struct msm_io_res *io_res, void *data) struct dsi_display *display; struct platform_device *pdev; int te_gpio, avdd_gpio; + struct gpio_desc *avdd_gpiod; if (!data) return -EINVAL; @@ -6063,7 +6073,7 @@ static int dsi_display_get_io_resources(struct msm_io_res *io_res, void *data) if (rc) return rc; - te_gpio = of_get_named_gpio(pdev->dev.of_node, "qcom,platform-te-gpio", 0); + te_gpio = display->disp_te_gpio; if (gpio_is_valid(te_gpio)) { rc = msm_dss_get_gpio_io_mem(te_gpio, &io_res->mem); if (rc) { @@ -6073,8 +6083,9 @@ static int dsi_display_get_io_resources(struct msm_io_res *io_res, void *data) } } - avdd_gpio = of_get_named_gpio(pdev->dev.of_node, - "qcom,avdd-regulator-gpio", 0); + avdd_gpiod = devm_gpiod_get(&pdev->dev, "qcom,avdd-regulator", + GPIOD_ASIS); + avdd_gpio = IS_ERR(avdd_gpiod) ? -EINVAL : desc_to_gpio(avdd_gpiod); if (gpio_is_valid(avdd_gpio)) { rc = msm_dss_get_gpio_io_mem(avdd_gpio, &io_res->mem); if (rc) diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index eb7dd81..2f86f32 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -192,7 +193,8 @@ struct dsi_display_ops { * @sw_te_using_wd: Is software te enabled * @display_lock: Mutex for dsi_display interface. * @disp_te_gpio: GPIO for panel TE interrupt. - * @is_te_irq_enabled:bool to specify whether TE interrupt is enabled. + * @disp_te_gpiod: GPIO descriptor for panel TE interrupt (kernel >= 7.1). +* @is_te_irq_enabled:bool to specify whether TE interrupt is enabled. * @esd_te_gate: completion gate to signal TE interrupt. * @ctrl_count: Number of DSI interfaces required by panel. * @ctrl: Controller information for DSI display. @@ -261,6 +263,7 @@ struct dsi_display { bool sw_te_using_wd; struct mutex display_lock; int disp_te_gpio; + struct gpio_desc *disp_te_gpiod; bool is_te_irq_enabled; struct completion esd_te_gate; diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index b7c411c..96c4abd 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -156,105 +157,21 @@ static int dsi_panel_post_vreg_get(struct dsi_panel *panel) static int dsi_panel_gpio_request(struct dsi_panel *panel) { - int rc = 0; - struct dsi_panel_reset_config *r_config = &panel->reset_config; - - if (panel->ctl_op_sync && !strcmp(panel->type, "secondary")) - return 0; - - if (gpio_is_valid(r_config->reset_gpio)) { - rc = gpio_request(r_config->reset_gpio, "reset_gpio"); - if (rc) { - DSI_ERR("request for reset_gpio failed, rc=%d\n", rc); - goto error; - } - } - - if (gpio_is_valid(r_config->disp_en_gpio)) { - rc = gpio_request(r_config->disp_en_gpio, "disp_en_gpio"); - if (rc) { - DSI_ERR("request for disp_en_gpio failed, rc=%d\n", rc); - goto error_release_reset; - } - } - - if (panel->need_post_on_supply) { - if (gpio_is_valid(r_config->oled_en_gpio)) { - rc = gpio_request_one(r_config->oled_en_gpio, GPIOF_IN, "oled_en_gpio"); - if (rc) { - DSI_ERR("request for oled_en_gpio failed, rc=%d\n", rc); - goto error_release_disp_en; - } - } - } - - if (gpio_is_valid(panel->bl_config.en_gpio)) { - rc = gpio_request(panel->bl_config.en_gpio, "bklt_en_gpio"); - if (rc) { - DSI_ERR("request for bklt_en_gpio failed, rc=%d\n", rc); - goto error_release_oled_en; - } - } - - if (gpio_is_valid(r_config->lcd_mode_sel_gpio)) { - rc = gpio_request(r_config->lcd_mode_sel_gpio, "mode_gpio"); - if (rc) { - DSI_ERR("request for mode_gpio failed, rc=%d\n", rc); - goto error_release_mode_sel; - } - } - - if (gpio_is_valid(panel->panel_test_gpio)) { - rc = gpio_request(panel->panel_test_gpio, "panel_test_gpio"); - if (rc) { - DSI_WARN("request for panel_test_gpio failed, rc=%d\n", - rc); - panel->panel_test_gpio = -1; - rc = 0; - } - } - - goto error; -error_release_mode_sel: - if (gpio_is_valid(panel->bl_config.en_gpio)) - gpio_free(panel->bl_config.en_gpio); -error_release_oled_en: - if (panel->need_post_on_supply && gpio_is_valid(r_config->oled_en_gpio)) - gpio_free(r_config->oled_en_gpio); -error_release_disp_en: - if (gpio_is_valid(r_config->disp_en_gpio)) - gpio_free(r_config->disp_en_gpio); -error_release_reset: - if (gpio_is_valid(r_config->reset_gpio)) - gpio_free(r_config->reset_gpio); -error: - return rc; + /* + * GPIOs are acquired via devm_gpiod_get() in dsi_panel_parse_gpios() + * and dsi_panel_parse_bl_config(); devm handles cleanup automatically. + * Nothing to do here. + */ + return 0; } static int dsi_panel_gpio_release(struct dsi_panel *panel) { - int rc = 0; - struct dsi_panel_reset_config *r_config = &panel->reset_config; - - if (gpio_is_valid(r_config->reset_gpio)) - gpio_free(r_config->reset_gpio); - - if (gpio_is_valid(r_config->disp_en_gpio)) - gpio_free(r_config->disp_en_gpio); - - if (panel->need_post_on_supply && gpio_is_valid(r_config->oled_en_gpio)) - gpio_free(r_config->oled_en_gpio); - - if (gpio_is_valid(panel->bl_config.en_gpio)) - gpio_free(panel->bl_config.en_gpio); - - if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) - gpio_free(panel->reset_config.lcd_mode_sel_gpio); - - if (gpio_is_valid(panel->panel_test_gpio)) - gpio_free(panel->panel_test_gpio); - - return rc; + /* + * GPIOs were acquired via devm_gpiod_get(); devm handles cleanup + * automatically when the device is unbound. + */ + return 0; } static int dsi_panel_trigger_esd_attack_sub(int reset_gpio) @@ -278,23 +195,24 @@ static int dsi_panel_vm_trigger_esd_attack(struct dsi_panel *panel) int reset_gpio; int rc = 0; - reset_gpio = utils->get_named_gpio(utils->data, - "qcom,platform-reset-gpio", 0); + { + struct gpio_desc *gpiod; + + gpiod = devm_gpiod_get(panel->parent, "qcom,platform-reset", + GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + DSI_ERR("[%s] reset gpio not provided\n", panel->name); + return -EINVAL; + } + reset_gpio = desc_to_gpio(gpiod); + } if (!gpio_is_valid(reset_gpio)) { DSI_ERR("[%s] reset gpio not provided\n", panel->name); return -EINVAL; } - rc = gpio_request(reset_gpio, "reset_gpio"); - if (rc) { - DSI_ERR("request for reset_gpio failed, rc=%d\n", rc); - return rc; - } - rc = dsi_panel_trigger_esd_attack_sub(reset_gpio); - gpio_free(reset_gpio); - return rc; } @@ -317,9 +235,11 @@ static int dsi_panel_trigger_esd_attack(struct dsi_panel *panel) reset_gpio = r_config->reset_gpio; if ((!strcmp(panel->type, "secondary")) && - (!gpio_is_valid(reset_gpio))) - reset_gpio = utils->get_named_gpio(utils->data, - "qcom,platform-reset-gpio", 0); + (!gpio_is_valid(reset_gpio))) { + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + "qcom,platform-reset", GPIOD_ASIS); + reset_gpio = IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); + } return dsi_panel_trigger_esd_attack_sub(reset_gpio); } @@ -3096,13 +3016,17 @@ static int dsi_panel_parse_power_cfg(struct dsi_panel *panel) int dsi_panel_get_io_resources(struct dsi_panel *panel, struct msm_io_res *io_res) { - struct dsi_parser_utils *utils = &panel->utils; struct list_head *mem_list = &io_res->mem; int reset_gpio; int rc = 0; - reset_gpio = utils->get_named_gpio(utils->data, - "qcom,platform-reset-gpio", 0); + { + struct gpio_desc *gpiod; + + gpiod = devm_gpiod_get(panel->parent, "qcom,platform-reset", + GPIOD_ASIS); + reset_gpio = IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); + } if (gpio_is_valid(reset_gpio)) { rc = msm_dss_get_gpio_io_mem(reset_gpio, mem_list); if (rc) { @@ -3120,52 +3044,62 @@ static int dsi_panel_parse_gpios(struct dsi_panel *panel) int rc = 0; const char *data; struct dsi_parser_utils *utils = &panel->utils; - char *reset_gpio_name, *mode_set_gpio_name, *oled_en_gpio_name; - if (!strcmp(panel->type, "primary")) { - reset_gpio_name = "qcom,platform-reset-gpio"; - mode_set_gpio_name = "qcom,panel-mode-gpio"; - oled_en_gpio_name = "qcom,platform-oled-en-gpio"; - } else { - reset_gpio_name = "qcom,platform-sec-reset-gpio"; - mode_set_gpio_name = "qcom,panel-sec-mode-gpio"; - oled_en_gpio_name = "qcom,platform-sec-oled-en-gpio"; + { + const char *con_id = (!strcmp(panel->type, "primary")) ? + "qcom,platform-reset" : "qcom,platform-sec-reset"; + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + con_id, GPIOD_ASIS); + panel->reset_config.reset_gpio = + IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); } - - panel->reset_config.reset_gpio = utils->get_named_gpio(utils->data, - reset_gpio_name, 0); if (!gpio_is_valid(panel->reset_config.reset_gpio) && !panel->host_config.ext_bridge_mode) { DSI_DEBUG("[%s] reset gpio not set, rc=%d\n", panel->name, panel->reset_config.reset_gpio); } - panel->reset_config.disp_en_gpio = utils->get_named_gpio(utils->data, - "qcom,5v-boost-gpio", - 0); - if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) { - DSI_DEBUG("[%s] 5v-boot-gpio is not set, rc=%d\n", - panel->name, rc); - panel->reset_config.disp_en_gpio = - utils->get_named_gpio(utils->data, - "qcom,platform-en-gpio", 0); - if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) { - DSI_DEBUG("[%s] platform-en-gpio is not set, rc=%d\n", - panel->name, rc); + { + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + "qcom,5v-boost", GPIOD_ASIS); + if (IS_ERR(gpiod)) { + DSI_DEBUG("[%s] 5v-boost-gpio is not set\n", + panel->name); + gpiod = devm_gpiod_get(panel->parent, + "qcom,platform-en", GPIOD_ASIS); + if (IS_ERR(gpiod)) + DSI_DEBUG("[%s] platform-en-gpio is not set\n", + panel->name); } + panel->reset_config.disp_en_gpio = + IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); } if (panel->need_post_on_supply) { - panel->reset_config.oled_en_gpio = panel->utils.get_named_gpio(panel->utils.data, - oled_en_gpio_name, 0); - if (!gpio_is_valid(panel->reset_config.oled_en_gpio)) - DSI_DEBUG("[%s] oled-en-gpio is not set\n", panel->name); + { + const char *con_id = (!strcmp(panel->type, "primary")) ? + "qcom,platform-oled-en" : + "qcom,platform-sec-oled-en"; + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + con_id, GPIOD_ASIS); + panel->reset_config.oled_en_gpio = + IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); + if (!gpio_is_valid(panel->reset_config.oled_en_gpio)) + DSI_DEBUG("[%s] oled-en-gpio is not set\n", + panel->name); + } } - panel->reset_config.lcd_mode_sel_gpio = utils->get_named_gpio( - utils->data, mode_set_gpio_name, 0); - if (!gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) - DSI_DEBUG("mode gpio not specified\n"); + { + const char *con_id = (!strcmp(panel->type, "primary")) ? + "qcom,panel-mode" : "qcom,panel-sec-mode"; + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + con_id, GPIOD_ASIS); + panel->reset_config.lcd_mode_sel_gpio = + IS_ERR(gpiod) ? -EINVAL : desc_to_gpio(gpiod); + if (!gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) + DSI_DEBUG("mode gpio not specified\n"); + } DSI_DEBUG("mode gpio=%d\n", panel->reset_config.lcd_mode_sel_gpio); @@ -3339,21 +3273,23 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel) } } - panel->bl_config.en_gpio = utils->get_named_gpio(utils->data, - "qcom,platform-bklight-en-gpio", - 0); - if (!gpio_is_valid(panel->bl_config.en_gpio)) { - if (panel->bl_config.en_gpio == -EPROBE_DEFER) { - DSI_DEBUG("[%s] failed to get bklt gpio, rc=%d\n", - panel->name, rc); - rc = -EPROBE_DEFER; - goto error; - } else { - DSI_DEBUG("[%s] failed to get bklt gpio, rc=%d\n", - panel->name, rc); + { + struct gpio_desc *gpiod = devm_gpiod_get(panel->parent, + "qcom,platform-bklight-en", GPIOD_ASIS); + if (IS_ERR(gpiod)) { + if (PTR_ERR(gpiod) == -EPROBE_DEFER) { + DSI_DEBUG("[%s] bklt gpio probe deferred\n", + panel->name); + rc = -EPROBE_DEFER; + goto error; + } + DSI_DEBUG("[%s] failed to get bklt gpio\n", + panel->name); + panel->bl_config.en_gpio = -EINVAL; rc = 0; goto error; } + panel->bl_config.en_gpio = desc_to_gpio(gpiod); } error: