1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/time.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/hrtimer.h>
25 #include <linux/delay.h>
26 #include <mach/hardware.h>
29 #include <asm/system.h>
30 #include <asm/mach-types.h>
31 #include <linux/semaphore.h>
32 #include <linux/spinlock.h>
40 static struct mdp4_overlay_pipe
*mddi_pipe
;
41 static struct mdp4_overlay_pipe
*pending_pipe
;
42 static struct msm_fb_data_type
*mddi_mfd
;
46 void mdp4_overlay_update_lcd(struct msm_fb_data_type
*mfd
)
48 MDPIBUF
*iBuf
= &mfd
->ibuf
;
53 uint16 mddi_vdo_packet_reg
;
54 struct mdp4_overlay_pipe
*pipe
;
56 if (mfd
->key
!= MFD_KEY
)
59 mddi_mfd
= mfd
; /* keep it */
68 format
= MDP_ARGB_8888
;
70 /* MDP cmd block enable */
71 mdp_pipe_ctrl(MDP_CMD_BLOCK
, MDP_BLOCK_POWER_ON
, FALSE
);
73 if (mddi_pipe
== NULL
) {
74 ptype
= mdp4_overlay_format2type(format
);
75 pipe
= mdp4_overlay_pipe_alloc();
76 pipe
->pipe_type
= ptype
;
78 pipe
->pipe_num
= OVERLAY_PIPE_RGB1
;
79 pipe
->mixer_num
= MDP4_MIXER0
;
80 pipe
->src_format
= format
;
81 mdp4_overlay_format2pipe(pipe
);
83 mddi_pipe
= pipe
; /* keep it */
86 mddi_vdo_packet_reg
= mfd
->panel_info
.mddi
.vdopkt
;
88 if (mfd
->panel_info
.type
== MDDI_PANEL
) {
89 if (mfd
->panel_info
.pdest
== DISPLAY_1
)
97 MDP_OUTP(MDP_BASE
+ 0x00090, mddi_ld_param
);
98 MDP_OUTP(MDP_BASE
+ 0x00094,
99 (MDDI_VDO_PACKET_DESC
<< 16) | mddi_vdo_packet_reg
);
105 src
= (uint8
*) iBuf
->buf
;
112 pipe
->src_height
= fbi
->var
.yres
;
113 pipe
->src_width
= fbi
->var
.xres
;
114 pipe
->src_h
= fbi
->var
.yres
;
115 pipe
->src_w
= fbi
->var
.xres
;
118 pipe
->dst_h
= fbi
->var
.yres
;
119 pipe
->dst_w
= fbi
->var
.xres
;
122 pipe
->srcp0_addr
= (uint32
)src
;
123 pipe
->srcp0_ystride
= fbi
->var
.xres_virtual
* bpp
;
127 if (mdp4_overlay_active(MDP4_MIXER0
)) {
131 pipe
->src_height
= fbi
->var
.yres
;
132 pipe
->src_width
= fbi
->var
.xres
;
133 pipe
->src_h
= fbi
->var
.yres
;
134 pipe
->src_w
= fbi
->var
.xres
;
137 pipe
->dst_h
= fbi
->var
.yres
;
138 pipe
->dst_w
= fbi
->var
.xres
;
141 pipe
->srcp0_addr
= (uint32
) src
;
142 pipe
->srcp0_ystride
= fbi
->var
.xres_virtual
* bpp
;
144 /* starting input address */
145 src
+= (iBuf
->dma_x
+ iBuf
->dma_y
* iBuf
->ibuf_width
) * bpp
;
147 pipe
->src_height
= iBuf
->dma_h
;
148 pipe
->src_width
= iBuf
->dma_w
;
149 pipe
->src_h
= iBuf
->dma_h
;
150 pipe
->src_w
= iBuf
->dma_w
;
153 pipe
->dst_h
= iBuf
->dma_h
;
154 pipe
->dst_w
= iBuf
->dma_w
;
155 pipe
->dst_y
= iBuf
->dma_y
;
156 pipe
->dst_x
= iBuf
->dma_x
;
157 pipe
->srcp0_addr
= (uint32
) src
;
158 pipe
->srcp0_ystride
= iBuf
->ibuf_width
* bpp
;
162 pipe
->mixer_stage
= MDP4_MIXER_STAGE_BASE
;
164 mdp4_overlay_rgb_setup(pipe
);
166 mdp4_mixer_stage_up(pipe
);
168 mdp4_overlayproc_cfg(pipe
);
170 mdp4_overlay_dmap_xy(pipe
);
172 mdp4_overlay_dmap_cfg(mfd
, 0);
174 /* MDP cmd block disable */
175 mdp_pipe_ctrl(MDP_CMD_BLOCK
, MDP_BLOCK_POWER_OFF
, FALSE
);
180 * mdp4_overlay0_done_mddi: called from isr
182 void mdp4_overlay0_done_mddi()
185 complete(&pending_pipe
->comp
);
188 void mdp4_mddi_overlay_restore(void)
190 /* mutex holded by caller */
191 mdp4_overlay_update_lcd(mddi_mfd
);
192 mdp4_mddi_overlay_kickoff(mddi_mfd
, mddi_pipe
);
195 void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type
*mfd
,
196 struct mdp4_overlay_pipe
*pipe
)
198 #ifdef MDP4_NONBLOCKING
201 spin_lock_irqsave(&mdp_spin_lock
, flag
);
202 if (mfd
->dma
->busy
== TRUE
) {
203 INIT_COMPLETION(pipe
->comp
);
206 spin_unlock_irqrestore(&mdp_spin_lock
, flag
);
208 if (pending_pipe
!= NULL
) {
209 /* wait until DMA finishes the current job */
210 wait_for_completion_killable(&pipe
->comp
);
214 mdp_enable_irq(MDP_OVERLAY0_TERM
);
215 mfd
->dma
->busy
= TRUE
;
216 /* start OVERLAY pipe */
217 mdp_pipe_kickoff(MDP_OVERLAY0_TERM
, mfd
);
221 mdp_enable_irq(MDP_OVERLAY0_TERM
);
222 mfd
->dma
->busy
= TRUE
;
223 INIT_COMPLETION(pipe
->comp
);
226 /* start OVERLAY pipe */
227 mdp_pipe_kickoff(MDP_OVERLAY0_TERM
, mfd
);
230 /* wait until DMA finishes the current job */
231 wait_for_completion_killable(&pipe
->comp
);
232 mdp_disable_irq(MDP_OVERLAY0_TERM
);
237 void mdp4_mddi_overlay(struct msm_fb_data_type
*mfd
)
239 mutex_lock(&mfd
->dma
->ov_mutex
);
241 if ((mfd
) && (!mfd
->dma
->busy
) && (mfd
->panel_power_on
)) {
242 mdp4_overlay_update_lcd(mfd
);
244 mdp4_mddi_overlay_kickoff(mfd
, mddi_pipe
);
246 /* signal if pan function is waiting for the update completion */
247 if (mfd
->pan_waiting
) {
248 mfd
->pan_waiting
= FALSE
;
249 complete(&mfd
->pan_comp
);
253 mutex_unlock(&mfd
->dma
->ov_mutex
);