dp_catalog_v200.c 6.5 KB

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