hdmi_phy.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * HDMI PHY
  4. *
  5. * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/err.h>
  9. #include <linux/io.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/slab.h>
  12. #include <linux/seq_file.h>
  13. #include "omapdss.h"
  14. #include "dss.h"
  15. #include "hdmi.h"
  16. void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
  17. {
  18. #define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
  19. hdmi_read_reg(phy->base, r))
  20. DUMPPHY(HDMI_TXPHY_TX_CTRL);
  21. DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
  22. DUMPPHY(HDMI_TXPHY_POWER_CTRL);
  23. DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
  24. if (phy->features->bist_ctrl)
  25. DUMPPHY(HDMI_TXPHY_BIST_CONTROL);
  26. }
  27. int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes)
  28. {
  29. int i;
  30. for (i = 0; i < 8; i += 2) {
  31. u8 lane, pol;
  32. int dx, dy;
  33. dx = lanes[i];
  34. dy = lanes[i + 1];
  35. if (dx < 0 || dx >= 8)
  36. return -EINVAL;
  37. if (dy < 0 || dy >= 8)
  38. return -EINVAL;
  39. if (dx & 1) {
  40. if (dy != dx - 1)
  41. return -EINVAL;
  42. pol = 1;
  43. } else {
  44. if (dy != dx + 1)
  45. return -EINVAL;
  46. pol = 0;
  47. }
  48. lane = dx / 2;
  49. phy->lane_function[lane] = i / 2;
  50. phy->lane_polarity[lane] = pol;
  51. }
  52. return 0;
  53. }
  54. static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
  55. {
  56. static const u16 pad_cfg_list[] = {
  57. 0x0123,
  58. 0x0132,
  59. 0x0312,
  60. 0x0321,
  61. 0x0231,
  62. 0x0213,
  63. 0x1023,
  64. 0x1032,
  65. 0x3012,
  66. 0x3021,
  67. 0x2031,
  68. 0x2013,
  69. 0x1203,
  70. 0x1302,
  71. 0x3102,
  72. 0x3201,
  73. 0x2301,
  74. 0x2103,
  75. 0x1230,
  76. 0x1320,
  77. 0x3120,
  78. 0x3210,
  79. 0x2310,
  80. 0x2130,
  81. };
  82. u16 lane_cfg = 0;
  83. int i;
  84. unsigned int lane_cfg_val;
  85. u16 pol_val = 0;
  86. for (i = 0; i < 4; ++i)
  87. lane_cfg |= phy->lane_function[i] << ((3 - i) * 4);
  88. pol_val |= phy->lane_polarity[0] << 0;
  89. pol_val |= phy->lane_polarity[1] << 3;
  90. pol_val |= phy->lane_polarity[2] << 2;
  91. pol_val |= phy->lane_polarity[3] << 1;
  92. for (i = 0; i < ARRAY_SIZE(pad_cfg_list); ++i)
  93. if (pad_cfg_list[i] == lane_cfg)
  94. break;
  95. if (WARN_ON(i == ARRAY_SIZE(pad_cfg_list)))
  96. i = 0;
  97. lane_cfg_val = i;
  98. REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, lane_cfg_val, 26, 22);
  99. REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
  100. }
  101. int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
  102. unsigned long lfbitclk)
  103. {
  104. u8 freqout;
  105. /*
  106. * Read address 0 in order to get the SCP reset done completed
  107. * Dummy access performed to make sure reset is done
  108. */
  109. hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
  110. /*
  111. * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the
  112. * HDMI_PHYPWRCMD_LDOON command.
  113. */
  114. if (phy->features->bist_ctrl)
  115. REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
  116. /*
  117. * If the hfbitclk != lfbitclk, it means the lfbitclk was configured
  118. * to be used for TMDS.
  119. */
  120. if (hfbitclk != lfbitclk)
  121. freqout = 0;
  122. else if (hfbitclk / 10 < phy->features->max_phy)
  123. freqout = 1;
  124. else
  125. freqout = 2;
  126. /*
  127. * Write to phy address 0 to configure the clock
  128. * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
  129. */
  130. REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, freqout, 31, 30);
  131. /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
  132. hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
  133. /* Setup max LDO voltage */
  134. if (phy->features->ldo_voltage)
  135. REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
  136. hdmi_phy_configure_lanes(phy);
  137. return 0;
  138. }
  139. static const struct hdmi_phy_features omap44xx_phy_feats = {
  140. .bist_ctrl = false,
  141. .ldo_voltage = true,
  142. .max_phy = 185675000,
  143. };
  144. static const struct hdmi_phy_features omap54xx_phy_feats = {
  145. .bist_ctrl = true,
  146. .ldo_voltage = false,
  147. .max_phy = 186000000,
  148. };
  149. int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy,
  150. unsigned int version)
  151. {
  152. if (version == 4)
  153. phy->features = &omap44xx_phy_feats;
  154. else
  155. phy->features = &omap54xx_phy_feats;
  156. phy->base = devm_platform_ioremap_resource_byname(pdev, "phy");
  157. if (IS_ERR(phy->base))
  158. return PTR_ERR(phy->base);
  159. return 0;
  160. }