1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * TPD12S015 HDMI ESD protection & level shifter chip driver 4 * 5 * Copyright (C) 2019 Texas Instruments Incorporated 6 * 7 * Based on the omapdrm-specific encoder-opa362 driver 8 * 9 * Copyright (C) 2013 Texas Instruments Incorporated 10 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/interrupt.h> 16 #include <linux/module.h> 17 #include <linux/mutex.h> 18 #include <linux/of.h> 19 #include <linux/of_graph.h> 20 #include <linux/platform_device.h> 21 22 #include <drm/drm_bridge.h> 23 24 struct tpd12s015_device { 25 struct drm_bridge bridge; 26 27 struct gpio_desc *ct_cp_hpd_gpio; 28 struct gpio_desc *ls_oe_gpio; 29 struct gpio_desc *hpd_gpio; 30 int hpd_irq; 31 }; 32 33 static inline struct tpd12s015_device *to_tpd12s015(struct drm_bridge *bridge) 34 { 35 return container_of(bridge, struct tpd12s015_device, bridge); 36 } 37 38 static int tpd12s015_attach(struct drm_bridge *bridge, 39 struct drm_encoder *encoder, 40 enum drm_bridge_attach_flags flags) 41 { 42 struct tpd12s015_device *tpd = to_tpd12s015(bridge); 43 int ret; 44 45 if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 46 return -EINVAL; 47 48 ret = drm_bridge_attach(encoder, tpd->bridge.next_bridge, 49 bridge, flags); 50 if (ret < 0) 51 return ret; 52 53 gpiod_set_value_cansleep(tpd->ls_oe_gpio, 1); 54 55 /* DC-DC converter needs at max 300us to get to 90% of 5V. */ 56 usleep_range(300, 1000); 57 58 return 0; 59 } 60 61 static void tpd12s015_detach(struct drm_bridge *bridge) 62 { 63 struct tpd12s015_device *tpd = to_tpd12s015(bridge); 64 65 gpiod_set_value_cansleep(tpd->ls_oe_gpio, 0); 66 } 67 68 static enum drm_connector_status tpd12s015_detect(struct drm_bridge *bridge) 69 { 70 struct tpd12s015_device *tpd = to_tpd12s015(bridge); 71 72 if (gpiod_get_value_cansleep(tpd->hpd_gpio)) 73 return connector_status_connected; 74 else 75 return connector_status_disconnected; 76 } 77 78 static enum drm_connector_status 79 tpd12s015_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) 80 { 81 return tpd12s015_detect(bridge); 82 } 83 84 static void tpd12s015_hpd_enable(struct drm_bridge *bridge) 85 { 86 struct tpd12s015_device *tpd = to_tpd12s015(bridge); 87 88 gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 1); 89 } 90 91 static void tpd12s015_hpd_disable(struct drm_bridge *bridge) 92 { 93 struct tpd12s015_device *tpd = to_tpd12s015(bridge); 94 95 gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 0); 96 } 97 98 static const struct drm_bridge_funcs tpd12s015_bridge_funcs = { 99 .attach = tpd12s015_attach, 100 .detach = tpd12s015_detach, 101 .detect = tpd12s015_bridge_detect, 102 .hpd_enable = tpd12s015_hpd_enable, 103 .hpd_disable = tpd12s015_hpd_disable, 104 }; 105 106 static irqreturn_t tpd12s015_hpd_isr(int irq, void *data) 107 { 108 struct tpd12s015_device *tpd = data; 109 struct drm_bridge *bridge = &tpd->bridge; 110 111 drm_bridge_hpd_notify(bridge, tpd12s015_detect(bridge)); 112 113 return IRQ_HANDLED; 114 } 115 116 static int tpd12s015_probe(struct platform_device *pdev) 117 { 118 struct tpd12s015_device *tpd; 119 struct device_node *node; 120 struct gpio_desc *gpio; 121 int ret; 122 123 tpd = devm_drm_bridge_alloc(&pdev->dev, struct tpd12s015_device, 124 bridge, &tpd12s015_bridge_funcs); 125 if (IS_ERR(tpd)) 126 return PTR_ERR(tpd); 127 128 platform_set_drvdata(pdev, tpd); 129 130 tpd->bridge.of_node = pdev->dev.of_node; 131 tpd->bridge.type = DRM_MODE_CONNECTOR_HDMIA; 132 tpd->bridge.ops = DRM_BRIDGE_OP_DETECT; 133 134 /* Get the next bridge, connected to port@1. */ 135 node = of_graph_get_remote_node(pdev->dev.of_node, 1, -1); 136 if (!node) 137 return -ENODEV; 138 139 tpd->bridge.next_bridge = of_drm_find_and_get_bridge(node); 140 of_node_put(node); 141 142 if (!tpd->bridge.next_bridge) 143 return -EPROBE_DEFER; 144 145 /* Get the control and HPD GPIOs. */ 146 gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0, 147 GPIOD_OUT_LOW); 148 if (IS_ERR(gpio)) 149 return PTR_ERR(gpio); 150 151 tpd->ct_cp_hpd_gpio = gpio; 152 153 gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1, 154 GPIOD_OUT_LOW); 155 if (IS_ERR(gpio)) 156 return PTR_ERR(gpio); 157 158 tpd->ls_oe_gpio = gpio; 159 160 gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2, GPIOD_IN); 161 if (IS_ERR(gpio)) 162 return PTR_ERR(gpio); 163 164 tpd->hpd_gpio = gpio; 165 166 /* Register the IRQ if the HPD GPIO is IRQ-capable. */ 167 tpd->hpd_irq = gpiod_to_irq(tpd->hpd_gpio); 168 if (tpd->hpd_irq >= 0) { 169 ret = devm_request_threaded_irq(&pdev->dev, tpd->hpd_irq, NULL, 170 tpd12s015_hpd_isr, 171 IRQF_TRIGGER_RISING | 172 IRQF_TRIGGER_FALLING | 173 IRQF_ONESHOT, 174 "tpd12s015 hpd", tpd); 175 if (ret) 176 return ret; 177 178 tpd->bridge.ops |= DRM_BRIDGE_OP_HPD; 179 } 180 181 /* Register the DRM bridge. */ 182 drm_bridge_add(&tpd->bridge); 183 184 return 0; 185 } 186 187 static void tpd12s015_remove(struct platform_device *pdev) 188 { 189 struct tpd12s015_device *tpd = platform_get_drvdata(pdev); 190 191 drm_bridge_remove(&tpd->bridge); 192 } 193 194 static const struct of_device_id tpd12s015_of_match[] = { 195 { .compatible = "ti,tpd12s015", }, 196 {}, 197 }; 198 199 MODULE_DEVICE_TABLE(of, tpd12s015_of_match); 200 201 static struct platform_driver tpd12s015_driver = { 202 .probe = tpd12s015_probe, 203 .remove = tpd12s015_remove, 204 .driver = { 205 .name = "tpd12s015", 206 .of_match_table = tpd12s015_of_match, 207 }, 208 }; 209 210 module_platform_driver(tpd12s015_driver); 211 212 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 213 MODULE_DESCRIPTION("TPD12S015 HDMI level shifter and ESD protection driver"); 214 MODULE_LICENSE("GPL"); 215