dp_catalog_v200.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/delay.h>
  6. #include "dp_catalog.h"
  7. #include "dp_reg.h"
  8. #include "dp_debug.h"
  9. #define dp_catalog_get_priv_v200(x) ({ \
  10. struct dp_catalog *dp_catalog; \
  11. dp_catalog = container_of(x, struct dp_catalog, x); \
  12. dp_catalog->priv.data; \
  13. })
  14. struct dp_catalog_io {
  15. struct dp_io_data *dp_ahb;
  16. struct dp_io_data *dp_aux;
  17. struct dp_io_data *dp_link;
  18. struct dp_io_data *dp_p0;
  19. struct dp_io_data *dp_phy;
  20. struct dp_io_data *dp_ln_tx0;
  21. struct dp_io_data *dp_ln_tx1;
  22. struct dp_io_data *dp_mmss_cc;
  23. struct dp_io_data *dp_pll;
  24. struct dp_io_data *usb3_dp_com;
  25. struct dp_io_data *hdcp_physical;
  26. struct dp_io_data *dp_p1;
  27. struct dp_io_data *dp_tcsr;
  28. };
  29. struct dp_catalog_private_v200 {
  30. struct device *dev;
  31. struct dp_catalog_io *io;
  32. char exe_mode[SZ_4];
  33. };
  34. static void dp_catalog_aux_clear_hw_interrupts_v200(struct dp_catalog_aux *aux)
  35. {
  36. struct dp_catalog_private_v200 *catalog;
  37. struct dp_io_data *io_data;
  38. u32 data = 0;
  39. if (!aux) {
  40. DP_ERR("invalid input\n");
  41. return;
  42. }
  43. catalog = dp_catalog_get_priv_v200(aux);
  44. io_data = catalog->io->dp_phy;
  45. data = dp_read(catalog->exe_mode, io_data,
  46. DP_PHY_AUX_INTERRUPT_STATUS_V200);
  47. dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
  48. 0x1f);
  49. wmb(); /* make sure 0x1f is written before next write */
  50. dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
  51. 0x9f);
  52. wmb(); /* make sure 0x9f is written before next write */
  53. dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
  54. 0);
  55. wmb(); /* make sure register is cleared */
  56. }
  57. static void dp_catalog_aux_setup_v200(struct dp_catalog_aux *aux,
  58. struct dp_aux_cfg *cfg)
  59. {
  60. struct dp_catalog_private_v200 *catalog;
  61. struct dp_io_data *io_data;
  62. int i = 0, sw_reset = 0;
  63. if (!aux || !cfg) {
  64. DP_ERR("invalid input\n");
  65. return;
  66. }
  67. catalog = dp_catalog_get_priv_v200(aux);
  68. io_data = catalog->io->dp_ahb;
  69. sw_reset = dp_read(catalog->exe_mode, io_data, DP_SW_RESET);
  70. sw_reset |= BIT(0);
  71. dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset);
  72. usleep_range(1000, 1010); /* h/w recommended delay */
  73. sw_reset &= ~BIT(0);
  74. dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset);
  75. dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x4); /* bit 2 */
  76. udelay(1000);
  77. dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x0); /* bit 2 */
  78. wmb(); /* make sure programming happened */
  79. io_data = catalog->io->dp_tcsr;
  80. dp_write(catalog->exe_mode, io_data, 0x4c, 0x1); /* bit 0 & 2 */
  81. wmb(); /* make sure programming happened */
  82. io_data = catalog->io->dp_phy;
  83. dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3c);
  84. wmb(); /* make sure PD programming happened */
  85. dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3d);
  86. wmb(); /* make sure PD programming happened */
  87. /* DP AUX CFG register programming */
  88. io_data = catalog->io->dp_phy;
  89. for (i = 0; i < PHY_AUX_CFG_MAX; i++)
  90. dp_write(catalog->exe_mode, io_data, cfg[i].offset,
  91. cfg[i].lut[cfg[i].current_index]);
  92. dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_MASK_V200,
  93. 0x1F);
  94. wmb(); /* make sure AUX configuration is done before enabling it */
  95. }
  96. static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel,
  97. u32 rate, u32 stream_rate_khz)
  98. {
  99. u32 pixel_m, pixel_n;
  100. u32 mvid, nvid;
  101. u32 const nvid_fixed = 0x8000;
  102. u32 const link_rate_hbr2 = 540000;
  103. u32 const link_rate_hbr3 = 810000;
  104. struct dp_catalog_private_v200 *catalog;
  105. struct dp_io_data *io_data;
  106. u32 strm_reg_off = 0;
  107. u32 mvid_reg_off = 0, nvid_reg_off = 0;
  108. if (!panel) {
  109. DP_ERR("invalid input\n");
  110. return;
  111. }
  112. if (panel->stream_id >= DP_STREAM_MAX) {
  113. DP_ERR("invalid stream_id:%d\n", panel->stream_id);
  114. return;
  115. }
  116. catalog = dp_catalog_get_priv_v200(panel);
  117. io_data = catalog->io->dp_mmss_cc;
  118. if (panel->stream_id == DP_STREAM_1)
  119. strm_reg_off = MMSS_DP_PIXEL1_M_V200 -
  120. MMSS_DP_PIXEL_M_V200;
  121. pixel_m = dp_read(catalog->exe_mode, io_data,
  122. MMSS_DP_PIXEL_M_V200 + strm_reg_off);
  123. pixel_n = dp_read(catalog->exe_mode, io_data,
  124. MMSS_DP_PIXEL_N_V200 + strm_reg_off);
  125. DP_DEBUG("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
  126. mvid = (pixel_m & 0xFFFF) * 5;
  127. nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
  128. if (nvid < nvid_fixed) {
  129. u32 temp;
  130. temp = (nvid_fixed / nvid) * nvid;
  131. mvid = (nvid_fixed / nvid) * mvid;
  132. nvid = temp;
  133. }
  134. DP_DEBUG("rate = %d\n", rate);
  135. if (panel->widebus_en)
  136. mvid <<= 1;
  137. if (link_rate_hbr2 == rate)
  138. nvid *= 2;
  139. if (link_rate_hbr3 == rate)
  140. nvid *= 3;
  141. io_data = catalog->io->dp_link;
  142. if (panel->stream_id == DP_STREAM_1) {
  143. mvid_reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID;
  144. nvid_reg_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID;
  145. }
  146. DP_DEBUG("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
  147. dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_MVID + mvid_reg_off,
  148. mvid);
  149. dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_NVID + nvid_reg_off,
  150. nvid);
  151. }
  152. static void dp_catalog_ctrl_lane_mapping_v200(struct dp_catalog_ctrl *ctrl,
  153. bool flipped, char *lane_map)
  154. {
  155. struct dp_catalog_private_v200 *catalog;
  156. struct dp_io_data *io_data;
  157. u8 l_map[4] = { 0 }, i = 0, j = 0;
  158. u32 lane_map_reg = 0;
  159. if (!ctrl) {
  160. DP_ERR("invalid input\n");
  161. return;
  162. }
  163. catalog = dp_catalog_get_priv_v200(ctrl);
  164. io_data = catalog->io->dp_link;
  165. /* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */
  166. if (flipped) {
  167. for (i = 0; i < DP_MAX_PHY_LN; i++) {
  168. if (lane_map[i] == DP_ML0) {
  169. for (j = 0; j < DP_MAX_PHY_LN; j++) {
  170. if (lane_map[j] == DP_ML3) {
  171. l_map[i] = DP_ML3;
  172. l_map[j] = DP_ML0;
  173. break;
  174. }
  175. }
  176. } else if (lane_map[i] == DP_ML1) {
  177. for (j = 0; j < DP_MAX_PHY_LN; j++) {
  178. if (lane_map[j] == DP_ML2) {
  179. l_map[i] = DP_ML2;
  180. l_map[j] = DP_ML1;
  181. break;
  182. }
  183. }
  184. }
  185. }
  186. } else {
  187. /* Normal orientation */
  188. for (i = 0; i < DP_MAX_PHY_LN; i++)
  189. l_map[i] = lane_map[i];
  190. }
  191. lane_map_reg = ((l_map[3]&3)<<6)|((l_map[2]&3)<<4)|((l_map[1]&3)<<2)
  192. |(l_map[0]&3);
  193. dp_write(catalog->exe_mode, io_data, DP_LOGICAL2PHYSICAL_LANE_MAPPING,
  194. lane_map_reg);
  195. }
  196. static void dp_catalog_ctrl_usb_reset_v200(struct dp_catalog_ctrl *ctrl,
  197. bool flip)
  198. {
  199. }
  200. static void dp_catalog_put_v200(struct dp_catalog *catalog)
  201. {
  202. struct dp_catalog_private_v200 *catalog_priv;
  203. if (!catalog || !catalog->priv.data)
  204. return;
  205. catalog_priv = catalog->priv.data;
  206. devm_kfree(catalog_priv->dev, catalog_priv);
  207. }
  208. static void dp_catalog_set_exe_mode_v200(struct dp_catalog *catalog, char *mode)
  209. {
  210. struct dp_catalog_private_v200 *catalog_priv;
  211. if (!catalog || !catalog->priv.data)
  212. return;
  213. catalog_priv = catalog->priv.data;
  214. strlcpy(catalog_priv->exe_mode, mode, sizeof(catalog_priv->exe_mode));
  215. }
  216. int dp_catalog_get_v200(struct device *dev, struct dp_catalog *catalog,
  217. void *io)
  218. {
  219. struct dp_catalog_private_v200 *catalog_priv;
  220. if (!dev || !catalog) {
  221. DP_ERR("invalid input\n");
  222. return -EINVAL;
  223. }
  224. catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL);
  225. if (!catalog_priv)
  226. return -ENOMEM;
  227. catalog_priv->dev = dev;
  228. catalog_priv->io = io;
  229. catalog->priv.data = catalog_priv;
  230. catalog->priv.put = dp_catalog_put_v200;
  231. catalog->priv.set_exe_mode = dp_catalog_set_exe_mode_v200;
  232. catalog->aux.clear_hw_interrupts =
  233. dp_catalog_aux_clear_hw_interrupts_v200;
  234. catalog->aux.setup = dp_catalog_aux_setup_v200;
  235. catalog->panel.config_msa = dp_catalog_panel_config_msa_v200;
  236. catalog->ctrl.lane_mapping = dp_catalog_ctrl_lane_mapping_v200;
  237. catalog->ctrl.usb_reset = dp_catalog_ctrl_usb_reset_v200;
  238. /* Set the default execution mode to hardware mode */
  239. dp_catalog_set_exe_mode_v200(catalog, "hw");
  240. return 0;
  241. }