0020-fix-PLL4_DCO-freq-over-range-cause-DP-not-display.patch 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. From 1c9d8953f936f6e1beee71af59aa5e2533be0ef1 Mon Sep 17 00:00:00 2001
  2. From: chao zeng <chao.zeng@siemens.com>
  3. Date: Fri, 11 Dec 2020 17:20:12 +0800
  4. Subject: [PATCH 20/26] fix:PLL4_DCO freq over range cause DP not display
  5. 1.some DP may be can not display.
  6. 2.reason: TI sysfw can not correct set PLL4 some frequency
  7. division parameter(M,N,M2),It will cause DCO over range,
  8. calculate DCO frequency not between HS1 and HS2 mode,
  9. So,CLKOUT is bypass mode,only out 25Mhz,Then DSS_PLL_CLKOUT
  10. and DPI_1_IN_CLK is always 25MHz,and It don't match the
  11. frequency of the monitor,so can not display.
  12. so,through dynamic acquisition of monitor frequency(Rate),
  13. calculation (M,N,M2) value and set correlation register.
  14. Signed-off-by: Sheng Long Wang <shenglong.wang.ext@siemens.com>
  15. ---
  16. drivers/gpu/drm/tidss/tidss_dispc7.c | 196 +++++++++++++++++++++++++++
  17. 1 file changed, 196 insertions(+)
  18. diff --git a/drivers/gpu/drm/tidss/tidss_dispc7.c b/drivers/gpu/drm/tidss/tidss_dispc7.c
  19. index 32f7535a0f83..b43cd213b6d9 100644
  20. --- a/drivers/gpu/drm/tidss/tidss_dispc7.c
  21. +++ b/drivers/gpu/drm/tidss/tidss_dispc7.c
  22. @@ -33,6 +33,19 @@
  23. #include "tidss_scale_coefs.h"
  24. #include "tidss_dispc7.h"
  25. +#define DSS_PLL_BASE_ADDR 0x00684000
  26. +#define PLL_KICK0_OFFSET 0x0010
  27. +#define PLL_KICK1_OFFSET 0x0014
  28. +#define PLL_FREQ_CTRL0_OFFSET 0x0020
  29. +#define PLL_FREQ_CTRL1_OFFSET 0x0024
  30. +#define PLL_CLKDIV_OFFSET 0x0028
  31. +#define PLL_PROG_OFFSET 0x002C
  32. +#define PLL_CTRL_OFFSET 0x0030
  33. +#define PLL_STAT_OFFSET 0x0034
  34. +#define KICK0_UNLOCK 0x68EF3490
  35. +#define KICK1_UNLOCK 0xD172BC5A
  36. +#define KICK_LOCK 0x00000000
  37. +
  38. static const char *dispc7_plane_name(struct dispc_device *dispc, u32 hw_plane);
  39. static const struct dispc7_features dispc7_am6_feats = {
  40. @@ -1122,11 +1135,139 @@ static unsigned int dispc7_pclk_diff(unsigned long rate,
  41. return (unsigned int)(abs(((rr - r) * 100) / r));
  42. }
  43. +static void dss_pll4_reg_write(u32 reg, u32 val)
  44. +{
  45. + void __iomem *regval;
  46. +
  47. + regval = ioremap(DSS_PLL_BASE_ADDR + reg ,SZ_4);
  48. + writel(val, regval);
  49. + mdelay(2);
  50. + iounmap(regval);
  51. +}
  52. +
  53. +static u32 dss_pll4_reg_read(u32 reg)
  54. +{
  55. + void __iomem *regval;
  56. + u32 data;
  57. +
  58. + regval = ioremap(DSS_PLL_BASE_ADDR + reg,SZ_4);
  59. + data = readl(regval);
  60. + iounmap(regval);
  61. +
  62. + return data;
  63. +}
  64. +
  65. +static int get_dp_clock_parameter(int Rate, u16 *M_INT, u8 *N_DIV, u8 *M2, u8 *choose_flag)
  66. +{
  67. + u16 m2_div[127] = {0};
  68. + u16 result[127][3] = {0};
  69. + u16 hs2_dco_freq = 0;
  70. + u16 hs1_dco_freq = 0;
  71. + u16 start,ck,N,M;
  72. + u16 first = 0, second = 0, mid = 0;
  73. +
  74. + u8 hs2_data_exist = 0;
  75. + u8 hs1_data_exist = 0;
  76. + u8 count = 0, ret = 0, i = 0;
  77. +
  78. + if (Rate < 6 || Rate > 2500) {
  79. + return 0;
  80. + }
  81. +
  82. + for (start = 750 / Rate + (750%Rate!=0); start <= 2500 / Rate; ++start) {
  83. + if (start >= 1 && start <= 127) {
  84. + m2_div[count] = start;
  85. + count++;
  86. + }
  87. + }
  88. +
  89. + for (i = 0; i < count; ++i) {
  90. + ck = Rate * m2_div[i];
  91. + for ( N = 0; N <= 255; ++N) {
  92. + M = (N + 1) * ck / 25;
  93. + if ((M * 25 == (N + 1) * ck) && (M >= 2) && (M <= 4095)) {
  94. + printk(KERN_DEBUG "M2=%d, N=%d, M=%d\n", m2_div[i], N, M);
  95. + result[i][0] = m2_div[i];
  96. + result[i][1] = M;
  97. + result[i][2] = N;
  98. + ret = 1;
  99. + }
  100. + }
  101. + }
  102. +
  103. + if (!ret) {
  104. + return 0;
  105. + }
  106. +
  107. + for (i = 0; i < count; ++i) {
  108. + if (Rate * m2_div[i] <= 1500) first++;
  109. + if (Rate * m2_div[i] >= 1250)
  110. + second++;
  111. + else
  112. + mid++;
  113. + }
  114. +
  115. + if (first == 0) {
  116. + hs2_data_exist = 1;
  117. + }
  118. +
  119. + if (second == 0) {
  120. + hs1_data_exist = 1;
  121. + }
  122. +
  123. + if((hs1_data_exist == 0) && (hs2_data_exist == 0)) {
  124. + hs2_dco_freq = 25 * result[first / 2][1] / (result[first / 2][2] + 1);
  125. + hs1_dco_freq = 25 * result[second / 2 + mid][1] / ( result[second / 2 + mid][2] +1);
  126. +
  127. + if ((abs(hs2_dco_freq - 1125) > abs(hs1_dco_freq - 1875))) {
  128. + printk(KERN_DEBUG "(hs1 mode) [1250-2500] : M2=%d, M=%d, N=%d\n",
  129. + result[second / 2 + mid][0], result[second / 2 + mid][1], result[second / 2 + mid][2]);
  130. + *M_INT = (u16)(result[second / 2 + mid][1]);
  131. + *N_DIV = (u8)(result[second / 2 + mid][2]);
  132. + *M2 = (u8)(result[second / 2 + mid][0]);
  133. + *choose_flag = 2;
  134. + } else {
  135. + printk(KERN_DEBUG "(hs2 mode)[750-1500] : M2=%d, M=%d, N=%d\n",
  136. + result[first / 2][0], result[first / 2][1], result[first / 2][2]);
  137. + *M_INT = (u16)(result[first / 2][1]);
  138. + *N_DIV = (u8)(result[first / 2][2]);
  139. + *M2 = (u8)(result[first / 2][0]);
  140. + *choose_flag = 1;
  141. + }
  142. + } else {
  143. + if ((hs2_data_exist == 0) && (hs1_data_exist == 1)) {
  144. + printk(KERN_DEBUG "(hs2 mode)[750-1500] : M2=%d, M=%d, N=%d\n",
  145. + result[first / 2][0], result[first / 2][1], result[first / 2][2]);
  146. + *M_INT = (u16)(result[first / 2][1]);
  147. + *N_DIV = (u8)(result[first / 2][2]);
  148. + *M2 = (u8)(result[first / 2][0]);
  149. + *choose_flag = 1;
  150. + } else if ((hs2_data_exist == 1) && (hs1_data_exist == 0)) {
  151. + printk(KERN_DEBUG "(hs1 mode)[1250--2500] : M2=%d, M=%d, N=%d\n",
  152. + result[second / 2 + mid][0], result[second / 2 + mid][1], result[second / 2 + mid][2]);
  153. + *M_INT = (u16)(result[second / 2 + mid][1]);
  154. + *N_DIV = (u8)(result[second / 2 + mid][2]);
  155. + *M2 = (u8)(result[second / 2 + mid][0]);
  156. + *choose_flag = 2;
  157. + } else {
  158. + return 0;
  159. + }
  160. + }
  161. +
  162. + return 1;
  163. +}
  164. +
  165. +
  166. static int dispc7_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
  167. unsigned long rate)
  168. {
  169. int r;
  170. unsigned long new_rate;
  171. + u32 data;
  172. + u16 M_INT;
  173. + u8 N_DIV;
  174. + u8 M2;
  175. + u8 choose_flag = 0;
  176. r = clk_set_rate(dispc->vp_clk[hw_videoport], rate);
  177. if (r) {
  178. @@ -1145,6 +1286,61 @@ static int dispc7_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
  179. dev_dbg(dispc->dev, "vp%d: new rate %lu Hz (requested %lu Hz)\n",
  180. hw_videoport, clk_get_rate(dispc->vp_clk[hw_videoport]), rate);
  181. + /**dynamic Get (M,N,M2) value**/
  182. + r = get_dp_clock_parameter(rate/1000000, &M_INT, &N_DIV, &M2, &choose_flag);
  183. + if(!r){
  184. + dev_err(dispc->dev,"get DP PLL parameter erro \n");
  185. + return 0;
  186. + }
  187. + mdelay(2);
  188. +
  189. + /**Unlock PLL registers**/
  190. + dss_pll4_reg_write(PLL_KICK0_OFFSET,KICK0_UNLOCK);
  191. + dss_pll4_reg_write(PLL_KICK1_OFFSET,KICK1_UNLOCK);
  192. +
  193. + /**Switch PLL outputs to bypass freq**/
  194. + dss_pll4_reg_write(PLL_CTRL_OFFSET,0x2100099);
  195. +
  196. + /**Prepare PLL for programming**/
  197. + dss_pll4_reg_write(PLL_PROG_OFFSET,0);
  198. +
  199. + /** DSS Clock Set **/
  200. + data = dss_pll4_reg_read(PLL_FREQ_CTRL0_OFFSET);
  201. + data &= 0xFFF00000; //clear bit [0:19]
  202. + data |= (u32)N_DIV;
  203. + data |= (u32)(M_INT << 8);
  204. + dss_pll4_reg_write(PLL_FREQ_CTRL0_OFFSET,data); //set M,N
  205. + if(choose_flag == 1)
  206. + dss_pll4_reg_write(PLL_FREQ_CTRL1_OFFSET,0x02000000); //set M.f HS2
  207. + else if (choose_flag == 2)
  208. + dss_pll4_reg_write(PLL_FREQ_CTRL1_OFFSET,0x04000000); //set M.f HS1
  209. +
  210. +
  211. + /**Set M2 **/
  212. + data = dss_pll4_reg_read(PLL_CLKDIV_OFFSET);
  213. + data &= ~((0x7F << 8)); //clear bit [8:14]
  214. + data |= (u32)(M2 << 8);
  215. + dss_pll4_reg_write(PLL_CLKDIV_OFFSET,data);
  216. +
  217. + /**Trigger PLL update to new values**/
  218. + dss_pll4_reg_write(PLL_PROG_OFFSET,0x2);
  219. +
  220. + /**Trigger PLL update to new values**/
  221. + dss_pll4_reg_write(PLL_PROG_OFFSET,0x102);
  222. +
  223. + /** Trigger PLL lock to new values**/
  224. + dss_pll4_reg_write(PLL_PROG_OFFSET,0x103);
  225. +
  226. + /** Send PLL to idle**/
  227. + dss_pll4_reg_write(PLL_PROG_OFFSET,0x1);
  228. +
  229. + /** Switch PLL outputs to locked freq**/
  230. + dss_pll4_reg_write(PLL_CTRL_OFFSET,0x2100019);
  231. +
  232. + /**Lock PLL registers **/
  233. + dss_pll4_reg_write(PLL_KICK0_OFFSET,KICK_LOCK);
  234. + dss_pll4_reg_write(PLL_KICK1_OFFSET,KICK_LOCK);
  235. +
  236. return 0;
  237. }
  238. --
  239. 2.31.1