hdmi.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright (C) 2013 Red Hat
  3. * Author: Rob Clark <robdclark@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "hdmi.h"
  18. static struct platform_device *hdmi_pdev;
  19. void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
  20. {
  21. uint32_t ctrl = 0;
  22. if (power_on) {
  23. ctrl |= HDMI_CTRL_ENABLE;
  24. if (!hdmi->hdmi_mode) {
  25. ctrl |= HDMI_CTRL_HDMI;
  26. hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
  27. ctrl &= ~HDMI_CTRL_HDMI;
  28. } else {
  29. ctrl |= HDMI_CTRL_HDMI;
  30. }
  31. } else {
  32. ctrl = HDMI_CTRL_HDMI;
  33. }
  34. hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
  35. DBG("HDMI Core: %s, HDMI_CTRL=0x%08x",
  36. power_on ? "Enable" : "Disable", ctrl);
  37. }
  38. static irqreturn_t hdmi_irq(int irq, void *dev_id)
  39. {
  40. struct hdmi *hdmi = dev_id;
  41. /* Process HPD: */
  42. hdmi_connector_irq(hdmi->connector);
  43. /* Process DDC: */
  44. hdmi_i2c_irq(hdmi->i2c);
  45. /* TODO audio.. */
  46. return IRQ_HANDLED;
  47. }
  48. void hdmi_destroy(struct hdmi *hdmi)
  49. {
  50. struct hdmi_phy *phy = hdmi->phy;
  51. if (phy)
  52. phy->funcs->destroy(phy);
  53. if (hdmi->i2c)
  54. hdmi_i2c_destroy(hdmi->i2c);
  55. put_device(&hdmi->pdev->dev);
  56. }
  57. /* initialize connector */
  58. int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,
  59. struct drm_connector *connector)
  60. {
  61. struct platform_device *pdev = hdmi_pdev;
  62. struct hdmi_platform_config *config;
  63. int ret;
  64. if (!pdev) {
  65. dev_err(dev->dev, "no hdmi device\n");
  66. ret = -ENXIO;
  67. goto fail;
  68. }
  69. config = pdev->dev.platform_data;
  70. get_device(&pdev->dev);
  71. hdmi->dev = dev;
  72. hdmi->pdev = pdev;
  73. hdmi->connector = connector;
  74. /* not sure about which phy maps to which msm.. probably I miss some */
  75. if (config->phy_init)
  76. hdmi->phy = config->phy_init(hdmi);
  77. else
  78. hdmi->phy = ERR_PTR(-ENXIO);
  79. if (IS_ERR(hdmi->phy)) {
  80. ret = PTR_ERR(hdmi->phy);
  81. dev_err(dev->dev, "failed to load phy: %d\n", ret);
  82. hdmi->phy = NULL;
  83. goto fail;
  84. }
  85. hdmi->mmio = msm_ioremap(pdev, "hdmi_msm_hdmi_addr", "HDMI");
  86. if (IS_ERR(hdmi->mmio)) {
  87. ret = PTR_ERR(hdmi->mmio);
  88. goto fail;
  89. }
  90. hdmi->mvs = devm_regulator_get(&pdev->dev, "8901_hdmi_mvs");
  91. if (IS_ERR(hdmi->mvs))
  92. hdmi->mvs = devm_regulator_get(&pdev->dev, "hdmi_mvs");
  93. if (IS_ERR(hdmi->mvs)) {
  94. ret = PTR_ERR(hdmi->mvs);
  95. dev_err(dev->dev, "failed to get mvs regulator: %d\n", ret);
  96. goto fail;
  97. }
  98. hdmi->mpp0 = devm_regulator_get(&pdev->dev, "8901_mpp0");
  99. if (IS_ERR(hdmi->mpp0))
  100. hdmi->mpp0 = NULL;
  101. hdmi->clk = devm_clk_get(&pdev->dev, "core_clk");
  102. if (IS_ERR(hdmi->clk)) {
  103. ret = PTR_ERR(hdmi->clk);
  104. dev_err(dev->dev, "failed to get 'clk': %d\n", ret);
  105. goto fail;
  106. }
  107. hdmi->m_pclk = devm_clk_get(&pdev->dev, "master_iface_clk");
  108. if (IS_ERR(hdmi->m_pclk)) {
  109. ret = PTR_ERR(hdmi->m_pclk);
  110. dev_err(dev->dev, "failed to get 'm_pclk': %d\n", ret);
  111. goto fail;
  112. }
  113. hdmi->s_pclk = devm_clk_get(&pdev->dev, "slave_iface_clk");
  114. if (IS_ERR(hdmi->s_pclk)) {
  115. ret = PTR_ERR(hdmi->s_pclk);
  116. dev_err(dev->dev, "failed to get 's_pclk': %d\n", ret);
  117. goto fail;
  118. }
  119. hdmi->i2c = hdmi_i2c_init(hdmi);
  120. if (IS_ERR(hdmi->i2c)) {
  121. ret = PTR_ERR(hdmi->i2c);
  122. dev_err(dev->dev, "failed to get i2c: %d\n", ret);
  123. hdmi->i2c = NULL;
  124. goto fail;
  125. }
  126. hdmi->irq = platform_get_irq(pdev, 0);
  127. if (hdmi->irq < 0) {
  128. ret = hdmi->irq;
  129. dev_err(dev->dev, "failed to get irq: %d\n", ret);
  130. goto fail;
  131. }
  132. ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
  133. NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
  134. "hdmi_isr", hdmi);
  135. if (ret < 0) {
  136. dev_err(dev->dev, "failed to request IRQ%u: %d\n",
  137. hdmi->irq, ret);
  138. goto fail;
  139. }
  140. return 0;
  141. fail:
  142. if (hdmi)
  143. hdmi_destroy(hdmi);
  144. return ret;
  145. }
  146. /*
  147. * The hdmi device:
  148. */
  149. static int hdmi_dev_probe(struct platform_device *pdev)
  150. {
  151. static struct hdmi_platform_config config = {};
  152. #ifdef CONFIG_OF
  153. /* TODO */
  154. #else
  155. if (cpu_is_apq8064()) {
  156. config.phy_init = hdmi_phy_8960_init;
  157. config.ddc_clk_gpio = 70;
  158. config.ddc_data_gpio = 71;
  159. config.hpd_gpio = 72;
  160. config.pmic_gpio = 13 + NR_GPIO_IRQS;
  161. } else if (cpu_is_msm8960()) {
  162. config.phy_init = hdmi_phy_8960_init;
  163. config.ddc_clk_gpio = 100;
  164. config.ddc_data_gpio = 101;
  165. config.hpd_gpio = 102;
  166. config.pmic_gpio = -1;
  167. } else if (cpu_is_msm8x60()) {
  168. config.phy_init = hdmi_phy_8x60_init;
  169. config.ddc_clk_gpio = 170;
  170. config.ddc_data_gpio = 171;
  171. config.hpd_gpio = 172;
  172. config.pmic_gpio = -1;
  173. }
  174. #endif
  175. pdev->dev.platform_data = &config;
  176. hdmi_pdev = pdev;
  177. return 0;
  178. }
  179. static int hdmi_dev_remove(struct platform_device *pdev)
  180. {
  181. hdmi_pdev = NULL;
  182. return 0;
  183. }
  184. static struct platform_driver hdmi_driver = {
  185. .probe = hdmi_dev_probe,
  186. .remove = hdmi_dev_remove,
  187. .driver.name = "hdmi_msm",
  188. };
  189. void __init hdmi_register(void)
  190. {
  191. platform_driver_register(&hdmi_driver);
  192. }
  193. void __exit hdmi_unregister(void)
  194. {
  195. platform_driver_unregister(&hdmi_driver);
  196. }