Commit | Line | Data |
---|---|---|
9d200153 SM |
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. |
2 | * | |
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. | |
6 | * | |
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. | |
11 | * | |
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 | |
15 | * 02110-1301, USA. | |
16 | */ | |
17 | ||
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> | |
27 | #include <linux/io.h> | |
28 | ||
29 | #include <asm/system.h> | |
30 | #include <asm/mach-types.h> | |
31 | #include <linux/semaphore.h> | |
32 | #include <linux/spinlock.h> | |
33 | ||
34 | #include <linux/fb.h> | |
35 | ||
36 | #include "mdp.h" | |
37 | #include "msm_fb.h" | |
38 | #include "mdp4.h" | |
39 | ||
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; | |
43 | ||
44 | #define WHOLESCREEN | |
45 | ||
46 | void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd) | |
47 | { | |
48 | MDPIBUF *iBuf = &mfd->ibuf; | |
49 | uint8 *src; | |
50 | int bpp, ptype; | |
51 | uint32 format; | |
52 | uint32 mddi_ld_param; | |
53 | uint16 mddi_vdo_packet_reg; | |
54 | struct mdp4_overlay_pipe *pipe; | |
55 | ||
56 | if (mfd->key != MFD_KEY) | |
57 | return; | |
58 | ||
59 | mddi_mfd = mfd; /* keep it */ | |
60 | ||
61 | bpp = iBuf->bpp; | |
62 | ||
63 | if (bpp == 2) | |
64 | format = MDP_RGB_565; | |
65 | else if (bpp == 3) | |
66 | format = MDP_RGB_888; | |
67 | else | |
68 | format = MDP_ARGB_8888; | |
69 | ||
70 | /* MDP cmd block enable */ | |
71 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | |
72 | ||
73 | if (mddi_pipe == NULL) { | |
74 | ptype = mdp4_overlay_format2type(format); | |
75 | pipe = mdp4_overlay_pipe_alloc(); | |
76 | pipe->pipe_type = ptype; | |
77 | /* use RGB1 pipe */ | |
78 | pipe->pipe_num = OVERLAY_PIPE_RGB1; | |
79 | pipe->mixer_num = MDP4_MIXER0; | |
80 | pipe->src_format = format; | |
81 | mdp4_overlay_format2pipe(pipe); | |
82 | ||
83 | mddi_pipe = pipe; /* keep it */ | |
84 | ||
85 | mddi_ld_param = 0; | |
86 | mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt; | |
87 | ||
88 | if (mfd->panel_info.type == MDDI_PANEL) { | |
89 | if (mfd->panel_info.pdest == DISPLAY_1) | |
90 | mddi_ld_param = 0; | |
91 | else | |
92 | mddi_ld_param = 1; | |
93 | } else { | |
94 | mddi_ld_param = 2; | |
95 | } | |
96 | ||
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); | |
100 | } else { | |
101 | pipe = mddi_pipe; | |
102 | } | |
103 | ||
104 | ||
105 | src = (uint8 *) iBuf->buf; | |
106 | ||
107 | #ifdef WHOLESCREEN | |
108 | { | |
109 | struct fb_info *fbi; | |
110 | ||
111 | fbi = mfd->fbi; | |
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; | |
116 | pipe->src_y = 0; | |
117 | pipe->src_x = 0; | |
118 | pipe->dst_h = fbi->var.yres; | |
119 | pipe->dst_w = fbi->var.xres; | |
120 | pipe->dst_y = 0; | |
121 | pipe->dst_x = 0; | |
122 | pipe->srcp0_addr = (uint32)src; | |
123 | pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; | |
124 | } | |
125 | ||
126 | #else | |
127 | if (mdp4_overlay_active(MDP4_MIXER0)) { | |
128 | struct fb_info *fbi; | |
129 | ||
130 | fbi = mfd->fbi; | |
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; | |
135 | pipe->src_y = 0; | |
136 | pipe->src_x = 0; | |
137 | pipe->dst_h = fbi->var.yres; | |
138 | pipe->dst_w = fbi->var.xres; | |
139 | pipe->dst_y = 0; | |
140 | pipe->dst_x = 0; | |
141 | pipe->srcp0_addr = (uint32) src; | |
142 | pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; | |
143 | } else { | |
144 | /* starting input address */ | |
145 | src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp; | |
146 | ||
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; | |
151 | pipe->src_y = 0; | |
152 | pipe->src_x = 0; | |
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; | |
159 | } | |
160 | #endif | |
161 | ||
162 | pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; | |
163 | ||
164 | mdp4_overlay_rgb_setup(pipe); | |
165 | ||
166 | mdp4_mixer_stage_up(pipe); | |
167 | ||
168 | mdp4_overlayproc_cfg(pipe); | |
169 | ||
170 | mdp4_overlay_dmap_xy(pipe); | |
171 | ||
172 | mdp4_overlay_dmap_cfg(mfd, 0); | |
173 | ||
174 | /* MDP cmd block disable */ | |
175 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | |
176 | ||
177 | } | |
178 | ||
179 | /* | |
180 | * mdp4_overlay0_done_mddi: called from isr | |
181 | */ | |
182 | void mdp4_overlay0_done_mddi() | |
183 | { | |
184 | if (pending_pipe) | |
185 | complete(&pending_pipe->comp); | |
186 | } | |
187 | ||
188 | void mdp4_mddi_overlay_restore(void) | |
189 | { | |
190 | /* mutex holded by caller */ | |
191 | mdp4_overlay_update_lcd(mddi_mfd); | |
192 | mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe); | |
193 | } | |
194 | ||
195 | void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd, | |
196 | struct mdp4_overlay_pipe *pipe) | |
197 | { | |
198 | #ifdef MDP4_NONBLOCKING | |
199 | unsigned long flag; | |
200 | ||
201 | spin_lock_irqsave(&mdp_spin_lock, flag); | |
202 | if (mfd->dma->busy == TRUE) { | |
203 | INIT_COMPLETION(pipe->comp); | |
204 | pending_pipe = pipe; | |
205 | } | |
206 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | |
207 | ||
208 | if (pending_pipe != NULL) { | |
209 | /* wait until DMA finishes the current job */ | |
210 | wait_for_completion_killable(&pipe->comp); | |
211 | pending_pipe = NULL; | |
212 | } | |
213 | down(&mfd->sem); | |
214 | mdp_enable_irq(MDP_OVERLAY0_TERM); | |
215 | mfd->dma->busy = TRUE; | |
216 | /* start OVERLAY pipe */ | |
217 | mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); | |
218 | up(&mfd->sem); | |
219 | #else | |
220 | down(&mfd->sem); | |
221 | mdp_enable_irq(MDP_OVERLAY0_TERM); | |
222 | mfd->dma->busy = TRUE; | |
223 | INIT_COMPLETION(pipe->comp); | |
224 | pending_pipe = pipe; | |
225 | ||
226 | /* start OVERLAY pipe */ | |
227 | mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); | |
228 | up(&mfd->sem); | |
229 | ||
230 | /* wait until DMA finishes the current job */ | |
231 | wait_for_completion_killable(&pipe->comp); | |
232 | mdp_disable_irq(MDP_OVERLAY0_TERM); | |
233 | #endif | |
234 | ||
235 | } | |
236 | ||
237 | void mdp4_mddi_overlay(struct msm_fb_data_type *mfd) | |
238 | { | |
239 | mutex_lock(&mfd->dma->ov_mutex); | |
240 | ||
241 | if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { | |
242 | mdp4_overlay_update_lcd(mfd); | |
243 | ||
244 | mdp4_mddi_overlay_kickoff(mfd, mddi_pipe); | |
245 | ||
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); | |
250 | } | |
251 | } | |
252 | ||
253 | mutex_unlock(&mfd->dma->ov_mutex); | |
254 | } |