net-next:asix: V2 Update VERSION
[zen-stable.git] / drivers / staging / gma500 / mdfld_device.c
blobf47aeb7a203942a3097868ccf65b52cda572c29e
1 /**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
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.
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.
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.
18 **************************************************************************/
20 #include <linux/backlight.h>
21 #include <drm/drmP.h>
22 #include <drm/drm.h>
23 #include "psb_reg.h"
24 #include "psb_intel_reg.h"
25 #include "psb_drm.h"
26 #include "psb_drv.h"
27 #include "mdfld_output.h"
28 #include "mdfld_dsi_output.h"
29 #include "mid_bios.h"
32 * Provide the Medfield specific backlight management
35 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
37 static int mdfld_brightness;
38 struct backlight_device *mdfld_backlight_device;
40 static int mfld_set_brightness(struct backlight_device *bd)
42 struct drm_device *dev = bl_get_data(mdfld_backlight_device);
43 struct drm_psb_private *dev_priv = dev->dev_private;
44 int level = bd->props.brightness;
46 /* Percentage 1-100% being valid */
47 if (level < 1)
48 level = 1;
50 if (gma_power_begin(dev, 0)) {
51 /* Calculate and set the brightness value */
52 u32 adjusted_level;
54 /* Adjust the backlight level with the percent in
55 * dev_priv->blc_adj2;
57 adjusted_level = level * dev_priv->blc_adj2;
58 adjusted_level = adjusted_level / 100;
59 #if 0
60 #ifndef CONFIG_MDFLD_DSI_DPU
61 if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) &&
62 (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
63 mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
64 dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
66 #endif
67 mdfld_dsi_brightness_control(dev, 0, adjusted_level);
69 if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
70 mdfld_dsi_brightness_control(dev, 2, adjusted_level);
71 #endif
72 gma_power_end(dev);
74 mdfld_brightness = level;
75 return 0;
78 int psb_get_brightness(struct backlight_device *bd)
80 /* return locally cached var instead of HW read (due to DPST etc.) */
81 /* FIXME: ideally return actual value in case firmware fiddled with
82 it */
83 return mdfld_brightness;
86 static const struct backlight_ops mfld_ops = {
87 .get_brightness = psb_get_brightness,
88 .update_status = mfld_set_brightness,
91 static int mdfld_backlight_init(struct drm_device *dev)
93 struct drm_psb_private *dev_priv = dev->dev_private;
94 struct backlight_properties props;
95 memset(&props, 0, sizeof(struct backlight_properties));
96 props.max_brightness = 100;
97 props.type = BACKLIGHT_PLATFORM;
99 mdfld_backlight_device = backlight_device_register("mfld-bl",
100 NULL, (void *)dev, &mfld_ops, &props);
102 if (IS_ERR(mdfld_backlight_device))
103 return PTR_ERR(mdfld_backlight_device);
105 dev_priv->blc_adj1 = 100;
106 dev_priv->blc_adj2 = 100;
107 mdfld_backlight_device->props.brightness = 100;
108 mdfld_backlight_device->props.max_brightness = 100;
109 backlight_update_status(mdfld_backlight_device);
110 dev_priv->backlight_device = mdfld_backlight_device;
111 return 0;
114 #endif
117 * Provide the Medfield specific chip logic and low level methods for
118 * power management.
121 static void mdfld_init_pm(struct drm_device *dev)
123 /* No work needed here yet */
127 * mdfld_save_display_registers - save registers for pipe
128 * @dev: our device
129 * @pipe: pipe to save
131 * Save the pipe state of the device before we power it off. Keep everything
132 * we need to put it back again
134 static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
136 struct drm_psb_private *dev_priv = dev->dev_private;
137 int i;
139 /* register */
140 u32 dpll_reg = MRST_DPLL_A;
141 u32 fp_reg = MRST_FPA0;
142 u32 pipeconf_reg = PIPEACONF;
143 u32 htot_reg = HTOTAL_A;
144 u32 hblank_reg = HBLANK_A;
145 u32 hsync_reg = HSYNC_A;
146 u32 vtot_reg = VTOTAL_A;
147 u32 vblank_reg = VBLANK_A;
148 u32 vsync_reg = VSYNC_A;
149 u32 pipesrc_reg = PIPEASRC;
150 u32 dspstride_reg = DSPASTRIDE;
151 u32 dsplinoff_reg = DSPALINOFF;
152 u32 dsptileoff_reg = DSPATILEOFF;
153 u32 dspsize_reg = DSPASIZE;
154 u32 dsppos_reg = DSPAPOS;
155 u32 dspsurf_reg = DSPASURF;
156 u32 mipi_reg = MIPI;
157 u32 dspcntr_reg = DSPACNTR;
158 u32 dspstatus_reg = PIPEASTAT;
159 u32 palette_reg = PALETTE_A;
161 /* pointer to values */
162 u32 *dpll_val = &dev_priv->saveDPLL_A;
163 u32 *fp_val = &dev_priv->saveFPA0;
164 u32 *pipeconf_val = &dev_priv->savePIPEACONF;
165 u32 *htot_val = &dev_priv->saveHTOTAL_A;
166 u32 *hblank_val = &dev_priv->saveHBLANK_A;
167 u32 *hsync_val = &dev_priv->saveHSYNC_A;
168 u32 *vtot_val = &dev_priv->saveVTOTAL_A;
169 u32 *vblank_val = &dev_priv->saveVBLANK_A;
170 u32 *vsync_val = &dev_priv->saveVSYNC_A;
171 u32 *pipesrc_val = &dev_priv->savePIPEASRC;
172 u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
173 u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
174 u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
175 u32 *dspsize_val = &dev_priv->saveDSPASIZE;
176 u32 *dsppos_val = &dev_priv->saveDSPAPOS;
177 u32 *dspsurf_val = &dev_priv->saveDSPASURF;
178 u32 *mipi_val = &dev_priv->saveMIPI;
179 u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
180 u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
181 u32 *palette_val = dev_priv->save_palette_a;
183 switch (pipe) {
184 case 0:
185 break;
186 case 1:
187 /* register */
188 dpll_reg = MDFLD_DPLL_B;
189 fp_reg = MDFLD_DPLL_DIV0;
190 pipeconf_reg = PIPEBCONF;
191 htot_reg = HTOTAL_B;
192 hblank_reg = HBLANK_B;
193 hsync_reg = HSYNC_B;
194 vtot_reg = VTOTAL_B;
195 vblank_reg = VBLANK_B;
196 vsync_reg = VSYNC_B;
197 pipesrc_reg = PIPEBSRC;
198 dspstride_reg = DSPBSTRIDE;
199 dsplinoff_reg = DSPBLINOFF;
200 dsptileoff_reg = DSPBTILEOFF;
201 dspsize_reg = DSPBSIZE;
202 dsppos_reg = DSPBPOS;
203 dspsurf_reg = DSPBSURF;
204 dspcntr_reg = DSPBCNTR;
205 dspstatus_reg = PIPEBSTAT;
206 palette_reg = PALETTE_B;
208 /* values */
209 dpll_val = &dev_priv->saveDPLL_B;
210 fp_val = &dev_priv->saveFPB0;
211 pipeconf_val = &dev_priv->savePIPEBCONF;
212 htot_val = &dev_priv->saveHTOTAL_B;
213 hblank_val = &dev_priv->saveHBLANK_B;
214 hsync_val = &dev_priv->saveHSYNC_B;
215 vtot_val = &dev_priv->saveVTOTAL_B;
216 vblank_val = &dev_priv->saveVBLANK_B;
217 vsync_val = &dev_priv->saveVSYNC_B;
218 pipesrc_val = &dev_priv->savePIPEBSRC;
219 dspstride_val = &dev_priv->saveDSPBSTRIDE;
220 dsplinoff_val = &dev_priv->saveDSPBLINOFF;
221 dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
222 dspsize_val = &dev_priv->saveDSPBSIZE;
223 dsppos_val = &dev_priv->saveDSPBPOS;
224 dspsurf_val = &dev_priv->saveDSPBSURF;
225 dspcntr_val = &dev_priv->saveDSPBCNTR;
226 dspstatus_val = &dev_priv->saveDSPBSTATUS;
227 palette_val = dev_priv->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;
250 /* pointer to values */
251 pipeconf_val = &dev_priv->savePIPECCONF;
252 htot_val = &dev_priv->saveHTOTAL_C;
253 hblank_val = &dev_priv->saveHBLANK_C;
254 hsync_val = &dev_priv->saveHSYNC_C;
255 vtot_val = &dev_priv->saveVTOTAL_C;
256 vblank_val = &dev_priv->saveVBLANK_C;
257 vsync_val = &dev_priv->saveVSYNC_C;
258 pipesrc_val = &dev_priv->savePIPECSRC;
259 dspstride_val = &dev_priv->saveDSPCSTRIDE;
260 dsplinoff_val = &dev_priv->saveDSPCLINOFF;
261 dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
262 dspsize_val = &dev_priv->saveDSPCSIZE;
263 dsppos_val = &dev_priv->saveDSPCPOS;
264 dspsurf_val = &dev_priv->saveDSPCSURF;
265 mipi_val = &dev_priv->saveMIPI_C;
266 dspcntr_val = &dev_priv->saveDSPCCNTR;
267 dspstatus_val = &dev_priv->saveDSPCSTATUS;
268 palette_val = dev_priv->save_palette_c;
269 break;
270 default:
271 DRM_ERROR("%s, invalid pipe number.\n", __func__);
272 return -EINVAL;
275 /* Pipe & plane A info */
276 *dpll_val = PSB_RVDC32(dpll_reg);
277 *fp_val = PSB_RVDC32(fp_reg);
278 *pipeconf_val = PSB_RVDC32(pipeconf_reg);
279 *htot_val = PSB_RVDC32(htot_reg);
280 *hblank_val = PSB_RVDC32(hblank_reg);
281 *hsync_val = PSB_RVDC32(hsync_reg);
282 *vtot_val = PSB_RVDC32(vtot_reg);
283 *vblank_val = PSB_RVDC32(vblank_reg);
284 *vsync_val = PSB_RVDC32(vsync_reg);
285 *pipesrc_val = PSB_RVDC32(pipesrc_reg);
286 *dspstride_val = PSB_RVDC32(dspstride_reg);
287 *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
288 *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
289 *dspsize_val = PSB_RVDC32(dspsize_reg);
290 *dsppos_val = PSB_RVDC32(dsppos_reg);
291 *dspsurf_val = PSB_RVDC32(dspsurf_reg);
292 *dspcntr_val = PSB_RVDC32(dspcntr_reg);
293 *dspstatus_val = PSB_RVDC32(dspstatus_reg);
295 /*save palette (gamma) */
296 for (i = 0; i < 256; i++)
297 palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
299 if (pipe == 1) {
300 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
301 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
302 dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
303 dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
304 return 0;
306 *mipi_val = PSB_RVDC32(mipi_reg);
307 return 0;
311 * mdfld_save_cursor_overlay_registers - save cursor overlay info
312 * @dev: our device
314 * Save the cursor and overlay register state
316 static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
318 struct drm_psb_private *dev_priv = dev->dev_private;
320 /* Save cursor regs */
321 dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
322 dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
323 dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
325 dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
326 dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
327 dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
329 dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
330 dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
331 dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
333 /* HW overlay */
334 dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
335 dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
336 dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
337 dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
338 dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
339 dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
340 dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
342 dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
343 dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
344 dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
345 dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
346 dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
347 dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
348 dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
350 return 0;
353 * mdfld_restore_display_registers - restore the state of a pipe
354 * @dev: our device
355 * @pipe: the pipe to restore
357 * Restore the state of a pipe to that which was saved by the register save
358 * functions.
360 static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
362 /* To get panel out of ULPS mode */
363 struct drm_psb_private *dev_priv = dev->dev_private;
364 struct mdfld_dsi_config *dsi_config = NULL;
365 u32 i = 0;
366 u32 dpll = 0;
367 u32 timeout = 0;
368 u32 reg_offset = 0;
370 /* register */
371 u32 dpll_reg = MRST_DPLL_A;
372 u32 fp_reg = MRST_FPA0;
373 u32 pipeconf_reg = PIPEACONF;
374 u32 htot_reg = HTOTAL_A;
375 u32 hblank_reg = HBLANK_A;
376 u32 hsync_reg = HSYNC_A;
377 u32 vtot_reg = VTOTAL_A;
378 u32 vblank_reg = VBLANK_A;
379 u32 vsync_reg = VSYNC_A;
380 u32 pipesrc_reg = PIPEASRC;
381 u32 dspstride_reg = DSPASTRIDE;
382 u32 dsplinoff_reg = DSPALINOFF;
383 u32 dsptileoff_reg = DSPATILEOFF;
384 u32 dspsize_reg = DSPASIZE;
385 u32 dsppos_reg = DSPAPOS;
386 u32 dspsurf_reg = DSPASURF;
387 u32 dspstatus_reg = PIPEASTAT;
388 u32 mipi_reg = MIPI;
389 u32 dspcntr_reg = DSPACNTR;
390 u32 palette_reg = PALETTE_A;
392 /* values */
393 u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
394 u32 fp_val = dev_priv->saveFPA0;
395 u32 pipeconf_val = dev_priv->savePIPEACONF;
396 u32 htot_val = dev_priv->saveHTOTAL_A;
397 u32 hblank_val = dev_priv->saveHBLANK_A;
398 u32 hsync_val = dev_priv->saveHSYNC_A;
399 u32 vtot_val = dev_priv->saveVTOTAL_A;
400 u32 vblank_val = dev_priv->saveVBLANK_A;
401 u32 vsync_val = dev_priv->saveVSYNC_A;
402 u32 pipesrc_val = dev_priv->savePIPEASRC;
403 u32 dspstride_val = dev_priv->saveDSPASTRIDE;
404 u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
405 u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
406 u32 dspsize_val = dev_priv->saveDSPASIZE;
407 u32 dsppos_val = dev_priv->saveDSPAPOS;
408 u32 dspsurf_val = dev_priv->saveDSPASURF;
409 u32 dspstatus_val = dev_priv->saveDSPASTATUS;
410 u32 mipi_val = dev_priv->saveMIPI;
411 u32 dspcntr_val = dev_priv->saveDSPACNTR;
412 u32 *palette_val = dev_priv->save_palette_a;
414 switch (pipe) {
415 case 0:
416 dsi_config = dev_priv->dsi_configs[0];
417 break;
418 case 1:
419 /* register */
420 dpll_reg = MDFLD_DPLL_B;
421 fp_reg = MDFLD_DPLL_DIV0;
422 pipeconf_reg = PIPEBCONF;
423 htot_reg = HTOTAL_B;
424 hblank_reg = HBLANK_B;
425 hsync_reg = HSYNC_B;
426 vtot_reg = VTOTAL_B;
427 vblank_reg = VBLANK_B;
428 vsync_reg = VSYNC_B;
429 pipesrc_reg = PIPEBSRC;
430 dspstride_reg = DSPBSTRIDE;
431 dsplinoff_reg = DSPBLINOFF;
432 dsptileoff_reg = DSPBTILEOFF;
433 dspsize_reg = DSPBSIZE;
434 dsppos_reg = DSPBPOS;
435 dspsurf_reg = DSPBSURF;
436 dspcntr_reg = DSPBCNTR;
437 palette_reg = PALETTE_B;
438 dspstatus_reg = PIPEBSTAT;
440 /* values */
441 dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
442 fp_val = dev_priv->saveFPB0;
443 pipeconf_val = dev_priv->savePIPEBCONF;
444 htot_val = dev_priv->saveHTOTAL_B;
445 hblank_val = dev_priv->saveHBLANK_B;
446 hsync_val = dev_priv->saveHSYNC_B;
447 vtot_val = dev_priv->saveVTOTAL_B;
448 vblank_val = dev_priv->saveVBLANK_B;
449 vsync_val = dev_priv->saveVSYNC_B;
450 pipesrc_val = dev_priv->savePIPEBSRC;
451 dspstride_val = dev_priv->saveDSPBSTRIDE;
452 dsplinoff_val = dev_priv->saveDSPBLINOFF;
453 dsptileoff_val = dev_priv->saveDSPBTILEOFF;
454 dspsize_val = dev_priv->saveDSPBSIZE;
455 dsppos_val = dev_priv->saveDSPBPOS;
456 dspsurf_val = dev_priv->saveDSPBSURF;
457 dspcntr_val = dev_priv->saveDSPBCNTR;
458 dspstatus_val = dev_priv->saveDSPBSTATUS;
459 palette_val = dev_priv->save_palette_b;
460 break;
461 case 2:
462 reg_offset = MIPIC_REG_OFFSET;
464 /* register */
465 pipeconf_reg = PIPECCONF;
466 htot_reg = HTOTAL_C;
467 hblank_reg = HBLANK_C;
468 hsync_reg = HSYNC_C;
469 vtot_reg = VTOTAL_C;
470 vblank_reg = VBLANK_C;
471 vsync_reg = VSYNC_C;
472 pipesrc_reg = PIPECSRC;
473 dspstride_reg = DSPCSTRIDE;
474 dsplinoff_reg = DSPCLINOFF;
475 dsptileoff_reg = DSPCTILEOFF;
476 dspsize_reg = DSPCSIZE;
477 dsppos_reg = DSPCPOS;
478 dspsurf_reg = DSPCSURF;
479 mipi_reg = MIPI_C;
480 dspcntr_reg = DSPCCNTR;
481 palette_reg = PALETTE_C;
482 dspstatus_reg = PIPECSTAT;
484 /* values */
485 pipeconf_val = dev_priv->savePIPECCONF;
486 htot_val = dev_priv->saveHTOTAL_C;
487 hblank_val = dev_priv->saveHBLANK_C;
488 hsync_val = dev_priv->saveHSYNC_C;
489 vtot_val = dev_priv->saveVTOTAL_C;
490 vblank_val = dev_priv->saveVBLANK_C;
491 vsync_val = dev_priv->saveVSYNC_C;
492 pipesrc_val = dev_priv->savePIPECSRC;
493 dspstride_val = dev_priv->saveDSPCSTRIDE;
494 dsplinoff_val = dev_priv->saveDSPCLINOFF;
495 dsptileoff_val = dev_priv->saveDSPCTILEOFF;
496 dspsize_val = dev_priv->saveDSPCSIZE;
497 dsppos_val = dev_priv->saveDSPCPOS;
498 dspsurf_val = dev_priv->saveDSPCSURF;
499 dspstatus_val = dev_priv->saveDSPCSTATUS;
500 mipi_val = dev_priv->saveMIPI_C;
501 dspcntr_val = dev_priv->saveDSPCCNTR;
502 palette_val = dev_priv->save_palette_c;
504 dsi_config = dev_priv->dsi_configs[1];
505 break;
506 default:
507 DRM_ERROR("%s, invalid pipe number.\n", __func__);
508 return -EINVAL;
511 /* Make sure VGA plane is off. it initializes to on after reset!*/
512 PSB_WVDC32(0x80000000, VGACNTRL);
513 if (pipe == 1) {
514 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
515 PSB_RVDC32(dpll_reg);
517 PSB_WVDC32(fp_val, fp_reg);
518 } else {
519 dpll = PSB_RVDC32(dpll_reg);
521 if (!(dpll & DPLL_VCO_ENABLE)) {
523 /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
524 if (dpll & MDFLD_PWR_GATE_EN) {
525 dpll &= ~MDFLD_PWR_GATE_EN;
526 PSB_WVDC32(dpll, dpll_reg);
527 udelay(500); /* FIXME: 1 ? */
530 PSB_WVDC32(fp_val, fp_reg);
531 PSB_WVDC32(dpll_val, dpll_reg);
532 /* FIXME_MDFLD PO - change 500 to 1 after PO */
533 udelay(500);
535 dpll_val |= DPLL_VCO_ENABLE;
536 PSB_WVDC32(dpll_val, dpll_reg);
537 PSB_RVDC32(dpll_reg);
539 /* wait for DSI PLL to lock */
540 while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
541 udelay(150);
542 timeout++;
545 if (timeout == 20000) {
546 DRM_ERROR("%s, can't lock DSIPLL.\n",
547 __func__);
548 return -EINVAL;
552 /* Restore mode */
553 PSB_WVDC32(htot_val, htot_reg);
554 PSB_WVDC32(hblank_val, hblank_reg);
555 PSB_WVDC32(hsync_val, hsync_reg);
556 PSB_WVDC32(vtot_val, vtot_reg);
557 PSB_WVDC32(vblank_val, vblank_reg);
558 PSB_WVDC32(vsync_val, vsync_reg);
559 PSB_WVDC32(pipesrc_val, pipesrc_reg);
560 PSB_WVDC32(dspstatus_val, dspstatus_reg);
562 /* Set up the plane */
563 PSB_WVDC32(dspstride_val, dspstride_reg);
564 PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
565 PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
566 PSB_WVDC32(dspsize_val, dspsize_reg);
567 PSB_WVDC32(dsppos_val, dsppos_reg);
568 PSB_WVDC32(dspsurf_val, dspsurf_reg);
570 if (pipe == 1) {
571 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
572 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
573 PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
574 PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
576 } else {
577 /* Set up pipe related registers */
578 PSB_WVDC32(mipi_val, mipi_reg);
579 /* Setup MIPI adapter + MIPI IP registers */
580 mdfld_dsi_controller_init(dsi_config, pipe);
581 msleep(20);
583 /* Enable the plane */
584 PSB_WVDC32(dspcntr_val, dspcntr_reg);
585 msleep(20);
586 /* Enable the pipe */
587 PSB_WVDC32(pipeconf_val, pipeconf_reg);
589 for (i = 0; i < 256; i++)
590 PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
591 if (pipe == 1)
592 return 0;
593 if (!mdfld_panel_dpi(dev))
594 mdfld_enable_te(dev, pipe);
595 return 0;
599 * mdfld_restore_cursor_overlay_registers - restore cursor
600 * @dev: our device
602 * Restore the cursor and overlay state that was saved earlier
604 static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
606 struct drm_psb_private *dev_priv = dev->dev_private;
608 /* Enable Cursor A */
609 PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
610 PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
611 PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
613 PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
614 PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
615 PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
617 PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
618 PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
619 PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
621 /* Restore HW overlay */
622 PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
623 PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
624 PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
625 PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
626 PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
627 PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
628 PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
630 PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
631 PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
632 PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
633 PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
634 PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
635 PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
636 PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
638 return 0;
642 * mdfld_save_display_registers - save registers lost on suspend
643 * @dev: our DRM device
645 * Save the state we need in order to be able to restore the interface
646 * upon resume from suspend
648 static int mdfld_save_registers(struct drm_device *dev)
650 /* FIXME: We need to shut down panels here if using them
651 and once the right bits are merged */
652 mdfld_save_cursor_overlay_registers(dev);
653 mdfld_save_display_registers(dev, 0);
654 mdfld_save_display_registers(dev, 0);
655 mdfld_save_display_registers(dev, 2);
656 mdfld_save_display_registers(dev, 1);
657 mdfld_disable_crtc(dev, 0);
658 mdfld_disable_crtc(dev, 2);
659 mdfld_disable_crtc(dev, 1);
660 return 0;
664 * mdfld_restore_display_registers - restore lost register state
665 * @dev: our DRM device
667 * Restore register state that was lost during suspend and resume.
669 static int mdfld_restore_registers(struct drm_device *dev)
671 mdfld_restore_display_registers(dev, 1);
672 mdfld_restore_display_registers(dev, 0);
673 mdfld_restore_display_registers(dev, 2);
674 mdfld_restore_cursor_overlay_registers(dev);
675 return 0;
678 static int mdfld_power_down(struct drm_device *dev)
680 /* FIXME */
681 return 0;
684 static int mdfld_power_up(struct drm_device *dev)
686 /* FIXME */
687 return 0;
690 const struct psb_ops mdfld_chip_ops = {
691 .name = "Medfield",
692 .accel_2d = 0,
693 .pipes = 3,
694 .crtcs = 2,
695 .sgx_offset = MRST_SGX_OFFSET,
697 .chip_setup = mid_chip_setup,
699 .crtc_helper = &mdfld_helper_funcs,
700 .crtc_funcs = &mdfld_intel_crtc_funcs,
702 .output_init = mdfld_output_init,
704 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
705 .backlight_init = mdfld_backlight_init,
706 #endif
708 .init_pm = mdfld_init_pm,
709 .save_regs = mdfld_save_registers,
710 .restore_regs = mdfld_restore_registers,
711 .power_down = mdfld_power_down,
712 .power_up = mdfld_power_up,