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