1 /* drivers/video/msm_fb/mdp.c
2  *
3  * MSM MDP Interface (used by framebuffer core)
4  *
5  * Copyright (C) 2007 QUALCOMM Incorporated
6  * Copyright (C) 2007 Google Incorporated
7  *
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.
11  *
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.
16  */
17 
18 #include <linux/kernel.h>
19 #include <linux/fb.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>
27 
28 #include <mach/msm_iomap.h>
29 #include <mach/msm_fb.h>
30 #include <linux/platform_device.h>
31 #include <linux/export.h>
32 
33 #include "mdp_hw.h"
34 
35 struct class *mdp_class;
36 
37 #define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
38 
39 static uint16_t mdp_default_ccs[] = {
40 	0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
41 	0x010, 0x080, 0x080
42 };
43 
44 static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
45 static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
46 static struct msmfb_callback *dma_callback;
47 static struct clk *clk;
48 static unsigned int mdp_irq_mask;
49 static DEFINE_SPINLOCK(mdp_lock);
50 DEFINE_MUTEX(mdp_mutex);
51 
enable_mdp_irq(struct mdp_info * mdp,uint32_t mask)52 static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
53 {
54 	unsigned long irq_flags;
55 	int ret = 0;
56 
57 	BUG_ON(!mask);
58 
59 	spin_lock_irqsave(&mdp_lock, irq_flags);
60 	/* if the mask bits are already set return an error, this interrupt
61 	 * is already enabled */
62 	if (mdp_irq_mask & mask) {
63 		printk(KERN_ERR "mdp irq already on already on %x %x\n",
64 		       mdp_irq_mask, mask);
65 		ret = -1;
66 	}
67 	/* if the mdp irq is not already enabled enable it */
68 	if (!mdp_irq_mask) {
69 		if (clk)
70 			clk_enable(clk);
71 		enable_irq(mdp->irq);
72 	}
73 
74 	/* update the irq mask to reflect the fact that the interrupt is
75 	 * enabled */
76 	mdp_irq_mask |= mask;
77 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
78 	return ret;
79 }
80 
locked_disable_mdp_irq(struct mdp_info * mdp,uint32_t mask)81 static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
82 {
83 	/* this interrupt is already disabled! */
84 	if (!(mdp_irq_mask & mask)) {
85 		printk(KERN_ERR "mdp irq already off %x %x\n",
86 		       mdp_irq_mask, mask);
87 		return -1;
88 	}
89 	/* update the irq mask to reflect the fact that the interrupt is
90 	 * disabled */
91 	mdp_irq_mask &= ~(mask);
92 	/* if no one is waiting on the interrupt, disable it */
93 	if (!mdp_irq_mask) {
94 		disable_irq_nosync(mdp->irq);
95 		if (clk)
96 			clk_disable(clk);
97 	}
98 	return 0;
99 }
100 
disable_mdp_irq(struct mdp_info * mdp,uint32_t mask)101 static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
102 {
103 	unsigned long irq_flags;
104 	int ret;
105 
106 	spin_lock_irqsave(&mdp_lock, irq_flags);
107 	ret = locked_disable_mdp_irq(mdp, mask);
108 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
109 	return ret;
110 }
111 
mdp_isr(int irq,void * data)112 static irqreturn_t mdp_isr(int irq, void *data)
113 {
114 	uint32_t status;
115 	unsigned long irq_flags;
116 	struct mdp_info *mdp = data;
117 
118 	spin_lock_irqsave(&mdp_lock, irq_flags);
119 
120 	status = mdp_readl(mdp, MDP_INTR_STATUS);
121 	mdp_writel(mdp, status, MDP_INTR_CLEAR);
122 
123 	status &= mdp_irq_mask;
124 	if (status & DL0_DMA2_TERM_DONE) {
125 		if (dma_callback) {
126 			dma_callback->func(dma_callback);
127 			dma_callback = NULL;
128 		}
129 		wake_up(&mdp_dma2_waitqueue);
130 	}
131 
132 	if (status & DL0_ROI_DONE)
133 		wake_up(&mdp_ppp_waitqueue);
134 
135 	if (status)
136 		locked_disable_mdp_irq(mdp, status);
137 
138 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
139 	return IRQ_HANDLED;
140 }
141 
mdp_check_mask(uint32_t mask)142 static uint32_t mdp_check_mask(uint32_t mask)
143 {
144 	uint32_t ret;
145 	unsigned long irq_flags;
146 
147 	spin_lock_irqsave(&mdp_lock, irq_flags);
148 	ret = mdp_irq_mask & mask;
149 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
150 	return ret;
151 }
152 
mdp_wait(struct mdp_info * mdp,uint32_t mask,wait_queue_head_t * wq)153 static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
154 {
155 	int ret = 0;
156 	unsigned long irq_flags;
157 
158 	wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
159 
160 	spin_lock_irqsave(&mdp_lock, irq_flags);
161 	if (mdp_irq_mask & mask) {
162 		locked_disable_mdp_irq(mdp, mask);
163 		printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
164 		       mask);
165 		ret = -ETIMEDOUT;
166 	}
167 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
168 
169 	return ret;
170 }
171 
mdp_dma_wait(struct mdp_device * mdp_dev)172 void mdp_dma_wait(struct mdp_device *mdp_dev)
173 {
174 #define MDP_MAX_TIMEOUTS 20
175 	static int timeout_count;
176 	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
177 
178 	if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
179 		timeout_count++;
180 	else
181 		timeout_count = 0;
182 
183 	if (timeout_count > MDP_MAX_TIMEOUTS) {
184 		printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
185 		       MDP_MAX_TIMEOUTS);
186 		BUG();
187 	}
188 }
189 
mdp_ppp_wait(struct mdp_info * mdp)190 static int mdp_ppp_wait(struct mdp_info *mdp)
191 {
192 	return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
193 }
194 
mdp_dma_to_mddi(struct mdp_info * mdp,uint32_t addr,uint32_t stride,uint32_t width,uint32_t height,uint32_t x,uint32_t y,struct msmfb_callback * callback)195 void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
196 		     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
197 		     struct msmfb_callback *callback)
198 {
199 	uint32_t dma2_cfg;
200 	uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
201 
202 	if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
203 		printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
204 		return;
205 	}
206 
207 	dma_callback = callback;
208 
209 	dma2_cfg = DMA_PACK_TIGHT |
210 		DMA_PACK_ALIGN_LSB |
211 		DMA_PACK_PATTERN_RGB |
212 		DMA_OUT_SEL_AHB |
213 		DMA_IBUF_NONCONTIGUOUS;
214 
215 	dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
216 
217 	dma2_cfg |= DMA_OUT_SEL_MDDI;
218 
219 	dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
220 
221 	dma2_cfg |= DMA_DITHER_EN;
222 
223 	/* setup size, address, and stride */
224 	mdp_writel(mdp, (height << 16) | (width),
225 		   MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
226 	mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
227 	mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
228 
229 	/* 666 18BPP */
230 	dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
231 
232 	/* set y & x offset and MDDI transaction parameters */
233 	mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
234 	mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
235 	mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
236 		   MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
237 
238 	mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
239 
240 	/* start DMA2 */
241 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
242 }
243 
mdp_dma(struct mdp_device * mdp_dev,uint32_t addr,uint32_t stride,uint32_t width,uint32_t height,uint32_t x,uint32_t y,struct msmfb_callback * callback,int interface)244 void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
245 	     uint32_t width, uint32_t height, uint32_t x, uint32_t y,
246 	     struct msmfb_callback *callback, int interface)
247 {
248 	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
249 
250 	if (interface == MSM_MDDI_PMDH_INTERFACE) {
251 		mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
252 				callback);
253 	}
254 }
255 
get_img(struct mdp_img * img,struct fb_info * info,unsigned long * start,unsigned long * len,struct file ** filep)256 int get_img(struct mdp_img *img, struct fb_info *info,
257 	    unsigned long *start, unsigned long *len,
258 	    struct file **filep)
259 {
260 	int put_needed, ret = 0;
261 	struct file *file;
262 
263 	file = fget_light(img->memory_id, &put_needed);
264 	if (file == NULL)
265 		return -1;
266 
267 	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
268 		*start = info->fix.smem_start;
269 		*len = info->fix.smem_len;
270 	} else
271 		ret = -1;
272 	fput_light(file, put_needed);
273 
274 	return ret;
275 }
276 
put_img(struct file * src_file,struct file * dst_file)277 void put_img(struct file *src_file, struct file *dst_file)
278 {
279 }
280 
mdp_blit(struct mdp_device * mdp_dev,struct fb_info * fb,struct mdp_blit_req * req)281 int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
282 	     struct mdp_blit_req *req)
283 {
284 	int ret;
285 	unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
286 	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
287 	struct file *src_file = 0, *dst_file = 0;
288 
289 	/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
290 	if (unlikely(req->src_rect.h == 0 ||
291 		     req->src_rect.w == 0)) {
292 		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
293 		return -EINVAL;
294 	}
295 	if (unlikely(req->dst_rect.h == 0 ||
296 		     req->dst_rect.w == 0))
297 		return -EINVAL;
298 
299 	/* do this first so that if this fails, the caller can always
300 	 * safely call put_img */
301 	if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
302 		printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
303 				"memory\n");
304 		return -EINVAL;
305 	}
306 
307 	if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
308 		printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
309 				"memory\n");
310 		return -EINVAL;
311 	}
312 	mutex_lock(&mdp_mutex);
313 
314 	/* transp_masking unimplemented */
315 	req->transp_mask = MDP_TRANSP_NOP;
316 	if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
317 		      req->alpha != MDP_ALPHA_NOP ||
318 		      HAS_ALPHA(req->src.format)) &&
319 		     (req->flags & MDP_ROT_90 &&
320 		      req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
321 		int i;
322 		unsigned int tiles = req->dst_rect.h / 16;
323 		unsigned int remainder = req->dst_rect.h % 16;
324 		req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
325 		req->dst_rect.h = 16;
326 		for (i = 0; i < tiles; i++) {
327 			enable_mdp_irq(mdp, DL0_ROI_DONE);
328 			ret = mdp_ppp_blit(mdp, req, src_file, src_start,
329 					   src_len, dst_file, dst_start,
330 					   dst_len);
331 			if (ret)
332 				goto err_bad_blit;
333 			ret = mdp_ppp_wait(mdp);
334 			if (ret)
335 				goto err_wait_failed;
336 			req->dst_rect.y += 16;
337 			req->src_rect.x += req->src_rect.w;
338 		}
339 		if (!remainder)
340 			goto end;
341 		req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
342 		req->dst_rect.h = remainder;
343 	}
344 	enable_mdp_irq(mdp, DL0_ROI_DONE);
345 	ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
346 			   dst_start,
347 			   dst_len);
348 	if (ret)
349 		goto err_bad_blit;
350 	ret = mdp_ppp_wait(mdp);
351 	if (ret)
352 		goto err_wait_failed;
353 end:
354 	put_img(src_file, dst_file);
355 	mutex_unlock(&mdp_mutex);
356 	return 0;
357 err_bad_blit:
358 	disable_mdp_irq(mdp, DL0_ROI_DONE);
359 err_wait_failed:
360 	put_img(src_file, dst_file);
361 	mutex_unlock(&mdp_mutex);
362 	return ret;
363 }
364 
mdp_set_grp_disp(struct mdp_device * mdp_dev,unsigned disp_id)365 void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
366 {
367 	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
368 
369 	disp_id &= 0xf;
370 	mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
371 }
372 
register_mdp_client(struct class_interface * cint)373 int register_mdp_client(struct class_interface *cint)
374 {
375 	if (!mdp_class) {
376 		pr_err("mdp: no mdp_class when registering mdp client\n");
377 		return -ENODEV;
378 	}
379 	cint->class = mdp_class;
380 	return class_interface_register(cint);
381 }
382 
383 #include "mdp_csc_table.h"
384 #include "mdp_scale_tables.h"
385 
mdp_probe(struct platform_device * pdev)386 int mdp_probe(struct platform_device *pdev)
387 {
388 	struct resource *resource;
389 	int ret;
390 	int n;
391 	struct mdp_info *mdp;
392 
393 	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
394 	if (!resource) {
395 		pr_err("mdp: can not get mdp mem resource!\n");
396 		return -ENOMEM;
397 	}
398 
399 	mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
400 	if (!mdp)
401 		return -ENOMEM;
402 
403 	mdp->irq = platform_get_irq(pdev, 0);
404 	if (mdp->irq < 0) {
405 		pr_err("mdp: can not get mdp irq\n");
406 		ret = mdp->irq;
407 		goto error_get_irq;
408 	}
409 
410 	mdp->base = ioremap(resource->start, resource_size(resource));
411 	if (mdp->base == 0) {
412 		printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
413 		ret = -ENOMEM;
414 		goto error_ioremap;
415 	}
416 
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;
421 
422 	clk = clk_get(&pdev->dev, "mdp_clk");
423 	if (IS_ERR(clk)) {
424 		printk(KERN_INFO "mdp: failed to get mdp clk");
425 		ret = PTR_ERR(clk);
426 		goto error_get_clk;
427 	}
428 
429 	ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
430 	if (ret)
431 		goto error_request_irq;
432 	disable_irq(mdp->irq);
433 	mdp_irq_mask = 0;
434 
435 	/* debug interface write access */
436 	mdp_writel(mdp, 1, 0x60);
437 
438 	mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
439 	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
440 
441 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
442 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
443 
444 	for (n = 0; n < ARRAY_SIZE(csc_table); n++)
445 		mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
446 
447 	/* clear up unused fg/main registers */
448 	/* comp.plane 2&3 ystride */
449 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
450 
451 	/* unpacked pattern */
452 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
453 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
454 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
455 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
456 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
457 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
458 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
459 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
460 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
461 
462 	/* comp.plane 2 & 3 */
463 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
464 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
465 
466 	/* clear unused bg registers */
467 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
468 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
469 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
470 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
471 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
472 
473 	for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
474 		mdp_writel(mdp, mdp_upscale_table[n].val,
475 		       mdp_upscale_table[n].reg);
476 
477 	for (n = 0; n < 9; n++)
478 		mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
479 	mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
480 	mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
481 	mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
482 
483 	/* register mdp device */
484 	mdp->mdp_dev.dev.parent = &pdev->dev;
485 	mdp->mdp_dev.dev.class = mdp_class;
486 	dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
487 
488 	/* if you can remove the platform device you'd have to implement
489 	 * this:
490 	mdp_dev.release = mdp_class; */
491 
492 	ret = device_register(&mdp->mdp_dev.dev);
493 	if (ret)
494 		goto error_device_register;
495 	return 0;
496 
497 error_device_register:
498 	free_irq(mdp->irq, mdp);
499 error_request_irq:
500 error_get_clk:
501 	iounmap(mdp->base);
502 error_get_irq:
503 error_ioremap:
504 	kfree(mdp);
505 	return ret;
506 }
507 
508 static struct platform_driver msm_mdp_driver = {
509 	.probe = mdp_probe,
510 	.driver = {.name = "msm_mdp"},
511 };
512 
mdp_init(void)513 static int __init mdp_init(void)
514 {
515 	mdp_class = class_create(THIS_MODULE, "msm_mdp");
516 	if (IS_ERR(mdp_class)) {
517 		printk(KERN_ERR "Error creating mdp class\n");
518 		return PTR_ERR(mdp_class);
519 	}
520 	return platform_driver_register(&msm_mdp_driver);
521 }
522 
523 subsys_initcall(mdp_init);
524