2 * Copyright © 2010-2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Jim Liu <jim.liu@intel.com>
25 * Jackie Li<yaodong.li@intel.com>
28 #include "mdfld_dsi_dbi_dpu.h"
29 #include "mdfld_dsi_dbi.h"
32 * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
35 static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info
*dpu_info
,
37 struct psb_drm_dpu_rect
*damaged_rect
)
41 struct psb_drm_dpu_rect
*rect
;
42 struct psb_drm_dpu_rect
*pipe_rect
;
44 struct mdfld_cursor_info
*cursor
;
45 mdfld_plane_t fb_plane
;
47 if (plane
== MDFLD_CURSORA
) {
48 cursor
= &dpu_info
->cursors
[0];
49 x
= dpu_info
->cursors
[0].x
;
50 y
= dpu_info
->cursors
[0].y
;
51 cursor_size
= dpu_info
->cursors
[0].size
;
52 pipe_rect
= &dpu_info
->damage_pipea
;
53 fb_plane
= MDFLD_PLANEA
;
55 cursor
= &dpu_info
->cursors
[1];
56 x
= dpu_info
->cursors
[1].x
;
57 y
= dpu_info
->cursors
[1].y
;
58 cursor_size
= dpu_info
->cursors
[1].size
;
59 pipe_rect
= &dpu_info
->damage_pipec
;
60 fb_plane
= MDFLD_PLANEC
;
62 new_x
= damaged_rect
->x
;
63 new_y
= damaged_rect
->y
;
65 if (x
== new_x
&& y
== new_y
)
68 rect
= &dpu_info
->damaged_rects
[plane
];
74 rect
->width
= (new_x
+ cursor_size
) - x
;
75 rect
->height
= (new_y
+ cursor_size
) - y
;
80 rect
->width
= (new_x
+ cursor_size
) - x
;
81 rect
->height
= (y
- new_y
);
88 rect
->width
= (x
+ cursor_size
) - new_x
;
89 rect
->height
= new_y
- y
;
94 rect
->width
= (x
+ cursor_size
) - new_x
;
95 rect
->height
= (y
+ cursor_size
) - new_y
;
101 else if (new_x
> 864)
108 else if (new_y
> 480)
114 * FIXME: this is a workaround for cursor plane update,
122 mdfld_check_boundary(dpu_info
, rect
);
123 mdfld_dpu_region_extent(pipe_rect
, rect
);
125 /* Update pending status of dpu_info */
126 dpu_info
->pending
|= (1 << plane
);
127 /* Update fb panel as well */
128 dpu_info
->pending
|= (1 << fb_plane
);
132 static int mdfld_fb_damage(struct mdfld_dbi_dpu_info
*dpu_info
,
134 struct psb_drm_dpu_rect
*damaged_rect
)
136 struct psb_drm_dpu_rect
*rect
;
138 if (plane
== MDFLD_PLANEA
)
139 rect
= &dpu_info
->damage_pipea
;
141 rect
= &dpu_info
->damage_pipec
;
143 mdfld_check_boundary(dpu_info
, damaged_rect
);
145 /* Add fb damage area to this pipe */
146 mdfld_dpu_region_extent(rect
, damaged_rect
);
148 /* Update pending status of dpu_info */
149 dpu_info
->pending
|= (1 << plane
);
153 /* Do nothing here, right now */
154 static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info
*dpu_info
,
156 struct psb_drm_dpu_rect
*damaged_rect
)
161 int mdfld_dbi_dpu_report_damage(struct drm_device
*dev
,
163 struct psb_drm_dpu_rect
*rect
)
165 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
166 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
169 /* DPU not in use, no damage reporting needed */
170 if (dpu_info
== NULL
)
173 spin_lock(&dpu_info
->dpu_update_lock
);
178 mdfld_fb_damage(dpu_info
, plane
, rect
);
182 mdfld_cursor_damage(dpu_info
, plane
, rect
);
186 mdfld_overlay_damage(dpu_info
, plane
, rect
);
189 DRM_ERROR("Invalid plane type %d\n", plane
);
192 spin_unlock(&dpu_info
->dpu_update_lock
);
196 int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device
*dev
)
198 struct drm_psb_private
*dev_priv
;
199 struct mdfld_dbi_dpu_info
*dpu_info
;
200 struct mdfld_dsi_config
*dsi_config
;
201 struct psb_drm_dpu_rect rect
;
205 DRM_ERROR("Invalid parameter\n");
209 dev_priv
= dev
->dev_private
;
210 dpu_info
= dev_priv
->dbi_dpu_info
;
212 /* This is fine - we may be in non DPU mode */
216 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++) {
217 dsi_config
= dev_priv
->dsi_configs
[i
];
220 rect
.width
= dsi_config
->fixed_mode
->hdisplay
;
221 rect
.height
= dsi_config
->fixed_mode
->vdisplay
;
222 mdfld_dbi_dpu_report_damage(dev
,
223 i
? (MDFLD_PLANEC
) : (MDFLD_PLANEA
),
228 mdfld_dpu_exit_dsr(dev
);
232 int mdfld_dsi_dbi_dsr_off(struct drm_device
*dev
,
233 struct psb_drm_dpu_rect
*rect
)
235 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
236 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
238 mdfld_dbi_dpu_report_damage(dev
, MDFLD_PLANEA
, rect
);
240 /* If dual display mode */
241 if (dpu_info
->dbi_output_num
== 2)
242 mdfld_dbi_dpu_report_damage(dev
, MDFLD_PLANEC
, rect
);
244 /* Force dsi to exit DSR mode */
245 mdfld_dpu_exit_dsr(dev
);
249 static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info
*dpu_info
,
252 struct drm_device
*dev
= dpu_info
->dev
;
253 u32 curpos_reg
= CURAPOS
;
254 u32 curbase_reg
= CURABASE
;
255 u32 curcntr_reg
= CURACNTR
;
256 struct mdfld_cursor_info
*cursor
= &dpu_info
->cursors
[0];
258 if (plane
== MDFLD_CURSORC
) {
259 curpos_reg
= CURCPOS
;
260 curbase_reg
= CURCBASE
;
261 curcntr_reg
= CURCCNTR
;
262 cursor
= &dpu_info
->cursors
[1];
265 REG_WRITE(curcntr_reg
, REG_READ(curcntr_reg
));
266 REG_WRITE(curpos_reg
,
267 (((cursor
->x
& CURSOR_POS_MASK
) << CURSOR_X_SHIFT
) |
268 ((cursor
->y
& CURSOR_POS_MASK
) << CURSOR_Y_SHIFT
)));
269 REG_WRITE(curbase_reg
, REG_READ(curbase_reg
));
272 static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info
*dpu_info
,
275 u32 pipesrc_reg
= PIPEASRC
;
276 u32 dspsize_reg
= DSPASIZE
;
277 u32 dspoff_reg
= DSPALINOFF
;
278 u32 dspsurf_reg
= DSPASURF
;
279 u32 dspstride_reg
= DSPASTRIDE
;
281 struct psb_drm_dpu_rect
*rect
= &dpu_info
->damage_pipea
;
282 struct drm_device
*dev
= dpu_info
->dev
;
284 if (plane
== MDFLD_PLANEC
) {
285 pipesrc_reg
= PIPECSRC
;
286 dspsize_reg
= DSPCSIZE
;
287 dspoff_reg
= DSPCLINOFF
;
288 dspsurf_reg
= DSPCSURF
;
289 dspstride_reg
= DSPCSTRIDE
;
290 rect
= &dpu_info
->damage_pipec
;
293 stride
= REG_READ(dspstride_reg
);
294 /* FIXME: should I do the pipe src update here? */
295 REG_WRITE(pipesrc_reg
, ((rect
->width
- 1) << 16) | (rect
->height
- 1));
297 REG_WRITE(dspsize_reg
, ((rect
->height
- 1) << 16) | (rect
->width
- 1));
298 REG_WRITE(dspoff_reg
, ((rect
->x
* 4) + (rect
->y
* stride
)));
299 REG_WRITE(dspsurf_reg
, REG_READ(dspsurf_reg
));
302 * TODO: wait for flip finished and restore the pipesrc reg,
303 * or cursor will be show at a wrong position
307 static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info
*dpu_info
,
313 * TODO: we are still in dbi normal mode now, we will try to use partial
316 static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output
*dbi_output
,
317 struct mdfld_dbi_dpu_info
*dpu_info
, int pipe
)
319 u8
*cb_addr
= (u8
*)dbi_output
->dbi_cb_addr
;
321 struct psb_drm_dpu_rect
*rect
= pipe
?
322 (&dpu_info
->damage_pipec
) : (&dpu_info
->damage_pipea
);
324 /* FIXME: lock command buffer, this may lead to a deadlock,
325 as we already hold the dpu_update_lock */
326 if (!spin_trylock(&dbi_output
->cb_lock
)) {
327 DRM_ERROR("lock command buffer failed, try again\n");
331 index
= &dbi_output
->cb_write
;
334 DRM_ERROR("DBI command buffer unclean\n");
339 *(cb_addr
+ ((*index
)++)) = set_column_address
;
340 *(cb_addr
+ ((*index
)++)) = rect
->x
>> 8;
341 *(cb_addr
+ ((*index
)++)) = rect
->x
;
342 *(cb_addr
+ ((*index
)++)) = (rect
->x
+ rect
->width
- 1) >> 8;
343 *(cb_addr
+ ((*index
)++)) = (rect
->x
+ rect
->width
- 1);
348 *(cb_addr
+ ((*index
)++)) = set_page_addr
;
349 *(cb_addr
+ ((*index
)++)) = rect
->y
>> 8;
350 *(cb_addr
+ ((*index
)++)) = rect
->y
;
351 *(cb_addr
+ ((*index
)++)) = (rect
->y
+ rect
->height
- 1) >> 8;
352 *(cb_addr
+ ((*index
)++)) = (rect
->y
+ rect
->height
- 1);
357 *(cb_addr
+ ((*index
)++)) = write_mem_start
;
362 static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output
*dbi_output
, int pipe
)
364 u32 cmd_phy
= dbi_output
->dbi_cb_phy
;
365 u32
*index
= &dbi_output
->cb_write
;
366 int reg_offset
= pipe
? MIPIC_REG_OFFSET
: 0;
367 struct drm_device
*dev
= dbi_output
->dev
;
369 if (*index
== 0 || !dbi_output
)
372 REG_WRITE((MIPIA_CMD_LEN_REG
+ reg_offset
), 0x010505);
373 REG_WRITE((MIPIA_CMD_ADD_REG
+ reg_offset
), cmd_phy
| 3);
377 /* FIXME: unlock command buffer */
378 spin_unlock(&dbi_output
->cb_lock
);
382 static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output
*dbi_output
,
383 struct mdfld_dbi_dpu_info
*dpu_info
, int pipe
)
385 struct drm_device
*dev
= dbi_output
->dev
;
386 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
387 mdfld_plane_t cursor_plane
= MDFLD_CURSORA
;
388 mdfld_plane_t fb_plane
= MDFLD_PLANEA
;
389 mdfld_plane_t overlay_plane
= MDFLD_OVERLAYA
;
391 u32 plane_mask
= MDFLD_PIPEA_PLANE_MASK
;
393 /* Damaged rects on this pipe */
395 cursor_plane
= MDFLD_CURSORC
;
396 fb_plane
= MDFLD_PLANEC
;
397 overlay_plane
= MDFLD_OVERLAYC
;
398 plane_mask
= MDFLD_PIPEC_PLANE_MASK
;
401 /*update cursor which assigned to @pipe*/
402 if (dpu_info
->pending
& (1 << cursor_plane
))
403 mdfld_dpu_cursor_plane_flush(dpu_info
, cursor_plane
);
405 /*update fb which assigned to @pipe*/
406 if (dpu_info
->pending
& (1 << fb_plane
))
407 mdfld_dpu_fb_plane_flush(dpu_info
, fb_plane
);
409 /* TODO: update overlay */
410 if (dpu_info
->pending
& (1 << overlay_plane
))
411 mdfld_dpu_overlay_plane_flush(dpu_info
, overlay_plane
);
413 /* Flush damage area to panel fb */
414 if (dpu_info
->pending
& plane_mask
) {
415 ret
= mdfld_dbi_prepare_cb(dbi_output
, dpu_info
, pipe
);
417 * TODO: remove b_dsr_enable later,
418 * added it so that text console could boot smoothly
420 /* Clean pending flags on this pipe */
421 if (!ret
&& dev_priv
->dsr_enable
) {
422 dpu_info
->pending
&= ~plane_mask
;
423 /* Reset overlay pipe damage rect */
424 mdfld_dpu_init_damage(dpu_info
, pipe
);
430 static int mdfld_dpu_update_fb(struct drm_device
*dev
)
432 struct drm_crtc
*crtc
;
433 struct psb_intel_crtc
*psb_crtc
;
434 struct mdfld_dsi_dbi_output
**dbi_output
;
435 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
436 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
437 bool pipe_updated
[2];
438 unsigned long irq_flags
;
439 u32 dpll_reg
= MRST_DPLL_A
;
440 u32 dspcntr_reg
= DSPACNTR
;
441 u32 pipeconf_reg
= PIPEACONF
;
442 u32 dsplinoff_reg
= DSPALINOFF
;
443 u32 dspsurf_reg
= DSPASURF
;
444 u32 mipi_state_reg
= MIPIA_INTR_STAT_REG
;
450 dbi_output
= dpu_info
->dbi_outputs
;
451 pipe_updated
[0] = pipe_updated
[1] = false;
453 if (!gma_power_begin(dev
, true))
456 /* Try to prevent any new damage reports */
457 if (!spin_trylock_irqsave(&dpu_info
->dpu_update_lock
, irq_flags
))
460 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++) {
461 crtc
= dbi_output
[i
]->base
.base
.crtc
;
462 psb_crtc
= (crtc
) ? to_psb_intel_crtc(crtc
) : NULL
;
464 pipe
= dbi_output
[i
]->channel_num
? 2 : 0;
467 dspcntr_reg
= DSPCCNTR
;
468 pipeconf_reg
= PIPECCONF
;
469 dsplinoff_reg
= DSPCLINOFF
;
470 dspsurf_reg
= DSPCSURF
;
471 reg_offset
= MIPIC_REG_OFFSET
;
474 if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG
+ reg_offset
))
476 !(REG_READ(dpll_reg
) & DPLL_VCO_ENABLE
) ||
477 !(REG_READ(dspcntr_reg
) & DISPLAY_PLANE_ENABLE
) ||
478 !(REG_READ(pipeconf_reg
) & DISPLAY_PLANE_ENABLE
)) {
480 "DBI FIFO is busy, DSI %d state %x\n",
482 REG_READ(mipi_state_reg
+ reg_offset
));
487 * If DBI output is in a exclusive state then the pipe
488 * change won't be updated
490 if (dbi_output
[i
]->dbi_panel_on
&&
491 !(dbi_output
[i
]->mode_flags
& MODE_SETTING_ON_GOING
) &&
493 psb_crtc
->mode_flags
& MODE_SETTING_ON_GOING
) &&
494 !(dbi_output
[i
]->mode_flags
& MODE_SETTING_IN_DSR
)) {
495 ret
= mdfld_dpu_update_pipe(dbi_output
[i
],
496 dpu_info
, dbi_output
[i
]->channel_num
? 2 : 0);
498 pipe_updated
[i
] = true;
502 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++)
504 mdfld_dbi_flush_cb(dbi_output
[i
],
505 dbi_output
[i
]->channel_num
? 2 : 0);
507 spin_unlock_irqrestore(&dpu_info
->dpu_update_lock
, irq_flags
);
512 static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output
*dbi_output
,
515 struct drm_device
*dev
= dbi_output
->dev
;
516 struct drm_crtc
*crtc
= dbi_output
->base
.base
.crtc
;
517 struct psb_intel_crtc
*psb_crtc
= (crtc
) ? to_psb_intel_crtc(crtc
)
520 u32 dpll_reg
= MRST_DPLL_A
;
521 u32 pipeconf_reg
= PIPEACONF
;
522 u32 dspcntr_reg
= DSPACNTR
;
523 u32 dspbase_reg
= DSPABASE
;
524 u32 dspsurf_reg
= DSPASURF
;
530 /* If mode setting on-going, back off */
531 if ((dbi_output
->mode_flags
& MODE_SETTING_ON_GOING
) ||
532 (psb_crtc
&& psb_crtc
->mode_flags
& MODE_SETTING_ON_GOING
))
536 dpll_reg
= MRST_DPLL_A
;
537 pipeconf_reg
= PIPECCONF
;
538 dspcntr_reg
= DSPCCNTR
;
539 dspbase_reg
= MDFLD_DSPCBASE
;
540 dspsurf_reg
= DSPCSURF
;
542 reg_offset
= MIPIC_REG_OFFSET
;
545 if (!gma_power_begin(dev
, true))
549 reg_val
= REG_READ(dpll_reg
);
550 if (!(reg_val
& DPLL_VCO_ENABLE
)) {
552 if (reg_val
& MDFLD_PWR_GATE_EN
) {
553 reg_val
&= ~MDFLD_PWR_GATE_EN
;
554 REG_WRITE(dpll_reg
, reg_val
);
559 reg_val
|= DPLL_VCO_ENABLE
;
560 REG_WRITE(dpll_reg
, reg_val
);
564 /* FIXME: add timeout */
565 while (!(REG_READ(pipeconf_reg
) & PIPECONF_DSIPLL_LOCK
))
570 reg_val
= REG_READ(pipeconf_reg
);
571 if (!(reg_val
& PIPEACONF_ENABLE
)) {
572 reg_val
|= PIPEACONF_ENABLE
;
573 REG_WRITE(pipeconf_reg
, reg_val
);
574 REG_READ(pipeconf_reg
);
576 mdfldWaitForPipeEnable(dev
, pipe
);
580 reg_val
= REG_READ(dspcntr_reg
);
581 if (!(reg_val
& DISPLAY_PLANE_ENABLE
)) {
582 reg_val
|= DISPLAY_PLANE_ENABLE
;
583 REG_WRITE(dspcntr_reg
, reg_val
);
584 REG_READ(dspcntr_reg
);
590 /* Clean IN_DSR flag */
591 dbi_output
->mode_flags
&= ~MODE_SETTING_IN_DSR
;
596 int mdfld_dpu_exit_dsr(struct drm_device
*dev
)
598 struct mdfld_dsi_dbi_output
**dbi_output
;
599 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
600 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
604 dbi_output
= dpu_info
->dbi_outputs
;
606 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++) {
607 /* If this output is not in DSR mode, don't call exit dsr */
608 if (dbi_output
[i
]->mode_flags
& MODE_SETTING_IN_DSR
)
609 __mdfld_dbi_exit_dsr(dbi_output
[i
],
610 dbi_output
[i
]->channel_num
? 2 : 0);
613 /* Enable TE interrupt */
614 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++) {
615 /* If this output is not in DSR mode, don't call exit dsr */
616 pipe
= dbi_output
[i
]->channel_num
? 2 : 0;
617 if (dbi_output
[i
]->dbi_panel_on
&& pipe
) {
618 mdfld_disable_te(dev
, 0);
619 mdfld_enable_te(dev
, 2);
620 } else if (dbi_output
[i
]->dbi_panel_on
&& !pipe
) {
621 mdfld_disable_te(dev
, 2);
622 mdfld_enable_te(dev
, 0);
628 static int mdfld_dpu_enter_dsr(struct drm_device
*dev
)
630 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
631 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
632 struct mdfld_dsi_dbi_output
**dbi_output
;
635 dbi_output
= dpu_info
->dbi_outputs
;
637 for (i
= 0; i
< dpu_info
->dbi_output_num
; i
++) {
638 /* If output is off or already in DSR state, don't re-enter */
639 if (dbi_output
[i
]->dbi_panel_on
&&
640 !(dbi_output
[i
]->mode_flags
& MODE_SETTING_IN_DSR
)) {
641 mdfld_dsi_dbi_enter_dsr(dbi_output
[i
],
642 dbi_output
[i
]->channel_num
? 2 : 0);
649 static void mdfld_dbi_dpu_timer_func(unsigned long data
)
651 struct drm_device
*dev
= (struct drm_device
*)data
;
652 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
653 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
654 struct timer_list
*dpu_timer
= &dpu_info
->dpu_timer
;
657 if (dpu_info
->pending
) {
658 dpu_info
->idle_count
= 0;
659 /* Update panel fb with damaged area */
660 mdfld_dpu_update_fb(dev
);
662 dpu_info
->idle_count
++;
665 if (dpu_info
->idle_count
>= MDFLD_MAX_IDLE_COUNT
) {
666 mdfld_dpu_enter_dsr(dev
);
667 /* Stop timer by return */
671 spin_lock_irqsave(&dpu_info
->dpu_timer_lock
, flags
);
672 if (!timer_pending(dpu_timer
)) {
673 dpu_timer
->expires
= jiffies
+ MDFLD_DSR_DELAY
;
674 add_timer(dpu_timer
);
676 spin_unlock_irqrestore(&dpu_info
->dpu_timer_lock
, flags
);
679 void mdfld_dpu_update_panel(struct drm_device
*dev
)
681 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
682 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
684 if (dpu_info
->pending
) {
685 dpu_info
->idle_count
= 0;
687 /*update panel fb with damaged area*/
688 mdfld_dpu_update_fb(dev
);
690 dpu_info
->idle_count
++;
693 if (dpu_info
->idle_count
>= MDFLD_MAX_IDLE_COUNT
) {
695 mdfld_dpu_enter_dsr(dev
);
699 static int mdfld_dbi_dpu_timer_init(struct drm_device
*dev
,
700 struct mdfld_dbi_dpu_info
*dpu_info
)
702 struct timer_list
*dpu_timer
= &dpu_info
->dpu_timer
;
705 spin_lock_init(&dpu_info
->dpu_timer_lock
);
706 spin_lock_irqsave(&dpu_info
->dpu_timer_lock
, flags
);
708 init_timer(dpu_timer
);
710 dpu_timer
->data
= (unsigned long)dev
;
711 dpu_timer
->function
= mdfld_dbi_dpu_timer_func
;
712 dpu_timer
->expires
= jiffies
+ MDFLD_DSR_DELAY
;
714 spin_unlock_irqrestore(&dpu_info
->dpu_timer_lock
, flags
);
719 void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info
*dpu_info
)
721 struct timer_list
*dpu_timer
= &dpu_info
->dpu_timer
;
724 spin_lock_irqsave(&dpu_info
->dpu_timer_lock
, flags
);
725 if (!timer_pending(dpu_timer
)) {
726 dpu_timer
->expires
= jiffies
+ MDFLD_DSR_DELAY
;
727 add_timer(dpu_timer
);
729 spin_unlock_irqrestore(&dpu_info
->dpu_timer_lock
, flags
);
732 int mdfld_dbi_dpu_init(struct drm_device
*dev
)
734 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
735 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
737 if (!dpu_info
|| IS_ERR(dpu_info
)) {
738 dpu_info
= kzalloc(sizeof(struct mdfld_dbi_dpu_info
),
741 DRM_ERROR("No memory\n");
744 dev_priv
->dbi_dpu_info
= dpu_info
;
749 dpu_info
->cursors
[0].size
= MDFLD_CURSOR_SIZE
;
750 dpu_info
->cursors
[1].size
= MDFLD_CURSOR_SIZE
;
752 /*init dpu_update_lock*/
753 spin_lock_init(&dpu_info
->dpu_update_lock
);
755 /*init dpu refresh timer*/
756 mdfld_dbi_dpu_timer_init(dev
, dpu_info
);
758 /*init pipe damage area*/
759 mdfld_dpu_init_damage(dpu_info
, 0);
760 mdfld_dpu_init_damage(dpu_info
, 2);
765 void mdfld_dbi_dpu_exit(struct drm_device
*dev
)
767 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
768 struct mdfld_dbi_dpu_info
*dpu_info
= dev_priv
->dbi_dpu_info
;
773 del_timer_sync(&dpu_info
->dpu_timer
);
775 dev_priv
->dbi_dpu_info
= NULL
;