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

drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer conflict

commit 6de79dd3a920 ("drm/bridge: display-connector: add ddc-en gpio
support") added a consumer for this GPIO in the HDMI connector device.
This new consumer conflicts with the pre-existing GPIO consumer in the
sun8i HDMI controller driver, which prevents the driver from probing:

[ 4.983358] display-connector connector: GPIO lookup for consumer ddc-en
[ 4.983364] display-connector connector: using device tree for GPIO lookup
[ 4.983392] gpio-226 (ddc-en): gpiod_request: status -16
[ 4.983399] sun8i-dw-hdmi 6000000.hdmi: Couldn't get ddc-en gpio
[ 4.983618] sun4i-drm display-engine: failed to bind 6000000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -16
[ 4.984082] sun4i-drm display-engine: Couldn't bind all pipelines components
[ 4.984171] sun4i-drm display-engine: adev bind failed: -16
[ 4.984179] sun8i-dw-hdmi: probe of 6000000.hdmi failed with error -16

Both drivers have the same behavior: they leave the GPIO active for the
life of the device. Let's take advantage of the new implementation, and
drop the now-obsolete code from the HDMI controller driver.

Fixes: 6de79dd3a920 ("drm/bridge: display-connector: add ddc-en gpio support")
Signed-off-by: Samuel Holland <samuel@sholland.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220614073100.11550-1-samuel@sholland.org

authored by

Samuel Holland and committed by
Maxime Ripard
92016904 0f9cd1ea

+4 -52
+4 -50
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
··· 93 93 return crtcs; 94 94 } 95 95 96 - static int sun8i_dw_hdmi_find_connector_pdev(struct device *dev, 97 - struct platform_device **pdev_out) 98 - { 99 - struct platform_device *pdev; 100 - struct device_node *remote; 101 - 102 - remote = of_graph_get_remote_node(dev->of_node, 1, -1); 103 - if (!remote) 104 - return -ENODEV; 105 - 106 - if (!of_device_is_compatible(remote, "hdmi-connector")) { 107 - of_node_put(remote); 108 - return -ENODEV; 109 - } 110 - 111 - pdev = of_find_device_by_node(remote); 112 - of_node_put(remote); 113 - if (!pdev) 114 - return -ENODEV; 115 - 116 - *pdev_out = pdev; 117 - return 0; 118 - } 119 - 120 96 static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, 121 97 void *data) 122 98 { 123 - struct platform_device *pdev = to_platform_device(dev), *connector_pdev; 99 + struct platform_device *pdev = to_platform_device(dev); 124 100 struct dw_hdmi_plat_data *plat_data; 125 101 struct drm_device *drm = data; 126 102 struct device_node *phy_node; ··· 143 167 return dev_err_probe(dev, PTR_ERR(hdmi->regulator), 144 168 "Couldn't get regulator\n"); 145 169 146 - ret = sun8i_dw_hdmi_find_connector_pdev(dev, &connector_pdev); 147 - if (!ret) { 148 - hdmi->ddc_en = gpiod_get_optional(&connector_pdev->dev, 149 - "ddc-en", GPIOD_OUT_HIGH); 150 - platform_device_put(connector_pdev); 151 - 152 - if (IS_ERR(hdmi->ddc_en)) { 153 - dev_err(dev, "Couldn't get ddc-en gpio\n"); 154 - return PTR_ERR(hdmi->ddc_en); 155 - } 156 - } 157 - 158 170 ret = regulator_enable(hdmi->regulator); 159 171 if (ret) { 160 172 dev_err(dev, "Failed to enable regulator\n"); 161 - goto err_unref_ddc_en; 173 + return ret; 162 174 } 163 - 164 - gpiod_set_value(hdmi->ddc_en, 1); 165 175 166 176 ret = reset_control_deassert(hdmi->rst_ctrl); 167 177 if (ret) { 168 178 dev_err(dev, "Could not deassert ctrl reset control\n"); 169 - goto err_disable_ddc_en; 179 + goto err_disable_regulator; 170 180 } 171 181 172 182 ret = clk_prepare_enable(hdmi->clk_tmds); ··· 207 245 clk_disable_unprepare(hdmi->clk_tmds); 208 246 err_assert_ctrl_reset: 209 247 reset_control_assert(hdmi->rst_ctrl); 210 - err_disable_ddc_en: 211 - gpiod_set_value(hdmi->ddc_en, 0); 248 + err_disable_regulator: 212 249 regulator_disable(hdmi->regulator); 213 - err_unref_ddc_en: 214 - if (hdmi->ddc_en) 215 - gpiod_put(hdmi->ddc_en); 216 250 217 251 return ret; 218 252 } ··· 222 264 sun8i_hdmi_phy_deinit(hdmi->phy); 223 265 clk_disable_unprepare(hdmi->clk_tmds); 224 266 reset_control_assert(hdmi->rst_ctrl); 225 - gpiod_set_value(hdmi->ddc_en, 0); 226 267 regulator_disable(hdmi->regulator); 227 - 228 - if (hdmi->ddc_en) 229 - gpiod_put(hdmi->ddc_en); 230 268 } 231 269 232 270 static const struct component_ops sun8i_dw_hdmi_ops = {
-2
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
··· 9 9 #include <drm/bridge/dw_hdmi.h> 10 10 #include <drm/drm_encoder.h> 11 11 #include <linux/clk.h> 12 - #include <linux/gpio/consumer.h> 13 12 #include <linux/regmap.h> 14 13 #include <linux/regulator/consumer.h> 15 14 #include <linux/reset.h> ··· 192 193 struct regulator *regulator; 193 194 const struct sun8i_dw_hdmi_quirks *quirks; 194 195 struct reset_control *rst_ctrl; 195 - struct gpio_desc *ddc_en; 196 196 }; 197 197 198 198 extern struct platform_driver sun8i_hdmi_phy_driver;