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 <linux/module.h> 11 #include <linux/of_gpio.h> 12 #include <linux/of_i2c.h> 13 14 #include "drm.h" 15 16 static int tegra_connector_get_modes(struct drm_connector *connector) 17 { 18 struct tegra_output *output = connector_to_output(connector); 19 struct edid *edid = NULL; 20 int err = 0; 21 22 if (output->edid) 23 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); 24 else if (output->ddc) 25 edid = drm_get_edid(connector, output->ddc); 26 27 drm_mode_connector_update_edid_property(connector, edid); 28 29 if (edid) { 30 err = drm_add_edid_modes(connector, edid); 31 kfree(edid); 32 } 33 34 return err; 35 } 36 37 static int tegra_connector_mode_valid(struct drm_connector *connector, 38 struct drm_display_mode *mode) 39 { 40 struct tegra_output *output = connector_to_output(connector); 41 enum drm_mode_status status = MODE_OK; 42 int err; 43 44 err = tegra_output_check_mode(output, mode, &status); 45 if (err < 0) 46 return MODE_ERROR; 47 48 return status; 49 } 50 51 static struct drm_encoder * 52 tegra_connector_best_encoder(struct drm_connector *connector) 53 { 54 struct tegra_output *output = connector_to_output(connector); 55 56 return &output->encoder; 57 } 58 59 static const struct drm_connector_helper_funcs connector_helper_funcs = { 60 .get_modes = tegra_connector_get_modes, 61 .mode_valid = tegra_connector_mode_valid, 62 .best_encoder = tegra_connector_best_encoder, 63 }; 64 65 static enum drm_connector_status 66 tegra_connector_detect(struct drm_connector *connector, bool force) 67 { 68 struct tegra_output *output = connector_to_output(connector); 69 enum drm_connector_status status = connector_status_unknown; 70 71 if (gpio_is_valid(output->hpd_gpio)) { 72 if (gpio_get_value(output->hpd_gpio) == 0) 73 status = connector_status_disconnected; 74 else 75 status = connector_status_connected; 76 } else { 77 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) 78 status = connector_status_connected; 79 } 80 81 return status; 82 } 83 84 static void tegra_connector_destroy(struct drm_connector *connector) 85 { 86 drm_sysfs_connector_remove(connector); 87 drm_connector_cleanup(connector); 88 } 89 90 static const struct drm_connector_funcs connector_funcs = { 91 .dpms = drm_helper_connector_dpms, 92 .detect = tegra_connector_detect, 93 .fill_modes = drm_helper_probe_single_connector_modes, 94 .destroy = tegra_connector_destroy, 95 }; 96 97 static void tegra_encoder_destroy(struct drm_encoder *encoder) 98 { 99 drm_encoder_cleanup(encoder); 100 } 101 102 static const struct drm_encoder_funcs encoder_funcs = { 103 .destroy = tegra_encoder_destroy, 104 }; 105 106 static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) 107 { 108 } 109 110 static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder, 111 const struct drm_display_mode *mode, 112 struct drm_display_mode *adjusted) 113 { 114 return true; 115 } 116 117 static void tegra_encoder_prepare(struct drm_encoder *encoder) 118 { 119 } 120 121 static void tegra_encoder_commit(struct drm_encoder *encoder) 122 { 123 } 124 125 static void tegra_encoder_mode_set(struct drm_encoder *encoder, 126 struct drm_display_mode *mode, 127 struct drm_display_mode *adjusted) 128 { 129 struct tegra_output *output = encoder_to_output(encoder); 130 int err; 131 132 err = tegra_output_enable(output); 133 if (err < 0) 134 dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err); 135 } 136 137 static const struct drm_encoder_helper_funcs encoder_helper_funcs = { 138 .dpms = tegra_encoder_dpms, 139 .mode_fixup = tegra_encoder_mode_fixup, 140 .prepare = tegra_encoder_prepare, 141 .commit = tegra_encoder_commit, 142 .mode_set = tegra_encoder_mode_set, 143 }; 144 145 static irqreturn_t hpd_irq(int irq, void *data) 146 { 147 struct tegra_output *output = data; 148 149 drm_helper_hpd_irq_event(output->connector.dev); 150 151 return IRQ_HANDLED; 152 } 153 154 int tegra_output_parse_dt(struct tegra_output *output) 155 { 156 enum of_gpio_flags flags; 157 struct device_node *ddc; 158 size_t size; 159 int err; 160 161 if (!output->of_node) 162 output->of_node = output->dev->of_node; 163 164 output->edid = of_get_property(output->of_node, "nvidia,edid", &size); 165 166 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); 167 if (ddc) { 168 output->ddc = of_find_i2c_adapter_by_node(ddc); 169 if (!output->ddc) { 170 err = -EPROBE_DEFER; 171 of_node_put(ddc); 172 return err; 173 } 174 175 of_node_put(ddc); 176 } 177 178 if (!output->edid && !output->ddc) 179 return -ENODEV; 180 181 output->hpd_gpio = of_get_named_gpio_flags(output->of_node, 182 "nvidia,hpd-gpio", 0, 183 &flags); 184 185 return 0; 186 } 187 188 int tegra_output_init(struct drm_device *drm, struct tegra_output *output) 189 { 190 int connector, encoder, err; 191 192 if (gpio_is_valid(output->hpd_gpio)) { 193 unsigned long flags; 194 195 err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN, 196 "HDMI hotplug detect"); 197 if (err < 0) { 198 dev_err(output->dev, "gpio_request_one(): %d\n", err); 199 return err; 200 } 201 202 err = gpio_to_irq(output->hpd_gpio); 203 if (err < 0) { 204 dev_err(output->dev, "gpio_to_irq(): %d\n", err); 205 goto free_hpd; 206 } 207 208 output->hpd_irq = err; 209 210 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 211 IRQF_ONESHOT; 212 213 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq, 214 flags, "hpd", output); 215 if (err < 0) { 216 dev_err(output->dev, "failed to request IRQ#%u: %d\n", 217 output->hpd_irq, err); 218 goto free_hpd; 219 } 220 221 output->connector.polled = DRM_CONNECTOR_POLL_HPD; 222 } 223 224 switch (output->type) { 225 case TEGRA_OUTPUT_RGB: 226 connector = DRM_MODE_CONNECTOR_LVDS; 227 encoder = DRM_MODE_ENCODER_LVDS; 228 break; 229 230 case TEGRA_OUTPUT_HDMI: 231 connector = DRM_MODE_CONNECTOR_HDMIA; 232 encoder = DRM_MODE_ENCODER_TMDS; 233 break; 234 235 default: 236 connector = DRM_MODE_CONNECTOR_Unknown; 237 encoder = DRM_MODE_ENCODER_NONE; 238 break; 239 } 240 241 drm_connector_init(drm, &output->connector, &connector_funcs, 242 connector); 243 drm_connector_helper_add(&output->connector, &connector_helper_funcs); 244 245 drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); 246 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); 247 248 drm_mode_connector_attach_encoder(&output->connector, &output->encoder); 249 drm_sysfs_connector_add(&output->connector); 250 251 output->encoder.possible_crtcs = 0x3; 252 253 return 0; 254 255 free_hpd: 256 gpio_free(output->hpd_gpio); 257 258 return err; 259 } 260 261 int tegra_output_exit(struct tegra_output *output) 262 { 263 if (gpio_is_valid(output->hpd_gpio)) { 264 free_irq(output->hpd_irq, output); 265 gpio_free(output->hpd_gpio); 266 } 267 268 if (output->ddc) 269 put_device(&output->ddc->dev); 270 271 return 0; 272 } 273