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