Merge remote branch 'alsa/devel' into topic/misc
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / msm / mdp4_overlay_mddi.c
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 }