1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2012 Avionic Design GmbH 4 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 5 */ 6 7 #include <linux/i2c.h> 8 #include <linux/of.h> 9 10 #include <drm/drm_atomic_helper.h> 11 #include <drm/drm_edid.h> 12 #include <drm/drm_of.h> 13 #include <drm/drm_panel.h> 14 #include <drm/drm_simple_kms_helper.h> 15 16 #include "drm.h" 17 #include "dc.h" 18 19 #include <media/cec-notifier.h> 20 21 int tegra_output_connector_get_modes(struct drm_connector *connector) 22 { 23 struct tegra_output *output = connector_to_output(connector); 24 struct edid *edid = NULL; 25 int err = 0; 26 27 /* 28 * If the panel provides one or more modes, use them exclusively and 29 * ignore any other means of obtaining a mode. 30 */ 31 if (output->panel) { 32 err = drm_panel_get_modes(output->panel, connector); 33 if (err > 0) 34 return err; 35 } 36 37 if (output->edid) 38 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); 39 else if (output->ddc) 40 edid = drm_get_edid(connector, output->ddc); 41 42 cec_notifier_set_phys_addr_from_edid(output->cec, edid); 43 drm_connector_update_edid_property(connector, edid); 44 45 if (edid) { 46 err = drm_add_edid_modes(connector, edid); 47 kfree(edid); 48 } 49 50 return err; 51 } 52 53 enum drm_connector_status 54 tegra_output_connector_detect(struct drm_connector *connector, bool force) 55 { 56 struct tegra_output *output = connector_to_output(connector); 57 enum drm_connector_status status = connector_status_unknown; 58 59 if (output->hpd_gpio) { 60 if (gpiod_get_value(output->hpd_gpio) == 0) 61 status = connector_status_disconnected; 62 else 63 status = connector_status_connected; 64 } else { 65 if (!output->panel) 66 status = connector_status_disconnected; 67 else 68 status = connector_status_connected; 69 } 70 71 if (status != connector_status_connected) 72 cec_notifier_phys_addr_invalidate(output->cec); 73 74 return status; 75 } 76 77 void tegra_output_connector_destroy(struct drm_connector *connector) 78 { 79 struct tegra_output *output = connector_to_output(connector); 80 81 if (output->cec) 82 cec_notifier_conn_unregister(output->cec); 83 84 drm_connector_unregister(connector); 85 drm_connector_cleanup(connector); 86 } 87 88 static irqreturn_t hpd_irq(int irq, void *data) 89 { 90 struct tegra_output *output = data; 91 92 if (output->connector.dev) 93 drm_helper_hpd_irq_event(output->connector.dev); 94 95 return IRQ_HANDLED; 96 } 97 98 int tegra_output_probe(struct tegra_output *output) 99 { 100 struct device_node *ddc, *panel; 101 unsigned long flags; 102 int err, size; 103 104 if (!output->of_node) 105 output->of_node = output->dev->of_node; 106 107 err = drm_of_find_panel_or_bridge(output->of_node, -1, -1, 108 &output->panel, &output->bridge); 109 if (err && err != -ENODEV) 110 return err; 111 112 panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); 113 if (panel) { 114 /* 115 * Don't mix nvidia,panel phandle with the graph in a 116 * device-tree. 117 */ 118 WARN_ON(output->panel || output->bridge); 119 120 output->panel = of_drm_find_panel(panel); 121 of_node_put(panel); 122 123 if (IS_ERR(output->panel)) 124 return PTR_ERR(output->panel); 125 } 126 127 output->edid = of_get_property(output->of_node, "nvidia,edid", &size); 128 129 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); 130 if (ddc) { 131 output->ddc = of_get_i2c_adapter_by_node(ddc); 132 of_node_put(ddc); 133 134 if (!output->ddc) { 135 err = -EPROBE_DEFER; 136 return err; 137 } 138 } 139 140 output->hpd_gpio = devm_fwnode_gpiod_get(output->dev, 141 of_fwnode_handle(output->of_node), 142 "nvidia,hpd", 143 GPIOD_IN, 144 "HDMI hotplug detect"); 145 if (IS_ERR(output->hpd_gpio)) { 146 if (PTR_ERR(output->hpd_gpio) != -ENOENT) { 147 err = PTR_ERR(output->hpd_gpio); 148 goto put_i2c; 149 } 150 151 output->hpd_gpio = NULL; 152 } 153 154 if (output->hpd_gpio) { 155 err = gpiod_to_irq(output->hpd_gpio); 156 if (err < 0) { 157 dev_err(output->dev, "gpiod_to_irq(): %d\n", err); 158 goto put_i2c; 159 } 160 161 output->hpd_irq = err; 162 163 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 164 IRQF_ONESHOT; 165 166 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq, 167 flags, "hpd", output); 168 if (err < 0) { 169 dev_err(output->dev, "failed to request IRQ#%u: %d\n", 170 output->hpd_irq, err); 171 goto put_i2c; 172 } 173 174 output->connector.polled = DRM_CONNECTOR_POLL_HPD; 175 176 /* 177 * Disable the interrupt until the connector has been 178 * initialized to avoid a race in the hotplug interrupt 179 * handler. 180 */ 181 disable_irq(output->hpd_irq); 182 } 183 184 return 0; 185 186 put_i2c: 187 if (output->ddc) 188 i2c_put_adapter(output->ddc); 189 190 return err; 191 } 192 193 void tegra_output_remove(struct tegra_output *output) 194 { 195 if (output->hpd_gpio) 196 free_irq(output->hpd_irq, output); 197 198 if (output->ddc) 199 i2c_put_adapter(output->ddc); 200 } 201 202 int tegra_output_init(struct drm_device *drm, struct tegra_output *output) 203 { 204 int connector_type; 205 206 /* 207 * The connector is now registered and ready to receive hotplug events 208 * so the hotplug interrupt can be enabled. 209 */ 210 if (output->hpd_gpio) 211 enable_irq(output->hpd_irq); 212 213 connector_type = output->connector.connector_type; 214 /* 215 * Create a CEC notifier for HDMI connector. 216 */ 217 if (connector_type == DRM_MODE_CONNECTOR_HDMIA || 218 connector_type == DRM_MODE_CONNECTOR_HDMIB) { 219 struct cec_connector_info conn_info; 220 221 cec_fill_conn_info_from_drm(&conn_info, &output->connector); 222 output->cec = cec_notifier_conn_register(output->dev, NULL, 223 &conn_info); 224 if (!output->cec) 225 return -ENOMEM; 226 } 227 228 return 0; 229 } 230 231 void tegra_output_exit(struct tegra_output *output) 232 { 233 /* 234 * The connector is going away, so the interrupt must be disabled to 235 * prevent the hotplug interrupt handler from potentially crashing. 236 */ 237 if (output->hpd_gpio) 238 disable_irq(output->hpd_irq); 239 } 240 241 void tegra_output_find_possible_crtcs(struct tegra_output *output, 242 struct drm_device *drm) 243 { 244 struct device *dev = output->dev; 245 struct drm_crtc *crtc; 246 unsigned int mask = 0; 247 248 drm_for_each_crtc(crtc, drm) { 249 struct tegra_dc *dc = to_tegra_dc(crtc); 250 251 if (tegra_dc_has_output(dc, dev)) 252 mask |= drm_crtc_mask(crtc); 253 } 254 255 if (mask == 0) { 256 dev_warn(dev, "missing output definition for heads in DT\n"); 257 mask = 0x3; 258 } 259 260 output->encoder.possible_crtcs = mask; 261 } 262 263 int tegra_output_suspend(struct tegra_output *output) 264 { 265 if (output->hpd_irq) 266 disable_irq(output->hpd_irq); 267 268 return 0; 269 } 270 271 int tegra_output_resume(struct tegra_output *output) 272 { 273 if (output->hpd_irq) 274 enable_irq(output->hpd_irq); 275 276 return 0; 277 } 278