1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2012 Avionic Design GmbH
4 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_panel.h>
13 #include <media/cec-notifier.h>
15 int tegra_output_connector_get_modes(struct drm_connector *connector)
17 struct tegra_output *output = connector_to_output(connector);
18 struct edid *edid = NULL;
22 * If the panel provides one or more modes, use them exclusively and
23 * ignore any other means of obtaining a mode.
26 err = output->panel->funcs->get_modes(output->panel);
32 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
34 edid = drm_get_edid(connector, output->ddc);
36 cec_notifier_set_phys_addr_from_edid(output->cec, edid);
37 drm_connector_update_edid_property(connector, edid);
40 err = drm_add_edid_modes(connector, edid);
47 enum drm_connector_status
48 tegra_output_connector_detect(struct drm_connector *connector, bool force)
50 struct tegra_output *output = connector_to_output(connector);
51 enum drm_connector_status status = connector_status_unknown;
53 if (output->hpd_gpio) {
54 if (gpiod_get_value(output->hpd_gpio) == 0)
55 status = connector_status_disconnected;
57 status = connector_status_connected;
60 status = connector_status_disconnected;
62 status = connector_status_connected;
65 if (status != connector_status_connected)
66 cec_notifier_phys_addr_invalidate(output->cec);
71 void tegra_output_connector_destroy(struct drm_connector *connector)
73 drm_connector_unregister(connector);
74 drm_connector_cleanup(connector);
77 void tegra_output_encoder_destroy(struct drm_encoder *encoder)
79 drm_encoder_cleanup(encoder);
82 static irqreturn_t hpd_irq(int irq, void *data)
84 struct tegra_output *output = data;
86 if (output->connector.dev)
87 drm_helper_hpd_irq_event(output->connector.dev);
92 int tegra_output_probe(struct tegra_output *output)
94 struct device_node *ddc, *panel;
99 output->of_node = output->dev->of_node;
101 panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
103 output->panel = of_drm_find_panel(panel);
104 if (IS_ERR(output->panel))
105 return PTR_ERR(output->panel);
110 output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
112 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
114 output->ddc = of_find_i2c_adapter_by_node(ddc);
124 output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev,
126 "nvidia,hpd-gpio", 0,
128 "HDMI hotplug detect");
129 if (IS_ERR(output->hpd_gpio))
130 return PTR_ERR(output->hpd_gpio);
132 if (output->hpd_gpio) {
133 err = gpiod_to_irq(output->hpd_gpio);
135 dev_err(output->dev, "gpiod_to_irq(): %d\n", err);
139 output->hpd_irq = err;
141 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
144 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
145 flags, "hpd", output);
147 dev_err(output->dev, "failed to request IRQ#%u: %d\n",
148 output->hpd_irq, err);
152 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
155 * Disable the interrupt until the connector has been
156 * initialized to avoid a race in the hotplug interrupt
159 disable_irq(output->hpd_irq);
162 output->cec = cec_notifier_get(output->dev);
169 void tegra_output_remove(struct tegra_output *output)
172 cec_notifier_put(output->cec);
174 if (output->hpd_gpio)
175 free_irq(output->hpd_irq, output);
178 put_device(&output->ddc->dev);
181 int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
186 err = drm_panel_attach(output->panel, &output->connector);
192 * The connector is now registered and ready to receive hotplug events
193 * so the hotplug interrupt can be enabled.
195 if (output->hpd_gpio)
196 enable_irq(output->hpd_irq);
201 void tegra_output_exit(struct tegra_output *output)
204 * The connector is going away, so the interrupt must be disabled to
205 * prevent the hotplug interrupt handler from potentially crashing.
207 if (output->hpd_gpio)
208 disable_irq(output->hpd_irq);
211 drm_panel_detach(output->panel);
214 void tegra_output_find_possible_crtcs(struct tegra_output *output,
215 struct drm_device *drm)
217 struct device *dev = output->dev;
218 struct drm_crtc *crtc;
219 unsigned int mask = 0;
221 drm_for_each_crtc(crtc, drm) {
222 struct tegra_dc *dc = to_tegra_dc(crtc);
224 if (tegra_dc_has_output(dc, dev))
225 mask |= drm_crtc_mask(crtc);
229 dev_warn(dev, "missing output definition for heads in DT\n");
233 output->encoder.possible_crtcs = mask;