hdmi_pll.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * HDMI PLL
  4. *
  5. * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
  6. */
  7. #define DSS_SUBSYS_NAME "HDMIPLL"
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/err.h>
  11. #include <linux/io.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/clk.h>
  14. #include <linux/seq_file.h>
  15. #include <linux/pm_runtime.h>
  16. #include "omapdss.h"
  17. #include "dss.h"
  18. #include "hdmi.h"
  19. void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
  20. {
  21. #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
  22. hdmi_read_reg(pll->base, r))
  23. DUMPPLL(PLLCTRL_PLL_CONTROL);
  24. DUMPPLL(PLLCTRL_PLL_STATUS);
  25. DUMPPLL(PLLCTRL_PLL_GO);
  26. DUMPPLL(PLLCTRL_CFG1);
  27. DUMPPLL(PLLCTRL_CFG2);
  28. DUMPPLL(PLLCTRL_CFG3);
  29. DUMPPLL(PLLCTRL_SSC_CFG1);
  30. DUMPPLL(PLLCTRL_SSC_CFG2);
  31. DUMPPLL(PLLCTRL_CFG4);
  32. }
  33. static int hdmi_pll_enable(struct dss_pll *dsspll)
  34. {
  35. struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
  36. struct hdmi_wp_data *wp = pll->wp;
  37. int r;
  38. r = pm_runtime_get_sync(&pll->pdev->dev);
  39. WARN_ON(r < 0);
  40. dss_ctrl_pll_enable(dsspll, true);
  41. r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
  42. if (r)
  43. return r;
  44. return 0;
  45. }
  46. static void hdmi_pll_disable(struct dss_pll *dsspll)
  47. {
  48. struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
  49. struct hdmi_wp_data *wp = pll->wp;
  50. int r;
  51. hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
  52. dss_ctrl_pll_enable(dsspll, false);
  53. r = pm_runtime_put_sync(&pll->pdev->dev);
  54. WARN_ON(r < 0 && r != -ENOSYS);
  55. }
  56. static const struct dss_pll_ops hdmi_pll_ops = {
  57. .enable = hdmi_pll_enable,
  58. .disable = hdmi_pll_disable,
  59. .set_config = dss_pll_write_config_type_b,
  60. };
  61. static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
  62. .type = DSS_PLL_TYPE_B,
  63. .n_max = 255,
  64. .m_min = 20,
  65. .m_max = 4095,
  66. .mX_max = 127,
  67. .fint_min = 500000,
  68. .fint_max = 2500000,
  69. .clkdco_min = 500000000,
  70. .clkdco_low = 1000000000,
  71. .clkdco_max = 2000000000,
  72. .n_msb = 8,
  73. .n_lsb = 1,
  74. .m_msb = 20,
  75. .m_lsb = 9,
  76. .mX_msb[0] = 24,
  77. .mX_lsb[0] = 18,
  78. .has_selfreqdco = true,
  79. };
  80. static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
  81. .type = DSS_PLL_TYPE_B,
  82. .n_max = 255,
  83. .m_min = 20,
  84. .m_max = 2045,
  85. .mX_max = 127,
  86. .fint_min = 620000,
  87. .fint_max = 2500000,
  88. .clkdco_min = 750000000,
  89. .clkdco_low = 1500000000,
  90. .clkdco_max = 2500000000UL,
  91. .n_msb = 8,
  92. .n_lsb = 1,
  93. .m_msb = 20,
  94. .m_lsb = 9,
  95. .mX_msb[0] = 24,
  96. .mX_lsb[0] = 18,
  97. .has_selfreqdco = true,
  98. .has_refsel = true,
  99. };
  100. static int hdmi_init_pll_data(struct dss_device *dss,
  101. struct platform_device *pdev,
  102. struct hdmi_pll_data *hpll)
  103. {
  104. struct dss_pll *pll = &hpll->pll;
  105. struct clk *clk;
  106. int r;
  107. clk = devm_clk_get(&pdev->dev, "sys_clk");
  108. if (IS_ERR(clk)) {
  109. DSSERR("can't get sys_clk\n");
  110. return PTR_ERR(clk);
  111. }
  112. pll->name = "hdmi";
  113. pll->id = DSS_PLL_HDMI;
  114. pll->base = hpll->base;
  115. pll->clkin = clk;
  116. if (hpll->wp->version == 4)
  117. pll->hw = &dss_omap4_hdmi_pll_hw;
  118. else
  119. pll->hw = &dss_omap5_hdmi_pll_hw;
  120. pll->ops = &hdmi_pll_ops;
  121. r = dss_pll_register(dss, pll);
  122. if (r)
  123. return r;
  124. return 0;
  125. }
  126. int hdmi_pll_init(struct dss_device *dss, struct platform_device *pdev,
  127. struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
  128. {
  129. int r;
  130. pll->pdev = pdev;
  131. pll->wp = wp;
  132. pll->base = devm_platform_ioremap_resource_byname(pdev, "pll");
  133. if (IS_ERR(pll->base))
  134. return PTR_ERR(pll->base);
  135. r = hdmi_init_pll_data(dss, pdev, pll);
  136. if (r) {
  137. DSSERR("failed to init HDMI PLL\n");
  138. return r;
  139. }
  140. return 0;
  141. }
  142. void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
  143. {
  144. struct dss_pll *pll = &hpll->pll;
  145. dss_pll_unregister(pll);
  146. }