phy-mtk-hdmi-mt2701.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 MediaTek Inc.
  4. * Author: Chunhui Dai <[email protected]>
  5. */
  6. #include "phy-mtk-hdmi.h"
  7. #include "phy-mtk-io.h"
  8. #define HDMI_CON0 0x00
  9. #define RG_HDMITX_DRV_IBIAS_MASK GENMASK(5, 0)
  10. #define RG_HDMITX_EN_SER_MASK GENMASK(15, 12)
  11. #define RG_HDMITX_EN_SLDO_MASK GENMASK(19, 16)
  12. #define RG_HDMITX_EN_PRED_MASK GENMASK(23, 20)
  13. #define RG_HDMITX_EN_IMP_MASK GENMASK(27, 24)
  14. #define RG_HDMITX_EN_DRV_MASK GENMASK(31, 28)
  15. #define HDMI_CON1 0x04
  16. #define RG_HDMITX_PRED_IBIAS_MASK GENMASK(21, 18)
  17. #define RG_HDMITX_PRED_IMP BIT(22)
  18. #define RG_HDMITX_DRV_IMP_MASK GENMASK(31, 26)
  19. #define HDMI_CON2 0x08
  20. #define RG_HDMITX_EN_TX_CKLDO BIT(0)
  21. #define RG_HDMITX_EN_TX_POSDIV BIT(1)
  22. #define RG_HDMITX_TX_POSDIV_MASK GENMASK(4, 3)
  23. #define RG_HDMITX_EN_MBIAS BIT(6)
  24. #define RG_HDMITX_MBIAS_LPF_EN BIT(7)
  25. #define HDMI_CON4 0x10
  26. #define RG_HDMITX_RESERVE_MASK GENMASK(31, 0)
  27. #define HDMI_CON6 0x18
  28. #define RG_HTPLL_BR_MASK GENMASK(1, 0)
  29. #define RG_HTPLL_BC_MASK GENMASK(3, 2)
  30. #define RG_HTPLL_BP_MASK GENMASK(7, 4)
  31. #define RG_HTPLL_IR_MASK GENMASK(11, 8)
  32. #define RG_HTPLL_IC_MASK GENMASK(15, 12)
  33. #define RG_HTPLL_POSDIV_MASK GENMASK(17, 16)
  34. #define RG_HTPLL_PREDIV_MASK GENMASK(19, 18)
  35. #define RG_HTPLL_FBKSEL_MASK GENMASK(21, 20)
  36. #define RG_HTPLL_RLH_EN BIT(22)
  37. #define RG_HTPLL_FBKDIV_MASK GENMASK(30, 24)
  38. #define RG_HTPLL_EN BIT(31)
  39. #define HDMI_CON7 0x1c
  40. #define RG_HTPLL_AUTOK_EN BIT(23)
  41. #define RG_HTPLL_DIVEN_MASK GENMASK(30, 28)
  42. static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
  43. {
  44. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  45. void __iomem *base = hdmi_phy->regs;
  46. mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
  47. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
  48. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  49. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
  50. usleep_range(80, 100);
  51. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);
  52. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
  53. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  54. usleep_range(80, 100);
  55. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  56. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  57. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  58. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  59. usleep_range(80, 100);
  60. return 0;
  61. }
  62. static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
  63. {
  64. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  65. void __iomem *base = hdmi_phy->regs;
  66. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  67. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  68. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  69. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  70. usleep_range(80, 100);
  71. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  72. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
  73. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);
  74. usleep_range(80, 100);
  75. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
  76. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  77. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
  78. mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
  79. usleep_range(80, 100);
  80. }
  81. static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  82. unsigned long *parent_rate)
  83. {
  84. return rate;
  85. }
  86. static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
  87. unsigned long parent_rate)
  88. {
  89. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  90. void __iomem *base = hdmi_phy->regs;
  91. u32 pos_div;
  92. if (rate <= 64000000)
  93. pos_div = 3;
  94. else if (rate <= 128000000)
  95. pos_div = 2;
  96. else
  97. pos_div = 1;
  98. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_PREDIV_MASK);
  99. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  100. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
  101. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IC_MASK, 0x1);
  102. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IR_MASK, 0x1);
  103. mtk_phy_update_field(base + HDMI_CON2, RG_HDMITX_TX_POSDIV_MASK, pos_div);
  104. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKSEL_MASK, 1);
  105. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKDIV_MASK, 19);
  106. mtk_phy_update_field(base + HDMI_CON7, RG_HTPLL_DIVEN_MASK, 0x2);
  107. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BP_MASK, 0xc);
  108. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BC_MASK, 0x2);
  109. mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BR_MASK, 0x1);
  110. mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PRED_IMP);
  111. mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_PRED_IBIAS_MASK, 0x3);
  112. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
  113. mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_DRV_IMP_MASK, 0x28);
  114. mtk_phy_update_field(base + HDMI_CON4, RG_HDMITX_RESERVE_MASK, 0x28);
  115. mtk_phy_update_field(base + HDMI_CON0, RG_HDMITX_DRV_IBIAS_MASK, 0xa);
  116. return 0;
  117. }
  118. static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
  119. unsigned long parent_rate)
  120. {
  121. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  122. unsigned long out_rate, val;
  123. u32 tmp;
  124. tmp = readl(hdmi_phy->regs + HDMI_CON6);
  125. val = FIELD_GET(RG_HTPLL_PREDIV_MASK, tmp);
  126. switch (val) {
  127. case 0x00:
  128. out_rate = parent_rate;
  129. break;
  130. case 0x01:
  131. out_rate = parent_rate / 2;
  132. break;
  133. default:
  134. out_rate = parent_rate / 4;
  135. break;
  136. }
  137. val = FIELD_GET(RG_HTPLL_FBKDIV_MASK, tmp);
  138. out_rate *= (val + 1) * 2;
  139. tmp = readl(hdmi_phy->regs + HDMI_CON2);
  140. val = FIELD_GET(RG_HDMITX_TX_POSDIV_MASK, tmp);
  141. out_rate >>= val;
  142. if (tmp & RG_HDMITX_EN_TX_POSDIV)
  143. out_rate /= 5;
  144. return out_rate;
  145. }
  146. static const struct clk_ops mtk_hdmi_phy_pll_ops = {
  147. .prepare = mtk_hdmi_pll_prepare,
  148. .unprepare = mtk_hdmi_pll_unprepare,
  149. .set_rate = mtk_hdmi_pll_set_rate,
  150. .round_rate = mtk_hdmi_pll_round_rate,
  151. .recalc_rate = mtk_hdmi_pll_recalc_rate,
  152. };
  153. static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
  154. {
  155. void __iomem *base = hdmi_phy->regs;
  156. mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
  157. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
  158. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  159. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
  160. usleep_range(80, 100);
  161. mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);
  162. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
  163. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  164. usleep_range(80, 100);
  165. mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  166. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  167. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  168. mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  169. usleep_range(80, 100);
  170. }
  171. static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
  172. {
  173. void __iomem *base = hdmi_phy->regs;
  174. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
  175. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
  176. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
  177. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
  178. usleep_range(80, 100);
  179. mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
  180. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
  181. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);
  182. usleep_range(80, 100);
  183. mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
  184. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
  185. mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
  186. mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
  187. usleep_range(80, 100);
  188. }
  189. struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
  190. .flags = CLK_SET_RATE_GATE,
  191. .pll_default_off = true,
  192. .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
  193. .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
  194. .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
  195. };
  196. MODULE_AUTHOR("Chunhui Dai <[email protected]>");
  197. MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
  198. MODULE_LICENSE("GPL v2");