1/* 2 * Copyright (c) 2014 The Linux Foundation. All rights reserved. 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <linux/of_irq.h> 20#include "hdmi.h" 21 22void hdmi_set_mode(struct hdmi *hdmi, bool power_on) 23{ 24 uint32_t ctrl = 0; 25 26 if (power_on) { 27 ctrl |= HDMI_CTRL_ENABLE; 28 if (!hdmi->hdmi_mode) { 29 ctrl |= HDMI_CTRL_HDMI; 30 hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); 31 ctrl &= ~HDMI_CTRL_HDMI; 32 } else { 33 ctrl |= HDMI_CTRL_HDMI; 34 } 35 } else { 36 ctrl = HDMI_CTRL_HDMI; 37 } 38 39 hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); 40 DBG("HDMI Core: %s, HDMI_CTRL=0x%08x", 41 power_on ? "Enable" : "Disable", ctrl); 42} 43 44static irqreturn_t hdmi_irq(int irq, void *dev_id) 45{ 46 struct hdmi *hdmi = dev_id; 47 48 /* Process HPD: */ 49 hdmi_connector_irq(hdmi->connector); 50 51 /* Process DDC: */ 52 hdmi_i2c_irq(hdmi->i2c); 53 54 /* TODO audio.. */ 55 56 return IRQ_HANDLED; 57} 58 59static void hdmi_destroy(struct hdmi *hdmi) 60{ 61 struct hdmi_phy *phy = hdmi->phy; 62 63 if (phy) 64 phy->funcs->destroy(phy); 65 66 if (hdmi->i2c) 67 hdmi_i2c_destroy(hdmi->i2c); 68 69 platform_set_drvdata(hdmi->pdev, NULL); 70} 71 72/* construct hdmi at bind/probe time, grab all the resources. If 73 * we are to EPROBE_DEFER we want to do it here, rather than later 74 * at modeset_init() time 75 */ 76static struct hdmi *hdmi_init(struct platform_device *pdev) 77{ 78 struct hdmi_platform_config *config = pdev->dev.platform_data; 79 struct hdmi *hdmi = NULL; 80 int i, ret; 81 82 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 83 if (!hdmi) { 84 ret = -ENOMEM; 85 goto fail; 86 } 87 88 hdmi->pdev = pdev; 89 hdmi->config = config; 90 91 /* not sure about which phy maps to which msm.. probably I miss some */ 92 if (config->phy_init) 93 hdmi->phy = config->phy_init(hdmi); 94 else 95 hdmi->phy = ERR_PTR(-ENXIO); 96 97 if (IS_ERR(hdmi->phy)) { 98 ret = PTR_ERR(hdmi->phy); 99 dev_err(&pdev->dev, "failed to load phy: %d\n", ret); 100 hdmi->phy = NULL; 101 goto fail; 102 } 103 104 hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); 105 if (IS_ERR(hdmi->mmio)) { 106 ret = PTR_ERR(hdmi->mmio); 107 goto fail; 108 } 109 110 hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) * 111 config->hpd_reg_cnt, GFP_KERNEL); 112 if (!hdmi->hpd_regs) { 113 ret = -ENOMEM; 114 goto fail; 115 } 116 for (i = 0; i < config->hpd_reg_cnt; i++) { 117 struct regulator *reg; 118 119 reg = devm_regulator_get(&pdev->dev, 120 config->hpd_reg_names[i]); 121 if (IS_ERR(reg)) { 122 ret = PTR_ERR(reg); 123 dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", 124 config->hpd_reg_names[i], ret); 125 goto fail; 126 } 127 128 hdmi->hpd_regs[i] = reg; 129 } 130 131 hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) * 132 config->pwr_reg_cnt, GFP_KERNEL); 133 if (!hdmi->pwr_regs) { 134 ret = -ENOMEM; 135 goto fail; 136 } 137 for (i = 0; i < config->pwr_reg_cnt; i++) { 138 struct regulator *reg; 139 140 reg = devm_regulator_get(&pdev->dev, 141 config->pwr_reg_names[i]); 142 if (IS_ERR(reg)) { 143 ret = PTR_ERR(reg); 144 dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", 145 config->pwr_reg_names[i], ret); 146 goto fail; 147 } 148 149 hdmi->pwr_regs[i] = reg; 150 } 151 152 hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) * 153 config->hpd_clk_cnt, GFP_KERNEL); 154 if (!hdmi->hpd_clks) { 155 ret = -ENOMEM; 156 goto fail; 157 } 158 for (i = 0; i < config->hpd_clk_cnt; i++) { 159 struct clk *clk; 160 161 clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); 162 if (IS_ERR(clk)) { 163 ret = PTR_ERR(clk); 164 dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", 165 config->hpd_clk_names[i], ret); 166 goto fail; 167 } 168 169 hdmi->hpd_clks[i] = clk; 170 } 171 172 hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) * 173 config->pwr_clk_cnt, GFP_KERNEL); 174 if (!hdmi->pwr_clks) { 175 ret = -ENOMEM; 176 goto fail; 177 } 178 for (i = 0; i < config->pwr_clk_cnt; i++) { 179 struct clk *clk; 180 181 clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); 182 if (IS_ERR(clk)) { 183 ret = PTR_ERR(clk); 184 dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", 185 config->pwr_clk_names[i], ret); 186 goto fail; 187 } 188 189 hdmi->pwr_clks[i] = clk; 190 } 191 192 hdmi->i2c = hdmi_i2c_init(hdmi); 193 if (IS_ERR(hdmi->i2c)) { 194 ret = PTR_ERR(hdmi->i2c); 195 dev_err(&pdev->dev, "failed to get i2c: %d\n", ret); 196 hdmi->i2c = NULL; 197 goto fail; 198 } 199 200 return hdmi; 201 202fail: 203 if (hdmi) 204 hdmi_destroy(hdmi); 205 206 return ERR_PTR(ret); 207} 208 209/* Second part of initialization, the drm/kms level modeset_init, 210 * constructs/initializes mode objects, etc, is called from master 211 * driver (not hdmi sub-device's probe/bind!) 212 * 213 * Any resource (regulator/clk/etc) which could be missing at boot 214 * should be handled in hdmi_init() so that failure happens from 215 * hdmi sub-device's probe. 216 */ 217int hdmi_modeset_init(struct hdmi *hdmi, 218 struct drm_device *dev, struct drm_encoder *encoder) 219{ 220 struct msm_drm_private *priv = dev->dev_private; 221 struct platform_device *pdev = hdmi->pdev; 222 int ret; 223 224 hdmi->dev = dev; 225 hdmi->encoder = encoder; 226 227 hdmi_audio_infoframe_init(&hdmi->audio.infoframe); 228 229 hdmi->bridge = hdmi_bridge_init(hdmi); 230 if (IS_ERR(hdmi->bridge)) { 231 ret = PTR_ERR(hdmi->bridge); 232 dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret); 233 hdmi->bridge = NULL; 234 goto fail; 235 } 236 237 hdmi->connector = hdmi_connector_init(hdmi); 238 if (IS_ERR(hdmi->connector)) { 239 ret = PTR_ERR(hdmi->connector); 240 dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret); 241 hdmi->connector = NULL; 242 goto fail; 243 } 244 245 hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 246 if (hdmi->irq < 0) { 247 ret = hdmi->irq; 248 dev_err(dev->dev, "failed to get irq: %d\n", ret); 249 goto fail; 250 } 251 252 ret = devm_request_irq(&pdev->dev, hdmi->irq, 253 hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 254 "hdmi_isr", hdmi); 255 if (ret < 0) { 256 dev_err(dev->dev, "failed to request IRQ%u: %d\n", 257 hdmi->irq, ret); 258 goto fail; 259 } 260 261 encoder->bridge = hdmi->bridge; 262 263 priv->bridges[priv->num_bridges++] = hdmi->bridge; 264 priv->connectors[priv->num_connectors++] = hdmi->connector; 265 266 platform_set_drvdata(pdev, hdmi); 267 268 return 0; 269 270fail: 271 /* bridge is normally destroyed by drm: */ 272 if (hdmi->bridge) { 273 hdmi_bridge_destroy(hdmi->bridge); 274 hdmi->bridge = NULL; 275 } 276 if (hdmi->connector) { 277 hdmi->connector->funcs->destroy(hdmi->connector); 278 hdmi->connector = NULL; 279 } 280 281 return ret; 282} 283 284/* 285 * The hdmi device: 286 */ 287 288#include <linux/of_gpio.h> 289 290#define HDMI_CFG(item, entry) \ 291 .item ## _names = item ##_names_ ## entry, \ 292 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry) 293 294static struct hdmi_platform_config hdmi_tx_8660_config = { 295 .phy_init = hdmi_phy_8x60_init, 296}; 297 298static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"}; 299static const char *hpd_clk_names_8960[] = {"core_clk", "master_iface_clk", "slave_iface_clk"}; 300 301static struct hdmi_platform_config hdmi_tx_8960_config = { 302 .phy_init = hdmi_phy_8960_init, 303 HDMI_CFG(hpd_reg, 8960), 304 HDMI_CFG(hpd_clk, 8960), 305}; 306 307static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; 308static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"}; 309static const char *pwr_clk_names_8x74[] = {"extp_clk", "alt_iface_clk"}; 310static const char *hpd_clk_names_8x74[] = {"iface_clk", "core_clk", "mdp_core_clk"}; 311static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; 312 313static struct hdmi_platform_config hdmi_tx_8074_config = { 314 .phy_init = hdmi_phy_8x74_init, 315 HDMI_CFG(pwr_reg, 8x74), 316 HDMI_CFG(hpd_reg, 8x74), 317 HDMI_CFG(pwr_clk, 8x74), 318 HDMI_CFG(hpd_clk, 8x74), 319 .hpd_freq = hpd_clk_freq_8x74, 320}; 321 322static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"}; 323 324static struct hdmi_platform_config hdmi_tx_8084_config = { 325 .phy_init = hdmi_phy_8x74_init, 326 HDMI_CFG(pwr_reg, 8x74), 327 HDMI_CFG(hpd_reg, 8084), 328 HDMI_CFG(pwr_clk, 8x74), 329 HDMI_CFG(hpd_clk, 8x74), 330 .hpd_freq = hpd_clk_freq_8x74, 331}; 332 333static const struct of_device_id dt_match[] = { 334 { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config }, 335 { .compatible = "qcom,hdmi-tx-8074", .data = &hdmi_tx_8074_config }, 336 { .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config }, 337 { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8660_config }, 338 {} 339}; 340 341#ifdef CONFIG_OF 342static int get_gpio(struct device *dev, struct device_node *of_node, const char *name) 343{ 344 int gpio = of_get_named_gpio(of_node, name, 0); 345 if (gpio < 0) { 346 char name2[32]; 347 snprintf(name2, sizeof(name2), "%s-gpio", name); 348 gpio = of_get_named_gpio(of_node, name2, 0); 349 if (gpio < 0) { 350 dev_err(dev, "failed to get gpio: %s (%d)\n", 351 name, gpio); 352 gpio = -1; 353 } 354 } 355 return gpio; 356} 357#endif 358 359static int hdmi_bind(struct device *dev, struct device *master, void *data) 360{ 361 struct drm_device *drm = dev_get_drvdata(master); 362 struct msm_drm_private *priv = drm->dev_private; 363 static struct hdmi_platform_config *hdmi_cfg; 364 struct hdmi *hdmi; 365#ifdef CONFIG_OF 366 struct device_node *of_node = dev->of_node; 367 const struct of_device_id *match; 368 369 match = of_match_node(dt_match, of_node); 370 if (match && match->data) { 371 hdmi_cfg = (struct hdmi_platform_config *)match->data; 372 DBG("hdmi phy: %s", match->compatible); 373 } else { 374 dev_err(dev, "unknown phy: %s\n", of_node->name); 375 return -ENXIO; 376 } 377 378 hdmi_cfg->mmio_name = "core_physical"; 379 hdmi_cfg->ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk"); 380 hdmi_cfg->ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data"); 381 hdmi_cfg->hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd"); 382 hdmi_cfg->mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en"); 383 hdmi_cfg->mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel"); 384 hdmi_cfg->mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm"); 385 386#else 387 static struct hdmi_platform_config config = {}; 388 static const char *hpd_clk_names[] = { 389 "core_clk", "master_iface_clk", "slave_iface_clk", 390 }; 391 if (cpu_is_apq8064()) { 392 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"}; 393 config.phy_init = hdmi_phy_8960_init; 394 config.mmio_name = "hdmi_msm_hdmi_addr"; 395 config.hpd_reg_names = hpd_reg_names; 396 config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names); 397 config.hpd_clk_names = hpd_clk_names; 398 config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names); 399 config.ddc_clk_gpio = 70; 400 config.ddc_data_gpio = 71; 401 config.hpd_gpio = 72; 402 config.mux_en_gpio = -1; 403 config.mux_sel_gpio = -1; 404 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) { 405 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"}; 406 config.phy_init = hdmi_phy_8960_init; 407 config.mmio_name = "hdmi_msm_hdmi_addr"; 408 config.hpd_reg_names = hpd_reg_names; 409 config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names); 410 config.hpd_clk_names = hpd_clk_names; 411 config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names); 412 config.ddc_clk_gpio = 100; 413 config.ddc_data_gpio = 101; 414 config.hpd_gpio = 102; 415 config.mux_en_gpio = -1; 416 config.mux_sel_gpio = -1; 417 } else if (cpu_is_msm8x60()) { 418 static const char *hpd_reg_names[] = { 419 "8901_hdmi_mvs", "8901_mpp0" 420 }; 421 config.phy_init = hdmi_phy_8x60_init; 422 config.mmio_name = "hdmi_msm_hdmi_addr"; 423 config.hpd_reg_names = hpd_reg_names; 424 config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names); 425 config.hpd_clk_names = hpd_clk_names; 426 config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names); 427 config.ddc_clk_gpio = 170; 428 config.ddc_data_gpio = 171; 429 config.hpd_gpio = 172; 430 config.mux_en_gpio = -1; 431 config.mux_sel_gpio = -1; 432 } 433 hdmi_cfg = &config; 434#endif 435 dev->platform_data = hdmi_cfg; 436 437 hdmi = hdmi_init(to_platform_device(dev)); 438 if (IS_ERR(hdmi)) 439 return PTR_ERR(hdmi); 440 priv->hdmi = hdmi; 441 442 return 0; 443} 444 445static void hdmi_unbind(struct device *dev, struct device *master, 446 void *data) 447{ 448 struct drm_device *drm = dev_get_drvdata(master); 449 struct msm_drm_private *priv = drm->dev_private; 450 if (priv->hdmi) { 451 hdmi_destroy(priv->hdmi); 452 priv->hdmi = NULL; 453 } 454} 455 456static const struct component_ops hdmi_ops = { 457 .bind = hdmi_bind, 458 .unbind = hdmi_unbind, 459}; 460 461static int hdmi_dev_probe(struct platform_device *pdev) 462{ 463 return component_add(&pdev->dev, &hdmi_ops); 464} 465 466static int hdmi_dev_remove(struct platform_device *pdev) 467{ 468 component_del(&pdev->dev, &hdmi_ops); 469 return 0; 470} 471 472static struct platform_driver hdmi_driver = { 473 .probe = hdmi_dev_probe, 474 .remove = hdmi_dev_remove, 475 .driver = { 476 .name = "hdmi_msm", 477 .of_match_table = dt_match, 478 }, 479}; 480 481void __init hdmi_register(void) 482{ 483 platform_driver_register(&hdmi_driver); 484} 485 486void __exit hdmi_unregister(void) 487{ 488 platform_driver_unregister(&hdmi_driver); 489} 490