hdmi_phy.c 4.1 KB

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