1 /* drivers/video/msm_fb/mdp.c
3 * MSM MDP Interface (used by framebuffer core)
5 * Copyright (C) 2007 QUALCOMM Incorporated
6 * Copyright (C) 2007 Google Incorporated
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/kernel.h>
20 #include <linux/msm_mdp.h>
21 #include <linux/interrupt.h>
22 #include <linux/wait.h>
23 #include <linux/clk.h>
24 #include <linux/file.h>
25 #include <linux/major.h>
26 #include <linux/slab.h>
28 #include <mach/msm_iomap.h>
29 #include <mach/msm_fb.h>
30 #include <linux/platform_device.h>
34 struct class *mdp_class
;
36 #define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
38 static uint16_t mdp_default_ccs
[] = {
39 0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
43 static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue
);
44 static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue
);
45 static struct msmfb_callback
*dma_callback
;
46 static struct clk
*clk
;
47 static unsigned int mdp_irq_mask
;
48 static DEFINE_SPINLOCK(mdp_lock
);
49 DEFINE_MUTEX(mdp_mutex
);
51 static int enable_mdp_irq(struct mdp_info
*mdp
, uint32_t mask
)
53 unsigned long irq_flags
;
58 spin_lock_irqsave(&mdp_lock
, irq_flags
);
59 /* if the mask bits are already set return an error, this interrupt
60 * is already enabled */
61 if (mdp_irq_mask
& mask
) {
62 printk(KERN_ERR
"mdp irq already on already on %x %x\n",
66 /* if the mdp irq is not already enabled enable it */
73 /* update the irq mask to reflect the fact that the interrupt is
76 spin_unlock_irqrestore(&mdp_lock
, irq_flags
);
80 static int locked_disable_mdp_irq(struct mdp_info
*mdp
, uint32_t mask
)
82 /* this interrupt is already disabled! */
83 if (!(mdp_irq_mask
& mask
)) {
84 printk(KERN_ERR
"mdp irq already off %x %x\n",
88 /* update the irq mask to reflect the fact that the interrupt is
90 mdp_irq_mask
&= ~(mask
);
91 /* if no one is waiting on the interrupt, disable it */
93 disable_irq_nosync(mdp
->irq
);
100 static int disable_mdp_irq(struct mdp_info
*mdp
, uint32_t mask
)
102 unsigned long irq_flags
;
105 spin_lock_irqsave(&mdp_lock
, irq_flags
);
106 ret
= locked_disable_mdp_irq(mdp
, mask
);
107 spin_unlock_irqrestore(&mdp_lock
, irq_flags
);
111 static irqreturn_t
mdp_isr(int irq
, void *data
)
114 unsigned long irq_flags
;
115 struct mdp_info
*mdp
= data
;
117 spin_lock_irqsave(&mdp_lock
, irq_flags
);
119 status
= mdp_readl(mdp
, MDP_INTR_STATUS
);
120 mdp_writel(mdp
, status
, MDP_INTR_CLEAR
);
122 status
&= mdp_irq_mask
;
123 if (status
& DL0_DMA2_TERM_DONE
) {
125 dma_callback
->func(dma_callback
);
128 wake_up(&mdp_dma2_waitqueue
);
131 if (status
& DL0_ROI_DONE
)
132 wake_up(&mdp_ppp_waitqueue
);
135 locked_disable_mdp_irq(mdp
, status
);
137 spin_unlock_irqrestore(&mdp_lock
, irq_flags
);
141 static uint32_t mdp_check_mask(uint32_t mask
)
144 unsigned long irq_flags
;
146 spin_lock_irqsave(&mdp_lock
, irq_flags
);
147 ret
= mdp_irq_mask
& mask
;
148 spin_unlock_irqrestore(&mdp_lock
, irq_flags
);
152 static int mdp_wait(struct mdp_info
*mdp
, uint32_t mask
, wait_queue_head_t
*wq
)
155 unsigned long irq_flags
;
157 wait_event_timeout(*wq
, !mdp_check_mask(mask
), HZ
);
159 spin_lock_irqsave(&mdp_lock
, irq_flags
);
160 if (mdp_irq_mask
& mask
) {
161 locked_disable_mdp_irq(mdp
, mask
);
162 printk(KERN_WARNING
"timeout waiting for mdp to complete %x\n",
166 spin_unlock_irqrestore(&mdp_lock
, irq_flags
);
171 void mdp_dma_wait(struct mdp_device
*mdp_dev
)
173 #define MDP_MAX_TIMEOUTS 20
174 static int timeout_count
;
175 struct mdp_info
*mdp
= container_of(mdp_dev
, struct mdp_info
, mdp_dev
);
177 if (mdp_wait(mdp
, DL0_DMA2_TERM_DONE
, &mdp_dma2_waitqueue
) == -ETIMEDOUT
)
182 if (timeout_count
> MDP_MAX_TIMEOUTS
) {
183 printk(KERN_ERR
"mdp: dma failed %d times, somethings wrong!\n",
189 static int mdp_ppp_wait(struct mdp_info
*mdp
)
191 return mdp_wait(mdp
, DL0_ROI_DONE
, &mdp_ppp_waitqueue
);
194 void mdp_dma_to_mddi(struct mdp_info
*mdp
, uint32_t addr
, uint32_t stride
,
195 uint32_t width
, uint32_t height
, uint32_t x
, uint32_t y
,
196 struct msmfb_callback
*callback
)
199 uint16_t ld_param
= 0; /* 0=PRIM, 1=SECD, 2=EXT */
201 if (enable_mdp_irq(mdp
, DL0_DMA2_TERM_DONE
)) {
202 printk(KERN_ERR
"mdp_dma_to_mddi: busy\n");
206 dma_callback
= callback
;
208 dma2_cfg
= DMA_PACK_TIGHT
|
210 DMA_PACK_PATTERN_RGB
|
212 DMA_IBUF_NONCONTIGUOUS
;
214 dma2_cfg
|= DMA_IBUF_FORMAT_RGB565
;
216 dma2_cfg
|= DMA_OUT_SEL_MDDI
;
218 dma2_cfg
|= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY
;
220 dma2_cfg
|= DMA_DITHER_EN
;
222 /* setup size, address, and stride */
223 mdp_writel(mdp
, (height
<< 16) | (width
),
224 MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0184);
225 mdp_writel(mdp
, addr
, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0188);
226 mdp_writel(mdp
, stride
, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x018C);
229 dma2_cfg
|= DMA_DSTC0G_6BITS
| DMA_DSTC1B_6BITS
| DMA_DSTC2R_6BITS
;
231 /* set y & x offset and MDDI transaction parameters */
232 mdp_writel(mdp
, (y
<< 16) | (x
), MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0194);
233 mdp_writel(mdp
, ld_param
, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01a0);
234 mdp_writel(mdp
, (MDDI_VDO_PACKET_DESC
<< 16) | MDDI_VDO_PACKET_PRIM
,
235 MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01a4);
237 mdp_writel(mdp
, dma2_cfg
, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0180);
240 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0044);
243 void mdp_dma(struct mdp_device
*mdp_dev
, uint32_t addr
, uint32_t stride
,
244 uint32_t width
, uint32_t height
, uint32_t x
, uint32_t y
,
245 struct msmfb_callback
*callback
, int interface
)
247 struct mdp_info
*mdp
= container_of(mdp_dev
, struct mdp_info
, mdp_dev
);
249 if (interface
== MSM_MDDI_PMDH_INTERFACE
) {
250 mdp_dma_to_mddi(mdp
, addr
, stride
, width
, height
, x
, y
,
255 int get_img(struct mdp_img
*img
, struct fb_info
*info
,
256 unsigned long *start
, unsigned long *len
,
259 int put_needed
, ret
= 0;
262 file
= fget_light(img
->memory_id
, &put_needed
);
266 if (MAJOR(file
->f_dentry
->d_inode
->i_rdev
) == FB_MAJOR
) {
267 *start
= info
->fix
.smem_start
;
268 *len
= info
->fix
.smem_len
;
271 fput_light(file
, put_needed
);
276 void put_img(struct file
*src_file
, struct file
*dst_file
)
280 int mdp_blit(struct mdp_device
*mdp_dev
, struct fb_info
*fb
,
281 struct mdp_blit_req
*req
)
284 unsigned long src_start
= 0, src_len
= 0, dst_start
= 0, dst_len
= 0;
285 struct mdp_info
*mdp
= container_of(mdp_dev
, struct mdp_info
, mdp_dev
);
286 struct file
*src_file
= 0, *dst_file
= 0;
288 /* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
289 if (unlikely(req
->src_rect
.h
== 0 ||
290 req
->src_rect
.w
== 0)) {
291 printk(KERN_ERR
"mpd_ppp: src img of zero size!\n");
294 if (unlikely(req
->dst_rect
.h
== 0 ||
295 req
->dst_rect
.w
== 0))
298 /* do this first so that if this fails, the caller can always
299 * safely call put_img */
300 if (unlikely(get_img(&req
->src
, fb
, &src_start
, &src_len
, &src_file
))) {
301 printk(KERN_ERR
"mpd_ppp: could not retrieve src image from "
306 if (unlikely(get_img(&req
->dst
, fb
, &dst_start
, &dst_len
, &dst_file
))) {
307 printk(KERN_ERR
"mpd_ppp: could not retrieve dst image from "
311 mutex_lock(&mdp_mutex
);
313 /* transp_masking unimplemented */
314 req
->transp_mask
= MDP_TRANSP_NOP
;
315 if (unlikely((req
->transp_mask
!= MDP_TRANSP_NOP
||
316 req
->alpha
!= MDP_ALPHA_NOP
||
317 HAS_ALPHA(req
->src
.format
)) &&
318 (req
->flags
& MDP_ROT_90
&&
319 req
->dst_rect
.w
<= 16 && req
->dst_rect
.h
>= 16))) {
321 unsigned int tiles
= req
->dst_rect
.h
/ 16;
322 unsigned int remainder
= req
->dst_rect
.h
% 16;
323 req
->src_rect
.w
= 16*req
->src_rect
.w
/ req
->dst_rect
.h
;
324 req
->dst_rect
.h
= 16;
325 for (i
= 0; i
< tiles
; i
++) {
326 enable_mdp_irq(mdp
, DL0_ROI_DONE
);
327 ret
= mdp_ppp_blit(mdp
, req
, src_file
, src_start
,
328 src_len
, dst_file
, dst_start
,
332 ret
= mdp_ppp_wait(mdp
);
334 goto err_wait_failed
;
335 req
->dst_rect
.y
+= 16;
336 req
->src_rect
.x
+= req
->src_rect
.w
;
340 req
->src_rect
.w
= remainder
*req
->src_rect
.w
/ req
->dst_rect
.h
;
341 req
->dst_rect
.h
= remainder
;
343 enable_mdp_irq(mdp
, DL0_ROI_DONE
);
344 ret
= mdp_ppp_blit(mdp
, req
, src_file
, src_start
, src_len
, dst_file
,
349 ret
= mdp_ppp_wait(mdp
);
351 goto err_wait_failed
;
353 put_img(src_file
, dst_file
);
354 mutex_unlock(&mdp_mutex
);
357 disable_mdp_irq(mdp
, DL0_ROI_DONE
);
359 put_img(src_file
, dst_file
);
360 mutex_unlock(&mdp_mutex
);
364 void mdp_set_grp_disp(struct mdp_device
*mdp_dev
, unsigned disp_id
)
366 struct mdp_info
*mdp
= container_of(mdp_dev
, struct mdp_info
, mdp_dev
);
369 mdp_writel(mdp
, disp_id
, MDP_FULL_BYPASS_WORD43
);
372 int register_mdp_client(struct class_interface
*cint
)
375 pr_err("mdp: no mdp_class when registering mdp client\n");
378 cint
->class = mdp_class
;
379 return class_interface_register(cint
);
382 #include "mdp_csc_table.h"
383 #include "mdp_scale_tables.h"
385 int mdp_probe(struct platform_device
*pdev
)
387 struct resource
*resource
;
390 struct mdp_info
*mdp
;
392 resource
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
394 pr_err("mdp: can not get mdp mem resource!\n");
398 mdp
= kzalloc(sizeof(struct mdp_info
), GFP_KERNEL
);
402 mdp
->irq
= platform_get_irq(pdev
, 0);
404 pr_err("mdp: can not get mdp irq\n");
409 mdp
->base
= ioremap(resource
->start
,
410 resource
->end
- resource
->start
);
411 if (mdp
->base
== 0) {
412 printk(KERN_ERR
"msmfb: cannot allocate mdp regs!\n");
417 mdp
->mdp_dev
.dma
= mdp_dma
;
418 mdp
->mdp_dev
.dma_wait
= mdp_dma_wait
;
419 mdp
->mdp_dev
.blit
= mdp_blit
;
420 mdp
->mdp_dev
.set_grp_disp
= mdp_set_grp_disp
;
422 clk
= clk_get(&pdev
->dev
, "mdp_clk");
424 printk(KERN_INFO
"mdp: failed to get mdp clk");
428 ret
= request_irq(mdp
->irq
, mdp_isr
, IRQF_DISABLED
, "msm_mdp", mdp
);
430 goto error_request_irq
;
431 disable_irq(mdp
->irq
);
434 /* debug interface write access */
435 mdp_writel(mdp
, 1, 0x60);
437 mdp_writel(mdp
, MDP_ANY_INTR_MASK
, MDP_INTR_ENABLE
);
438 mdp_writel(mdp
, 1, MDP_EBI2_PORTMAP_MODE
);
440 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01f8);
441 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01fc);
443 for (n
= 0; n
< ARRAY_SIZE(csc_table
); n
++)
444 mdp_writel(mdp
, csc_table
[n
].val
, csc_table
[n
].reg
);
446 /* clear up unused fg/main registers */
447 /* comp.plane 2&3 ystride */
448 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0120);
450 /* unpacked pattern */
451 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x012c);
452 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0130);
453 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0134);
454 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0158);
455 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x015c);
456 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0160);
457 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0170);
458 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0174);
459 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x017c);
461 /* comp.plane 2 & 3 */
462 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0114);
463 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x0118);
465 /* clear unused bg registers */
466 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01c8);
467 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01d0);
468 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01dc);
469 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01e0);
470 mdp_writel(mdp
, 0, MDP_CMD_DEBUG_ACCESS_BASE
+ 0x01e4);
472 for (n
= 0; n
< ARRAY_SIZE(mdp_upscale_table
); n
++)
473 mdp_writel(mdp
, mdp_upscale_table
[n
].val
,
474 mdp_upscale_table
[n
].reg
);
476 for (n
= 0; n
< 9; n
++)
477 mdp_writel(mdp
, mdp_default_ccs
[n
], 0x40440 + 4 * n
);
478 mdp_writel(mdp
, mdp_default_ccs
[9], 0x40500 + 4 * 0);
479 mdp_writel(mdp
, mdp_default_ccs
[10], 0x40500 + 4 * 0);
480 mdp_writel(mdp
, mdp_default_ccs
[11], 0x40500 + 4 * 0);
482 /* register mdp device */
483 mdp
->mdp_dev
.dev
.parent
= &pdev
->dev
;
484 mdp
->mdp_dev
.dev
.class = mdp_class
;
485 dev_set_name(&mdp
->mdp_dev
.dev
, "mdp%d", pdev
->id
);
487 /* if you can remove the platform device you'd have to implement
489 mdp_dev.release = mdp_class; */
491 ret
= device_register(&mdp
->mdp_dev
.dev
);
493 goto error_device_register
;
496 error_device_register
:
497 free_irq(mdp
->irq
, mdp
);
506 static struct platform_driver msm_mdp_driver
= {
508 .driver
= {.name
= "msm_mdp"},
511 static int __init
mdp_init(void)
513 mdp_class
= class_create(THIS_MODULE
, "msm_mdp");
514 if (IS_ERR(mdp_class
)) {
515 printk(KERN_ERR
"Error creating mdp class\n");
516 return PTR_ERR(mdp_class
);
518 return platform_driver_register(&msm_mdp_driver
);
521 subsys_initcall(mdp_init
);