1 /* 2 * Copyright (C) 2012 Avionic Design GmbH 3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <drm/drm_atomic_helper.h> 11 #include <drm/drm_panel.h> 12 #include "drm.h" 13 14 int tegra_output_connector_get_modes(struct drm_connector *connector) 15 { 16 struct tegra_output *output = connector_to_output(connector); 17 struct edid *edid = NULL; 18 int err = 0; 19 20 /* 21 * If the panel provides one or more modes, use them exclusively and 22 * ignore any other means of obtaining a mode. 23 */ 24 if (output->panel) { 25 err = output->panel->funcs->get_modes(output->panel); 26 if (err > 0) 27 return err; 28 } 29 30 if (output->edid) 31 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); 32 else if (output->ddc) 33 edid = drm_get_edid(connector, output->ddc); 34 35 drm_mode_connector_update_edid_property(connector, edid); 36 37 if (edid) { 38 err = drm_add_edid_modes(connector, edid); 39 kfree(edid); 40 } 41 42 return err; 43 } 44 45 struct drm_encoder * 46 tegra_output_connector_best_encoder(struct drm_connector *connector) 47 { 48 struct tegra_output *output = connector_to_output(connector); 49 50 return &output->encoder; 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 (gpio_is_valid(output->hpd_gpio)) { 60 if (output->hpd_gpio_flags & OF_GPIO_ACTIVE_LOW) { 61 if (gpio_get_value(output->hpd_gpio) != 0) 62 status = connector_status_disconnected; 63 else 64 status = connector_status_connected; 65 } else { 66 if (gpio_get_value(output->hpd_gpio) == 0) 67 status = connector_status_disconnected; 68 else 69 status = connector_status_connected; 70 } 71 } else { 72 if (!output->panel) 73 status = connector_status_disconnected; 74 else 75 status = connector_status_connected; 76 } 77 78 return status; 79 } 80 81 void tegra_output_connector_destroy(struct drm_connector *connector) 82 { 83 drm_connector_unregister(connector); 84 drm_connector_cleanup(connector); 85 } 86 87 void tegra_output_encoder_destroy(struct drm_encoder *encoder) 88 { 89 drm_encoder_cleanup(encoder); 90 } 91 92 static irqreturn_t hpd_irq(int irq, void *data) 93 { 94 struct tegra_output *output = data; 95 96 if (output->connector.dev) 97 drm_helper_hpd_irq_event(output->connector.dev); 98 99 return IRQ_HANDLED; 100 } 101 102 int tegra_output_probe(struct tegra_output *output) 103 { 104 struct device_node *ddc, *panel; 105 int err, size; 106 107 if (!output->of_node) 108 output->of_node = output->dev->of_node; 109 110 panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); 111 if (panel) { 112 output->panel = of_drm_find_panel(panel); 113 if (!output->panel) 114 return -EPROBE_DEFER; 115 116 of_node_put(panel); 117 } 118 119 output->edid = of_get_property(output->of_node, "nvidia,edid", &size); 120 121 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); 122 if (ddc) { 123 output->ddc = of_find_i2c_adapter_by_node(ddc); 124 if (!output->ddc) { 125 err = -EPROBE_DEFER; 126 of_node_put(ddc); 127 return err; 128 } 129 130 of_node_put(ddc); 131 } 132 133 output->hpd_gpio = of_get_named_gpio_flags(output->of_node, 134 "nvidia,hpd-gpio", 0, 135 &output->hpd_gpio_flags); 136 if (gpio_is_valid(output->hpd_gpio)) { 137 unsigned long flags; 138 139 err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN, 140 "HDMI hotplug detect"); 141 if (err < 0) { 142 dev_err(output->dev, "gpio_request_one(): %d\n", err); 143 return err; 144 } 145 146 err = gpio_to_irq(output->hpd_gpio); 147 if (err < 0) { 148 dev_err(output->dev, "gpio_to_irq(): %d\n", err); 149 gpio_free(output->hpd_gpio); 150 return err; 151 } 152 153 output->hpd_irq = err; 154 155 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 156 IRQF_ONESHOT; 157 158 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq, 159 flags, "hpd", output); 160 if (err < 0) { 161 dev_err(output->dev, "failed to request IRQ#%u: %d\n", 162 output->hpd_irq, err); 163 gpio_free(output->hpd_gpio); 164 return err; 165 } 166 167 output->connector.polled = DRM_CONNECTOR_POLL_HPD; 168 169 /* 170 * Disable the interrupt until the connector has been 171 * initialized to avoid a race in the hotplug interrupt 172 * handler. 173 */ 174 disable_irq(output->hpd_irq); 175 } 176 177 return 0; 178 } 179 180 void tegra_output_remove(struct tegra_output *output) 181 { 182 if (gpio_is_valid(output->hpd_gpio)) { 183 free_irq(output->hpd_irq, output); 184 gpio_free(output->hpd_gpio); 185 } 186 187 if (output->ddc) 188 put_device(&output->ddc->dev); 189 } 190 191 int tegra_output_init(struct drm_device *drm, struct tegra_output *output) 192 { 193 int err; 194 195 if (output->panel) { 196 err = drm_panel_attach(output->panel, &output->connector); 197 if (err < 0) 198 return err; 199 } 200 201 /* 202 * The connector is now registered and ready to receive hotplug events 203 * so the hotplug interrupt can be enabled. 204 */ 205 if (gpio_is_valid(output->hpd_gpio)) 206 enable_irq(output->hpd_irq); 207 208 return 0; 209 } 210 211 void tegra_output_exit(struct tegra_output *output) 212 { 213 /* 214 * The connector is going away, so the interrupt must be disabled to 215 * prevent the hotplug interrupt handler from potentially crashing. 216 */ 217 if (gpio_is_valid(output->hpd_gpio)) 218 disable_irq(output->hpd_irq); 219 220 if (output->panel) 221 drm_panel_detach(output->panel); 222 } 223