Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[sfrench/cifs-2.6.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 }