mdfld_device.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /**************************************************************************
  2. * Copyright (c) 2011, Intel Corporation.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. **************************************************************************/
  19. #include "psb_drv.h"
  20. #include "mid_bios.h"
  21. #include "mdfld_output.h"
  22. #include "mdfld_dsi_output.h"
  23. #include "tc35876x-dsi-lvds.h"
  24. #include <asm/intel_scu_ipc.h>
  25. #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
  26. #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
  27. #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
  28. #define BLC_PWM_FREQ_CALC_CONSTANT 32
  29. #define MHz 1000000
  30. #define BRIGHTNESS_MIN_LEVEL 1
  31. #define BRIGHTNESS_MAX_LEVEL 100
  32. #define BRIGHTNESS_MASK 0xFF
  33. #define BLC_POLARITY_NORMAL 0
  34. #define BLC_POLARITY_INVERSE 1
  35. #define BLC_ADJUSTMENT_MAX 100
  36. #define MDFLD_BLC_PWM_PRECISION_FACTOR 10
  37. #define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE
  38. #define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2
  39. #define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
  40. #define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16)
  41. static struct backlight_device *mdfld_backlight_device;
  42. int mdfld_set_brightness(struct backlight_device *bd)
  43. {
  44. struct drm_device *dev =
  45. (struct drm_device *)bl_get_data(mdfld_backlight_device);
  46. struct drm_psb_private *dev_priv = dev->dev_private;
  47. int level = bd->props.brightness;
  48. DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
  49. /* Perform value bounds checking */
  50. if (level < BRIGHTNESS_MIN_LEVEL)
  51. level = BRIGHTNESS_MIN_LEVEL;
  52. if (gma_power_begin(dev, false)) {
  53. u32 adjusted_level = 0;
  54. /*
  55. * Adjust the backlight level with the percent in
  56. * dev_priv->blc_adj2
  57. */
  58. adjusted_level = level * dev_priv->blc_adj2;
  59. adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
  60. dev_priv->brightness_adjusted = adjusted_level;
  61. if (mdfld_get_panel_type(dev, 0) == TC35876X) {
  62. if (dev_priv->dpi_panel_on[0] ||
  63. dev_priv->dpi_panel_on[2])
  64. tc35876x_brightness_control(dev,
  65. dev_priv->brightness_adjusted);
  66. } else {
  67. if (dev_priv->dpi_panel_on[0])
  68. mdfld_dsi_brightness_control(dev, 0,
  69. dev_priv->brightness_adjusted);
  70. }
  71. if (dev_priv->dpi_panel_on[2])
  72. mdfld_dsi_brightness_control(dev, 2,
  73. dev_priv->brightness_adjusted);
  74. gma_power_end(dev);
  75. }
  76. /* cache the brightness for later use */
  77. dev_priv->brightness = level;
  78. return 0;
  79. }
  80. static int mdfld_get_brightness(struct backlight_device *bd)
  81. {
  82. struct drm_device *dev =
  83. (struct drm_device *)bl_get_data(mdfld_backlight_device);
  84. struct drm_psb_private *dev_priv = dev->dev_private;
  85. DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness);
  86. /* return locally cached var instead of HW read (due to DPST etc.) */
  87. return dev_priv->brightness;
  88. }
  89. static const struct backlight_ops mdfld_ops = {
  90. .get_brightness = mdfld_get_brightness,
  91. .update_status = mdfld_set_brightness,
  92. };
  93. static int device_backlight_init(struct drm_device *dev)
  94. {
  95. struct drm_psb_private *dev_priv = (struct drm_psb_private *)
  96. dev->dev_private;
  97. dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
  98. dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
  99. return 0;
  100. }
  101. static int mdfld_backlight_init(struct drm_device *dev)
  102. {
  103. struct backlight_properties props;
  104. int ret = 0;
  105. memset(&props, 0, sizeof(struct backlight_properties));
  106. props.max_brightness = BRIGHTNESS_MAX_LEVEL;
  107. props.type = BACKLIGHT_PLATFORM;
  108. mdfld_backlight_device = backlight_device_register("mdfld-bl",
  109. NULL, (void *)dev, &mdfld_ops, &props);
  110. if (IS_ERR(mdfld_backlight_device))
  111. return PTR_ERR(mdfld_backlight_device);
  112. ret = device_backlight_init(dev);
  113. if (ret)
  114. return ret;
  115. mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
  116. mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
  117. backlight_update_status(mdfld_backlight_device);
  118. return 0;
  119. }
  120. #endif
  121. struct backlight_device *mdfld_get_backlight_device(void)
  122. {
  123. #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
  124. return mdfld_backlight_device;
  125. #else
  126. return NULL;
  127. #endif
  128. }
  129. /*
  130. * mdfld_save_display_registers
  131. *
  132. * Description: We are going to suspend so save current display
  133. * register state.
  134. *
  135. * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
  136. */
  137. static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
  138. {
  139. struct drm_psb_private *dev_priv = dev->dev_private;
  140. struct medfield_state *regs = &dev_priv->regs.mdfld;
  141. int i;
  142. /* register */
  143. u32 dpll_reg = MRST_DPLL_A;
  144. u32 fp_reg = MRST_FPA0;
  145. u32 pipeconf_reg = PIPEACONF;
  146. u32 htot_reg = HTOTAL_A;
  147. u32 hblank_reg = HBLANK_A;
  148. u32 hsync_reg = HSYNC_A;
  149. u32 vtot_reg = VTOTAL_A;
  150. u32 vblank_reg = VBLANK_A;
  151. u32 vsync_reg = VSYNC_A;
  152. u32 pipesrc_reg = PIPEASRC;
  153. u32 dspstride_reg = DSPASTRIDE;
  154. u32 dsplinoff_reg = DSPALINOFF;
  155. u32 dsptileoff_reg = DSPATILEOFF;
  156. u32 dspsize_reg = DSPASIZE;
  157. u32 dsppos_reg = DSPAPOS;
  158. u32 dspsurf_reg = DSPASURF;
  159. u32 mipi_reg = MIPI;
  160. u32 dspcntr_reg = DSPACNTR;
  161. u32 dspstatus_reg = PIPEASTAT;
  162. u32 palette_reg = PALETTE_A;
  163. /* pointer to values */
  164. u32 *dpll_val = &regs->saveDPLL_A;
  165. u32 *fp_val = &regs->saveFPA0;
  166. u32 *pipeconf_val = &regs->savePIPEACONF;
  167. u32 *htot_val = &regs->saveHTOTAL_A;
  168. u32 *hblank_val = &regs->saveHBLANK_A;
  169. u32 *hsync_val = &regs->saveHSYNC_A;
  170. u32 *vtot_val = &regs->saveVTOTAL_A;
  171. u32 *vblank_val = &regs->saveVBLANK_A;
  172. u32 *vsync_val = &regs->saveVSYNC_A;
  173. u32 *pipesrc_val = &regs->savePIPEASRC;
  174. u32 *dspstride_val = &regs->saveDSPASTRIDE;
  175. u32 *dsplinoff_val = &regs->saveDSPALINOFF;
  176. u32 *dsptileoff_val = &regs->saveDSPATILEOFF;
  177. u32 *dspsize_val = &regs->saveDSPASIZE;
  178. u32 *dsppos_val = &regs->saveDSPAPOS;
  179. u32 *dspsurf_val = &regs->saveDSPASURF;
  180. u32 *mipi_val = &regs->saveMIPI;
  181. u32 *dspcntr_val = &regs->saveDSPACNTR;
  182. u32 *dspstatus_val = &regs->saveDSPASTATUS;
  183. u32 *palette_val = regs->save_palette_a;
  184. switch (pipe) {
  185. case 0:
  186. break;
  187. case 1:
  188. /* regester */
  189. dpll_reg = MDFLD_DPLL_B;
  190. fp_reg = MDFLD_DPLL_DIV0;
  191. pipeconf_reg = PIPEBCONF;
  192. htot_reg = HTOTAL_B;
  193. hblank_reg = HBLANK_B;
  194. hsync_reg = HSYNC_B;
  195. vtot_reg = VTOTAL_B;
  196. vblank_reg = VBLANK_B;
  197. vsync_reg = VSYNC_B;
  198. pipesrc_reg = PIPEBSRC;
  199. dspstride_reg = DSPBSTRIDE;
  200. dsplinoff_reg = DSPBLINOFF;
  201. dsptileoff_reg = DSPBTILEOFF;
  202. dspsize_reg = DSPBSIZE;
  203. dsppos_reg = DSPBPOS;
  204. dspsurf_reg = DSPBSURF;
  205. dspcntr_reg = DSPBCNTR;
  206. dspstatus_reg = PIPEBSTAT;
  207. palette_reg = PALETTE_B;
  208. /* values */
  209. dpll_val = &regs->saveDPLL_B;
  210. fp_val = &regs->saveFPB0;
  211. pipeconf_val = &regs->savePIPEBCONF;
  212. htot_val = &regs->saveHTOTAL_B;
  213. hblank_val = &regs->saveHBLANK_B;
  214. hsync_val = &regs->saveHSYNC_B;
  215. vtot_val = &regs->saveVTOTAL_B;
  216. vblank_val = &regs->saveVBLANK_B;
  217. vsync_val = &regs->saveVSYNC_B;
  218. pipesrc_val = &regs->savePIPEBSRC;
  219. dspstride_val = &regs->saveDSPBSTRIDE;
  220. dsplinoff_val = &regs->saveDSPBLINOFF;
  221. dsptileoff_val = &regs->saveDSPBTILEOFF;
  222. dspsize_val = &regs->saveDSPBSIZE;
  223. dsppos_val = &regs->saveDSPBPOS;
  224. dspsurf_val = &regs->saveDSPBSURF;
  225. dspcntr_val = &regs->saveDSPBCNTR;
  226. dspstatus_val = &regs->saveDSPBSTATUS;
  227. palette_val = regs->save_palette_b;
  228. break;
  229. case 2:
  230. /* register */
  231. pipeconf_reg = PIPECCONF;
  232. htot_reg = HTOTAL_C;
  233. hblank_reg = HBLANK_C;
  234. hsync_reg = HSYNC_C;
  235. vtot_reg = VTOTAL_C;
  236. vblank_reg = VBLANK_C;
  237. vsync_reg = VSYNC_C;
  238. pipesrc_reg = PIPECSRC;
  239. dspstride_reg = DSPCSTRIDE;
  240. dsplinoff_reg = DSPCLINOFF;
  241. dsptileoff_reg = DSPCTILEOFF;
  242. dspsize_reg = DSPCSIZE;
  243. dsppos_reg = DSPCPOS;
  244. dspsurf_reg = DSPCSURF;
  245. mipi_reg = MIPI_C;
  246. dspcntr_reg = DSPCCNTR;
  247. dspstatus_reg = PIPECSTAT;
  248. palette_reg = PALETTE_C;
  249. /* pointer to values */
  250. pipeconf_val = &regs->savePIPECCONF;
  251. htot_val = &regs->saveHTOTAL_C;
  252. hblank_val = &regs->saveHBLANK_C;
  253. hsync_val = &regs->saveHSYNC_C;
  254. vtot_val = &regs->saveVTOTAL_C;
  255. vblank_val = &regs->saveVBLANK_C;
  256. vsync_val = &regs->saveVSYNC_C;
  257. pipesrc_val = &regs->savePIPECSRC;
  258. dspstride_val = &regs->saveDSPCSTRIDE;
  259. dsplinoff_val = &regs->saveDSPCLINOFF;
  260. dsptileoff_val = &regs->saveDSPCTILEOFF;
  261. dspsize_val = &regs->saveDSPCSIZE;
  262. dsppos_val = &regs->saveDSPCPOS;
  263. dspsurf_val = &regs->saveDSPCSURF;
  264. mipi_val = &regs->saveMIPI_C;
  265. dspcntr_val = &regs->saveDSPCCNTR;
  266. dspstatus_val = &regs->saveDSPCSTATUS;
  267. palette_val = regs->save_palette_c;
  268. break;
  269. default:
  270. DRM_ERROR("%s, invalid pipe number.\n", __func__);
  271. return -EINVAL;
  272. }
  273. /* Pipe & plane A info */
  274. *dpll_val = PSB_RVDC32(dpll_reg);
  275. *fp_val = PSB_RVDC32(fp_reg);
  276. *pipeconf_val = PSB_RVDC32(pipeconf_reg);
  277. *htot_val = PSB_RVDC32(htot_reg);
  278. *hblank_val = PSB_RVDC32(hblank_reg);
  279. *hsync_val = PSB_RVDC32(hsync_reg);
  280. *vtot_val = PSB_RVDC32(vtot_reg);
  281. *vblank_val = PSB_RVDC32(vblank_reg);
  282. *vsync_val = PSB_RVDC32(vsync_reg);
  283. *pipesrc_val = PSB_RVDC32(pipesrc_reg);
  284. *dspstride_val = PSB_RVDC32(dspstride_reg);
  285. *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
  286. *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
  287. *dspsize_val = PSB_RVDC32(dspsize_reg);
  288. *dsppos_val = PSB_RVDC32(dsppos_reg);
  289. *dspsurf_val = PSB_RVDC32(dspsurf_reg);
  290. *dspcntr_val = PSB_RVDC32(dspcntr_reg);
  291. *dspstatus_val = PSB_RVDC32(dspstatus_reg);
  292. /*save palette (gamma) */
  293. for (i = 0; i < 256; i++)
  294. palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
  295. if (pipe == 1) {
  296. regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
  297. regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
  298. regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
  299. regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
  300. return 0;
  301. }
  302. *mipi_val = PSB_RVDC32(mipi_reg);
  303. return 0;
  304. }
  305. /*
  306. * mdfld_restore_display_registers
  307. *
  308. * Description: We are going to resume so restore display register state.
  309. *
  310. * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
  311. */
  312. static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
  313. {
  314. /* To get panel out of ULPS mode. */
  315. u32 temp = 0;
  316. u32 device_ready_reg = DEVICE_READY_REG;
  317. struct drm_psb_private *dev_priv = dev->dev_private;
  318. struct mdfld_dsi_config *dsi_config = NULL;
  319. struct medfield_state *regs = &dev_priv->regs.mdfld;
  320. u32 i = 0;
  321. u32 dpll = 0;
  322. u32 timeout = 0;
  323. /* regester */
  324. u32 dpll_reg = MRST_DPLL_A;
  325. u32 fp_reg = MRST_FPA0;
  326. u32 pipeconf_reg = PIPEACONF;
  327. u32 htot_reg = HTOTAL_A;
  328. u32 hblank_reg = HBLANK_A;
  329. u32 hsync_reg = HSYNC_A;
  330. u32 vtot_reg = VTOTAL_A;
  331. u32 vblank_reg = VBLANK_A;
  332. u32 vsync_reg = VSYNC_A;
  333. u32 pipesrc_reg = PIPEASRC;
  334. u32 dspstride_reg = DSPASTRIDE;
  335. u32 dsplinoff_reg = DSPALINOFF;
  336. u32 dsptileoff_reg = DSPATILEOFF;
  337. u32 dspsize_reg = DSPASIZE;
  338. u32 dsppos_reg = DSPAPOS;
  339. u32 dspsurf_reg = DSPASURF;
  340. u32 dspstatus_reg = PIPEASTAT;
  341. u32 mipi_reg = MIPI;
  342. u32 dspcntr_reg = DSPACNTR;
  343. u32 palette_reg = PALETTE_A;
  344. /* values */
  345. u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE;
  346. u32 fp_val = regs->saveFPA0;
  347. u32 pipeconf_val = regs->savePIPEACONF;
  348. u32 htot_val = regs->saveHTOTAL_A;
  349. u32 hblank_val = regs->saveHBLANK_A;
  350. u32 hsync_val = regs->saveHSYNC_A;
  351. u32 vtot_val = regs->saveVTOTAL_A;
  352. u32 vblank_val = regs->saveVBLANK_A;
  353. u32 vsync_val = regs->saveVSYNC_A;
  354. u32 pipesrc_val = regs->savePIPEASRC;
  355. u32 dspstride_val = regs->saveDSPASTRIDE;
  356. u32 dsplinoff_val = regs->saveDSPALINOFF;
  357. u32 dsptileoff_val = regs->saveDSPATILEOFF;
  358. u32 dspsize_val = regs->saveDSPASIZE;
  359. u32 dsppos_val = regs->saveDSPAPOS;
  360. u32 dspsurf_val = regs->saveDSPASURF;
  361. u32 dspstatus_val = regs->saveDSPASTATUS;
  362. u32 mipi_val = regs->saveMIPI;
  363. u32 dspcntr_val = regs->saveDSPACNTR;
  364. u32 *palette_val = regs->save_palette_a;
  365. switch (pipe) {
  366. case 0:
  367. dsi_config = dev_priv->dsi_configs[0];
  368. break;
  369. case 1:
  370. /* regester */
  371. dpll_reg = MDFLD_DPLL_B;
  372. fp_reg = MDFLD_DPLL_DIV0;
  373. pipeconf_reg = PIPEBCONF;
  374. htot_reg = HTOTAL_B;
  375. hblank_reg = HBLANK_B;
  376. hsync_reg = HSYNC_B;
  377. vtot_reg = VTOTAL_B;
  378. vblank_reg = VBLANK_B;
  379. vsync_reg = VSYNC_B;
  380. pipesrc_reg = PIPEBSRC;
  381. dspstride_reg = DSPBSTRIDE;
  382. dsplinoff_reg = DSPBLINOFF;
  383. dsptileoff_reg = DSPBTILEOFF;
  384. dspsize_reg = DSPBSIZE;
  385. dsppos_reg = DSPBPOS;
  386. dspsurf_reg = DSPBSURF;
  387. dspcntr_reg = DSPBCNTR;
  388. dspstatus_reg = PIPEBSTAT;
  389. palette_reg = PALETTE_B;
  390. /* values */
  391. dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE;
  392. fp_val = regs->saveFPB0;
  393. pipeconf_val = regs->savePIPEBCONF;
  394. htot_val = regs->saveHTOTAL_B;
  395. hblank_val = regs->saveHBLANK_B;
  396. hsync_val = regs->saveHSYNC_B;
  397. vtot_val = regs->saveVTOTAL_B;
  398. vblank_val = regs->saveVBLANK_B;
  399. vsync_val = regs->saveVSYNC_B;
  400. pipesrc_val = regs->savePIPEBSRC;
  401. dspstride_val = regs->saveDSPBSTRIDE;
  402. dsplinoff_val = regs->saveDSPBLINOFF;
  403. dsptileoff_val = regs->saveDSPBTILEOFF;
  404. dspsize_val = regs->saveDSPBSIZE;
  405. dsppos_val = regs->saveDSPBPOS;
  406. dspsurf_val = regs->saveDSPBSURF;
  407. dspcntr_val = regs->saveDSPBCNTR;
  408. dspstatus_val = regs->saveDSPBSTATUS;
  409. palette_val = regs->save_palette_b;
  410. break;
  411. case 2:
  412. /* regester */
  413. pipeconf_reg = PIPECCONF;
  414. htot_reg = HTOTAL_C;
  415. hblank_reg = HBLANK_C;
  416. hsync_reg = HSYNC_C;
  417. vtot_reg = VTOTAL_C;
  418. vblank_reg = VBLANK_C;
  419. vsync_reg = VSYNC_C;
  420. pipesrc_reg = PIPECSRC;
  421. dspstride_reg = DSPCSTRIDE;
  422. dsplinoff_reg = DSPCLINOFF;
  423. dsptileoff_reg = DSPCTILEOFF;
  424. dspsize_reg = DSPCSIZE;
  425. dsppos_reg = DSPCPOS;
  426. dspsurf_reg = DSPCSURF;
  427. mipi_reg = MIPI_C;
  428. dspcntr_reg = DSPCCNTR;
  429. dspstatus_reg = PIPECSTAT;
  430. palette_reg = PALETTE_C;
  431. /* values */
  432. pipeconf_val = regs->savePIPECCONF;
  433. htot_val = regs->saveHTOTAL_C;
  434. hblank_val = regs->saveHBLANK_C;
  435. hsync_val = regs->saveHSYNC_C;
  436. vtot_val = regs->saveVTOTAL_C;
  437. vblank_val = regs->saveVBLANK_C;
  438. vsync_val = regs->saveVSYNC_C;
  439. pipesrc_val = regs->savePIPECSRC;
  440. dspstride_val = regs->saveDSPCSTRIDE;
  441. dsplinoff_val = regs->saveDSPCLINOFF;
  442. dsptileoff_val = regs->saveDSPCTILEOFF;
  443. dspsize_val = regs->saveDSPCSIZE;
  444. dsppos_val = regs->saveDSPCPOS;
  445. dspsurf_val = regs->saveDSPCSURF;
  446. mipi_val = regs->saveMIPI_C;
  447. dspcntr_val = regs->saveDSPCCNTR;
  448. dspstatus_val = regs->saveDSPCSTATUS;
  449. palette_val = regs->save_palette_c;
  450. dsi_config = dev_priv->dsi_configs[1];
  451. break;
  452. default:
  453. DRM_ERROR("%s, invalid pipe number.\n", __func__);
  454. return -EINVAL;
  455. }
  456. /*make sure VGA plane is off. it initializes to on after reset!*/
  457. PSB_WVDC32(0x80000000, VGACNTRL);
  458. if (pipe == 1) {
  459. PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
  460. PSB_RVDC32(dpll_reg);
  461. PSB_WVDC32(fp_val, fp_reg);
  462. } else {
  463. dpll = PSB_RVDC32(dpll_reg);
  464. if (!(dpll & DPLL_VCO_ENABLE)) {
  465. /* When ungating power of DPLL, needs to wait 0.5us
  466. before enable the VCO */
  467. if (dpll & MDFLD_PWR_GATE_EN) {
  468. dpll &= ~MDFLD_PWR_GATE_EN;
  469. PSB_WVDC32(dpll, dpll_reg);
  470. /* FIXME_MDFLD PO - change 500 to 1 after PO */
  471. udelay(500);
  472. }
  473. PSB_WVDC32(fp_val, fp_reg);
  474. PSB_WVDC32(dpll_val, dpll_reg);
  475. /* FIXME_MDFLD PO - change 500 to 1 after PO */
  476. udelay(500);
  477. dpll_val |= DPLL_VCO_ENABLE;
  478. PSB_WVDC32(dpll_val, dpll_reg);
  479. PSB_RVDC32(dpll_reg);
  480. /* wait for DSI PLL to lock */
  481. while (timeout < 20000 &&
  482. !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
  483. udelay(150);
  484. timeout++;
  485. }
  486. if (timeout == 20000) {
  487. DRM_ERROR("%s, can't lock DSIPLL.\n",
  488. __func__);
  489. return -EINVAL;
  490. }
  491. }
  492. }
  493. /* Restore mode */
  494. PSB_WVDC32(htot_val, htot_reg);
  495. PSB_WVDC32(hblank_val, hblank_reg);
  496. PSB_WVDC32(hsync_val, hsync_reg);
  497. PSB_WVDC32(vtot_val, vtot_reg);
  498. PSB_WVDC32(vblank_val, vblank_reg);
  499. PSB_WVDC32(vsync_val, vsync_reg);
  500. PSB_WVDC32(pipesrc_val, pipesrc_reg);
  501. PSB_WVDC32(dspstatus_val, dspstatus_reg);
  502. /*set up the plane*/
  503. PSB_WVDC32(dspstride_val, dspstride_reg);
  504. PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
  505. PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
  506. PSB_WVDC32(dspsize_val, dspsize_reg);
  507. PSB_WVDC32(dsppos_val, dsppos_reg);
  508. PSB_WVDC32(dspsurf_val, dspsurf_reg);
  509. if (pipe == 1) {
  510. /* restore palette (gamma) */
  511. /*DRM_UDELAY(50000); */
  512. for (i = 0; i < 256; i++)
  513. PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
  514. PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
  515. PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
  516. /*TODO: resume HDMI port */
  517. /*TODO: resume pipe*/
  518. /*enable the plane*/
  519. PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
  520. return 0;
  521. }
  522. /*set up pipe related registers*/
  523. PSB_WVDC32(mipi_val, mipi_reg);
  524. /*setup MIPI adapter + MIPI IP registers*/
  525. if (dsi_config)
  526. mdfld_dsi_controller_init(dsi_config, pipe);
  527. if (in_atomic() || in_interrupt())
  528. mdelay(20);
  529. else
  530. msleep(20);
  531. /*enable the plane*/
  532. PSB_WVDC32(dspcntr_val, dspcntr_reg);
  533. if (in_atomic() || in_interrupt())
  534. mdelay(20);
  535. else
  536. msleep(20);
  537. /* LP Hold Release */
  538. temp = REG_READ(mipi_reg);
  539. temp |= LP_OUTPUT_HOLD_RELEASE;
  540. REG_WRITE(mipi_reg, temp);
  541. mdelay(1);
  542. /* Set DSI host to exit from Utra Low Power State */
  543. temp = REG_READ(device_ready_reg);
  544. temp &= ~ULPS_MASK;
  545. temp |= 0x3;
  546. temp |= EXIT_ULPS_DEV_READY;
  547. REG_WRITE(device_ready_reg, temp);
  548. mdelay(1);
  549. temp = REG_READ(device_ready_reg);
  550. temp &= ~ULPS_MASK;
  551. temp |= EXITING_ULPS;
  552. REG_WRITE(device_ready_reg, temp);
  553. mdelay(1);
  554. /*enable the pipe*/
  555. PSB_WVDC32(pipeconf_val, pipeconf_reg);
  556. /* restore palette (gamma) */
  557. /*DRM_UDELAY(50000); */
  558. for (i = 0; i < 256; i++)
  559. PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
  560. return 0;
  561. }
  562. static int mdfld_save_registers(struct drm_device *dev)
  563. {
  564. /* mdfld_save_cursor_overlay_registers(dev); */
  565. mdfld_save_display_registers(dev, 0);
  566. mdfld_save_display_registers(dev, 2);
  567. mdfld_disable_crtc(dev, 0);
  568. mdfld_disable_crtc(dev, 2);
  569. return 0;
  570. }
  571. static int mdfld_restore_registers(struct drm_device *dev)
  572. {
  573. mdfld_restore_display_registers(dev, 2);
  574. mdfld_restore_display_registers(dev, 0);
  575. /* mdfld_restore_cursor_overlay_registers(dev); */
  576. return 0;
  577. }
  578. static int mdfld_power_down(struct drm_device *dev)
  579. {
  580. /* FIXME */
  581. return 0;
  582. }
  583. static int mdfld_power_up(struct drm_device *dev)
  584. {
  585. /* FIXME */
  586. return 0;
  587. }
  588. const struct psb_ops mdfld_chip_ops = {
  589. .name = "mdfld",
  590. .accel_2d = 0,
  591. .pipes = 3,
  592. .crtcs = 3,
  593. .sgx_offset = MRST_SGX_OFFSET,
  594. .chip_setup = mid_chip_setup,
  595. .crtc_helper = &mdfld_helper_funcs,
  596. .crtc_funcs = &psb_intel_crtc_funcs,
  597. .output_init = mdfld_output_init,
  598. #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
  599. .backlight_init = mdfld_backlight_init,
  600. #endif
  601. .save_regs = mdfld_save_registers,
  602. .restore_regs = mdfld_restore_registers,
  603. .power_down = mdfld_power_down,
  604. .power_up = mdfld_power_up,
  605. };