suspend_gx.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2007 Advanced Micro Devices, Inc.
  4. * Copyright (C) 2008 Andres Salomon <[email protected]>
  5. */
  6. #include <linux/fb.h>
  7. #include <asm/io.h>
  8. #include <asm/msr.h>
  9. #include <linux/cs5535.h>
  10. #include <asm/delay.h>
  11. #include "gxfb.h"
  12. static void gx_save_regs(struct gxfb_par *par)
  13. {
  14. int i;
  15. /* wait for the BLT engine to stop being busy */
  16. do {
  17. i = read_gp(par, GP_BLT_STATUS);
  18. } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
  19. /* save MSRs */
  20. rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
  21. rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
  22. write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
  23. /* save registers */
  24. memcpy(par->gp, par->gp_regs, sizeof(par->gp));
  25. memcpy(par->dc, par->dc_regs, sizeof(par->dc));
  26. memcpy(par->vp, par->vid_regs, sizeof(par->vp));
  27. memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
  28. /* save the palette */
  29. write_dc(par, DC_PAL_ADDRESS, 0);
  30. for (i = 0; i < ARRAY_SIZE(par->pal); i++)
  31. par->pal[i] = read_dc(par, DC_PAL_DATA);
  32. }
  33. static void gx_set_dotpll(uint32_t dotpll_hi)
  34. {
  35. uint32_t dotpll_lo;
  36. int i;
  37. rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
  38. dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
  39. dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
  40. wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
  41. /* wait for the PLL to lock */
  42. for (i = 0; i < 200; i++) {
  43. rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
  44. if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
  45. break;
  46. udelay(1);
  47. }
  48. /* PLL set, unlock */
  49. dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
  50. wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
  51. }
  52. static void gx_restore_gfx_proc(struct gxfb_par *par)
  53. {
  54. int i;
  55. for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
  56. switch (i) {
  57. case GP_VECTOR_MODE:
  58. case GP_BLT_MODE:
  59. case GP_BLT_STATUS:
  60. case GP_HST_SRC:
  61. /* don't restore these registers */
  62. break;
  63. default:
  64. write_gp(par, i, par->gp[i]);
  65. }
  66. }
  67. }
  68. static void gx_restore_display_ctlr(struct gxfb_par *par)
  69. {
  70. int i;
  71. for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
  72. switch (i) {
  73. case DC_UNLOCK:
  74. /* unlock the DC; runs first */
  75. write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
  76. break;
  77. case DC_GENERAL_CFG:
  78. /* write without the enables */
  79. write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
  80. DC_GENERAL_CFG_ICNE |
  81. DC_GENERAL_CFG_CURE |
  82. DC_GENERAL_CFG_DFLE));
  83. break;
  84. case DC_DISPLAY_CFG:
  85. /* write without the enables */
  86. write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
  87. DC_DISPLAY_CFG_GDEN |
  88. DC_DISPLAY_CFG_TGEN));
  89. break;
  90. case DC_RSVD_0:
  91. case DC_RSVD_1:
  92. case DC_RSVD_2:
  93. case DC_RSVD_3:
  94. case DC_RSVD_4:
  95. case DC_LINE_CNT:
  96. case DC_PAL_ADDRESS:
  97. case DC_PAL_DATA:
  98. case DC_DFIFO_DIAG:
  99. case DC_CFIFO_DIAG:
  100. case DC_RSVD_5:
  101. /* don't restore these registers */
  102. break;
  103. default:
  104. write_dc(par, i, par->dc[i]);
  105. }
  106. }
  107. /* restore the palette */
  108. write_dc(par, DC_PAL_ADDRESS, 0);
  109. for (i = 0; i < ARRAY_SIZE(par->pal); i++)
  110. write_dc(par, DC_PAL_DATA, par->pal[i]);
  111. }
  112. static void gx_restore_video_proc(struct gxfb_par *par)
  113. {
  114. int i;
  115. wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
  116. for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
  117. switch (i) {
  118. case VP_VCFG:
  119. /* don't enable video yet */
  120. write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
  121. break;
  122. case VP_DCFG:
  123. /* don't enable CRT yet */
  124. write_vp(par, i, par->vp[i] &
  125. ~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
  126. VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
  127. break;
  128. case VP_GAR:
  129. case VP_GDR:
  130. case VP_RSVD_0:
  131. case VP_RSVD_1:
  132. case VP_RSVD_2:
  133. case VP_RSVD_3:
  134. case VP_CRC32:
  135. case VP_AWT:
  136. case VP_VTM:
  137. /* don't restore these registers */
  138. break;
  139. default:
  140. write_vp(par, i, par->vp[i]);
  141. }
  142. }
  143. }
  144. static void gx_restore_regs(struct gxfb_par *par)
  145. {
  146. int i;
  147. gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
  148. gx_restore_gfx_proc(par);
  149. gx_restore_display_ctlr(par);
  150. gx_restore_video_proc(par);
  151. /* Flat Panel */
  152. for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
  153. if (i != FP_PM && i != FP_RSVD_0)
  154. write_fp(par, i, par->fp[i]);
  155. }
  156. }
  157. static void gx_disable_graphics(struct gxfb_par *par)
  158. {
  159. /* shut down the engine */
  160. write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
  161. write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
  162. VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
  163. /* turn off the flat panel */
  164. write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
  165. /* turn off display */
  166. write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
  167. write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
  168. ~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
  169. DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
  170. write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
  171. ~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
  172. DC_DISPLAY_CFG_TGEN));
  173. write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
  174. }
  175. static void gx_enable_graphics(struct gxfb_par *par)
  176. {
  177. uint32_t fp;
  178. fp = read_fp(par, FP_PM);
  179. if (par->fp[FP_PM] & FP_PM_P) {
  180. /* power on the panel if not already power{ed,ing} on */
  181. if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
  182. write_fp(par, FP_PM, par->fp[FP_PM]);
  183. } else {
  184. /* power down the panel if not already power{ed,ing} down */
  185. if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
  186. write_fp(par, FP_PM, par->fp[FP_PM]);
  187. }
  188. /* turn everything on */
  189. write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
  190. write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
  191. write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
  192. /* do this last; it will enable the FIFO load */
  193. write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
  194. /* lock the door behind us */
  195. write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
  196. }
  197. int gx_powerdown(struct fb_info *info)
  198. {
  199. struct gxfb_par *par = info->par;
  200. if (par->powered_down)
  201. return 0;
  202. gx_save_regs(par);
  203. gx_disable_graphics(par);
  204. par->powered_down = 1;
  205. return 0;
  206. }
  207. int gx_powerup(struct fb_info *info)
  208. {
  209. struct gxfb_par *par = info->par;
  210. if (!par->powered_down)
  211. return 0;
  212. gx_restore_regs(par);
  213. gx_enable_graphics(par);
  214. par->powered_down = 0;
  215. return 0;
  216. }