aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/msm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/msm')
-rw-r--r--drivers/video/msm/Makefile19
-rw-r--r--drivers/video/msm/mddi.c828
-rw-r--r--drivers/video/msm/mddi_client_dummy.c97
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c255
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c283
-rw-r--r--drivers/video/msm/mddi_hw.h305
-rw-r--r--drivers/video/msm/mdp.c538
-rw-r--r--drivers/video/msm/mdp_csc_table.h582
-rw-r--r--drivers/video/msm/mdp_hw.h621
-rw-r--r--drivers/video/msm/mdp_ppp.c750
-rw-r--r--drivers/video/msm/mdp_scale_tables.c766
-rw-r--r--drivers/video/msm/mdp_scale_tables.h38
-rw-r--r--drivers/video/msm/msm_fb.c636
13 files changed, 5718 insertions, 0 deletions
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
new file mode 100644
index 000000000000..802d6ae523fb
--- /dev/null
+++ b/drivers/video/msm/Makefile
@@ -0,0 +1,19 @@
1
2# core framebuffer
3#
4obj-y := msm_fb.o
5
6# MDP DMA/PPP engine
7#
8obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
9
10# MDDI interface
11#
12obj-y += mddi.o
13
14# MDDI client/panel drivers
15#
16obj-y += mddi_client_dummy.o
17obj-y += mddi_client_toshiba.o
18obj-y += mddi_client_nt35399.o
19
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
new file mode 100644
index 000000000000..f2de5a1acd6d
--- /dev/null
+++ b/drivers/video/msm/mddi.c
@@ -0,0 +1,828 @@
1/*
2 * MSM MDDI Transport
3 *
4 * Copyright (C) 2007 Google Incorporated
5 * Copyright (C) 2007 QUALCOMM Incorporated
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/dma-mapping.h>
21#include <linux/interrupt.h>
22#include <linux/platform_device.h>
23#include <linux/delay.h>
24#include <linux/spinlock.h>
25#include <linux/clk.h>
26#include <linux/io.h>
27#include <mach/msm_iomap.h>
28#include <mach/irqs.h>
29#include <mach/board.h>
30#include <linux/delay.h>
31
32#include <mach/msm_fb.h>
33#include "mddi_hw.h"
34
35#define FLAG_DISABLE_HIBERNATION 0x0001
36#define FLAG_HAVE_CAPS 0x0002
37#define FLAG_HAS_VSYNC_IRQ 0x0004
38#define FLAG_HAVE_STATUS 0x0008
39
40#define CMD_GET_CLIENT_CAP 0x0601
41#define CMD_GET_CLIENT_STATUS 0x0602
42
43union mddi_rev {
44 unsigned char raw[MDDI_REV_BUFFER_SIZE];
45 struct mddi_rev_packet hdr;
46 struct mddi_client_status status;
47 struct mddi_client_caps caps;
48 struct mddi_register_access reg;
49};
50
51struct reg_read_info {
52 struct completion done;
53 uint32_t reg;
54 uint32_t status;
55 uint32_t result;
56};
57
58struct mddi_info {
59 uint16_t flags;
60 uint16_t version;
61 char __iomem *base;
62 int irq;
63 struct clk *clk;
64 struct msm_mddi_client_data client_data;
65
66 /* buffer for rev encap packets */
67 void *rev_data;
68 dma_addr_t rev_addr;
69 struct mddi_llentry *reg_write_data;
70 dma_addr_t reg_write_addr;
71 struct mddi_llentry *reg_read_data;
72 dma_addr_t reg_read_addr;
73 size_t rev_data_curr;
74
75 spinlock_t int_lock;
76 uint32_t int_enable;
77 uint32_t got_int;
78 wait_queue_head_t int_wait;
79
80 struct mutex reg_write_lock;
81 struct mutex reg_read_lock;
82 struct reg_read_info *reg_read;
83
84 struct mddi_client_caps caps;
85 struct mddi_client_status status;
86
87 void (*power_client)(struct msm_mddi_client_data *, int);
88
89 /* client device published to bind us to the
90 * appropriate mddi_client driver
91 */
92 char client_name[20];
93
94 struct platform_device client_pdev;
95};
96
97static void mddi_init_rev_encap(struct mddi_info *mddi);
98
99#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
100#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
101
102void mddi_activate_link(struct msm_mddi_client_data *cdata)
103{
104 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
105 client_data);
106
107 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
108}
109
110static void mddi_handle_link_list_done(struct mddi_info *mddi)
111{
112}
113
114static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
115{
116 printk(KERN_INFO "mddi: resetting rev ptr\n");
117 mddi->rev_data_curr = 0;
118 mddi_writel(mddi->rev_addr, REV_PTR);
119 mddi_writel(mddi->rev_addr, REV_PTR);
120 mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
121}
122
123static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
124{
125 int i;
126 struct reg_read_info *ri;
127
128 if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
129 (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
130
131 switch (rev->hdr.type) {
132 case TYPE_CLIENT_CAPS:
133 memcpy(&mddi->caps, &rev->caps,
134 sizeof(struct mddi_client_caps));
135 mddi->flags |= FLAG_HAVE_CAPS;
136 wake_up(&mddi->int_wait);
137 break;
138 case TYPE_CLIENT_STATUS:
139 memcpy(&mddi->status, &rev->status,
140 sizeof(struct mddi_client_status));
141 mddi->flags |= FLAG_HAVE_STATUS;
142 wake_up(&mddi->int_wait);
143 break;
144 case TYPE_REGISTER_ACCESS:
145 ri = mddi->reg_read;
146 if (ri == 0) {
147 printk(KERN_INFO "rev: got reg %x = %x without "
148 " pending read\n",
149 rev->reg.register_address,
150 rev->reg.register_data_list);
151 break;
152 }
153 if (ri->reg != rev->reg.register_address) {
154 printk(KERN_INFO "rev: got reg %x = %x for "
155 "wrong register, expected "
156 "%x\n",
157 rev->reg.register_address,
158 rev->reg.register_data_list, ri->reg);
159 break;
160 }
161 mddi->reg_read = NULL;
162 ri->status = 0;
163 ri->result = rev->reg.register_data_list;
164 complete(&ri->done);
165 break;
166 default:
167 printk(KERN_INFO "rev: unknown reverse packet: "
168 "len=%04x type=%04x CURR_REV_PTR=%x\n",
169 rev->hdr.length, rev->hdr.type,
170 mddi_readl(CURR_REV_PTR));
171 for (i = 0; i < rev->hdr.length + 2; i++) {
172 if ((i % 16) == 0)
173 printk(KERN_INFO "\n");
174 printk(KERN_INFO " %02x", rev->raw[i]);
175 }
176 printk(KERN_INFO "\n");
177 mddi_reset_rev_encap_ptr(mddi);
178 }
179 } else {
180 printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
181 rev->hdr.length, mddi_readl(CURR_REV_PTR));
182 mddi_reset_rev_encap_ptr(mddi);
183 }
184}
185
186static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
187
188static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
189{
190 union mddi_rev *rev = mddi->rev_data;
191 uint32_t rev_data_count;
192 uint32_t rev_crc_err_count;
193 int i;
194 struct reg_read_info *ri;
195 size_t prev_offset;
196 uint16_t length;
197
198 union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
199
200 /* clear the interrupt */
201 mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
202 rev_data_count = mddi_readl(REV_PKT_CNT);
203 rev_crc_err_count = mddi_readl(REV_CRC_ERR);
204 if (rev_data_count > 1)
205 printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
206
207 if (rev_crc_err_count) {
208 printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
209 rev_crc_err_count, mddi_readl(INT));
210 ri = mddi->reg_read;
211 if (ri == 0) {
212 printk(KERN_INFO "rev: got crc error without pending "
213 "read\n");
214 } else {
215 mddi->reg_read = NULL;
216 ri->status = -EIO;
217 ri->result = -1;
218 complete(&ri->done);
219 }
220 }
221
222 if (rev_data_count == 0)
223 return;
224
225 prev_offset = mddi->rev_data_curr;
226
227 length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
228 mddi->rev_data_curr++;
229 if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
230 mddi->rev_data_curr = 0;
231 length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
232 mddi->rev_data_curr += 1 + length;
233 if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
234 mddi->rev_data_curr =
235 mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
236
237 if (length > MDDI_REV_BUFFER_SIZE - 2) {
238 printk(KERN_INFO "mddi: rev data length greater than buffer"
239 "size\n");
240 mddi_reset_rev_encap_ptr(mddi);
241 return;
242 }
243
244 if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
245 union mddi_rev tmprev;
246 size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
247 memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
248 memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
249 mddi_handle_rev_data(mddi, &tmprev);
250 } else {
251 mddi_handle_rev_data(mddi, crev);
252 }
253
254 if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
255 mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
256 mddi_writel(mddi->rev_addr, REV_PTR);
257 }
258}
259
260static irqreturn_t mddi_isr(int irq, void *data)
261{
262 struct msm_mddi_client_data *cdata = data;
263 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
264 client_data);
265 uint32_t active, status;
266
267 spin_lock(&mddi->int_lock);
268
269 active = mddi_readl(INT);
270 status = mddi_readl(STAT);
271
272 mddi_writel(active, INT);
273
274 /* ignore any interrupts we have disabled */
275 active &= mddi->int_enable;
276
277 mddi->got_int |= active;
278 wake_up(&mddi->int_wait);
279
280 if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
281 mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
282 mddi_handle_link_list_done(mddi);
283 }
284 if (active & MDDI_INT_REV_DATA_AVAIL)
285 mddi_handle_rev_data_avail(mddi);
286
287 if (active & ~MDDI_INT_NEED_CLEAR)
288 mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
289
290 if (active & MDDI_INT_LINK_ACTIVE) {
291 mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
292 mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
293 }
294
295 if (active & MDDI_INT_IN_HIBERNATION) {
296 mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
297 mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
298 }
299
300 mddi_writel(mddi->int_enable, INTEN);
301 spin_unlock(&mddi->int_lock);
302
303 return IRQ_HANDLED;
304}
305
306static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
307 uint32_t intmask, int timeout)
308{
309 unsigned long irq_flags;
310
311 spin_lock_irqsave(&mddi->int_lock, irq_flags);
312 mddi->got_int &= ~intmask;
313 mddi->int_enable |= intmask;
314 mddi_writel(mddi->int_enable, INTEN);
315 spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
316 return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
317 timeout);
318}
319
320static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
321{
322 if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
323 printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout "
324 "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
325 current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
326 mddi->got_int);
327}
328
329static void mddi_init_rev_encap(struct mddi_info *mddi)
330{
331 memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
332 mddi_writel(mddi->rev_addr, REV_PTR);
333 mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
334 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
335}
336
337void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
338{
339 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
340 client_data);
341 mddi_writel(MDDI_CMD_POWERDOWN, CMD);
342 mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
343 mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
344 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
345}
346
347
348static uint16_t mddi_init_registers(struct mddi_info *mddi)
349{
350 mddi_writel(0x0001, VERSION);
351 mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
352 mddi_writel(0x0003, SPM); /* subframes per media */
353 mddi_writel(0x0005, TA1_LEN);
354 mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
355 mddi_writel(0x0096, DRIVE_HI);
356 /* 0x32 normal, 0x50 for Toshiba display */
357 mddi_writel(0x0050, DRIVE_LO);
358 mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
359 mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
360
361 mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
362 mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
363
364 /* disable periodic rev encap */
365 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
366 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
367
368 if (mddi_readl(PAD_CTL) == 0) {
369 /* If we are turning on band gap, need to wait 5us before
370 * turning on the rest of the PAD */
371 mddi_writel(0x08000, PAD_CTL);
372 udelay(5);
373 }
374
375 /* Recommendation from PAD hw team */
376 mddi_writel(0xa850f, PAD_CTL);
377
378
379 /* Need an even number for counts */
380 mddi_writel(0x60006, DRIVER_START_CNT);
381
382 mddi_set_auto_hibernate(&mddi->client_data, 0);
383
384 mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
385 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
386
387 mddi_init_rev_encap(mddi);
388 return mddi_readl(CORE_VER) & 0xffff;
389}
390
391static void mddi_suspend(struct msm_mddi_client_data *cdata)
392{
393 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
394 client_data);
395 /* turn off the client */
396 if (mddi->power_client)
397 mddi->power_client(&mddi->client_data, 0);
398 /* turn off the link */
399 mddi_writel(MDDI_CMD_RESET, CMD);
400 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
401 /* turn off the clock */
402 clk_disable(mddi->clk);
403}
404
405static void mddi_resume(struct msm_mddi_client_data *cdata)
406{
407 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
408 client_data);
409 mddi_set_auto_hibernate(&mddi->client_data, 0);
410 /* turn on the client */
411 if (mddi->power_client)
412 mddi->power_client(&mddi->client_data, 1);
413 /* turn on the clock */
414 clk_enable(mddi->clk);
415 /* set up the local registers */
416 mddi->rev_data_curr = 0;
417 mddi_init_registers(mddi);
418 mddi_writel(mddi->int_enable, INTEN);
419 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
420 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
421 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
422 mddi_set_auto_hibernate(&mddi->client_data, 1);
423}
424
425static int __init mddi_get_client_caps(struct mddi_info *mddi)
426{
427 int i, j;
428
429 /* clear any stale interrupts */
430 mddi_writel(0xffffffff, INT);
431
432 mddi->int_enable = MDDI_INT_LINK_ACTIVE |
433 MDDI_INT_IN_HIBERNATION |
434 MDDI_INT_PRI_LINK_LIST_DONE |
435 MDDI_INT_REV_DATA_AVAIL |
436 MDDI_INT_REV_OVERFLOW |
437 MDDI_INT_REV_OVERWRITE |
438 MDDI_INT_RTD_FAILURE;
439 mddi_writel(mddi->int_enable, INTEN);
440
441 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
442 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
443
444 for (j = 0; j < 3; j++) {
445 /* the toshiba vga panel does not respond to get
446 * caps unless you SEND_RTD, but the first SEND_RTD
447 * will fail...
448 */
449 for (i = 0; i < 4; i++) {
450 uint32_t stat;
451
452 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
453 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
454 stat = mddi_readl(STAT);
455 printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
456 "rtd val %x\n", mddi_readl(INT), stat,
457 mddi_readl(RTD_VAL));
458 if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
459 break;
460 msleep(1);
461 }
462
463 mddi_writel(CMD_GET_CLIENT_CAP, CMD);
464 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
465 wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
466 HZ / 100);
467
468 if (mddi->flags & FLAG_HAVE_CAPS)
469 break;
470 printk(KERN_INFO KERN_ERR "mddi_init, timeout waiting for "
471 "caps\n");
472 }
473 return mddi->flags & FLAG_HAVE_CAPS;
474}
475
476/* link must be active when this is called */
477int mddi_check_status(struct mddi_info *mddi)
478{
479 int ret = -1, retry = 3;
480 mutex_lock(&mddi->reg_read_lock);
481 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
482 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
483
484 do {
485 mddi->flags &= ~FLAG_HAVE_STATUS;
486 mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
487 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
488 wait_event_timeout(mddi->int_wait,
489 mddi->flags & FLAG_HAVE_STATUS,
490 HZ / 100);
491
492 if (mddi->flags & FLAG_HAVE_STATUS) {
493 if (mddi->status.crc_error_count)
494 printk(KERN_INFO "mddi status: crc_error "
495 "count: %d\n",
496 mddi->status.crc_error_count);
497 else
498 ret = 0;
499 break;
500 } else
501 printk(KERN_INFO "mddi status: failed to get client "
502 "status\n");
503 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
504 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
505 } while (--retry);
506
507 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
508 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
509 mutex_unlock(&mddi->reg_read_lock);
510 return ret;
511}
512
513
514void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
515 uint32_t reg)
516{
517 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
518 client_data);
519 struct mddi_llentry *ll;
520 struct mddi_register_access *ra;
521
522 mutex_lock(&mddi->reg_write_lock);
523
524 ll = mddi->reg_write_data;
525
526 ra = &(ll->u.r);
527 ra->length = 14 + 4;
528 ra->type = TYPE_REGISTER_ACCESS;
529 ra->client_id = 0;
530 ra->read_write_info = MDDI_WRITE | 1;
531 ra->crc16 = 0;
532
533 ra->register_address = reg;
534 ra->register_data_list = val;
535
536 ll->flags = 1;
537 ll->header_count = 14;
538 ll->data_count = 4;
539 ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
540 u.r.register_data_list);
541 ll->next = 0;
542 ll->reserved = 0;
543
544 mddi_writel(mddi->reg_write_addr, PRI_PTR);
545
546 mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
547 mutex_unlock(&mddi->reg_write_lock);
548}
549
550uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
551{
552 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
553 client_data);
554 struct mddi_llentry *ll;
555 struct mddi_register_access *ra;
556 struct reg_read_info ri;
557 unsigned s;
558 int retry_count = 2;
559 unsigned long irq_flags;
560
561 mutex_lock(&mddi->reg_read_lock);
562
563 ll = mddi->reg_read_data;
564
565 ra = &(ll->u.r);
566 ra->length = 14;
567 ra->type = TYPE_REGISTER_ACCESS;
568 ra->client_id = 0;
569 ra->read_write_info = MDDI_READ | 1;
570 ra->crc16 = 0;
571
572 ra->register_address = reg;
573
574 ll->flags = 0x11;
575 ll->header_count = 14;
576 ll->data_count = 0;
577 ll->data = 0;
578 ll->next = 0;
579 ll->reserved = 0;
580
581 s = mddi_readl(STAT);
582
583 ri.reg = reg;
584 ri.status = -1;
585
586 do {
587 init_completion(&ri.done);
588 mddi->reg_read = &ri;
589 mddi_writel(mddi->reg_read_addr, PRI_PTR);
590
591 mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
592
593 /* Enable Periodic Reverse Encapsulation. */
594 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
595 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
596 if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
597 !ri.done.done) {
598 printk(KERN_INFO "mddi_remote_read(%x) timeout "
599 "(%d %d %d)\n",
600 reg, ri.status, ri.result, ri.done.done);
601 spin_lock_irqsave(&mddi->int_lock, irq_flags);
602 mddi->reg_read = NULL;
603 spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
604 ri.status = -1;
605 ri.result = -1;
606 }
607 if (ri.status == 0)
608 break;
609
610 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
611 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
612 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
613 printk(KERN_INFO "mddi_remote_read: failed, sent "
614 "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
615 "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
616 mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
617 } while (retry_count-- > 0);
618 /* Disable Periodic Reverse Encapsulation. */
619 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
620 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
621 mddi->reg_read = NULL;
622 mutex_unlock(&mddi->reg_read_lock);
623 return ri.result;
624}
625
626static struct mddi_info mddi_info[2];
627
628static int __init mddi_clk_setup(struct platform_device *pdev,
629 struct mddi_info *mddi,
630 unsigned long clk_rate)
631{
632 int ret;
633
634 /* set up the clocks */
635 mddi->clk = clk_get(&pdev->dev, "mddi_clk");
636 if (IS_ERR(mddi->clk)) {
637 printk(KERN_INFO "mddi: failed to get clock\n");
638 return PTR_ERR(mddi->clk);
639 }
640 ret = clk_enable(mddi->clk);
641 if (ret)
642 goto fail;
643 ret = clk_set_rate(mddi->clk, clk_rate);
644 if (ret)
645 goto fail;
646 return 0;
647
648fail:
649 clk_put(mddi->clk);
650 return ret;
651}
652
653static int __init mddi_rev_data_setup(struct mddi_info *mddi)
654{
655 void *dma;
656 dma_addr_t dma_addr;
657
658 /* set up dma buffer */
659 dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
660 if (dma == 0)
661 return -ENOMEM;
662 mddi->rev_data = dma;
663 mddi->rev_data_curr = 0;
664 mddi->rev_addr = dma_addr;
665 mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
666 mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
667 mddi->reg_read_data = mddi->reg_write_data + 1;
668 mddi->reg_read_addr = mddi->reg_write_addr +
669 sizeof(*mddi->reg_write_data);
670 return 0;
671}
672
673static int __init mddi_probe(struct platform_device *pdev)
674{
675 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
676 struct mddi_info *mddi = &mddi_info[pdev->id];
677 struct resource *resource;
678 int ret, i;
679
680 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
681 if (!resource) {
682 printk(KERN_ERR "mddi: no associated mem resource!\n");
683 return -ENOMEM;
684 }
685 mddi->base = ioremap(resource->start, resource->end - resource->start);
686 if (!mddi->base) {
687 printk(KERN_ERR "mddi: failed to remap base!\n");
688 ret = -EINVAL;
689 goto error_ioremap;
690 }
691 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
692 if (!resource) {
693 printk(KERN_ERR "mddi: no associated irq resource!\n");
694 ret = -EINVAL;
695 goto error_get_irq_resource;
696 }
697 mddi->irq = resource->start;
698 printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
699 mddi->irq);
700 mddi->power_client = pdata->power_client;
701
702 mutex_init(&mddi->reg_write_lock);
703 mutex_init(&mddi->reg_read_lock);
704 spin_lock_init(&mddi->int_lock);
705 init_waitqueue_head(&mddi->int_wait);
706
707 ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
708 if (ret) {
709 printk(KERN_ERR "mddi: failed to setup clock!\n");
710 goto error_clk_setup;
711 }
712
713 ret = mddi_rev_data_setup(mddi);
714 if (ret) {
715 printk(KERN_ERR "mddi: failed to setup rev data!\n");
716 goto error_rev_data;
717 }
718
719 mddi->int_enable = 0;
720 mddi_writel(mddi->int_enable, INTEN);
721 ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
722 &mddi->client_data);
723 if (ret) {
724 printk(KERN_ERR "mddi: failed to request enable irq!\n");
725 goto error_request_irq;
726 }
727
728 /* turn on the mddi client bridge chip */
729 if (mddi->power_client)
730 mddi->power_client(&mddi->client_data, 1);
731
732 /* initialize the mddi registers */
733 mddi_set_auto_hibernate(&mddi->client_data, 0);
734 mddi_writel(MDDI_CMD_RESET, CMD);
735 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
736 mddi->version = mddi_init_registers(mddi);
737 if (mddi->version < 0x20) {
738 printk(KERN_ERR "mddi: unsupported version 0x%x\n",
739 mddi->version);
740 ret = -ENODEV;
741 goto error_mddi_version;
742 }
743
744 /* read the capabilities off the client */
745 if (!mddi_get_client_caps(mddi)) {
746 printk(KERN_INFO "mddi: no client found\n");
747 /* power down the panel */
748 mddi_writel(MDDI_CMD_POWERDOWN, CMD);
749 printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
750 msleep(100);
751 printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
752 return 0;
753 }
754 mddi_set_auto_hibernate(&mddi->client_data, 1);
755
756 if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
757 pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
758
759 mddi->client_pdev.id = 0;
760 for (i = 0; i < pdata->num_clients; i++) {
761 if (pdata->client_platform_data[i].product_id ==
762 (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
763 mddi->client_data.private_client_data =
764 pdata->client_platform_data[i].client_data;
765 mddi->client_pdev.name =
766 pdata->client_platform_data[i].name;
767 mddi->client_pdev.id =
768 pdata->client_platform_data[i].id;
769 /* XXX: possibly set clock */
770 break;
771 }
772 }
773
774 if (i >= pdata->num_clients)
775 mddi->client_pdev.name = "mddi_c_dummy";
776 printk(KERN_INFO "mddi: registering panel %s\n",
777 mddi->client_pdev.name);
778
779 mddi->client_data.suspend = mddi_suspend;
780 mddi->client_data.resume = mddi_resume;
781 mddi->client_data.activate_link = mddi_activate_link;
782 mddi->client_data.remote_write = mddi_remote_write;
783 mddi->client_data.remote_read = mddi_remote_read;
784 mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
785 mddi->client_data.fb_resource = pdata->fb_resource;
786 if (pdev->id == 0)
787 mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
788 else if (pdev->id == 1)
789 mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
790 else {
791 printk(KERN_ERR "mddi: can not determine interface %d!\n",
792 pdev->id);
793 ret = -EINVAL;
794 goto error_mddi_interface;
795 }
796
797 mddi->client_pdev.dev.platform_data = &mddi->client_data;
798 printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
799 platform_device_register(&mddi->client_pdev);
800 return 0;
801
802error_mddi_interface:
803error_mddi_version:
804 free_irq(mddi->irq, 0);
805error_request_irq:
806 dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
807error_rev_data:
808error_clk_setup:
809error_get_irq_resource:
810 iounmap(mddi->base);
811error_ioremap:
812
813 printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
814 return ret;
815}
816
817
818static struct platform_driver mddi_driver = {
819 .probe = mddi_probe,
820 .driver = { .name = "msm_mddi" },
821};
822
823static int __init _mddi_init(void)
824{
825 return platform_driver_register(&mddi_driver);
826}
827
828module_init(_mddi_init);
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
new file mode 100644
index 000000000000..ebbae87885b6
--- /dev/null
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -0,0 +1,97 @@
1/* drivers/video/msm_fb/mddi_client_dummy.c
2 *
3 * Support for "dummy" mddi client devices which require no
4 * special initialization code.
5 *
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/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21
22#include <mach/msm_fb.h>
23
24struct panel_info {
25 struct platform_device pdev;
26 struct msm_panel_data panel_data;
27};
28
29static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
30{
31 return 0;
32}
33
34static int mddi_dummy_resume(struct msm_panel_data *panel_data)
35{
36 return 0;
37}
38
39static int mddi_dummy_blank(struct msm_panel_data *panel_data)
40{
41 return 0;
42}
43
44static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
45{
46 return 0;
47}
48
49static int mddi_dummy_probe(struct platform_device *pdev)
50{
51 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
52 struct panel_info *panel =
53 kzalloc(sizeof(struct panel_info), GFP_KERNEL);
54 int ret;
55 if (!panel)
56 return -ENOMEM;
57 platform_set_drvdata(pdev, panel);
58 panel->panel_data.suspend = mddi_dummy_suspend;
59 panel->panel_data.resume = mddi_dummy_resume;
60 panel->panel_data.blank = mddi_dummy_blank;
61 panel->panel_data.unblank = mddi_dummy_unblank;
62 panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
63 panel->pdev.name = "msm_panel";
64 panel->pdev.id = pdev->id;
65 platform_device_add_resources(&panel->pdev,
66 client_data->fb_resource, 1);
67 panel->panel_data.fb_data = client_data->private_client_data;
68 panel->pdev.dev.platform_data = &panel->panel_data;
69 ret = platform_device_register(&panel->pdev);
70 if (ret) {
71 kfree(panel);
72 return ret;
73 }
74 return 0;
75}
76
77static int mddi_dummy_remove(struct platform_device *pdev)
78{
79 struct panel_info *panel = platform_get_drvdata(pdev);
80 kfree(panel);
81 return 0;
82}
83
84static struct platform_driver mddi_client_dummy = {
85 .probe = mddi_dummy_probe,
86 .remove = mddi_dummy_remove,
87 .driver = { .name = "mddi_c_dummy" },
88};
89
90static int __init mddi_client_dummy_init(void)
91{
92 platform_driver_register(&mddi_client_dummy);
93 return 0;
94}
95
96module_init(mddi_client_dummy_init);
97
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
new file mode 100644
index 000000000000..9c78050ac799
--- /dev/null
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -0,0 +1,255 @@
1/* drivers/video/msm_fb/mddi_client_nt35399.c
2 *
3 * Support for Novatek NT35399 MDDI client of Sapphire
4 *
5 * Copyright (C) 2008 HTC Incorporated
6 * Author: Solomon Chiu (solomon_chiu@htc.com)
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/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21#include <linux/interrupt.h>
22#include <linux/gpio.h>
23#include <mach/msm_fb.h>
24
25static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
26
27struct panel_info {
28 struct msm_mddi_client_data *client_data;
29 struct platform_device pdev;
30 struct msm_panel_data panel_data;
31 struct msmfb_callback *fb_callback;
32 struct work_struct panel_work;
33 struct workqueue_struct *fb_wq;
34 int nt35399_got_int;
35};
36
37static void
38nt35399_request_vsync(struct msm_panel_data *panel_data,
39 struct msmfb_callback *callback)
40{
41 struct panel_info *panel = container_of(panel_data, struct panel_info,
42 panel_data);
43 struct msm_mddi_client_data *client_data = panel->client_data;
44
45 panel->fb_callback = callback;
46 if (panel->nt35399_got_int) {
47 panel->nt35399_got_int = 0;
48 client_data->activate_link(client_data); /* clears interrupt */
49 }
50}
51
52static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
53{
54 struct panel_info *panel = container_of(panel_data, struct panel_info,
55 panel_data);
56 struct msm_mddi_client_data *client_data = panel->client_data;
57
58 if (panel->nt35399_got_int) {
59 panel->nt35399_got_int = 0;
60 client_data->activate_link(client_data); /* clears interrupt */
61 }
62
63 if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
64 HZ/2) == 0)
65 printk(KERN_ERR "timeout waiting for VSYNC\n");
66
67 panel->nt35399_got_int = 0;
68 /* interrupt clears when screen dma starts */
69}
70
71static int nt35399_suspend(struct msm_panel_data *panel_data)
72{
73 struct panel_info *panel = container_of(panel_data, struct panel_info,
74 panel_data);
75 struct msm_mddi_client_data *client_data = panel->client_data;
76
77 struct msm_mddi_bridge_platform_data *bridge_data =
78 client_data->private_client_data;
79 int ret;
80
81 ret = bridge_data->uninit(bridge_data, client_data);
82 if (ret) {
83 printk(KERN_INFO "mddi nt35399 client: non zero return from "
84 "uninit\n");
85 return ret;
86 }
87 client_data->suspend(client_data);
88 return 0;
89}
90
91static int nt35399_resume(struct msm_panel_data *panel_data)
92{
93 struct panel_info *panel = container_of(panel_data, struct panel_info,
94 panel_data);
95 struct msm_mddi_client_data *client_data = panel->client_data;
96
97 struct msm_mddi_bridge_platform_data *bridge_data =
98 client_data->private_client_data;
99 int ret;
100
101 client_data->resume(client_data);
102 ret = bridge_data->init(bridge_data, client_data);
103 if (ret)
104 return ret;
105 return 0;
106}
107
108static int nt35399_blank(struct msm_panel_data *panel_data)
109{
110 struct panel_info *panel = container_of(panel_data, struct panel_info,
111 panel_data);
112 struct msm_mddi_client_data *client_data = panel->client_data;
113 struct msm_mddi_bridge_platform_data *bridge_data =
114 client_data->private_client_data;
115
116 return bridge_data->blank(bridge_data, client_data);
117}
118
119static int nt35399_unblank(struct msm_panel_data *panel_data)
120{
121 struct panel_info *panel = container_of(panel_data, struct panel_info,
122 panel_data);
123 struct msm_mddi_client_data *client_data = panel->client_data;
124 struct msm_mddi_bridge_platform_data *bridge_data =
125 client_data->private_client_data;
126
127 return bridge_data->unblank(bridge_data, client_data);
128}
129
130irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
131{
132 struct panel_info *panel = data;
133
134 panel->nt35399_got_int = 1;
135
136 if (panel->fb_callback) {
137 panel->fb_callback->func(panel->fb_callback);
138 panel->fb_callback = NULL;
139 }
140
141 wake_up(&nt35399_vsync_wait);
142
143 return IRQ_HANDLED;
144}
145
146static int setup_vsync(struct panel_info *panel, int init)
147{
148 int ret;
149 int gpio = 97;
150 unsigned int irq;
151
152 if (!init) {
153 ret = 0;
154 goto uninit;
155 }
156 ret = gpio_request(gpio, "vsync");
157 if (ret)
158 goto err_request_gpio_failed;
159
160 ret = gpio_direction_input(gpio);
161 if (ret)
162 goto err_gpio_direction_input_failed;
163
164 ret = irq = gpio_to_irq(gpio);
165 if (ret < 0)
166 goto err_get_irq_num_failed;
167
168 ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING,
169 "vsync", panel);
170 if (ret)
171 goto err_request_irq_failed;
172
173 printk(KERN_INFO "vsync on gpio %d now %d\n",
174 gpio, gpio_get_value(gpio));
175 return 0;
176
177uninit:
178 free_irq(gpio_to_irq(gpio), panel->client_data);
179err_request_irq_failed:
180err_get_irq_num_failed:
181err_gpio_direction_input_failed:
182 gpio_free(gpio);
183err_request_gpio_failed:
184 return ret;
185}
186
187static int mddi_nt35399_probe(struct platform_device *pdev)
188{
189 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
190 struct msm_mddi_bridge_platform_data *bridge_data =
191 client_data->private_client_data;
192
193 int ret;
194
195 struct panel_info *panel = kzalloc(sizeof(struct panel_info),
196 GFP_KERNEL);
197
198 printk(KERN_DEBUG "%s: enter.\n", __func__);
199
200 if (!panel)
201 return -ENOMEM;
202 platform_set_drvdata(pdev, panel);
203
204 ret = setup_vsync(panel, 1);
205 if (ret) {
206 dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
207 return ret;
208 }
209
210 panel->client_data = client_data;
211 panel->panel_data.suspend = nt35399_suspend;
212 panel->panel_data.resume = nt35399_resume;
213 panel->panel_data.wait_vsync = nt35399_wait_vsync;
214 panel->panel_data.request_vsync = nt35399_request_vsync;
215 panel->panel_data.blank = nt35399_blank;
216 panel->panel_data.unblank = nt35399_unblank;
217 panel->panel_data.fb_data = &bridge_data->fb_data;
218 panel->panel_data.caps = 0;
219
220 panel->pdev.name = "msm_panel";
221 panel->pdev.id = pdev->id;
222 panel->pdev.resource = client_data->fb_resource;
223 panel->pdev.num_resources = 1;
224 panel->pdev.dev.platform_data = &panel->panel_data;
225
226 if (bridge_data->init)
227 bridge_data->init(bridge_data, client_data);
228
229 platform_device_register(&panel->pdev);
230
231 return 0;
232}
233
234static int mddi_nt35399_remove(struct platform_device *pdev)
235{
236 struct panel_info *panel = platform_get_drvdata(pdev);
237
238 setup_vsync(panel, 0);
239 kfree(panel);
240 return 0;
241}
242
243static struct platform_driver mddi_client_0bda_8a47 = {
244 .probe = mddi_nt35399_probe,
245 .remove = mddi_nt35399_remove,
246 .driver = { .name = "mddi_c_0bda_8a47" },
247};
248
249static int __init mddi_client_nt35399_init(void)
250{
251 return platform_driver_register(&mddi_client_0bda_8a47);
252}
253
254module_init(mddi_client_nt35399_init);
255
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
new file mode 100644
index 000000000000..80d0f5fdf0b1
--- /dev/null
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -0,0 +1,283 @@
1/* drivers/video/msm_fb/mddi_client_toshiba.c
2 *
3 * Support for Toshiba TC358720XBG mddi client devices which require no
4 * special initialization code.
5 *
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/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21#include <linux/interrupt.h>
22#include <linux/gpio.h>
23#include <mach/msm_fb.h>
24
25
26#define LCD_CONTROL_BLOCK_BASE 0x110000
27#define CMN (LCD_CONTROL_BLOCK_BASE|0x10)
28#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
29#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
30#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
31#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
32#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
33#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
34#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58)
35#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
36
37#define BASE5 0x150000
38#define BASE6 0x160000
39#define BASE7 0x170000
40
41#define GPIOIEV (BASE5 + 0x10)
42#define GPIOIE (BASE5 + 0x14)
43#define GPIORIS (BASE5 + 0x18)
44#define GPIOMIS (BASE5 + 0x1C)
45#define GPIOIC (BASE5 + 0x20)
46
47#define INTMASK (BASE6 + 0x0C)
48#define INTMASK_VWAKEOUT (1U << 0)
49#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8)
50#define GPIOSEL (BASE7 + 0x00)
51#define GPIOSEL_VWAKEINT (1U << 0)
52
53static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait);
54
55struct panel_info {
56 struct msm_mddi_client_data *client_data;
57 struct platform_device pdev;
58 struct msm_panel_data panel_data;
59 struct msmfb_callback *toshiba_callback;
60 int toshiba_got_int;
61};
62
63
64static void toshiba_request_vsync(struct msm_panel_data *panel_data,
65 struct msmfb_callback *callback)
66{
67 struct panel_info *panel = container_of(panel_data, struct panel_info,
68 panel_data);
69 struct msm_mddi_client_data *client_data = panel->client_data;
70
71 panel->toshiba_callback = callback;
72 if (panel->toshiba_got_int) {
73 panel->toshiba_got_int = 0;
74 client_data->activate_link(client_data);
75 }
76}
77
78static void toshiba_clear_vsync(struct msm_panel_data *panel_data)
79{
80 struct panel_info *panel = container_of(panel_data, struct panel_info,
81 panel_data);
82 struct msm_mddi_client_data *client_data = panel->client_data;
83
84 client_data->activate_link(client_data);
85}
86
87static void toshiba_wait_vsync(struct msm_panel_data *panel_data)
88{
89 struct panel_info *panel = container_of(panel_data, struct panel_info,
90 panel_data);
91 struct msm_mddi_client_data *client_data = panel->client_data;
92
93 if (panel->toshiba_got_int) {
94 panel->toshiba_got_int = 0;
95 client_data->activate_link(client_data); /* clears interrupt */
96 }
97 if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
98 HZ/2) == 0)
99 printk(KERN_ERR "timeout waiting for VSYNC\n");
100 panel->toshiba_got_int = 0;
101 /* interrupt clears when screen dma starts */
102}
103
104static int toshiba_suspend(struct msm_panel_data *panel_data)
105{
106 struct panel_info *panel = container_of(panel_data, struct panel_info,
107 panel_data);
108 struct msm_mddi_client_data *client_data = panel->client_data;
109
110 struct msm_mddi_bridge_platform_data *bridge_data =
111 client_data->private_client_data;
112 int ret;
113
114 ret = bridge_data->uninit(bridge_data, client_data);
115 if (ret) {
116 printk(KERN_INFO "mddi toshiba client: non zero return from "
117 "uninit\n");
118 return ret;
119 }
120 client_data->suspend(client_data);
121 return 0;
122}
123
124static int toshiba_resume(struct msm_panel_data *panel_data)
125{
126 struct panel_info *panel = container_of(panel_data, struct panel_info,
127 panel_data);
128 struct msm_mddi_client_data *client_data = panel->client_data;
129
130 struct msm_mddi_bridge_platform_data *bridge_data =
131 client_data->private_client_data;
132 int ret;
133
134 client_data->resume(client_data);
135 ret = bridge_data->init(bridge_data, client_data);
136 if (ret)
137 return ret;
138 return 0;
139}
140
141static int toshiba_blank(struct msm_panel_data *panel_data)
142{
143 struct panel_info *panel = container_of(panel_data, struct panel_info,
144 panel_data);
145 struct msm_mddi_client_data *client_data = panel->client_data;
146 struct msm_mddi_bridge_platform_data *bridge_data =
147 client_data->private_client_data;
148
149 return bridge_data->blank(bridge_data, client_data);
150}
151
152static int toshiba_unblank(struct msm_panel_data *panel_data)
153{
154 struct panel_info *panel = container_of(panel_data, struct panel_info,
155 panel_data);
156 struct msm_mddi_client_data *client_data = panel->client_data;
157 struct msm_mddi_bridge_platform_data *bridge_data =
158 client_data->private_client_data;
159
160 return bridge_data->unblank(bridge_data, client_data);
161}
162
163irqreturn_t toshiba_vsync_interrupt(int irq, void *data)
164{
165 struct panel_info *panel = data;
166
167 panel->toshiba_got_int = 1;
168 if (panel->toshiba_callback) {
169 panel->toshiba_callback->func(panel->toshiba_callback);
170 panel->toshiba_callback = 0;
171 }
172 wake_up(&toshiba_vsync_wait);
173 return IRQ_HANDLED;
174}
175
176static int setup_vsync(struct panel_info *panel,
177 int init)
178{
179 int ret;
180 int gpio = 97;
181 unsigned int irq;
182
183 if (!init) {
184 ret = 0;
185 goto uninit;
186 }
187 ret = gpio_request(gpio, "vsync");
188 if (ret)
189 goto err_request_gpio_failed;
190
191 ret = gpio_direction_input(gpio);
192 if (ret)
193 goto err_gpio_direction_input_failed;
194
195 ret = irq = gpio_to_irq(gpio);
196 if (ret < 0)
197 goto err_get_irq_num_failed;
198
199 ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
200 "vsync", panel);
201 if (ret)
202 goto err_request_irq_failed;
203 printk(KERN_INFO "vsync on gpio %d now %d\n",
204 gpio, gpio_get_value(gpio));
205 return 0;
206
207uninit:
208 free_irq(gpio_to_irq(gpio), panel);
209err_request_irq_failed:
210err_get_irq_num_failed:
211err_gpio_direction_input_failed:
212 gpio_free(gpio);
213err_request_gpio_failed:
214 return ret;
215}
216
217static int mddi_toshiba_probe(struct platform_device *pdev)
218{
219 int ret;
220 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
221 struct msm_mddi_bridge_platform_data *bridge_data =
222 client_data->private_client_data;
223 struct panel_info *panel =
224 kzalloc(sizeof(struct panel_info), GFP_KERNEL);
225 if (!panel)
226 return -ENOMEM;
227 platform_set_drvdata(pdev, panel);
228
229 /* mddi_remote_write(mddi, 0, WAKEUP); */
230 client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
231 client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
232
233 ret = setup_vsync(panel, 1);
234 if (ret) {
235 dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
236 return ret;
237 }
238
239 panel->client_data = client_data;
240 panel->panel_data.suspend = toshiba_suspend;
241 panel->panel_data.resume = toshiba_resume;
242 panel->panel_data.wait_vsync = toshiba_wait_vsync;
243 panel->panel_data.request_vsync = toshiba_request_vsync;
244 panel->panel_data.clear_vsync = toshiba_clear_vsync;
245 panel->panel_data.blank = toshiba_blank;
246 panel->panel_data.unblank = toshiba_unblank;
247 panel->panel_data.fb_data = &bridge_data->fb_data;
248 panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
249
250 panel->pdev.name = "msm_panel";
251 panel->pdev.id = pdev->id;
252 panel->pdev.resource = client_data->fb_resource;
253 panel->pdev.num_resources = 1;
254 panel->pdev.dev.platform_data = &panel->panel_data;
255 bridge_data->init(bridge_data, client_data);
256 platform_device_register(&panel->pdev);
257
258 return 0;
259}
260
261static int mddi_toshiba_remove(struct platform_device *pdev)
262{
263 struct panel_info *panel = platform_get_drvdata(pdev);
264
265 setup_vsync(panel, 0);
266 kfree(panel);
267 return 0;
268}
269
270static struct platform_driver mddi_client_d263_0000 = {
271 .probe = mddi_toshiba_probe,
272 .remove = mddi_toshiba_remove,
273 .driver = { .name = "mddi_c_d263_0000" },
274};
275
276static int __init mddi_client_toshiba_init(void)
277{
278 platform_driver_register(&mddi_client_d263_0000);
279 return 0;
280}
281
282module_init(mddi_client_toshiba_init);
283
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h
new file mode 100644
index 000000000000..45cc01fc1e7f
--- /dev/null
+++ b/drivers/video/msm/mddi_hw.h
@@ -0,0 +1,305 @@
1/* drivers/video/msm_fb/mddi_hw.h
2 *
3 * MSM MDDI Hardware Registers and Structures
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#ifndef _MDDI_HW_H_
19#define _MDDI_HW_H_
20
21#include <linux/types.h>
22
23#define MDDI_CMD 0x0000
24#define MDDI_VERSION 0x0004
25#define MDDI_PRI_PTR 0x0008
26#define MDDI_SEC_PTR 0x000c
27#define MDDI_BPS 0x0010
28#define MDDI_SPM 0x0014
29#define MDDI_INT 0x0018
30#define MDDI_INTEN 0x001c
31#define MDDI_REV_PTR 0x0020
32#define MDDI_REV_SIZE 0x0024
33#define MDDI_STAT 0x0028
34#define MDDI_REV_RATE_DIV 0x002c
35#define MDDI_REV_CRC_ERR 0x0030
36#define MDDI_TA1_LEN 0x0034
37#define MDDI_TA2_LEN 0x0038
38#define MDDI_TEST_BUS 0x003c
39#define MDDI_TEST 0x0040
40#define MDDI_REV_PKT_CNT 0x0044
41#define MDDI_DRIVE_HI 0x0048
42#define MDDI_DRIVE_LO 0x004c
43#define MDDI_DISP_WAKE 0x0050
44#define MDDI_REV_ENCAP_SZ 0x0054
45#define MDDI_RTD_VAL 0x0058
46#define MDDI_PAD_CTL 0x0068
47#define MDDI_DRIVER_START_CNT 0x006c
48#define MDDI_NEXT_PRI_PTR 0x0070
49#define MDDI_NEXT_SEC_PTR 0x0074
50#define MDDI_MISR_CTL 0x0078
51#define MDDI_MISR_DATA 0x007c
52#define MDDI_SF_CNT 0x0080
53#define MDDI_MF_CNT 0x0084
54#define MDDI_CURR_REV_PTR 0x0088
55#define MDDI_CORE_VER 0x008c
56
57#define MDDI_INT_PRI_PTR_READ 0x0001
58#define MDDI_INT_SEC_PTR_READ 0x0002
59#define MDDI_INT_REV_DATA_AVAIL 0x0004
60#define MDDI_INT_DISP_REQ 0x0008
61#define MDDI_INT_PRI_UNDERFLOW 0x0010
62#define MDDI_INT_SEC_UNDERFLOW 0x0020
63#define MDDI_INT_REV_OVERFLOW 0x0040
64#define MDDI_INT_CRC_ERROR 0x0080
65#define MDDI_INT_MDDI_IN 0x0100
66#define MDDI_INT_PRI_OVERWRITE 0x0200
67#define MDDI_INT_SEC_OVERWRITE 0x0400
68#define MDDI_INT_REV_OVERWRITE 0x0800
69#define MDDI_INT_DMA_FAILURE 0x1000
70#define MDDI_INT_LINK_ACTIVE 0x2000
71#define MDDI_INT_IN_HIBERNATION 0x4000
72#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
73#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
74#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
75#define MDDI_INT_RTD_FAILURE 0x40000
76#define MDDI_INT_REV_PKT_RECEIVED 0x80000
77#define MDDI_INT_REV_PKTS_AVAIL 0x100000
78
79#define MDDI_INT_NEED_CLEAR ( \
80 MDDI_INT_REV_DATA_AVAIL | \
81 MDDI_INT_PRI_UNDERFLOW | \
82 MDDI_INT_SEC_UNDERFLOW | \
83 MDDI_INT_REV_OVERFLOW | \
84 MDDI_INT_CRC_ERROR | \
85 MDDI_INT_REV_PKT_RECEIVED)
86
87
88#define MDDI_STAT_LINK_ACTIVE 0x0001
89#define MDDI_STAT_NEW_REV_PTR 0x0002
90#define MDDI_STAT_NEW_PRI_PTR 0x0004
91#define MDDI_STAT_NEW_SEC_PTR 0x0008
92#define MDDI_STAT_IN_HIBERNATION 0x0010
93#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
94#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
95#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
96#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
97#define MDDI_STAT_PENDING_POWERDOWN 0x0200
98#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
99#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
100
101
102#define MDDI_CMD_POWERDOWN 0x0100
103#define MDDI_CMD_POWERUP 0x0200
104#define MDDI_CMD_HIBERNATE 0x0300
105#define MDDI_CMD_RESET 0x0400
106#define MDDI_CMD_DISP_IGNORE 0x0501
107#define MDDI_CMD_DISP_LISTEN 0x0500
108#define MDDI_CMD_SEND_REV_ENCAP 0x0600
109#define MDDI_CMD_GET_CLIENT_CAP 0x0601
110#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
111#define MDDI_CMD_SEND_RTD 0x0700
112#define MDDI_CMD_LINK_ACTIVE 0x0900
113#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
114#define MDDI_CMD_FORCE_NEW_REV_PTR 0x0C00
115
116
117
118#define MDDI_VIDEO_REV_PKT_SIZE 0x40
119#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
120#define MDDI_MAX_REV_PKT_SIZE 0x60
121
122/* #define MDDI_REV_BUFFER_SIZE 128 */
123#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4)
124
125/* MDP sends 256 pixel packets, so lower value hibernates more without
126 * significantly increasing latency of waiting for next subframe */
127#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
128#define MDDI_HOST_TA2_LEN 0x000c
129#define MDDI_HOST_REV_RATE_DIV 0x0002
130
131
132struct __attribute__((packed)) mddi_rev_packet {
133 uint16_t length;
134 uint16_t type;
135 uint16_t client_id;
136};
137
138struct __attribute__((packed)) mddi_client_status {
139 uint16_t length;
140 uint16_t type;
141 uint16_t client_id;
142 uint16_t reverse_link_request; /* bytes needed in rev encap message */
143 uint8_t crc_error_count;
144 uint8_t capability_change;
145 uint16_t graphics_busy_flags;
146 uint16_t crc16;
147};
148
149struct __attribute__((packed)) mddi_client_caps {
150 uint16_t length; /* length, exclusive of this field */
151 uint16_t type; /* 66 */
152 uint16_t client_id;
153
154 uint16_t Protocol_Version;
155 uint16_t Minimum_Protocol_Version;
156 uint16_t Data_Rate_Capability;
157 uint8_t Interface_Type_Capability;
158 uint8_t Number_of_Alt_Displays;
159 uint16_t PostCal_Data_Rate;
160 uint16_t Bitmap_Width;
161 uint16_t Bitmap_Height;
162 uint16_t Display_Window_Width;
163 uint16_t Display_Window_Height;
164 uint32_t Color_Map_Size;
165 uint16_t Color_Map_RGB_Width;
166 uint16_t RGB_Capability;
167 uint8_t Monochrome_Capability;
168 uint8_t Reserved_1;
169 uint16_t Y_Cb_Cr_Capability;
170 uint16_t Bayer_Capability;
171 uint16_t Alpha_Cursor_Image_Planes;
172 uint32_t Client_Feature_Capability_Indicators;
173 uint8_t Maximum_Video_Frame_Rate_Capability;
174 uint8_t Minimum_Video_Frame_Rate_Capability;
175 uint16_t Minimum_Sub_frame_Rate;
176 uint16_t Audio_Buffer_Depth;
177 uint16_t Audio_Channel_Capability;
178 uint16_t Audio_Sample_Rate_Capability;
179 uint8_t Audio_Sample_Resolution;
180 uint8_t Mic_Audio_Sample_Resolution;
181 uint16_t Mic_Sample_Rate_Capability;
182 uint8_t Keyboard_Data_Format;
183 uint8_t pointing_device_data_format;
184 uint16_t content_protection_type;
185 uint16_t Mfr_Name;
186 uint16_t Product_Code;
187 uint16_t Reserved_3;
188 uint32_t Serial_Number;
189 uint8_t Week_of_Manufacture;
190 uint8_t Year_of_Manufacture;
191
192 uint16_t crc16;
193} mddi_client_capability_type;
194
195
196struct __attribute__((packed)) mddi_video_stream {
197 uint16_t length;
198 uint16_t type; /* 16 */
199 uint16_t client_id; /* 0 */
200
201 uint16_t video_data_format_descriptor;
202/* format of each pixel in the Pixel Data in the present stream in the
203 * present packet.
204 * If bits [15:13] = 000 monochrome
205 * If bits [15:13] = 001 color pixels (palette).
206 * If bits [15:13] = 010 color pixels in raw RGB
207 * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
208 * If bits [15:13] = 100 Bayer pixels
209 */
210
211 uint16_t pixel_data_attributes;
212/* interpreted as follows:
213 * Bits [1:0] = 11 pixel data is displayed to both eyes
214 * Bits [1:0] = 10 pixel data is routed to the left eye only.
215 * Bits [1:0] = 01 pixel data is routed to the right eye only.
216 * Bits [1:0] = 00 pixel data is routed to the alternate display.
217 * Bit 2 is 0 Pixel Data is in the standard progressive format.
218 * Bit 2 is 1 Pixel Data is in interlace format.
219 * Bit 3 is 0 Pixel Data is in the standard progressive format.
220 * Bit 3 is 1 Pixel Data is in alternate pixel format.
221 * Bit 4 is 0 Pixel Data is to or from the display frame buffer.
222 * Bit 4 is 1 Pixel Data is to or from the camera.
223 * Bit 5 is 0 pixel data contains the next consecutive row of pixels.
224 * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
225 * X Start, and Y Start parameters are not defined and
226 * shall be ignored by the client.
227 * Bits [7:6] = 01 Pixel data is written to the offline image buffer.
228 * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
229 * Bits [7:6] = 11 Pixel data is written to all image buffers.
230 * Bits [7:6] = 10 Invalid. Reserved for future use.
231 * Bits 8 through 11 alternate display number.
232 * Bits 12 through 14 are reserved for future use and shall be set to zero.
233 * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
234 */
235
236 uint16_t x_left_edge;
237 uint16_t y_top_edge;
238 /* X,Y coordinate of the top left edge of the screen window */
239
240 uint16_t x_right_edge;
241 uint16_t y_bottom_edge;
242 /* X,Y coordinate of the bottom right edge of the window being
243 * updated. */
244
245 uint16_t x_start;
246 uint16_t y_start;
247 /* (X Start, Y Start) is the first pixel in the Pixel Data field
248 * below. */
249
250 uint16_t pixel_count;
251 /* number of pixels in the Pixel Data field below. */
252
253 uint16_t parameter_CRC;
254 /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
255
256 uint16_t reserved;
257 /* 16-bit variable to make structure align on 4 byte boundary */
258};
259
260#define TYPE_VIDEO_STREAM 16
261#define TYPE_CLIENT_CAPS 66
262#define TYPE_REGISTER_ACCESS 146
263#define TYPE_CLIENT_STATUS 70
264
265struct __attribute__((packed)) mddi_register_access {
266 uint16_t length;
267 uint16_t type; /* 146 */
268 uint16_t client_id;
269
270 uint16_t read_write_info;
271 /* Bits 13:0 a 14-bit unsigned integer that specifies the number of
272 * 32-bit Register Data List items to be transferred in the
273 * Register Data List field.
274 * Bits[15:14] = 00 Write to register(s);
275 * Bits[15:14] = 10 Read from register(s);
276 * Bits[15:14] = 11 Response to a Read.
277 * Bits[15:14] = 01 this value is reserved for future use. */
278#define MDDI_WRITE (0 << 14)
279#define MDDI_READ (2 << 14)
280#define MDDI_READ_RESP (3 << 14)
281
282 uint32_t register_address;
283 /* the register address that is to be written to or read from. */
284
285 uint16_t crc16;
286
287 uint32_t register_data_list;
288 /* list of 4-byte register data values for/from client registers */
289};
290
291struct __attribute__((packed)) mddi_llentry {
292 uint16_t flags;
293 uint16_t header_count;
294 uint16_t data_count;
295 dma_addr_t data; /* 32 bit */
296 struct mddi_llentry *next;
297 uint16_t reserved;
298 union {
299 struct mddi_video_stream v;
300 struct mddi_register_access r;
301 uint32_t _[12];
302 } u;
303};
304
305#endif
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
new file mode 100644
index 000000000000..99636a2b20f2
--- /dev/null
+++ b/drivers/video/msm/mdp.c
@@ -0,0 +1,538 @@
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#ifdef CONFIG_ANDROID_PMEM
26#include <linux/android_pmem.h>
27#endif
28#include <linux/major.h>
29
30#include <mach/msm_iomap.h>
31#include <mach/msm_fb.h>
32#include <linux/platform_device.h>
33
34#include "mdp_hw.h"
35
36struct class *mdp_class;
37
38#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
39
40static uint16_t mdp_default_ccs[] = {
41 0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
42 0x010, 0x080, 0x080
43};
44
45static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
46static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
47static struct msmfb_callback *dma_callback;
48static struct clk *clk;
49static unsigned int mdp_irq_mask;
50static DEFINE_SPINLOCK(mdp_lock);
51DEFINE_MUTEX(mdp_mutex);
52
53static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
54{
55 unsigned long irq_flags;
56 int ret = 0;
57
58 BUG_ON(!mask);
59
60 spin_lock_irqsave(&mdp_lock, irq_flags);
61 /* if the mask bits are already set return an error, this interrupt
62 * is already enabled */
63 if (mdp_irq_mask & mask) {
64 printk(KERN_ERR "mdp irq already on already on %x %x\n",
65 mdp_irq_mask, mask);
66 ret = -1;
67 }
68 /* if the mdp irq is not already enabled enable it */
69 if (!mdp_irq_mask) {
70 if (clk)
71 clk_enable(clk);
72 enable_irq(mdp->irq);
73 }
74
75 /* update the irq mask to reflect the fact that the interrupt is
76 * enabled */
77 mdp_irq_mask |= mask;
78 spin_unlock_irqrestore(&mdp_lock, irq_flags);
79 return ret;
80}
81
82static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
83{
84 /* this interrupt is already disabled! */
85 if (!(mdp_irq_mask & mask)) {
86 printk(KERN_ERR "mdp irq already off %x %x\n",
87 mdp_irq_mask, mask);
88 return -1;
89 }
90 /* update the irq mask to reflect the fact that the interrupt is
91 * disabled */
92 mdp_irq_mask &= ~(mask);
93 /* if no one is waiting on the interrupt, disable it */
94 if (!mdp_irq_mask) {
95 disable_irq(mdp->irq);
96 if (clk)
97 clk_disable(clk);
98 }
99 return 0;
100}
101
102static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
103{
104 unsigned long irq_flags;
105 int ret;
106
107 spin_lock_irqsave(&mdp_lock, irq_flags);
108 ret = locked_disable_mdp_irq(mdp, mask);
109 spin_unlock_irqrestore(&mdp_lock, irq_flags);
110 return ret;
111}
112
113static irqreturn_t mdp_isr(int irq, void *data)
114{
115 uint32_t status;
116 unsigned long irq_flags;
117 struct mdp_info *mdp = data;
118
119 spin_lock_irqsave(&mdp_lock, irq_flags);
120
121 status = mdp_readl(mdp, MDP_INTR_STATUS);
122 mdp_writel(mdp, status, MDP_INTR_CLEAR);
123
124 status &= mdp_irq_mask;
125 if (status & DL0_DMA2_TERM_DONE) {
126 if (dma_callback) {
127 dma_callback->func(dma_callback);
128 dma_callback = NULL;
129 }
130 wake_up(&mdp_dma2_waitqueue);
131 }
132
133 if (status & DL0_ROI_DONE)
134 wake_up(&mdp_ppp_waitqueue);
135
136 if (status)
137 locked_disable_mdp_irq(mdp, status);
138
139 spin_unlock_irqrestore(&mdp_lock, irq_flags);
140 return IRQ_HANDLED;
141}
142
143static uint32_t mdp_check_mask(uint32_t mask)
144{
145 uint32_t ret;
146 unsigned long irq_flags;
147
148 spin_lock_irqsave(&mdp_lock, irq_flags);
149 ret = mdp_irq_mask & mask;
150 spin_unlock_irqrestore(&mdp_lock, irq_flags);
151 return ret;
152}
153
154static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
155{
156 int ret = 0;
157 unsigned long irq_flags;
158
159 wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
160
161 spin_lock_irqsave(&mdp_lock, irq_flags);
162 if (mdp_irq_mask & mask) {
163 locked_disable_mdp_irq(mdp, mask);
164 printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
165 mask);
166 ret = -ETIMEDOUT;
167 }
168 spin_unlock_irqrestore(&mdp_lock, irq_flags);
169
170 return ret;
171}
172
173void mdp_dma_wait(struct mdp_device *mdp_dev)
174{
175#define MDP_MAX_TIMEOUTS 20
176 static int timeout_count;
177 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
178
179 if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
180 timeout_count++;
181 else
182 timeout_count = 0;
183
184 if (timeout_count > MDP_MAX_TIMEOUTS) {
185 printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
186 MDP_MAX_TIMEOUTS);
187 BUG();
188 }
189}
190
191static int mdp_ppp_wait(struct mdp_info *mdp)
192{
193 return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
194}
195
196void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
197 uint32_t width, uint32_t height, uint32_t x, uint32_t y,
198 struct msmfb_callback *callback)
199{
200 uint32_t dma2_cfg;
201 uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
202
203 if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
204 printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
205 return;
206 }
207
208 dma_callback = callback;
209
210 dma2_cfg = DMA_PACK_TIGHT |
211 DMA_PACK_ALIGN_LSB |
212 DMA_PACK_PATTERN_RGB |
213 DMA_OUT_SEL_AHB |
214 DMA_IBUF_NONCONTIGUOUS;
215
216 dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
217
218 dma2_cfg |= DMA_OUT_SEL_MDDI;
219
220 dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
221
222 dma2_cfg |= DMA_DITHER_EN;
223
224 /* setup size, address, and stride */
225 mdp_writel(mdp, (height << 16) | (width),
226 MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
227 mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
228 mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
229
230 /* 666 18BPP */
231 dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
232
233 /* set y & x offset and MDDI transaction parameters */
234 mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
235 mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
236 mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
237 MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
238
239 mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
240
241 /* start DMA2 */
242 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
243}
244
245void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
246 uint32_t width, uint32_t height, uint32_t x, uint32_t y,
247 struct msmfb_callback *callback, int interface)
248{
249 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
250
251 if (interface == MSM_MDDI_PMDH_INTERFACE) {
252 mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
253 callback);
254 }
255}
256
257int get_img(struct mdp_img *img, struct fb_info *info,
258 unsigned long *start, unsigned long *len,
259 struct file **filep)
260{
261 int put_needed, ret = 0;
262 struct file *file;
263 unsigned long vstart;
264
265#ifdef CONFIG_ANDROID_PMEM
266 if (!get_pmem_file(img->memory_id, start, &vstart, len, filep))
267 return 0;
268#endif
269
270 file = fget_light(img->memory_id, &put_needed);
271 if (file == NULL)
272 return -1;
273
274 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
275 *start = info->fix.smem_start;
276 *len = info->fix.smem_len;
277 } else
278 ret = -1;
279 fput_light(file, put_needed);
280
281 return ret;
282}
283
284void put_img(struct file *src_file, struct file *dst_file)
285{
286#ifdef CONFIG_ANDROID_PMEM
287 if (src_file)
288 put_pmem_file(src_file);
289 if (dst_file)
290 put_pmem_file(dst_file);
291#endif
292}
293
294int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
295 struct mdp_blit_req *req)
296{
297 int ret;
298 unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
299 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
300 struct file *src_file = 0, *dst_file = 0;
301
302 /* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
303 if (unlikely(req->src_rect.h == 0 ||
304 req->src_rect.w == 0)) {
305 printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
306 return -EINVAL;
307 }
308 if (unlikely(req->dst_rect.h == 0 ||
309 req->dst_rect.w == 0))
310 return -EINVAL;
311
312 /* do this first so that if this fails, the caller can always
313 * safely call put_img */
314 if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
315 printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
316 "memory\n");
317 return -EINVAL;
318 }
319
320 if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
321 printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
322 "memory\n");
323#ifdef CONFIG_ANDROID_PMEM
324 put_pmem_file(src_file);
325#endif
326 return -EINVAL;
327 }
328 mutex_lock(&mdp_mutex);
329
330 /* transp_masking unimplemented */
331 req->transp_mask = MDP_TRANSP_NOP;
332 if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
333 req->alpha != MDP_ALPHA_NOP ||
334 HAS_ALPHA(req->src.format)) &&
335 (req->flags & MDP_ROT_90 &&
336 req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
337 int i;
338 unsigned int tiles = req->dst_rect.h / 16;
339 unsigned int remainder = req->dst_rect.h % 16;
340 req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
341 req->dst_rect.h = 16;
342 for (i = 0; i < tiles; i++) {
343 enable_mdp_irq(mdp, DL0_ROI_DONE);
344 ret = mdp_ppp_blit(mdp, req, src_file, src_start,
345 src_len, dst_file, dst_start,
346 dst_len);
347 if (ret)
348 goto err_bad_blit;
349 ret = mdp_ppp_wait(mdp);
350 if (ret)
351 goto err_wait_failed;
352 req->dst_rect.y += 16;
353 req->src_rect.x += req->src_rect.w;
354 }
355 if (!remainder)
356 goto end;
357 req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
358 req->dst_rect.h = remainder;
359 }
360 enable_mdp_irq(mdp, DL0_ROI_DONE);
361 ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
362 dst_start,
363 dst_len);
364 if (ret)
365 goto err_bad_blit;
366 ret = mdp_ppp_wait(mdp);
367 if (ret)
368 goto err_wait_failed;
369end:
370 put_img(src_file, dst_file);
371 mutex_unlock(&mdp_mutex);
372 return 0;
373err_bad_blit:
374 disable_mdp_irq(mdp, DL0_ROI_DONE);
375err_wait_failed:
376 put_img(src_file, dst_file);
377 mutex_unlock(&mdp_mutex);
378 return ret;
379}
380
381void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
382{
383 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
384
385 disp_id &= 0xf;
386 mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
387}
388
389int register_mdp_client(struct class_interface *cint)
390{
391 if (!mdp_class) {
392 pr_err("mdp: no mdp_class when registering mdp client\n");
393 return -ENODEV;
394 }
395 cint->class = mdp_class;
396 return class_interface_register(cint);
397}
398
399#include "mdp_csc_table.h"
400#include "mdp_scale_tables.h"
401
402int mdp_probe(struct platform_device *pdev)
403{
404 struct resource *resource;
405 int ret;
406 int n;
407 struct mdp_info *mdp;
408
409 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
410 if (!resource) {
411 pr_err("mdp: can not get mdp mem resource!\n");
412 return -ENOMEM;
413 }
414
415 mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
416 if (!mdp)
417 return -ENOMEM;
418
419 mdp->irq = platform_get_irq(pdev, 0);
420 if (mdp->irq < 0) {
421 pr_err("mdp: can not get mdp irq\n");
422 ret = mdp->irq;
423 goto error_get_irq;
424 }
425
426 mdp->base = ioremap(resource->start,
427 resource->end - resource->start);
428 if (mdp->base == 0) {
429 printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
430 ret = -ENOMEM;
431 goto error_ioremap;
432 }
433
434 mdp->mdp_dev.dma = mdp_dma;
435 mdp->mdp_dev.dma_wait = mdp_dma_wait;
436 mdp->mdp_dev.blit = mdp_blit;
437 mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
438
439 clk = clk_get(&pdev->dev, "mdp_clk");
440 if (IS_ERR(clk)) {
441 printk(KERN_INFO "mdp: failed to get mdp clk");
442 return PTR_ERR(clk);
443 }
444
445 ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
446 if (ret)
447 goto error_request_irq;
448 disable_irq(mdp->irq);
449 mdp_irq_mask = 0;
450
451 /* debug interface write access */
452 mdp_writel(mdp, 1, 0x60);
453
454 mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
455 mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
456
457 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
458 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
459
460 for (n = 0; n < ARRAY_SIZE(csc_table); n++)
461 mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
462
463 /* clear up unused fg/main registers */
464 /* comp.plane 2&3 ystride */
465 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
466
467 /* unpacked pattern */
468 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
469 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
470 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
471 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
472 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
473 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
474 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
475 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
476 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
477
478 /* comp.plane 2 & 3 */
479 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
480 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
481
482 /* clear unused bg registers */
483 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
484 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
485 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
486 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
487 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
488
489 for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
490 mdp_writel(mdp, mdp_upscale_table[n].val,
491 mdp_upscale_table[n].reg);
492
493 for (n = 0; n < 9; n++)
494 mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
495 mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
496 mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
497 mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
498
499 /* register mdp device */
500 mdp->mdp_dev.dev.parent = &pdev->dev;
501 mdp->mdp_dev.dev.class = mdp_class;
502 snprintf(mdp->mdp_dev.dev.bus_id, BUS_ID_SIZE, "mdp%d", pdev->id);
503
504 /* if you can remove the platform device you'd have to implement
505 * this:
506 mdp_dev.release = mdp_class; */
507
508 ret = device_register(&mdp->mdp_dev.dev);
509 if (ret)
510 goto error_device_register;
511 return 0;
512
513error_device_register:
514 free_irq(mdp->irq, mdp);
515error_request_irq:
516 iounmap(mdp->base);
517error_get_irq:
518error_ioremap:
519 kfree(mdp);
520 return ret;
521}
522
523static struct platform_driver msm_mdp_driver = {
524 .probe = mdp_probe,
525 .driver = {.name = "msm_mdp"},
526};
527
528static int __init mdp_init(void)
529{
530 mdp_class = class_create(THIS_MODULE, "msm_mdp");
531 if (IS_ERR(mdp_class)) {
532 printk(KERN_ERR "Error creating mdp class\n");
533 return PTR_ERR(mdp_class);
534 }
535 return platform_driver_register(&msm_mdp_driver);
536}
537
538subsys_initcall(mdp_init);
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
new file mode 100644
index 000000000000..d1cde30ead52
--- /dev/null
+++ b/drivers/video/msm/mdp_csc_table.h
@@ -0,0 +1,582 @@
1/* drivers/video/msm_fb/mdp_csc_table.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16static struct {
17 uint32_t reg;
18 uint32_t val;
19} csc_table[] = {
20 { 0x40400, 0x83 },
21 { 0x40404, 0x102 },
22 { 0x40408, 0x32 },
23 { 0x4040c, 0xffffffb5 },
24 { 0x40410, 0xffffff6c },
25 { 0x40414, 0xe1 },
26 { 0x40418, 0xe1 },
27 { 0x4041c, 0xffffff45 },
28 { 0x40420, 0xffffffdc },
29 { 0x40440, 0x254 },
30 { 0x40444, 0x0 },
31 { 0x40448, 0x331 },
32 { 0x4044c, 0x254 },
33 { 0x40450, 0xffffff38 },
34 { 0x40454, 0xfffffe61 },
35 { 0x40458, 0x254 },
36 { 0x4045c, 0x409 },
37 { 0x40460, 0x0 },
38 { 0x40480, 0x5d },
39 { 0x40484, 0x13a },
40 { 0x40488, 0x20 },
41 { 0x4048c, 0xffffffcd },
42 { 0x40490, 0xffffff54 },
43 { 0x40494, 0xe1 },
44 { 0x40498, 0xe1 },
45 { 0x4049c, 0xffffff35 },
46 { 0x404a0, 0xffffffec },
47 { 0x404c0, 0x254 },
48 { 0x404c4, 0x0 },
49 { 0x404c8, 0x396 },
50 { 0x404cc, 0x254 },
51 { 0x404d0, 0xffffff94 },
52 { 0x404d4, 0xfffffef0 },
53 { 0x404d8, 0x254 },
54 { 0x404dc, 0x43a },
55 { 0x404e0, 0x0 },
56 { 0x40500, 0x10 },
57 { 0x40504, 0x80 },
58 { 0x40508, 0x80 },
59 { 0x40540, 0x10 },
60 { 0x40544, 0x80 },
61 { 0x40548, 0x80 },
62 { 0x40580, 0x10 },
63 { 0x40584, 0xeb },
64 { 0x40588, 0x10 },
65 { 0x4058c, 0xf0 },
66 { 0x405c0, 0x10 },
67 { 0x405c4, 0xeb },
68 { 0x405c8, 0x10 },
69 { 0x405cc, 0xf0 },
70 { 0x40800, 0x0 },
71 { 0x40804, 0x151515 },
72 { 0x40808, 0x1d1d1d },
73 { 0x4080c, 0x232323 },
74 { 0x40810, 0x272727 },
75 { 0x40814, 0x2b2b2b },
76 { 0x40818, 0x2f2f2f },
77 { 0x4081c, 0x333333 },
78 { 0x40820, 0x363636 },
79 { 0x40824, 0x393939 },
80 { 0x40828, 0x3b3b3b },
81 { 0x4082c, 0x3e3e3e },
82 { 0x40830, 0x404040 },
83 { 0x40834, 0x434343 },
84 { 0x40838, 0x454545 },
85 { 0x4083c, 0x474747 },
86 { 0x40840, 0x494949 },
87 { 0x40844, 0x4b4b4b },
88 { 0x40848, 0x4d4d4d },
89 { 0x4084c, 0x4f4f4f },
90 { 0x40850, 0x515151 },
91 { 0x40854, 0x535353 },
92 { 0x40858, 0x555555 },
93 { 0x4085c, 0x565656 },
94 { 0x40860, 0x585858 },
95 { 0x40864, 0x5a5a5a },
96 { 0x40868, 0x5b5b5b },
97 { 0x4086c, 0x5d5d5d },
98 { 0x40870, 0x5e5e5e },
99 { 0x40874, 0x606060 },
100 { 0x40878, 0x616161 },
101 { 0x4087c, 0x636363 },
102 { 0x40880, 0x646464 },
103 { 0x40884, 0x666666 },
104 { 0x40888, 0x676767 },
105 { 0x4088c, 0x686868 },
106 { 0x40890, 0x6a6a6a },
107 { 0x40894, 0x6b6b6b },
108 { 0x40898, 0x6c6c6c },
109 { 0x4089c, 0x6e6e6e },
110 { 0x408a0, 0x6f6f6f },
111 { 0x408a4, 0x707070 },
112 { 0x408a8, 0x717171 },
113 { 0x408ac, 0x727272 },
114 { 0x408b0, 0x747474 },
115 { 0x408b4, 0x757575 },
116 { 0x408b8, 0x767676 },
117 { 0x408bc, 0x777777 },
118 { 0x408c0, 0x787878 },
119 { 0x408c4, 0x797979 },
120 { 0x408c8, 0x7a7a7a },
121 { 0x408cc, 0x7c7c7c },
122 { 0x408d0, 0x7d7d7d },
123 { 0x408d4, 0x7e7e7e },
124 { 0x408d8, 0x7f7f7f },
125 { 0x408dc, 0x808080 },
126 { 0x408e0, 0x818181 },
127 { 0x408e4, 0x828282 },
128 { 0x408e8, 0x838383 },
129 { 0x408ec, 0x848484 },
130 { 0x408f0, 0x858585 },
131 { 0x408f4, 0x868686 },
132 { 0x408f8, 0x878787 },
133 { 0x408fc, 0x888888 },
134 { 0x40900, 0x898989 },
135 { 0x40904, 0x8a8a8a },
136 { 0x40908, 0x8b8b8b },
137 { 0x4090c, 0x8c8c8c },
138 { 0x40910, 0x8d8d8d },
139 { 0x40914, 0x8e8e8e },
140 { 0x40918, 0x8f8f8f },
141 { 0x4091c, 0x8f8f8f },
142 { 0x40920, 0x909090 },
143 { 0x40924, 0x919191 },
144 { 0x40928, 0x929292 },
145 { 0x4092c, 0x939393 },
146 { 0x40930, 0x949494 },
147 { 0x40934, 0x959595 },
148 { 0x40938, 0x969696 },
149 { 0x4093c, 0x969696 },
150 { 0x40940, 0x979797 },
151 { 0x40944, 0x989898 },
152 { 0x40948, 0x999999 },
153 { 0x4094c, 0x9a9a9a },
154 { 0x40950, 0x9b9b9b },
155 { 0x40954, 0x9c9c9c },
156 { 0x40958, 0x9c9c9c },
157 { 0x4095c, 0x9d9d9d },
158 { 0x40960, 0x9e9e9e },
159 { 0x40964, 0x9f9f9f },
160 { 0x40968, 0xa0a0a0 },
161 { 0x4096c, 0xa0a0a0 },
162 { 0x40970, 0xa1a1a1 },
163 { 0x40974, 0xa2a2a2 },
164 { 0x40978, 0xa3a3a3 },
165 { 0x4097c, 0xa4a4a4 },
166 { 0x40980, 0xa4a4a4 },
167 { 0x40984, 0xa5a5a5 },
168 { 0x40988, 0xa6a6a6 },
169 { 0x4098c, 0xa7a7a7 },
170 { 0x40990, 0xa7a7a7 },
171 { 0x40994, 0xa8a8a8 },
172 { 0x40998, 0xa9a9a9 },
173 { 0x4099c, 0xaaaaaa },
174 { 0x409a0, 0xaaaaaa },
175 { 0x409a4, 0xababab },
176 { 0x409a8, 0xacacac },
177 { 0x409ac, 0xadadad },
178 { 0x409b0, 0xadadad },
179 { 0x409b4, 0xaeaeae },
180 { 0x409b8, 0xafafaf },
181 { 0x409bc, 0xafafaf },
182 { 0x409c0, 0xb0b0b0 },
183 { 0x409c4, 0xb1b1b1 },
184 { 0x409c8, 0xb2b2b2 },
185 { 0x409cc, 0xb2b2b2 },
186 { 0x409d0, 0xb3b3b3 },
187 { 0x409d4, 0xb4b4b4 },
188 { 0x409d8, 0xb4b4b4 },
189 { 0x409dc, 0xb5b5b5 },
190 { 0x409e0, 0xb6b6b6 },
191 { 0x409e4, 0xb6b6b6 },
192 { 0x409e8, 0xb7b7b7 },
193 { 0x409ec, 0xb8b8b8 },
194 { 0x409f0, 0xb8b8b8 },
195 { 0x409f4, 0xb9b9b9 },
196 { 0x409f8, 0xbababa },
197 { 0x409fc, 0xbababa },
198 { 0x40a00, 0xbbbbbb },
199 { 0x40a04, 0xbcbcbc },
200 { 0x40a08, 0xbcbcbc },
201 { 0x40a0c, 0xbdbdbd },
202 { 0x40a10, 0xbebebe },
203 { 0x40a14, 0xbebebe },
204 { 0x40a18, 0xbfbfbf },
205 { 0x40a1c, 0xc0c0c0 },
206 { 0x40a20, 0xc0c0c0 },
207 { 0x40a24, 0xc1c1c1 },
208 { 0x40a28, 0xc1c1c1 },
209 { 0x40a2c, 0xc2c2c2 },
210 { 0x40a30, 0xc3c3c3 },
211 { 0x40a34, 0xc3c3c3 },
212 { 0x40a38, 0xc4c4c4 },
213 { 0x40a3c, 0xc5c5c5 },
214 { 0x40a40, 0xc5c5c5 },
215 { 0x40a44, 0xc6c6c6 },
216 { 0x40a48, 0xc6c6c6 },
217 { 0x40a4c, 0xc7c7c7 },
218 { 0x40a50, 0xc8c8c8 },
219 { 0x40a54, 0xc8c8c8 },
220 { 0x40a58, 0xc9c9c9 },
221 { 0x40a5c, 0xc9c9c9 },
222 { 0x40a60, 0xcacaca },
223 { 0x40a64, 0xcbcbcb },
224 { 0x40a68, 0xcbcbcb },
225 { 0x40a6c, 0xcccccc },
226 { 0x40a70, 0xcccccc },
227 { 0x40a74, 0xcdcdcd },
228 { 0x40a78, 0xcecece },
229 { 0x40a7c, 0xcecece },
230 { 0x40a80, 0xcfcfcf },
231 { 0x40a84, 0xcfcfcf },
232 { 0x40a88, 0xd0d0d0 },
233 { 0x40a8c, 0xd0d0d0 },
234 { 0x40a90, 0xd1d1d1 },
235 { 0x40a94, 0xd2d2d2 },
236 { 0x40a98, 0xd2d2d2 },
237 { 0x40a9c, 0xd3d3d3 },
238 { 0x40aa0, 0xd3d3d3 },
239 { 0x40aa4, 0xd4d4d4 },
240 { 0x40aa8, 0xd4d4d4 },
241 { 0x40aac, 0xd5d5d5 },
242 { 0x40ab0, 0xd6d6d6 },
243 { 0x40ab4, 0xd6d6d6 },
244 { 0x40ab8, 0xd7d7d7 },
245 { 0x40abc, 0xd7d7d7 },
246 { 0x40ac0, 0xd8d8d8 },
247 { 0x40ac4, 0xd8d8d8 },
248 { 0x40ac8, 0xd9d9d9 },
249 { 0x40acc, 0xd9d9d9 },
250 { 0x40ad0, 0xdadada },
251 { 0x40ad4, 0xdbdbdb },
252 { 0x40ad8, 0xdbdbdb },
253 { 0x40adc, 0xdcdcdc },
254 { 0x40ae0, 0xdcdcdc },
255 { 0x40ae4, 0xdddddd },
256 { 0x40ae8, 0xdddddd },
257 { 0x40aec, 0xdedede },
258 { 0x40af0, 0xdedede },
259 { 0x40af4, 0xdfdfdf },
260 { 0x40af8, 0xdfdfdf },
261 { 0x40afc, 0xe0e0e0 },
262 { 0x40b00, 0xe0e0e0 },
263 { 0x40b04, 0xe1e1e1 },
264 { 0x40b08, 0xe1e1e1 },
265 { 0x40b0c, 0xe2e2e2 },
266 { 0x40b10, 0xe3e3e3 },
267 { 0x40b14, 0xe3e3e3 },
268 { 0x40b18, 0xe4e4e4 },
269 { 0x40b1c, 0xe4e4e4 },
270 { 0x40b20, 0xe5e5e5 },
271 { 0x40b24, 0xe5e5e5 },
272 { 0x40b28, 0xe6e6e6 },
273 { 0x40b2c, 0xe6e6e6 },
274 { 0x40b30, 0xe7e7e7 },
275 { 0x40b34, 0xe7e7e7 },
276 { 0x40b38, 0xe8e8e8 },
277 { 0x40b3c, 0xe8e8e8 },
278 { 0x40b40, 0xe9e9e9 },
279 { 0x40b44, 0xe9e9e9 },
280 { 0x40b48, 0xeaeaea },
281 { 0x40b4c, 0xeaeaea },
282 { 0x40b50, 0xebebeb },
283 { 0x40b54, 0xebebeb },
284 { 0x40b58, 0xececec },
285 { 0x40b5c, 0xececec },
286 { 0x40b60, 0xededed },
287 { 0x40b64, 0xededed },
288 { 0x40b68, 0xeeeeee },
289 { 0x40b6c, 0xeeeeee },
290 { 0x40b70, 0xefefef },
291 { 0x40b74, 0xefefef },
292 { 0x40b78, 0xf0f0f0 },
293 { 0x40b7c, 0xf0f0f0 },
294 { 0x40b80, 0xf1f1f1 },
295 { 0x40b84, 0xf1f1f1 },
296 { 0x40b88, 0xf2f2f2 },
297 { 0x40b8c, 0xf2f2f2 },
298 { 0x40b90, 0xf2f2f2 },
299 { 0x40b94, 0xf3f3f3 },
300 { 0x40b98, 0xf3f3f3 },
301 { 0x40b9c, 0xf4f4f4 },
302 { 0x40ba0, 0xf4f4f4 },
303 { 0x40ba4, 0xf5f5f5 },
304 { 0x40ba8, 0xf5f5f5 },
305 { 0x40bac, 0xf6f6f6 },
306 { 0x40bb0, 0xf6f6f6 },
307 { 0x40bb4, 0xf7f7f7 },
308 { 0x40bb8, 0xf7f7f7 },
309 { 0x40bbc, 0xf8f8f8 },
310 { 0x40bc0, 0xf8f8f8 },
311 { 0x40bc4, 0xf9f9f9 },
312 { 0x40bc8, 0xf9f9f9 },
313 { 0x40bcc, 0xfafafa },
314 { 0x40bd0, 0xfafafa },
315 { 0x40bd4, 0xfafafa },
316 { 0x40bd8, 0xfbfbfb },
317 { 0x40bdc, 0xfbfbfb },
318 { 0x40be0, 0xfcfcfc },
319 { 0x40be4, 0xfcfcfc },
320 { 0x40be8, 0xfdfdfd },
321 { 0x40bec, 0xfdfdfd },
322 { 0x40bf0, 0xfefefe },
323 { 0x40bf4, 0xfefefe },
324 { 0x40bf8, 0xffffff },
325 { 0x40bfc, 0xffffff },
326 { 0x40c00, 0x0 },
327 { 0x40c04, 0x0 },
328 { 0x40c08, 0x0 },
329 { 0x40c0c, 0x0 },
330 { 0x40c10, 0x0 },
331 { 0x40c14, 0x0 },
332 { 0x40c18, 0x0 },
333 { 0x40c1c, 0x0 },
334 { 0x40c20, 0x0 },
335 { 0x40c24, 0x0 },
336 { 0x40c28, 0x0 },
337 { 0x40c2c, 0x0 },
338 { 0x40c30, 0x0 },
339 { 0x40c34, 0x0 },
340 { 0x40c38, 0x0 },
341 { 0x40c3c, 0x0 },
342 { 0x40c40, 0x10101 },
343 { 0x40c44, 0x10101 },
344 { 0x40c48, 0x10101 },
345 { 0x40c4c, 0x10101 },
346 { 0x40c50, 0x10101 },
347 { 0x40c54, 0x10101 },
348 { 0x40c58, 0x10101 },
349 { 0x40c5c, 0x10101 },
350 { 0x40c60, 0x10101 },
351 { 0x40c64, 0x10101 },
352 { 0x40c68, 0x20202 },
353 { 0x40c6c, 0x20202 },
354 { 0x40c70, 0x20202 },
355 { 0x40c74, 0x20202 },
356 { 0x40c78, 0x20202 },
357 { 0x40c7c, 0x20202 },
358 { 0x40c80, 0x30303 },
359 { 0x40c84, 0x30303 },
360 { 0x40c88, 0x30303 },
361 { 0x40c8c, 0x30303 },
362 { 0x40c90, 0x30303 },
363 { 0x40c94, 0x40404 },
364 { 0x40c98, 0x40404 },
365 { 0x40c9c, 0x40404 },
366 { 0x40ca0, 0x40404 },
367 { 0x40ca4, 0x40404 },
368 { 0x40ca8, 0x50505 },
369 { 0x40cac, 0x50505 },
370 { 0x40cb0, 0x50505 },
371 { 0x40cb4, 0x50505 },
372 { 0x40cb8, 0x60606 },
373 { 0x40cbc, 0x60606 },
374 { 0x40cc0, 0x60606 },
375 { 0x40cc4, 0x70707 },
376 { 0x40cc8, 0x70707 },
377 { 0x40ccc, 0x70707 },
378 { 0x40cd0, 0x70707 },
379 { 0x40cd4, 0x80808 },
380 { 0x40cd8, 0x80808 },
381 { 0x40cdc, 0x80808 },
382 { 0x40ce0, 0x90909 },
383 { 0x40ce4, 0x90909 },
384 { 0x40ce8, 0xa0a0a },
385 { 0x40cec, 0xa0a0a },
386 { 0x40cf0, 0xa0a0a },
387 { 0x40cf4, 0xb0b0b },
388 { 0x40cf8, 0xb0b0b },
389 { 0x40cfc, 0xb0b0b },
390 { 0x40d00, 0xc0c0c },
391 { 0x40d04, 0xc0c0c },
392 { 0x40d08, 0xd0d0d },
393 { 0x40d0c, 0xd0d0d },
394 { 0x40d10, 0xe0e0e },
395 { 0x40d14, 0xe0e0e },
396 { 0x40d18, 0xe0e0e },
397 { 0x40d1c, 0xf0f0f },
398 { 0x40d20, 0xf0f0f },
399 { 0x40d24, 0x101010 },
400 { 0x40d28, 0x101010 },
401 { 0x40d2c, 0x111111 },
402 { 0x40d30, 0x111111 },
403 { 0x40d34, 0x121212 },
404 { 0x40d38, 0x121212 },
405 { 0x40d3c, 0x131313 },
406 { 0x40d40, 0x131313 },
407 { 0x40d44, 0x141414 },
408 { 0x40d48, 0x151515 },
409 { 0x40d4c, 0x151515 },
410 { 0x40d50, 0x161616 },
411 { 0x40d54, 0x161616 },
412 { 0x40d58, 0x171717 },
413 { 0x40d5c, 0x171717 },
414 { 0x40d60, 0x181818 },
415 { 0x40d64, 0x191919 },
416 { 0x40d68, 0x191919 },
417 { 0x40d6c, 0x1a1a1a },
418 { 0x40d70, 0x1b1b1b },
419 { 0x40d74, 0x1b1b1b },
420 { 0x40d78, 0x1c1c1c },
421 { 0x40d7c, 0x1c1c1c },
422 { 0x40d80, 0x1d1d1d },
423 { 0x40d84, 0x1e1e1e },
424 { 0x40d88, 0x1f1f1f },
425 { 0x40d8c, 0x1f1f1f },
426 { 0x40d90, 0x202020 },
427 { 0x40d94, 0x212121 },
428 { 0x40d98, 0x212121 },
429 { 0x40d9c, 0x222222 },
430 { 0x40da0, 0x232323 },
431 { 0x40da4, 0x242424 },
432 { 0x40da8, 0x242424 },
433 { 0x40dac, 0x252525 },
434 { 0x40db0, 0x262626 },
435 { 0x40db4, 0x272727 },
436 { 0x40db8, 0x272727 },
437 { 0x40dbc, 0x282828 },
438 { 0x40dc0, 0x292929 },
439 { 0x40dc4, 0x2a2a2a },
440 { 0x40dc8, 0x2b2b2b },
441 { 0x40dcc, 0x2c2c2c },
442 { 0x40dd0, 0x2c2c2c },
443 { 0x40dd4, 0x2d2d2d },
444 { 0x40dd8, 0x2e2e2e },
445 { 0x40ddc, 0x2f2f2f },
446 { 0x40de0, 0x303030 },
447 { 0x40de4, 0x313131 },
448 { 0x40de8, 0x323232 },
449 { 0x40dec, 0x333333 },
450 { 0x40df0, 0x333333 },
451 { 0x40df4, 0x343434 },
452 { 0x40df8, 0x353535 },
453 { 0x40dfc, 0x363636 },
454 { 0x40e00, 0x373737 },
455 { 0x40e04, 0x383838 },
456 { 0x40e08, 0x393939 },
457 { 0x40e0c, 0x3a3a3a },
458 { 0x40e10, 0x3b3b3b },
459 { 0x40e14, 0x3c3c3c },
460 { 0x40e18, 0x3d3d3d },
461 { 0x40e1c, 0x3e3e3e },
462 { 0x40e20, 0x3f3f3f },
463 { 0x40e24, 0x404040 },
464 { 0x40e28, 0x414141 },
465 { 0x40e2c, 0x424242 },
466 { 0x40e30, 0x434343 },
467 { 0x40e34, 0x444444 },
468 { 0x40e38, 0x464646 },
469 { 0x40e3c, 0x474747 },
470 { 0x40e40, 0x484848 },
471 { 0x40e44, 0x494949 },
472 { 0x40e48, 0x4a4a4a },
473 { 0x40e4c, 0x4b4b4b },
474 { 0x40e50, 0x4c4c4c },
475 { 0x40e54, 0x4d4d4d },
476 { 0x40e58, 0x4f4f4f },
477 { 0x40e5c, 0x505050 },
478 { 0x40e60, 0x515151 },
479 { 0x40e64, 0x525252 },
480 { 0x40e68, 0x535353 },
481 { 0x40e6c, 0x545454 },
482 { 0x40e70, 0x565656 },
483 { 0x40e74, 0x575757 },
484 { 0x40e78, 0x585858 },
485 { 0x40e7c, 0x595959 },
486 { 0x40e80, 0x5b5b5b },
487 { 0x40e84, 0x5c5c5c },
488 { 0x40e88, 0x5d5d5d },
489 { 0x40e8c, 0x5e5e5e },
490 { 0x40e90, 0x606060 },
491 { 0x40e94, 0x616161 },
492 { 0x40e98, 0x626262 },
493 { 0x40e9c, 0x646464 },
494 { 0x40ea0, 0x656565 },
495 { 0x40ea4, 0x666666 },
496 { 0x40ea8, 0x686868 },
497 { 0x40eac, 0x696969 },
498 { 0x40eb0, 0x6a6a6a },
499 { 0x40eb4, 0x6c6c6c },
500 { 0x40eb8, 0x6d6d6d },
501 { 0x40ebc, 0x6f6f6f },
502 { 0x40ec0, 0x707070 },
503 { 0x40ec4, 0x717171 },
504 { 0x40ec8, 0x737373 },
505 { 0x40ecc, 0x747474 },
506 { 0x40ed0, 0x767676 },
507 { 0x40ed4, 0x777777 },
508 { 0x40ed8, 0x797979 },
509 { 0x40edc, 0x7a7a7a },
510 { 0x40ee0, 0x7c7c7c },
511 { 0x40ee4, 0x7d7d7d },
512 { 0x40ee8, 0x7f7f7f },
513 { 0x40eec, 0x808080 },
514 { 0x40ef0, 0x828282 },
515 { 0x40ef4, 0x838383 },
516 { 0x40ef8, 0x858585 },
517 { 0x40efc, 0x868686 },
518 { 0x40f00, 0x888888 },
519 { 0x40f04, 0x898989 },
520 { 0x40f08, 0x8b8b8b },
521 { 0x40f0c, 0x8d8d8d },
522 { 0x40f10, 0x8e8e8e },
523 { 0x40f14, 0x909090 },
524 { 0x40f18, 0x919191 },
525 { 0x40f1c, 0x939393 },
526 { 0x40f20, 0x959595 },
527 { 0x40f24, 0x969696 },
528 { 0x40f28, 0x989898 },
529 { 0x40f2c, 0x9a9a9a },
530 { 0x40f30, 0x9b9b9b },
531 { 0x40f34, 0x9d9d9d },
532 { 0x40f38, 0x9f9f9f },
533 { 0x40f3c, 0xa1a1a1 },
534 { 0x40f40, 0xa2a2a2 },
535 { 0x40f44, 0xa4a4a4 },
536 { 0x40f48, 0xa6a6a6 },
537 { 0x40f4c, 0xa7a7a7 },
538 { 0x40f50, 0xa9a9a9 },
539 { 0x40f54, 0xababab },
540 { 0x40f58, 0xadadad },
541 { 0x40f5c, 0xafafaf },
542 { 0x40f60, 0xb0b0b0 },
543 { 0x40f64, 0xb2b2b2 },
544 { 0x40f68, 0xb4b4b4 },
545 { 0x40f6c, 0xb6b6b6 },
546 { 0x40f70, 0xb8b8b8 },
547 { 0x40f74, 0xbababa },
548 { 0x40f78, 0xbbbbbb },
549 { 0x40f7c, 0xbdbdbd },
550 { 0x40f80, 0xbfbfbf },
551 { 0x40f84, 0xc1c1c1 },
552 { 0x40f88, 0xc3c3c3 },
553 { 0x40f8c, 0xc5c5c5 },
554 { 0x40f90, 0xc7c7c7 },
555 { 0x40f94, 0xc9c9c9 },
556 { 0x40f98, 0xcbcbcb },
557 { 0x40f9c, 0xcdcdcd },
558 { 0x40fa0, 0xcfcfcf },
559 { 0x40fa4, 0xd1d1d1 },
560 { 0x40fa8, 0xd3d3d3 },
561 { 0x40fac, 0xd5d5d5 },
562 { 0x40fb0, 0xd7d7d7 },
563 { 0x40fb4, 0xd9d9d9 },
564 { 0x40fb8, 0xdbdbdb },
565 { 0x40fbc, 0xdddddd },
566 { 0x40fc0, 0xdfdfdf },
567 { 0x40fc4, 0xe1e1e1 },
568 { 0x40fc8, 0xe3e3e3 },
569 { 0x40fcc, 0xe5e5e5 },
570 { 0x40fd0, 0xe7e7e7 },
571 { 0x40fd4, 0xe9e9e9 },
572 { 0x40fd8, 0xebebeb },
573 { 0x40fdc, 0xeeeeee },
574 { 0x40fe0, 0xf0f0f0 },
575 { 0x40fe4, 0xf2f2f2 },
576 { 0x40fe8, 0xf4f4f4 },
577 { 0x40fec, 0xf6f6f6 },
578 { 0x40ff0, 0xf8f8f8 },
579 { 0x40ff4, 0xfbfbfb },
580 { 0x40ff8, 0xfdfdfd },
581 { 0x40ffc, 0xffffff },
582};
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
new file mode 100644
index 000000000000..4e3deb4e592b
--- /dev/null
+++ b/drivers/video/msm/mdp_hw.h
@@ -0,0 +1,621 @@
1/* drivers/video/msm_fb/mdp_hw.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MDP_HW_H_
16#define _MDP_HW_H_
17
18#include <mach/msm_iomap.h>
19#include <mach/msm_fb.h>
20
21struct mdp_info {
22 struct mdp_device mdp_dev;
23 char * __iomem base;
24 int irq;
25};
26struct mdp_blit_req;
27struct mdp_device;
28int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
29 struct file *src_file, unsigned long src_start,
30 unsigned long src_len, struct file *dst_file,
31 unsigned long dst_start, unsigned long dst_len);
32#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
33#define mdp_readl(mdp, offset) readl(mdp->base + offset)
34
35#define MDP_SYNC_CONFIG_0 (0x00000)
36#define MDP_SYNC_CONFIG_1 (0x00004)
37#define MDP_SYNC_CONFIG_2 (0x00008)
38#define MDP_SYNC_STATUS_0 (0x0000c)
39#define MDP_SYNC_STATUS_1 (0x00010)
40#define MDP_SYNC_STATUS_2 (0x00014)
41#define MDP_SYNC_THRESH_0 (0x00018)
42#define MDP_SYNC_THRESH_1 (0x0001c)
43#define MDP_INTR_ENABLE (0x00020)
44#define MDP_INTR_STATUS (0x00024)
45#define MDP_INTR_CLEAR (0x00028)
46#define MDP_DISPLAY0_START (0x00030)
47#define MDP_DISPLAY1_START (0x00034)
48#define MDP_DISPLAY_STATUS (0x00038)
49#define MDP_EBI2_LCD0 (0x0003c)
50#define MDP_EBI2_LCD1 (0x00040)
51#define MDP_DISPLAY0_ADDR (0x00054)
52#define MDP_DISPLAY1_ADDR (0x00058)
53#define MDP_EBI2_PORTMAP_MODE (0x0005c)
54#define MDP_MODE (0x00060)
55#define MDP_TV_OUT_STATUS (0x00064)
56#define MDP_HW_VERSION (0x00070)
57#define MDP_SW_RESET (0x00074)
58#define MDP_AXI_ERROR_MASTER_STOP (0x00078)
59#define MDP_SEL_CLK_OR_HCLK_TEST_BUS (0x0007c)
60#define MDP_PRIMARY_VSYNC_OUT_CTRL (0x00080)
61#define MDP_SECONDARY_VSYNC_OUT_CTRL (0x00084)
62#define MDP_EXTERNAL_VSYNC_OUT_CTRL (0x00088)
63#define MDP_VSYNC_CTRL (0x0008c)
64#define MDP_CGC_EN (0x00100)
65#define MDP_CMD_STATUS (0x10008)
66#define MDP_PROFILE_EN (0x10010)
67#define MDP_PROFILE_COUNT (0x10014)
68#define MDP_DMA_START (0x10044)
69#define MDP_FULL_BYPASS_WORD0 (0x10100)
70#define MDP_FULL_BYPASS_WORD1 (0x10104)
71#define MDP_COMMAND_CONFIG (0x10104)
72#define MDP_FULL_BYPASS_WORD2 (0x10108)
73#define MDP_FULL_BYPASS_WORD3 (0x1010c)
74#define MDP_FULL_BYPASS_WORD4 (0x10110)
75#define MDP_FULL_BYPASS_WORD6 (0x10118)
76#define MDP_FULL_BYPASS_WORD7 (0x1011c)
77#define MDP_FULL_BYPASS_WORD8 (0x10120)
78#define MDP_FULL_BYPASS_WORD9 (0x10124)
79#define MDP_PPP_SOURCE_CONFIG (0x10124)
80#define MDP_FULL_BYPASS_WORD10 (0x10128)
81#define MDP_FULL_BYPASS_WORD11 (0x1012c)
82#define MDP_FULL_BYPASS_WORD12 (0x10130)
83#define MDP_FULL_BYPASS_WORD13 (0x10134)
84#define MDP_FULL_BYPASS_WORD14 (0x10138)
85#define MDP_PPP_OPERATION_CONFIG (0x10138)
86#define MDP_FULL_BYPASS_WORD15 (0x1013c)
87#define MDP_FULL_BYPASS_WORD16 (0x10140)
88#define MDP_FULL_BYPASS_WORD17 (0x10144)
89#define MDP_FULL_BYPASS_WORD18 (0x10148)
90#define MDP_FULL_BYPASS_WORD19 (0x1014c)
91#define MDP_FULL_BYPASS_WORD20 (0x10150)
92#define MDP_PPP_DESTINATION_CONFIG (0x10150)
93#define MDP_FULL_BYPASS_WORD21 (0x10154)
94#define MDP_FULL_BYPASS_WORD22 (0x10158)
95#define MDP_FULL_BYPASS_WORD23 (0x1015c)
96#define MDP_FULL_BYPASS_WORD24 (0x10160)
97#define MDP_FULL_BYPASS_WORD25 (0x10164)
98#define MDP_FULL_BYPASS_WORD26 (0x10168)
99#define MDP_FULL_BYPASS_WORD27 (0x1016c)
100#define MDP_FULL_BYPASS_WORD29 (0x10174)
101#define MDP_FULL_BYPASS_WORD30 (0x10178)
102#define MDP_FULL_BYPASS_WORD31 (0x1017c)
103#define MDP_FULL_BYPASS_WORD32 (0x10180)
104#define MDP_DMA_CONFIG (0x10180)
105#define MDP_FULL_BYPASS_WORD33 (0x10184)
106#define MDP_FULL_BYPASS_WORD34 (0x10188)
107#define MDP_FULL_BYPASS_WORD35 (0x1018c)
108#define MDP_FULL_BYPASS_WORD37 (0x10194)
109#define MDP_FULL_BYPASS_WORD39 (0x1019c)
110#define MDP_FULL_BYPASS_WORD40 (0x101a0)
111#define MDP_FULL_BYPASS_WORD41 (0x101a4)
112#define MDP_FULL_BYPASS_WORD43 (0x101ac)
113#define MDP_FULL_BYPASS_WORD46 (0x101b8)
114#define MDP_FULL_BYPASS_WORD47 (0x101bc)
115#define MDP_FULL_BYPASS_WORD48 (0x101c0)
116#define MDP_FULL_BYPASS_WORD49 (0x101c4)
117#define MDP_FULL_BYPASS_WORD50 (0x101c8)
118#define MDP_FULL_BYPASS_WORD51 (0x101cc)
119#define MDP_FULL_BYPASS_WORD52 (0x101d0)
120#define MDP_FULL_BYPASS_WORD53 (0x101d4)
121#define MDP_FULL_BYPASS_WORD54 (0x101d8)
122#define MDP_FULL_BYPASS_WORD55 (0x101dc)
123#define MDP_FULL_BYPASS_WORD56 (0x101e0)
124#define MDP_FULL_BYPASS_WORD57 (0x101e4)
125#define MDP_FULL_BYPASS_WORD58 (0x101e8)
126#define MDP_FULL_BYPASS_WORD59 (0x101ec)
127#define MDP_FULL_BYPASS_WORD60 (0x101f0)
128#define MDP_VSYNC_THRESHOLD (0x101f0)
129#define MDP_FULL_BYPASS_WORD61 (0x101f4)
130#define MDP_FULL_BYPASS_WORD62 (0x101f8)
131#define MDP_FULL_BYPASS_WORD63 (0x101fc)
132#define MDP_TFETCH_TEST_MODE (0x20004)
133#define MDP_TFETCH_STATUS (0x20008)
134#define MDP_TFETCH_TILE_COUNT (0x20010)
135#define MDP_TFETCH_FETCH_COUNT (0x20014)
136#define MDP_TFETCH_CONSTANT_COLOR (0x20040)
137#define MDP_CSC_BYPASS (0x40004)
138#define MDP_SCALE_COEFF_LSB (0x5fffc)
139#define MDP_TV_OUT_CTL (0xc0000)
140#define MDP_TV_OUT_FIR_COEFF (0xc0004)
141#define MDP_TV_OUT_BUF_ADDR (0xc0008)
142#define MDP_TV_OUT_CC_DATA (0xc000c)
143#define MDP_TV_OUT_SOBEL (0xc0010)
144#define MDP_TV_OUT_Y_CLAMP (0xc0018)
145#define MDP_TV_OUT_CB_CLAMP (0xc001c)
146#define MDP_TV_OUT_CR_CLAMP (0xc0020)
147#define MDP_TEST_MODE_CLK (0xd0000)
148#define MDP_TEST_MISR_RESET_CLK (0xd0004)
149#define MDP_TEST_EXPORT_MISR_CLK (0xd0008)
150#define MDP_TEST_MISR_CURR_VAL_CLK (0xd000c)
151#define MDP_TEST_MODE_HCLK (0xd0100)
152#define MDP_TEST_MISR_RESET_HCLK (0xd0104)
153#define MDP_TEST_EXPORT_MISR_HCLK (0xd0108)
154#define MDP_TEST_MISR_CURR_VAL_HCLK (0xd010c)
155#define MDP_TEST_MODE_DCLK (0xd0200)
156#define MDP_TEST_MISR_RESET_DCLK (0xd0204)
157#define MDP_TEST_EXPORT_MISR_DCLK (0xd0208)
158#define MDP_TEST_MISR_CURR_VAL_DCLK (0xd020c)
159#define MDP_TEST_CAPTURED_DCLK (0xd0210)
160#define MDP_TEST_MISR_CAPT_VAL_DCLK (0xd0214)
161#define MDP_LCDC_CTL (0xe0000)
162#define MDP_LCDC_HSYNC_CTL (0xe0004)
163#define MDP_LCDC_VSYNC_CTL (0xe0008)
164#define MDP_LCDC_ACTIVE_HCTL (0xe000c)
165#define MDP_LCDC_ACTIVE_VCTL (0xe0010)
166#define MDP_LCDC_BORDER_CLR (0xe0014)
167#define MDP_LCDC_H_BLANK (0xe0018)
168#define MDP_LCDC_V_BLANK (0xe001c)
169#define MDP_LCDC_UNDERFLOW_CLR (0xe0020)
170#define MDP_LCDC_HSYNC_SKEW (0xe0024)
171#define MDP_LCDC_TEST_CTL (0xe0028)
172#define MDP_LCDC_LINE_IRQ (0xe002c)
173#define MDP_LCDC_CTL_POLARITY (0xe0030)
174#define MDP_LCDC_DMA_CONFIG (0xe1000)
175#define MDP_LCDC_DMA_SIZE (0xe1004)
176#define MDP_LCDC_DMA_IBUF_ADDR (0xe1008)
177#define MDP_LCDC_DMA_IBUF_Y_STRIDE (0xe100c)
178
179
180#define MDP_DMA2_TERM 0x1
181#define MDP_DMA3_TERM 0x2
182#define MDP_PPP_TERM 0x3
183
184/* MDP_INTR_ENABLE */
185#define DL0_ROI_DONE (1<<0)
186#define DL1_ROI_DONE (1<<1)
187#define DL0_DMA2_TERM_DONE (1<<2)
188#define DL1_DMA2_TERM_DONE (1<<3)
189#define DL0_PPP_TERM_DONE (1<<4)
190#define DL1_PPP_TERM_DONE (1<<5)
191#define TV_OUT_DMA3_DONE (1<<6)
192#define TV_ENC_UNDERRUN (1<<7)
193#define DL0_FETCH_DONE (1<<11)
194#define DL1_FETCH_DONE (1<<12)
195
196#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
197 DL1_ROI_DONE| \
198 DL0_PPP_TERM_DONE| \
199 DL1_PPP_TERM_DONE)
200
201#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
202 DL1_ROI_DONE| \
203 DL0_DMA2_TERM_DONE| \
204 DL1_DMA2_TERM_DONE| \
205 DL0_PPP_TERM_DONE| \
206 DL1_PPP_TERM_DONE| \
207 DL0_FETCH_DONE| \
208 DL1_FETCH_DONE| \
209 TV_ENC_UNDERRUN)
210
211#define MDP_TOP_LUMA 16
212#define MDP_TOP_CHROMA 0
213#define MDP_BOTTOM_LUMA 19
214#define MDP_BOTTOM_CHROMA 3
215#define MDP_LEFT_LUMA 22
216#define MDP_LEFT_CHROMA 6
217#define MDP_RIGHT_LUMA 25
218#define MDP_RIGHT_CHROMA 9
219
220#define CLR_G 0x0
221#define CLR_B 0x1
222#define CLR_R 0x2
223#define CLR_ALPHA 0x3
224
225#define CLR_Y CLR_G
226#define CLR_CB CLR_B
227#define CLR_CR CLR_R
228
229/* from lsb to msb */
230#define MDP_GET_PACK_PATTERN(a, x, y, z, bit) \
231 (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
232
233/* MDP_SYNC_CONFIG_0/1/2 */
234#define MDP_SYNCFG_HGT_LOC 22
235#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21)
236#define MDP_SYNCFG_VSYNC_INT_EN (1<<20)
237
238/* MDP_SYNC_THRESH_0 */
239#define MDP_PRIM_BELOW_LOC 0
240#define MDP_PRIM_ABOVE_LOC 8
241
242/* MDP_{PRIMARY,SECONDARY,EXTERNAL}_VSYNC_OUT_CRL */
243#define VSYNC_PULSE_EN (1<<31)
244#define VSYNC_PULSE_INV (1<<30)
245
246/* MDP_VSYNC_CTRL */
247#define DISP0_VSYNC_MAP_VSYNC0 0
248#define DISP0_VSYNC_MAP_VSYNC1 (1<<0)
249#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1))
250
251#define DISP1_VSYNC_MAP_VSYNC0 0
252#define DISP1_VSYNC_MAP_VSYNC1 (1<<2)
253#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3))
254
255#define PRIMARY_LCD_SYNC_EN (1<<4)
256#define PRIMARY_LCD_SYNC_DISABLE 0
257
258#define SECONDARY_LCD_SYNC_EN (1<<5)
259#define SECONDARY_LCD_SYNC_DISABLE 0
260
261#define EXTERNAL_LCD_SYNC_EN (1<<6)
262#define EXTERNAL_LCD_SYNC_DISABLE 0
263
264/* MDP_VSYNC_THRESHOLD / MDP_FULL_BYPASS_WORD60 */
265#define VSYNC_THRESHOLD_ABOVE_LOC 0
266#define VSYNC_THRESHOLD_BELOW_LOC 16
267#define VSYNC_ANTI_TEAR_EN (1<<31)
268
269/* MDP_COMMAND_CONFIG / MDP_FULL_BYPASS_WORD1 */
270#define MDP_CMD_DBGBUS_EN (1<<0)
271
272/* MDP_PPP_SOURCE_CONFIG / MDP_FULL_BYPASS_WORD9&53 */
273#define PPP_SRC_C0G_8BIT ((1<<1)|(1<<0))
274#define PPP_SRC_C1B_8BIT ((1<<3)|(1<<2))
275#define PPP_SRC_C2R_8BIT ((1<<5)|(1<<4))
276#define PPP_SRC_C3A_8BIT ((1<<7)|(1<<6))
277
278#define PPP_SRC_C0G_6BIT (1<<1)
279#define PPP_SRC_C1B_6BIT (1<<3)
280#define PPP_SRC_C2R_6BIT (1<<5)
281
282#define PPP_SRC_C0G_5BIT (1<<0)
283#define PPP_SRC_C1B_5BIT (1<<2)
284#define PPP_SRC_C2R_5BIT (1<<4)
285
286#define PPP_SRC_C3ALPHA_EN (1<<8)
287
288#define PPP_SRC_BPP_1BYTES 0
289#define PPP_SRC_BPP_2BYTES (1<<9)
290#define PPP_SRC_BPP_3BYTES (1<<10)
291#define PPP_SRC_BPP_4BYTES ((1<<10)|(1<<9))
292
293#define PPP_SRC_BPP_ROI_ODD_X (1<<11)
294#define PPP_SRC_BPP_ROI_ODD_Y (1<<12)
295#define PPP_SRC_INTERLVD_2COMPONENTS (1<<13)
296#define PPP_SRC_INTERLVD_3COMPONENTS (1<<14)
297#define PPP_SRC_INTERLVD_4COMPONENTS ((1<<14)|(1<<13))
298
299
300/* RGB666 unpack format
301** TIGHT means R6+G6+B6 together
302** LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
303** or 2+R6 +2+G6 +2+B6 (with LSB)
304*/
305#define PPP_SRC_PACK_TIGHT (1<<17)
306#define PPP_SRC_PACK_LOOSE 0
307#define PPP_SRC_PACK_ALIGN_LSB 0
308#define PPP_SRC_PACK_ALIGN_MSB (1<<18)
309
310#define PPP_SRC_PLANE_INTERLVD 0
311#define PPP_SRC_PLANE_PSEUDOPLNR (1<<20)
312
313#define PPP_SRC_WMV9_MODE (1<<21)
314
315/* MDP_PPP_OPERATION_CONFIG / MDP_FULL_BYPASS_WORD14 */
316#define PPP_OP_SCALE_X_ON (1<<0)
317#define PPP_OP_SCALE_Y_ON (1<<1)
318
319#define PPP_OP_CONVERT_RGB2YCBCR 0
320#define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
321#define PPP_OP_CONVERT_ON (1<<3)
322
323#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
324#define PPP_OP_CONVERT_MATRIX_SECONDARY (1<<4)
325
326#define PPP_OP_LUT_C0_ON (1<<5)
327#define PPP_OP_LUT_C1_ON (1<<6)
328#define PPP_OP_LUT_C2_ON (1<<7)
329
330/* rotate or blend enable */
331#define PPP_OP_ROT_ON (1<<8)
332
333#define PPP_OP_ROT_90 (1<<9)
334#define PPP_OP_FLIP_LR (1<<10)
335#define PPP_OP_FLIP_UD (1<<11)
336
337#define PPP_OP_BLEND_ON (1<<12)
338
339#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
340#define PPP_OP_BLEND_DSTPIXEL_ALPHA (1<<13)
341#define PPP_OP_BLEND_CONSTANT_ALPHA (1<<14)
342#define PPP_OP_BLEND_SRCPIXEL_TRANSP ((1<<13)|(1<<14))
343
344#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
345#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE (1<<15)
346
347#define PPP_OP_DITHER_EN (1<<16)
348
349#define PPP_OP_COLOR_SPACE_RGB 0
350#define PPP_OP_COLOR_SPACE_YCBCR (1<<17)
351
352#define PPP_OP_SRC_CHROMA_RGB 0
353#define PPP_OP_SRC_CHROMA_H2V1 (1<<18)
354#define PPP_OP_SRC_CHROMA_H1V2 (1<<19)
355#define PPP_OP_SRC_CHROMA_420 ((1<<18)|(1<<19))
356#define PPP_OP_SRC_CHROMA_COSITE 0
357#define PPP_OP_SRC_CHROMA_OFFSITE (1<<20)
358
359#define PPP_OP_DST_CHROMA_RGB 0
360#define PPP_OP_DST_CHROMA_H2V1 (1<<21)
361#define PPP_OP_DST_CHROMA_H1V2 (1<<22)
362#define PPP_OP_DST_CHROMA_420 ((1<<21)|(1<<22))
363#define PPP_OP_DST_CHROMA_COSITE 0
364#define PPP_OP_DST_CHROMA_OFFSITE (1<<23)
365
366#define PPP_BLEND_ALPHA_TRANSP (1<<24)
367
368#define PPP_OP_BG_CHROMA_RGB 0
369#define PPP_OP_BG_CHROMA_H2V1 (1<<25)
370#define PPP_OP_BG_CHROMA_H1V2 (1<<26)
371#define PPP_OP_BG_CHROMA_420 ((1<<25)|(1<<26))
372#define PPP_OP_BG_CHROMA_SITE_COSITE 0
373#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)
374
375/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
376#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
377#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
378#define PPP_DST_C2R_8BIT ((1<<5)|(1<<4))
379#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
380
381#define PPP_DST_C0G_6BIT (1<<1)
382#define PPP_DST_C1B_6BIT (1<<3)
383#define PPP_DST_C2R_6BIT (1<<5)
384
385#define PPP_DST_C0G_5BIT (1<<0)
386#define PPP_DST_C1B_5BIT (1<<2)
387#define PPP_DST_C2R_5BIT (1<<4)
388
389#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
390#define PPP_DST_C3ALPHA_EN (1<<8)
391
392#define PPP_DST_INTERLVD_2COMPONENTS (1<<9)
393#define PPP_DST_INTERLVD_3COMPONENTS (1<<10)
394#define PPP_DST_INTERLVD_4COMPONENTS ((1<<10)|(1<<9))
395#define PPP_DST_INTERLVD_6COMPONENTS ((1<<11)|(1<<9))
396
397#define PPP_DST_PACK_LOOSE 0
398#define PPP_DST_PACK_TIGHT (1<<13)
399#define PPP_DST_PACK_ALIGN_LSB 0
400#define PPP_DST_PACK_ALIGN_MSB (1<<14)
401
402#define PPP_DST_OUT_SEL_AXI 0
403#define PPP_DST_OUT_SEL_MDDI (1<<15)
404
405#define PPP_DST_BPP_2BYTES (1<<16)
406#define PPP_DST_BPP_3BYTES (1<<17)
407#define PPP_DST_BPP_4BYTES ((1<<17)|(1<<16))
408
409#define PPP_DST_PLANE_INTERLVD 0
410#define PPP_DST_PLANE_PLANAR (1<<18)
411#define PPP_DST_PLANE_PSEUDOPLNR (1<<19)
412
413#define PPP_DST_TO_TV (1<<20)
414
415#define PPP_DST_MDDI_PRIMARY 0
416#define PPP_DST_MDDI_SECONDARY (1<<21)
417#define PPP_DST_MDDI_EXTERNAL (1<<22)
418
419/* image configurations by image type */
420#define PPP_CFG_MDP_RGB_565(dir) (PPP_##dir##_C2R_5BIT | \
421 PPP_##dir##_C0G_6BIT | \
422 PPP_##dir##_C1B_5BIT | \
423 PPP_##dir##_BPP_2BYTES | \
424 PPP_##dir##_INTERLVD_3COMPONENTS | \
425 PPP_##dir##_PACK_TIGHT | \
426 PPP_##dir##_PACK_ALIGN_LSB | \
427 PPP_##dir##_PLANE_INTERLVD)
428
429#define PPP_CFG_MDP_RGB_888(dir) (PPP_##dir##_C2R_8BIT | \
430 PPP_##dir##_C0G_8BIT | \
431 PPP_##dir##_C1B_8BIT | \
432 PPP_##dir##_BPP_3BYTES | \
433 PPP_##dir##_INTERLVD_3COMPONENTS | \
434 PPP_##dir##_PACK_TIGHT | \
435 PPP_##dir##_PACK_ALIGN_LSB | \
436 PPP_##dir##_PLANE_INTERLVD)
437
438#define PPP_CFG_MDP_ARGB_8888(dir) (PPP_##dir##_C2R_8BIT | \
439 PPP_##dir##_C0G_8BIT | \
440 PPP_##dir##_C1B_8BIT | \
441 PPP_##dir##_C3A_8BIT | \
442 PPP_##dir##_C3ALPHA_EN | \
443 PPP_##dir##_BPP_4BYTES | \
444 PPP_##dir##_INTERLVD_4COMPONENTS | \
445 PPP_##dir##_PACK_TIGHT | \
446 PPP_##dir##_PACK_ALIGN_LSB | \
447 PPP_##dir##_PLANE_INTERLVD)
448
449#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
450#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
451#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
452
453#define PPP_CFG_MDP_Y_CBCR_H2V2(dir) (PPP_##dir##_C2R_8BIT | \
454 PPP_##dir##_C0G_8BIT | \
455 PPP_##dir##_C1B_8BIT | \
456 PPP_##dir##_C3A_8BIT | \
457 PPP_##dir##_BPP_2BYTES | \
458 PPP_##dir##_INTERLVD_2COMPONENTS | \
459 PPP_##dir##_PACK_TIGHT | \
460 PPP_##dir##_PACK_ALIGN_LSB | \
461 PPP_##dir##_PLANE_PSEUDOPLNR)
462
463#define PPP_CFG_MDP_Y_CRCB_H2V2(dir) PPP_CFG_MDP_Y_CBCR_H2V2(dir)
464
465#define PPP_CFG_MDP_YCRYCB_H2V1(dir) (PPP_##dir##_C2R_8BIT | \
466 PPP_##dir##_C0G_8BIT | \
467 PPP_##dir##_C1B_8BIT | \
468 PPP_##dir##_C3A_8BIT | \
469 PPP_##dir##_BPP_2BYTES | \
470 PPP_##dir##_INTERLVD_4COMPONENTS | \
471 PPP_##dir##_PACK_TIGHT | \
472 PPP_##dir##_PACK_ALIGN_LSB |\
473 PPP_##dir##_PLANE_INTERLVD)
474
475#define PPP_CFG_MDP_Y_CBCR_H2V1(dir) (PPP_##dir##_C2R_8BIT | \
476 PPP_##dir##_C0G_8BIT | \
477 PPP_##dir##_C1B_8BIT | \
478 PPP_##dir##_C3A_8BIT | \
479 PPP_##dir##_BPP_2BYTES | \
480 PPP_##dir##_INTERLVD_2COMPONENTS | \
481 PPP_##dir##_PACK_TIGHT | \
482 PPP_##dir##_PACK_ALIGN_LSB | \
483 PPP_##dir##_PLANE_PSEUDOPLNR)
484
485#define PPP_CFG_MDP_Y_CRCB_H2V1(dir) PPP_CFG_MDP_Y_CBCR_H2V1(dir)
486
487#define PPP_PACK_PATTERN_MDP_RGB_565 \
488 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
489#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
490#define PPP_PACK_PATTERN_MDP_XRGB_8888 \
491 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
492#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
493#define PPP_PACK_PATTERN_MDP_RGBA_8888 \
494 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
495#define PPP_PACK_PATTERN_MDP_BGRA_8888 \
496 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
497#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
498 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
499#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
500#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 \
501 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8)
502#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V2 PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1
503#define PPP_PACK_PATTERN_MDP_YCRYCB_H2V1 \
504 MDP_GET_PACK_PATTERN(CLR_Y, CLR_R, CLR_Y, CLR_B, 8)
505
506#define PPP_CHROMA_SAMP_MDP_RGB_565(dir) PPP_OP_##dir##_CHROMA_RGB
507#define PPP_CHROMA_SAMP_MDP_RGB_888(dir) PPP_OP_##dir##_CHROMA_RGB
508#define PPP_CHROMA_SAMP_MDP_XRGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
509#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
510#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
511#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
512#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
513#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
514#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
515#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V2(dir) PPP_OP_##dir##_CHROMA_420
516#define PPP_CHROMA_SAMP_MDP_YCRYCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
517
518/* Helpful array generation macros */
519#define PPP_ARRAY0(name) \
520 [MDP_RGB_565] = PPP_##name##_MDP_RGB_565,\
521 [MDP_RGB_888] = PPP_##name##_MDP_RGB_888,\
522 [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888,\
523 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
524 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
525 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
526 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
527 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
528 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
529 [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2,\
530 [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1
531
532#define PPP_ARRAY1(name, dir) \
533 [MDP_RGB_565] = PPP_##name##_MDP_RGB_565(dir),\
534 [MDP_RGB_888] = PPP_##name##_MDP_RGB_888(dir),\
535 [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888(dir),\
536 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
537 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
538 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
539 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
540 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
541 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
542 [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2(dir),\
543 [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1(dir)
544
545#define IS_YCRCB(img) ((img == MDP_Y_CRCB_H2V2) | (img == MDP_Y_CBCR_H2V2) | \
546 (img == MDP_Y_CRCB_H2V1) | (img == MDP_Y_CBCR_H2V1) | \
547 (img == MDP_YCRYCB_H2V1))
548#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
549 (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
550 (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888))
551#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
552 (img == MDP_BGRA_8888))
553
554#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
555 (img == MDP_Y_CBCR_H2V2) | \
556 (img == MDP_Y_CRCB_H2V1) | \
557 (img == MDP_Y_CBCR_H2V1))
558
559/* Mappings from addr to purpose */
560#define PPP_ADDR_SRC_ROI MDP_FULL_BYPASS_WORD2
561#define PPP_ADDR_SRC0 MDP_FULL_BYPASS_WORD3
562#define PPP_ADDR_SRC1 MDP_FULL_BYPASS_WORD4
563#define PPP_ADDR_SRC_YSTRIDE MDP_FULL_BYPASS_WORD7
564#define PPP_ADDR_SRC_CFG MDP_FULL_BYPASS_WORD9
565#define PPP_ADDR_SRC_PACK_PATTERN MDP_FULL_BYPASS_WORD10
566#define PPP_ADDR_OPERATION MDP_FULL_BYPASS_WORD14
567#define PPP_ADDR_PHASEX_INIT MDP_FULL_BYPASS_WORD15
568#define PPP_ADDR_PHASEY_INIT MDP_FULL_BYPASS_WORD16
569#define PPP_ADDR_PHASEX_STEP MDP_FULL_BYPASS_WORD17
570#define PPP_ADDR_PHASEY_STEP MDP_FULL_BYPASS_WORD18
571#define PPP_ADDR_ALPHA_TRANSP MDP_FULL_BYPASS_WORD19
572#define PPP_ADDR_DST_CFG MDP_FULL_BYPASS_WORD20
573#define PPP_ADDR_DST_PACK_PATTERN MDP_FULL_BYPASS_WORD21
574#define PPP_ADDR_DST_ROI MDP_FULL_BYPASS_WORD25
575#define PPP_ADDR_DST0 MDP_FULL_BYPASS_WORD26
576#define PPP_ADDR_DST1 MDP_FULL_BYPASS_WORD27
577#define PPP_ADDR_DST_YSTRIDE MDP_FULL_BYPASS_WORD30
578#define PPP_ADDR_EDGE MDP_FULL_BYPASS_WORD46
579#define PPP_ADDR_BG0 MDP_FULL_BYPASS_WORD48
580#define PPP_ADDR_BG1 MDP_FULL_BYPASS_WORD49
581#define PPP_ADDR_BG_YSTRIDE MDP_FULL_BYPASS_WORD51
582#define PPP_ADDR_BG_CFG MDP_FULL_BYPASS_WORD53
583#define PPP_ADDR_BG_PACK_PATTERN MDP_FULL_BYPASS_WORD54
584
585/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
586#define DMA_DSTC0G_6BITS (1<<1)
587#define DMA_DSTC1B_6BITS (1<<3)
588#define DMA_DSTC2R_6BITS (1<<5)
589#define DMA_DSTC0G_5BITS (1<<0)
590#define DMA_DSTC1B_5BITS (1<<2)
591#define DMA_DSTC2R_5BITS (1<<4)
592
593#define DMA_PACK_TIGHT (1<<6)
594#define DMA_PACK_LOOSE 0
595#define DMA_PACK_ALIGN_LSB 0
596#define DMA_PACK_ALIGN_MSB (1<<7)
597#define DMA_PACK_PATTERN_RGB \
598 (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
599
600#define DMA_OUT_SEL_AHB 0
601#define DMA_OUT_SEL_MDDI (1<<14)
602#define DMA_AHBM_LCD_SEL_PRIMARY 0
603#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
604#define DMA_IBUF_C3ALPHA_EN (1<<16)
605#define DMA_DITHER_EN (1<<17)
606
607#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
608#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
609#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
610
611#define DMA_IBUF_FORMAT_RGB565 (1<<20)
612#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
613
614#define DMA_IBUF_NONCONTIGUOUS (1<<21)
615
616/* MDDI REGISTER ? */
617#define MDDI_VDO_PACKET_DESC 0x5666
618#define MDDI_VDO_PACKET_PRIM 0xC3
619#define MDDI_VDO_PACKET_SECD 0xC0
620
621#endif
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
new file mode 100644
index 000000000000..ba2c4673b648
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp.c
@@ -0,0 +1,750 @@
1/* drivers/video/msm/mdp_ppp.c
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#include <linux/fb.h>
16#include <linux/file.h>
17#include <linux/delay.h>
18#include <linux/msm_mdp.h>
19#include <linux/android_pmem.h>
20#include <mach/msm_fb.h>
21
22#include "mdp_hw.h"
23#include "mdp_scale_tables.h"
24
25#define DLOG(x...) do {} while (0)
26
27#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
28static int downscale_y_table = MDP_DOWNSCALE_MAX;
29static int downscale_x_table = MDP_DOWNSCALE_MAX;
30
31struct mdp_regs {
32 uint32_t src0;
33 uint32_t src1;
34 uint32_t dst0;
35 uint32_t dst1;
36 uint32_t src_cfg;
37 uint32_t dst_cfg;
38 uint32_t src_pack;
39 uint32_t dst_pack;
40 uint32_t src_rect;
41 uint32_t dst_rect;
42 uint32_t src_ystride;
43 uint32_t dst_ystride;
44 uint32_t op;
45 uint32_t src_bpp;
46 uint32_t dst_bpp;
47 uint32_t edge;
48 uint32_t phasex_init;
49 uint32_t phasey_init;
50 uint32_t phasex_step;
51 uint32_t phasey_step;
52};
53
54static uint32_t pack_pattern[] = {
55 PPP_ARRAY0(PACK_PATTERN)
56};
57
58static uint32_t src_img_cfg[] = {
59 PPP_ARRAY1(CFG, SRC)
60};
61
62static uint32_t dst_img_cfg[] = {
63 PPP_ARRAY1(CFG, DST)
64};
65
66static uint32_t bytes_per_pixel[] = {
67 [MDP_RGB_565] = 2,
68 [MDP_RGB_888] = 3,
69 [MDP_XRGB_8888] = 4,
70 [MDP_ARGB_8888] = 4,
71 [MDP_RGBA_8888] = 4,
72 [MDP_BGRA_8888] = 4,
73 [MDP_Y_CBCR_H2V1] = 1,
74 [MDP_Y_CBCR_H2V2] = 1,
75 [MDP_Y_CRCB_H2V1] = 1,
76 [MDP_Y_CRCB_H2V2] = 1,
77 [MDP_YCRYCB_H2V1] = 2
78};
79
80static uint32_t dst_op_chroma[] = {
81 PPP_ARRAY1(CHROMA_SAMP, DST)
82};
83
84static uint32_t src_op_chroma[] = {
85 PPP_ARRAY1(CHROMA_SAMP, SRC)
86};
87
88static uint32_t bg_op_chroma[] = {
89 PPP_ARRAY1(CHROMA_SAMP, BG)
90};
91
92static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
93{
94 regs->dst0 += (req->dst_rect.w -
95 min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
96 regs->dst1 += (req->dst_rect.w -
97 min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
98}
99
100static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
101{
102 regs->dst0 += (req->dst_rect.h -
103 min((uint32_t)16, req->dst_rect.h)) *
104 regs->dst_ystride;
105 regs->dst1 += (req->dst_rect.h -
106 min((uint32_t)16, req->dst_rect.h)) *
107 regs->dst_ystride;
108}
109
110static void blit_rotate(struct mdp_blit_req *req,
111 struct mdp_regs *regs)
112{
113 if (req->flags == MDP_ROT_NOP)
114 return;
115
116 regs->op |= PPP_OP_ROT_ON;
117 if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) &&
118 !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR))
119 rotate_dst_addr_x(req, regs);
120 if (req->flags & MDP_ROT_90)
121 regs->op |= PPP_OP_ROT_90;
122 if (req->flags & MDP_FLIP_UD) {
123 regs->op |= PPP_OP_FLIP_UD;
124 rotate_dst_addr_y(req, regs);
125 }
126 if (req->flags & MDP_FLIP_LR)
127 regs->op |= PPP_OP_FLIP_LR;
128}
129
130static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
131{
132 if (req->src.format == req->dst.format)
133 return;
134 if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
135 regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
136 } else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
137 regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
138 if (req->dst.format == MDP_RGB_565)
139 regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
140 }
141}
142
143#define GET_BIT_RANGE(value, high, low) \
144 (((1 << (high - low + 1)) - 1) & (value >> low))
145static uint32_t transp_convert(struct mdp_blit_req *req)
146{
147 uint32_t transp = 0;
148 if (req->src.format == MDP_RGB_565) {
149 /* pad each value to 8 bits by copying the high bits into the
150 * low end, convert RGB to RBG by switching low 2 components */
151 transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) |
152 (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16;
153
154 transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) |
155 (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8;
156
157 transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) |
158 (GET_BIT_RANGE(req->transp_mask, 10, 9));
159 } else {
160 /* convert RGB to RBG */
161 transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) |
162 (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) |
163 (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8);
164 }
165 return transp;
166}
167#undef GET_BIT_RANGE
168
169static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
170{
171 /* TRANSP BLEND */
172 if (req->transp_mask != MDP_TRANSP_NOP) {
173 req->transp_mask = transp_convert(req);
174 if (req->alpha != MDP_ALPHA_NOP) {
175 /* use blended transparancy mode
176 * pixel = (src == transp) ? dst : blend
177 * blend is combo of blend_eq_sel and
178 * blend_alpha_sel */
179 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
180 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
181 PPP_OP_BLEND_CONSTANT_ALPHA |
182 PPP_BLEND_ALPHA_TRANSP;
183 } else {
184 /* simple transparancy mode
185 * pixel = (src == transp) ? dst : src */
186 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
187 PPP_OP_BLEND_SRCPIXEL_TRANSP;
188 }
189 }
190
191 req->alpha &= 0xff;
192 /* ALPHA BLEND */
193 if (HAS_ALPHA(req->src.format)) {
194 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
195 PPP_OP_BLEND_SRCPIXEL_ALPHA;
196 } else if (req->alpha < MDP_ALPHA_NOP) {
197 /* just blend by alpha */
198 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
199 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
200 PPP_OP_BLEND_CONSTANT_ALPHA;
201 }
202
203 regs->op |= bg_op_chroma[req->dst.format];
204}
205
206#define ONE_HALF (1LL << 32)
207#define ONE (1LL << 33)
208#define TWO (2LL << 33)
209#define THREE (3LL << 33)
210#define FRAC_MASK (ONE - 1)
211#define INT_MASK (~FRAC_MASK)
212
213static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
214 uint32_t *phase_init, uint32_t *phase_step)
215{
216 /* to improve precicsion calculations are done in U31.33 and converted
217 * to U3.29 at the end */
218 int64_t k1, k2, k3, k4, tmp;
219 uint64_t n, d, os, os_p, od, od_p, oreq;
220 unsigned rpa = 0;
221 int64_t ip64, delta;
222
223 if (dim_out % 3 == 0)
224 rpa = !(dim_in % (dim_out / 3));
225
226 n = ((uint64_t)dim_out) << 34;
227 d = dim_in;
228 if (!d)
229 return -1;
230 do_div(n, d);
231 k3 = (n + 1) >> 1;
232 if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
233 DLOG("crap bad scale\n");
234 return -1;
235 }
236 n = ((uint64_t)dim_in) << 34;
237 d = (uint64_t)dim_out;
238 if (!d)
239 return -1;
240 do_div(n, d);
241 k1 = (n + 1) >> 1;
242 k2 = (k1 - ONE) >> 1;
243
244 *phase_init = (int)(k2 >> 4);
245 k4 = (k3 - ONE) >> 1;
246
247 if (rpa) {
248 os = ((uint64_t)origin << 33) - ONE_HALF;
249 tmp = (dim_out * os) + ONE_HALF;
250 if (!dim_in)
251 return -1;
252 do_div(tmp, dim_in);
253 od = tmp - ONE_HALF;
254 } else {
255 os = ((uint64_t)origin << 1) - 1;
256 od = (((k3 * os) >> 1) + k4);
257 }
258
259 od_p = od & INT_MASK;
260 if (od_p != od)
261 od_p += ONE;
262
263 if (rpa) {
264 tmp = (dim_in * od_p) + ONE_HALF;
265 if (!dim_in)
266 return -1;
267 do_div(tmp, dim_in);
268 os_p = tmp - ONE_HALF;
269 } else {
270 os_p = ((k1 * (od_p >> 33)) + k2);
271 }
272
273 oreq = (os_p & INT_MASK) - ONE;
274
275 ip64 = os_p - oreq;
276 delta = ((int64_t)(origin) << 33) - oreq;
277 ip64 -= delta;
278 /* limit to valid range before the left shift */
279 delta = (ip64 & (1LL << 63)) ? 4 : -4;
280 delta <<= 33;
281 while (abs((int)(ip64 >> 33)) > 4)
282 ip64 += delta;
283 *phase_init = (int)(ip64 >> 4);
284 *phase_step = (uint32_t)(k1 >> 4);
285 return 0;
286}
287
288static void load_scale_table(const struct mdp_info *mdp,
289 struct mdp_table_entry *table, int len)
290{
291 int i;
292 for (i = 0; i < len; i++)
293 mdp_writel(mdp, table[i].val, table[i].reg);
294}
295
296enum {
297IMG_LEFT,
298IMG_RIGHT,
299IMG_TOP,
300IMG_BOTTOM,
301};
302
303static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
304 uint32_t *interp1, uint32_t *interp2,
305 uint32_t *repeat1, uint32_t *repeat2) {
306 if (src > 3 * dst) {
307 *interp1 = 0;
308 *interp2 = src - 1;
309 *repeat1 = 0;
310 *repeat2 = 0;
311 } else if (src == 3 * dst) {
312 *interp1 = 0;
313 *interp2 = src;
314 *repeat1 = 0;
315 *repeat2 = 1;
316 } else if (src > dst && src < 3 * dst) {
317 *interp1 = -1;
318 *interp2 = src;
319 *repeat1 = 1;
320 *repeat2 = 1;
321 } else if (src == dst) {
322 *interp1 = -1;
323 *interp2 = src + 1;
324 *repeat1 = 1;
325 *repeat2 = 2;
326 } else {
327 *interp1 = -2;
328 *interp2 = src + 1;
329 *repeat1 = 2;
330 *repeat2 = 2;
331 }
332 *interp1 += src_coord;
333 *interp2 += src_coord;
334}
335
336static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
337{
338 int32_t luma_interp[4];
339 int32_t luma_repeat[4];
340 int32_t chroma_interp[4];
341 int32_t chroma_bound[4];
342 int32_t chroma_repeat[4];
343 uint32_t dst_w, dst_h;
344
345 memset(&luma_interp, 0, sizeof(int32_t) * 4);
346 memset(&luma_repeat, 0, sizeof(int32_t) * 4);
347 memset(&chroma_interp, 0, sizeof(int32_t) * 4);
348 memset(&chroma_bound, 0, sizeof(int32_t) * 4);
349 memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
350 regs->edge = 0;
351
352 if (req->flags & MDP_ROT_90) {
353 dst_w = req->dst_rect.h;
354 dst_h = req->dst_rect.w;
355 } else {
356 dst_w = req->dst_rect.w;
357 dst_h = req->dst_rect.h;
358 }
359
360 if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
361 get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
362 &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
363 &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
364 get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
365 &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
366 &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
367 } else {
368 luma_interp[IMG_LEFT] = req->src_rect.x;
369 luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
370 luma_interp[IMG_TOP] = req->src_rect.y;
371 luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
372 luma_repeat[IMG_LEFT] = 0;
373 luma_repeat[IMG_TOP] = 0;
374 luma_repeat[IMG_RIGHT] = 0;
375 luma_repeat[IMG_BOTTOM] = 0;
376 }
377
378 chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
379 chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
380 chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
381 chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
382
383 chroma_bound[IMG_LEFT] = req->src_rect.x;
384 chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
385 chroma_bound[IMG_TOP] = req->src_rect.y;
386 chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
387
388 if (IS_YCRCB(req->src.format)) {
389 chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
390 chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
391
392 chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
393 chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
394 }
395
396 if (req->src.format == MDP_Y_CBCR_H2V2 ||
397 req->src.format == MDP_Y_CRCB_H2V2) {
398 chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
399 chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
400 >> 1;
401 chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
402 chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
403 }
404
405 chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
406 chroma_interp[IMG_LEFT];
407 chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
408 chroma_bound[IMG_RIGHT];
409 chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
410 chroma_interp[IMG_TOP];
411 chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
412 chroma_bound[IMG_BOTTOM];
413
414 if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
415 chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
416 chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
417 chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
418 luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
419 luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
420 luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
421 luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
422 return -1;
423
424 regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
425 regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
426 regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
427 regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
428 regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
429 regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
430 regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
431 regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
432 return 0;
433}
434
435static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
436 struct mdp_regs *regs)
437{
438 uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
439 uint32_t scale_factor_x, scale_factor_y;
440 uint32_t downscale;
441 uint32_t dst_w, dst_h;
442
443 if (req->flags & MDP_ROT_90) {
444 dst_w = req->dst_rect.h;
445 dst_h = req->dst_rect.w;
446 } else {
447 dst_w = req->dst_rect.w;
448 dst_h = req->dst_rect.h;
449 }
450 if ((req->src_rect.w == dst_w) && (req->src_rect.h == dst_h) &&
451 !(req->flags & MDP_BLUR)) {
452 regs->phasex_init = 0;
453 regs->phasey_init = 0;
454 regs->phasex_step = 0;
455 regs->phasey_step = 0;
456 return 0;
457 }
458
459 if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
460 &phase_step_x) ||
461 scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
462 &phase_step_y))
463 return -1;
464
465 scale_factor_x = (dst_w * 10) / req->src_rect.w;
466 scale_factor_y = (dst_h * 10) / req->src_rect.h;
467
468 if (scale_factor_x > 8)
469 downscale = MDP_DOWNSCALE_PT8TO1;
470 else if (scale_factor_x > 6)
471 downscale = MDP_DOWNSCALE_PT6TOPT8;
472 else if (scale_factor_x > 4)
473 downscale = MDP_DOWNSCALE_PT4TOPT6;
474 else
475 downscale = MDP_DOWNSCALE_PT2TOPT4;
476 if (downscale != downscale_x_table) {
477 load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
478 downscale_x_table = downscale;
479 }
480
481 if (scale_factor_y > 8)
482 downscale = MDP_DOWNSCALE_PT8TO1;
483 else if (scale_factor_y > 6)
484 downscale = MDP_DOWNSCALE_PT6TOPT8;
485 else if (scale_factor_y > 4)
486 downscale = MDP_DOWNSCALE_PT4TOPT6;
487 else
488 downscale = MDP_DOWNSCALE_PT2TOPT4;
489 if (downscale != downscale_y_table) {
490 load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
491 downscale_y_table = downscale;
492 }
493
494 regs->phasex_init = phase_init_x;
495 regs->phasey_init = phase_init_y;
496 regs->phasex_step = phase_step_x;
497 regs->phasey_step = phase_step_y;
498 regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
499 return 0;
500
501}
502
503static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
504 struct mdp_regs *regs)
505{
506 if (!(req->flags & MDP_BLUR))
507 return;
508
509 if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
510 downscale_y_table == MDP_DOWNSCALE_BLUR)) {
511 load_scale_table(mdp, mdp_gaussian_blur_table, 128);
512 downscale_x_table = MDP_DOWNSCALE_BLUR;
513 downscale_y_table = MDP_DOWNSCALE_BLUR;
514 }
515
516 regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
517}
518
519
520#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
521
522#define Y_TO_CRCB_RATIO(format) \
523 ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
524 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
525
526static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
527 uint32_t *len0, uint32_t *len1)
528{
529 *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
530 if (IS_PSEUDOPLNR(img->format))
531 *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
532 else
533 *len1 = 0;
534}
535
536static int valid_src_dst(unsigned long src_start, unsigned long src_len,
537 unsigned long dst_start, unsigned long dst_len,
538 struct mdp_blit_req *req, struct mdp_regs *regs)
539{
540 unsigned long src_min_ok = src_start;
541 unsigned long src_max_ok = src_start + src_len;
542 unsigned long dst_min_ok = dst_start;
543 unsigned long dst_max_ok = dst_start + dst_len;
544 uint32_t src0_len, src1_len, dst0_len, dst1_len;
545 get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
546 &src1_len);
547 get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
548 &dst1_len);
549
550 if (regs->src0 < src_min_ok || regs->src0 > src_max_ok ||
551 regs->src0 + src0_len > src_max_ok) {
552 DLOG("invalid_src %x %x %lx %lx\n", regs->src0,
553 src0_len, src_min_ok, src_max_ok);
554 return 0;
555 }
556 if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
557 if (regs->src1 < src_min_ok || regs->src1 > src_max_ok ||
558 regs->src1 + src1_len > src_max_ok) {
559 DLOG("invalid_src1");
560 return 0;
561 }
562 }
563 if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok ||
564 regs->dst0 + dst0_len > dst_max_ok) {
565 DLOG("invalid_dst");
566 return 0;
567 }
568 if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
569 if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok ||
570 regs->dst1 + dst1_len > dst_max_ok) {
571 DLOG("invalid_dst1");
572 return 0;
573 }
574 }
575 return 1;
576}
577
578
579static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
580 struct file *src_file, struct file *dst_file)
581{
582#ifdef CONFIG_ANDROID_PMEM
583 uint32_t src0_len, src1_len, dst0_len, dst1_len;
584
585 /* flush src images to memory before dma to mdp */
586 get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
587 &src1_len);
588 flush_pmem_file(src_file, req->src.offset, src0_len);
589 if (IS_PSEUDOPLNR(req->src.format))
590 flush_pmem_file(src_file, req->src.offset + src0_len,
591 src1_len);
592
593 /* flush dst images */
594 get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
595 &dst1_len);
596 flush_pmem_file(dst_file, req->dst.offset, dst0_len);
597 if (IS_PSEUDOPLNR(req->dst.format))
598 flush_pmem_file(dst_file, req->dst.offset + dst0_len,
599 dst1_len);
600#endif
601}
602
603static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
604 uint32_t base, uint32_t bpp, uint32_t cfg,
605 uint32_t *addr, uint32_t *ystride)
606{
607 uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
608 uint32_t compress_h = 2;
609 uint32_t offset;
610
611 if (IS_PSEUDOPLNR(img->format)) {
612 offset = (rect->x / compress_h) * compress_h;
613 offset += rect->y == 0 ? 0 :
614 ((rect->y + 1) / compress_v) * img->width;
615 *addr = base + (img->width * img->height * bpp);
616 *addr += offset * bpp;
617 *ystride |= *ystride << 16;
618 } else {
619 *addr = 0;
620 }
621}
622
623static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
624 struct mdp_regs *regs, struct file *src_file,
625 struct file *dst_file)
626{
627 mdp_writel(mdp, 1, 0x060);
628 mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
629 mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
630 mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
631 mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
632 mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
633 mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
634
635 mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
636 mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
637 mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
638 mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
639 mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
640
641 mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
642 PPP_ADDR_ALPHA_TRANSP);
643
644 mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
645 mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
646 mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
647 mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
648 mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
649 mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
650
651 mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
652 if (regs->op & PPP_OP_BLEND_ON) {
653 mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
654 mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
655 mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
656 mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
657 mdp_writel(mdp, pack_pattern[req->dst.format],
658 PPP_ADDR_BG_PACK_PATTERN);
659 }
660 flush_imgs(req, regs, src_file, dst_file);
661 mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
662 return 0;
663}
664
665int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
666 struct file *src_file, unsigned long src_start, unsigned long src_len,
667 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
668{
669 struct mdp_regs regs = {0};
670
671 if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
672 req->dst.format >= MDP_IMGTYPE_LIMIT)) {
673 printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
674 return -EINVAL;
675 }
676
677 if (unlikely(req->src_rect.x > req->src.width ||
678 req->src_rect.y > req->src.height ||
679 req->dst_rect.x > req->dst.width ||
680 req->dst_rect.y > req->dst.height)) {
681 printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
682 return -EINVAL;
683 }
684
685 /* set the src image configuration */
686 regs.src_cfg = src_img_cfg[req->src.format];
687 regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
688 regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
689 regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
690 regs.src_pack = pack_pattern[req->src.format];
691
692 /* set the dest image configuration */
693 regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
694 regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
695 regs.dst_pack = pack_pattern[req->dst.format];
696
697 /* set src, bpp, start pixel and ystride */
698 regs.src_bpp = bytes_per_pixel[req->src.format];
699 regs.src0 = src_start + req->src.offset;
700 regs.src_ystride = req->src.width * regs.src_bpp;
701 get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
702 regs.src_cfg, &regs.src1, &regs.src_ystride);
703 regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
704 regs.src_bpp;
705
706 /* set dst, bpp, start pixel and ystride */
707 regs.dst_bpp = bytes_per_pixel[req->dst.format];
708 regs.dst0 = dst_start + req->dst.offset;
709 regs.dst_ystride = req->dst.width * regs.dst_bpp;
710 get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
711 regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
712 regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
713 regs.dst_bpp;
714
715 if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
716 &regs)) {
717 printk(KERN_ERR "mpd_ppp: final src or dst location is "
718 "invalid, are you trying to make an image too large "
719 "or to place it outside the screen?\n");
720 return -EINVAL;
721 }
722
723 /* set up operation register */
724 regs.op = 0;
725 blit_rotate(req, &regs);
726 blit_convert(req, &regs);
727 if (req->flags & MDP_DITHER)
728 regs.op |= PPP_OP_DITHER_EN;
729 blit_blend(req, &regs);
730 if (blit_scale(mdp, req, &regs)) {
731 printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
732 return -EINVAL;
733 }
734 blit_blur(mdp, req, &regs);
735 regs.op |= dst_op_chroma[req->dst.format] |
736 src_op_chroma[req->src.format];
737
738 /* if the image is YCRYCB, the x and w must be even */
739 if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) {
740 req->src_rect.x = req->src_rect.x & (~0x1);
741 req->src_rect.w = req->src_rect.w & (~0x1);
742 req->dst_rect.x = req->dst_rect.x & (~0x1);
743 req->dst_rect.w = req->dst_rect.w & (~0x1);
744 }
745 if (get_edge_cond(req, &regs))
746 return -EINVAL;
747
748 send_blit(mdp, req, &regs, src_file, dst_file);
749 return 0;
750}
diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/msm/mdp_scale_tables.c
new file mode 100644
index 000000000000..604783b2e17c
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.c
@@ -0,0 +1,766 @@
1/* drivers/video/msm_fb/mdp_scale_tables.c
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include "mdp_scale_tables.h"
17#include "mdp_hw.h"
18
19struct mdp_table_entry mdp_upscale_table[] = {
20 { 0x5fffc, 0x0 },
21 { 0x50200, 0x7fc00000 },
22 { 0x5fffc, 0xff80000d },
23 { 0x50204, 0x7ec003f9 },
24 { 0x5fffc, 0xfec0001c },
25 { 0x50208, 0x7d4003f3 },
26 { 0x5fffc, 0xfe40002b },
27 { 0x5020c, 0x7b8003ed },
28 { 0x5fffc, 0xfd80003c },
29 { 0x50210, 0x794003e8 },
30 { 0x5fffc, 0xfcc0004d },
31 { 0x50214, 0x76c003e4 },
32 { 0x5fffc, 0xfc40005f },
33 { 0x50218, 0x73c003e0 },
34 { 0x5fffc, 0xfb800071 },
35 { 0x5021c, 0x708003de },
36 { 0x5fffc, 0xfac00085 },
37 { 0x50220, 0x6d0003db },
38 { 0x5fffc, 0xfa000098 },
39 { 0x50224, 0x698003d9 },
40 { 0x5fffc, 0xf98000ac },
41 { 0x50228, 0x654003d8 },
42 { 0x5fffc, 0xf8c000c1 },
43 { 0x5022c, 0x610003d7 },
44 { 0x5fffc, 0xf84000d5 },
45 { 0x50230, 0x5c8003d7 },
46 { 0x5fffc, 0xf7c000e9 },
47 { 0x50234, 0x580003d7 },
48 { 0x5fffc, 0xf74000fd },
49 { 0x50238, 0x534003d8 },
50 { 0x5fffc, 0xf6c00112 },
51 { 0x5023c, 0x4e8003d8 },
52 { 0x5fffc, 0xf6800126 },
53 { 0x50240, 0x494003da },
54 { 0x5fffc, 0xf600013a },
55 { 0x50244, 0x448003db },
56 { 0x5fffc, 0xf600014d },
57 { 0x50248, 0x3f4003dd },
58 { 0x5fffc, 0xf5c00160 },
59 { 0x5024c, 0x3a4003df },
60 { 0x5fffc, 0xf5c00172 },
61 { 0x50250, 0x354003e1 },
62 { 0x5fffc, 0xf5c00184 },
63 { 0x50254, 0x304003e3 },
64 { 0x5fffc, 0xf6000195 },
65 { 0x50258, 0x2b0003e6 },
66 { 0x5fffc, 0xf64001a6 },
67 { 0x5025c, 0x260003e8 },
68 { 0x5fffc, 0xf6c001b4 },
69 { 0x50260, 0x214003eb },
70 { 0x5fffc, 0xf78001c2 },
71 { 0x50264, 0x1c4003ee },
72 { 0x5fffc, 0xf80001cf },
73 { 0x50268, 0x17c003f1 },
74 { 0x5fffc, 0xf90001db },
75 { 0x5026c, 0x134003f3 },
76 { 0x5fffc, 0xfa0001e5 },
77 { 0x50270, 0xf0003f6 },
78 { 0x5fffc, 0xfb4001ee },
79 { 0x50274, 0xac003f9 },
80 { 0x5fffc, 0xfcc001f5 },
81 { 0x50278, 0x70003fb },
82 { 0x5fffc, 0xfe4001fb },
83 { 0x5027c, 0x34003fe },
84};
85
86static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = {
87 { 0x5fffc, 0x740008c },
88 { 0x50280, 0x33800088 },
89 { 0x5fffc, 0x800008e },
90 { 0x50284, 0x33400084 },
91 { 0x5fffc, 0x8400092 },
92 { 0x50288, 0x33000080 },
93 { 0x5fffc, 0x9000094 },
94 { 0x5028c, 0x3300007b },
95 { 0x5fffc, 0x9c00098 },
96 { 0x50290, 0x32400077 },
97 { 0x5fffc, 0xa40009b },
98 { 0x50294, 0x32000073 },
99 { 0x5fffc, 0xb00009d },
100 { 0x50298, 0x31c0006f },
101 { 0x5fffc, 0xbc000a0 },
102 { 0x5029c, 0x3140006b },
103 { 0x5fffc, 0xc8000a2 },
104 { 0x502a0, 0x31000067 },
105 { 0x5fffc, 0xd8000a5 },
106 { 0x502a4, 0x30800062 },
107 { 0x5fffc, 0xe4000a8 },
108 { 0x502a8, 0x2fc0005f },
109 { 0x5fffc, 0xec000aa },
110 { 0x502ac, 0x2fc0005b },
111 { 0x5fffc, 0xf8000ad },
112 { 0x502b0, 0x2f400057 },
113 { 0x5fffc, 0x108000b0 },
114 { 0x502b4, 0x2e400054 },
115 { 0x5fffc, 0x114000b2 },
116 { 0x502b8, 0x2e000050 },
117 { 0x5fffc, 0x124000b4 },
118 { 0x502bc, 0x2d80004c },
119 { 0x5fffc, 0x130000b6 },
120 { 0x502c0, 0x2d000049 },
121 { 0x5fffc, 0x140000b8 },
122 { 0x502c4, 0x2c800045 },
123 { 0x5fffc, 0x150000b9 },
124 { 0x502c8, 0x2c000042 },
125 { 0x5fffc, 0x15c000bd },
126 { 0x502cc, 0x2b40003e },
127 { 0x5fffc, 0x16c000bf },
128 { 0x502d0, 0x2a80003b },
129 { 0x5fffc, 0x17c000bf },
130 { 0x502d4, 0x2a000039 },
131 { 0x5fffc, 0x188000c2 },
132 { 0x502d8, 0x29400036 },
133 { 0x5fffc, 0x19c000c4 },
134 { 0x502dc, 0x28800032 },
135 { 0x5fffc, 0x1ac000c5 },
136 { 0x502e0, 0x2800002f },
137 { 0x5fffc, 0x1bc000c7 },
138 { 0x502e4, 0x2740002c },
139 { 0x5fffc, 0x1cc000c8 },
140 { 0x502e8, 0x26c00029 },
141 { 0x5fffc, 0x1dc000c9 },
142 { 0x502ec, 0x26000027 },
143 { 0x5fffc, 0x1ec000cc },
144 { 0x502f0, 0x25000024 },
145 { 0x5fffc, 0x200000cc },
146 { 0x502f4, 0x24800021 },
147 { 0x5fffc, 0x210000cd },
148 { 0x502f8, 0x23800020 },
149 { 0x5fffc, 0x220000ce },
150 { 0x502fc, 0x2300001d },
151};
152
153static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = {
154 { 0x5fffc, 0x740008c },
155 { 0x50280, 0x33800088 },
156 { 0x5fffc, 0x800008e },
157 { 0x50284, 0x33400084 },
158 { 0x5fffc, 0x8400092 },
159 { 0x50288, 0x33000080 },
160 { 0x5fffc, 0x9000094 },
161 { 0x5028c, 0x3300007b },
162 { 0x5fffc, 0x9c00098 },
163 { 0x50290, 0x32400077 },
164 { 0x5fffc, 0xa40009b },
165 { 0x50294, 0x32000073 },
166 { 0x5fffc, 0xb00009d },
167 { 0x50298, 0x31c0006f },
168 { 0x5fffc, 0xbc000a0 },
169 { 0x5029c, 0x3140006b },
170 { 0x5fffc, 0xc8000a2 },
171 { 0x502a0, 0x31000067 },
172 { 0x5fffc, 0xd8000a5 },
173 { 0x502a4, 0x30800062 },
174 { 0x5fffc, 0xe4000a8 },
175 { 0x502a8, 0x2fc0005f },
176 { 0x5fffc, 0xec000aa },
177 { 0x502ac, 0x2fc0005b },
178 { 0x5fffc, 0xf8000ad },
179 { 0x502b0, 0x2f400057 },
180 { 0x5fffc, 0x108000b0 },
181 { 0x502b4, 0x2e400054 },
182 { 0x5fffc, 0x114000b2 },
183 { 0x502b8, 0x2e000050 },
184 { 0x5fffc, 0x124000b4 },
185 { 0x502bc, 0x2d80004c },
186 { 0x5fffc, 0x130000b6 },
187 { 0x502c0, 0x2d000049 },
188 { 0x5fffc, 0x140000b8 },
189 { 0x502c4, 0x2c800045 },
190 { 0x5fffc, 0x150000b9 },
191 { 0x502c8, 0x2c000042 },
192 { 0x5fffc, 0x15c000bd },
193 { 0x502cc, 0x2b40003e },
194 { 0x5fffc, 0x16c000bf },
195 { 0x502d0, 0x2a80003b },
196 { 0x5fffc, 0x17c000bf },
197 { 0x502d4, 0x2a000039 },
198 { 0x5fffc, 0x188000c2 },
199 { 0x502d8, 0x29400036 },
200 { 0x5fffc, 0x19c000c4 },
201 { 0x502dc, 0x28800032 },
202 { 0x5fffc, 0x1ac000c5 },
203 { 0x502e0, 0x2800002f },
204 { 0x5fffc, 0x1bc000c7 },
205 { 0x502e4, 0x2740002c },
206 { 0x5fffc, 0x1cc000c8 },
207 { 0x502e8, 0x26c00029 },
208 { 0x5fffc, 0x1dc000c9 },
209 { 0x502ec, 0x26000027 },
210 { 0x5fffc, 0x1ec000cc },
211 { 0x502f0, 0x25000024 },
212 { 0x5fffc, 0x200000cc },
213 { 0x502f4, 0x24800021 },
214 { 0x5fffc, 0x210000cd },
215 { 0x502f8, 0x23800020 },
216 { 0x5fffc, 0x220000ce },
217 { 0x502fc, 0x2300001d },
218};
219
220static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = {
221 { 0x5fffc, 0xfe000070 },
222 { 0x50280, 0x4bc00068 },
223 { 0x5fffc, 0xfe000078 },
224 { 0x50284, 0x4bc00060 },
225 { 0x5fffc, 0xfe000080 },
226 { 0x50288, 0x4b800059 },
227 { 0x5fffc, 0xfe000089 },
228 { 0x5028c, 0x4b000052 },
229 { 0x5fffc, 0xfe400091 },
230 { 0x50290, 0x4a80004b },
231 { 0x5fffc, 0xfe40009a },
232 { 0x50294, 0x4a000044 },
233 { 0x5fffc, 0xfe8000a3 },
234 { 0x50298, 0x4940003d },
235 { 0x5fffc, 0xfec000ac },
236 { 0x5029c, 0x48400037 },
237 { 0x5fffc, 0xff0000b4 },
238 { 0x502a0, 0x47800031 },
239 { 0x5fffc, 0xff8000bd },
240 { 0x502a4, 0x4640002b },
241 { 0x5fffc, 0xc5 },
242 { 0x502a8, 0x45000026 },
243 { 0x5fffc, 0x8000ce },
244 { 0x502ac, 0x43800021 },
245 { 0x5fffc, 0x10000d6 },
246 { 0x502b0, 0x4240001c },
247 { 0x5fffc, 0x18000df },
248 { 0x502b4, 0x40800018 },
249 { 0x5fffc, 0x24000e6 },
250 { 0x502b8, 0x3f000014 },
251 { 0x5fffc, 0x30000ee },
252 { 0x502bc, 0x3d400010 },
253 { 0x5fffc, 0x40000f5 },
254 { 0x502c0, 0x3b80000c },
255 { 0x5fffc, 0x50000fc },
256 { 0x502c4, 0x39800009 },
257 { 0x5fffc, 0x6000102 },
258 { 0x502c8, 0x37c00006 },
259 { 0x5fffc, 0x7000109 },
260 { 0x502cc, 0x35800004 },
261 { 0x5fffc, 0x840010e },
262 { 0x502d0, 0x33800002 },
263 { 0x5fffc, 0x9800114 },
264 { 0x502d4, 0x31400000 },
265 { 0x5fffc, 0xac00119 },
266 { 0x502d8, 0x2f4003fe },
267 { 0x5fffc, 0xc40011e },
268 { 0x502dc, 0x2d0003fc },
269 { 0x5fffc, 0xdc00121 },
270 { 0x502e0, 0x2b0003fb },
271 { 0x5fffc, 0xf400125 },
272 { 0x502e4, 0x28c003fa },
273 { 0x5fffc, 0x11000128 },
274 { 0x502e8, 0x268003f9 },
275 { 0x5fffc, 0x12c0012a },
276 { 0x502ec, 0x244003f9 },
277 { 0x5fffc, 0x1480012c },
278 { 0x502f0, 0x224003f8 },
279 { 0x5fffc, 0x1640012e },
280 { 0x502f4, 0x200003f8 },
281 { 0x5fffc, 0x1800012f },
282 { 0x502f8, 0x1e0003f8 },
283 { 0x5fffc, 0x1a00012f },
284 { 0x502fc, 0x1c0003f8 },
285};
286
287static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = {
288 { 0x5fffc, 0x0 },
289 { 0x50280, 0x7fc00000 },
290 { 0x5fffc, 0xff80000d },
291 { 0x50284, 0x7ec003f9 },
292 { 0x5fffc, 0xfec0001c },
293 { 0x50288, 0x7d4003f3 },
294 { 0x5fffc, 0xfe40002b },
295 { 0x5028c, 0x7b8003ed },
296 { 0x5fffc, 0xfd80003c },
297 { 0x50290, 0x794003e8 },
298 { 0x5fffc, 0xfcc0004d },
299 { 0x50294, 0x76c003e4 },
300 { 0x5fffc, 0xfc40005f },
301 { 0x50298, 0x73c003e0 },
302 { 0x5fffc, 0xfb800071 },
303 { 0x5029c, 0x708003de },
304 { 0x5fffc, 0xfac00085 },
305 { 0x502a0, 0x6d0003db },
306 { 0x5fffc, 0xfa000098 },
307 { 0x502a4, 0x698003d9 },
308 { 0x5fffc, 0xf98000ac },
309 { 0x502a8, 0x654003d8 },
310 { 0x5fffc, 0xf8c000c1 },
311 { 0x502ac, 0x610003d7 },
312 { 0x5fffc, 0xf84000d5 },
313 { 0x502b0, 0x5c8003d7 },
314 { 0x5fffc, 0xf7c000e9 },
315 { 0x502b4, 0x580003d7 },
316 { 0x5fffc, 0xf74000fd },
317 { 0x502b8, 0x534003d8 },
318 { 0x5fffc, 0xf6c00112 },
319 { 0x502bc, 0x4e8003d8 },
320 { 0x5fffc, 0xf6800126 },
321 { 0x502c0, 0x494003da },
322 { 0x5fffc, 0xf600013a },
323 { 0x502c4, 0x448003db },
324 { 0x5fffc, 0xf600014d },
325 { 0x502c8, 0x3f4003dd },
326 { 0x5fffc, 0xf5c00160 },
327 { 0x502cc, 0x3a4003df },
328 { 0x5fffc, 0xf5c00172 },
329 { 0x502d0, 0x354003e1 },
330 { 0x5fffc, 0xf5c00184 },
331 { 0x502d4, 0x304003e3 },
332 { 0x5fffc, 0xf6000195 },
333 { 0x502d8, 0x2b0003e6 },
334 { 0x5fffc, 0xf64001a6 },
335 { 0x502dc, 0x260003e8 },
336 { 0x5fffc, 0xf6c001b4 },
337 { 0x502e0, 0x214003eb },
338 { 0x5fffc, 0xf78001c2 },
339 { 0x502e4, 0x1c4003ee },
340 { 0x5fffc, 0xf80001cf },
341 { 0x502e8, 0x17c003f1 },
342 { 0x5fffc, 0xf90001db },
343 { 0x502ec, 0x134003f3 },
344 { 0x5fffc, 0xfa0001e5 },
345 { 0x502f0, 0xf0003f6 },
346 { 0x5fffc, 0xfb4001ee },
347 { 0x502f4, 0xac003f9 },
348 { 0x5fffc, 0xfcc001f5 },
349 { 0x502f8, 0x70003fb },
350 { 0x5fffc, 0xfe4001fb },
351 { 0x502fc, 0x34003fe },
352};
353
354struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = {
355 [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4,
356 [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6,
357 [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8,
358 [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_x_table_PT8TO1,
359};
360
361static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = {
362 { 0x5fffc, 0x740008c },
363 { 0x50300, 0x33800088 },
364 { 0x5fffc, 0x800008e },
365 { 0x50304, 0x33400084 },
366 { 0x5fffc, 0x8400092 },
367 { 0x50308, 0x33000080 },
368 { 0x5fffc, 0x9000094 },
369 { 0x5030c, 0x3300007b },
370 { 0x5fffc, 0x9c00098 },
371 { 0x50310, 0x32400077 },
372 { 0x5fffc, 0xa40009b },
373 { 0x50314, 0x32000073 },
374 { 0x5fffc, 0xb00009d },
375 { 0x50318, 0x31c0006f },
376 { 0x5fffc, 0xbc000a0 },
377 { 0x5031c, 0x3140006b },
378 { 0x5fffc, 0xc8000a2 },
379 { 0x50320, 0x31000067 },
380 { 0x5fffc, 0xd8000a5 },
381 { 0x50324, 0x30800062 },
382 { 0x5fffc, 0xe4000a8 },
383 { 0x50328, 0x2fc0005f },
384 { 0x5fffc, 0xec000aa },
385 { 0x5032c, 0x2fc0005b },
386 { 0x5fffc, 0xf8000ad },
387 { 0x50330, 0x2f400057 },
388 { 0x5fffc, 0x108000b0 },
389 { 0x50334, 0x2e400054 },
390 { 0x5fffc, 0x114000b2 },
391 { 0x50338, 0x2e000050 },
392 { 0x5fffc, 0x124000b4 },
393 { 0x5033c, 0x2d80004c },
394 { 0x5fffc, 0x130000b6 },
395 { 0x50340, 0x2d000049 },
396 { 0x5fffc, 0x140000b8 },
397 { 0x50344, 0x2c800045 },
398 { 0x5fffc, 0x150000b9 },
399 { 0x50348, 0x2c000042 },
400 { 0x5fffc, 0x15c000bd },
401 { 0x5034c, 0x2b40003e },
402 { 0x5fffc, 0x16c000bf },
403 { 0x50350, 0x2a80003b },
404 { 0x5fffc, 0x17c000bf },
405 { 0x50354, 0x2a000039 },
406 { 0x5fffc, 0x188000c2 },
407 { 0x50358, 0x29400036 },
408 { 0x5fffc, 0x19c000c4 },
409 { 0x5035c, 0x28800032 },
410 { 0x5fffc, 0x1ac000c5 },
411 { 0x50360, 0x2800002f },
412 { 0x5fffc, 0x1bc000c7 },
413 { 0x50364, 0x2740002c },
414 { 0x5fffc, 0x1cc000c8 },
415 { 0x50368, 0x26c00029 },
416 { 0x5fffc, 0x1dc000c9 },
417 { 0x5036c, 0x26000027 },
418 { 0x5fffc, 0x1ec000cc },
419 { 0x50370, 0x25000024 },
420 { 0x5fffc, 0x200000cc },
421 { 0x50374, 0x24800021 },
422 { 0x5fffc, 0x210000cd },
423 { 0x50378, 0x23800020 },
424 { 0x5fffc, 0x220000ce },
425 { 0x5037c, 0x2300001d },
426};
427
428static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = {
429 { 0x5fffc, 0x740008c },
430 { 0x50300, 0x33800088 },
431 { 0x5fffc, 0x800008e },
432 { 0x50304, 0x33400084 },
433 { 0x5fffc, 0x8400092 },
434 { 0x50308, 0x33000080 },
435 { 0x5fffc, 0x9000094 },
436 { 0x5030c, 0x3300007b },
437 { 0x5fffc, 0x9c00098 },
438 { 0x50310, 0x32400077 },
439 { 0x5fffc, 0xa40009b },
440 { 0x50314, 0x32000073 },
441 { 0x5fffc, 0xb00009d },
442 { 0x50318, 0x31c0006f },
443 { 0x5fffc, 0xbc000a0 },
444 { 0x5031c, 0x3140006b },
445 { 0x5fffc, 0xc8000a2 },
446 { 0x50320, 0x31000067 },
447 { 0x5fffc, 0xd8000a5 },
448 { 0x50324, 0x30800062 },
449 { 0x5fffc, 0xe4000a8 },
450 { 0x50328, 0x2fc0005f },
451 { 0x5fffc, 0xec000aa },
452 { 0x5032c, 0x2fc0005b },
453 { 0x5fffc, 0xf8000ad },
454 { 0x50330, 0x2f400057 },
455 { 0x5fffc, 0x108000b0 },
456 { 0x50334, 0x2e400054 },
457 { 0x5fffc, 0x114000b2 },
458 { 0x50338, 0x2e000050 },
459 { 0x5fffc, 0x124000b4 },
460 { 0x5033c, 0x2d80004c },
461 { 0x5fffc, 0x130000b6 },
462 { 0x50340, 0x2d000049 },
463 { 0x5fffc, 0x140000b8 },
464 { 0x50344, 0x2c800045 },
465 { 0x5fffc, 0x150000b9 },
466 { 0x50348, 0x2c000042 },
467 { 0x5fffc, 0x15c000bd },
468 { 0x5034c, 0x2b40003e },
469 { 0x5fffc, 0x16c000bf },
470 { 0x50350, 0x2a80003b },
471 { 0x5fffc, 0x17c000bf },
472 { 0x50354, 0x2a000039 },
473 { 0x5fffc, 0x188000c2 },
474 { 0x50358, 0x29400036 },
475 { 0x5fffc, 0x19c000c4 },
476 { 0x5035c, 0x28800032 },
477 { 0x5fffc, 0x1ac000c5 },
478 { 0x50360, 0x2800002f },
479 { 0x5fffc, 0x1bc000c7 },
480 { 0x50364, 0x2740002c },
481 { 0x5fffc, 0x1cc000c8 },
482 { 0x50368, 0x26c00029 },
483 { 0x5fffc, 0x1dc000c9 },
484 { 0x5036c, 0x26000027 },
485 { 0x5fffc, 0x1ec000cc },
486 { 0x50370, 0x25000024 },
487 { 0x5fffc, 0x200000cc },
488 { 0x50374, 0x24800021 },
489 { 0x5fffc, 0x210000cd },
490 { 0x50378, 0x23800020 },
491 { 0x5fffc, 0x220000ce },
492 { 0x5037c, 0x2300001d },
493};
494
495static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = {
496 { 0x5fffc, 0xfe000070 },
497 { 0x50300, 0x4bc00068 },
498 { 0x5fffc, 0xfe000078 },
499 { 0x50304, 0x4bc00060 },
500 { 0x5fffc, 0xfe000080 },
501 { 0x50308, 0x4b800059 },
502 { 0x5fffc, 0xfe000089 },
503 { 0x5030c, 0x4b000052 },
504 { 0x5fffc, 0xfe400091 },
505 { 0x50310, 0x4a80004b },
506 { 0x5fffc, 0xfe40009a },
507 { 0x50314, 0x4a000044 },
508 { 0x5fffc, 0xfe8000a3 },
509 { 0x50318, 0x4940003d },
510 { 0x5fffc, 0xfec000ac },
511 { 0x5031c, 0x48400037 },
512 { 0x5fffc, 0xff0000b4 },
513 { 0x50320, 0x47800031 },
514 { 0x5fffc, 0xff8000bd },
515 { 0x50324, 0x4640002b },
516 { 0x5fffc, 0xc5 },
517 { 0x50328, 0x45000026 },
518 { 0x5fffc, 0x8000ce },
519 { 0x5032c, 0x43800021 },
520 { 0x5fffc, 0x10000d6 },
521 { 0x50330, 0x4240001c },
522 { 0x5fffc, 0x18000df },
523 { 0x50334, 0x40800018 },
524 { 0x5fffc, 0x24000e6 },
525 { 0x50338, 0x3f000014 },
526 { 0x5fffc, 0x30000ee },
527 { 0x5033c, 0x3d400010 },
528 { 0x5fffc, 0x40000f5 },
529 { 0x50340, 0x3b80000c },
530 { 0x5fffc, 0x50000fc },
531 { 0x50344, 0x39800009 },
532 { 0x5fffc, 0x6000102 },
533 { 0x50348, 0x37c00006 },
534 { 0x5fffc, 0x7000109 },
535 { 0x5034c, 0x35800004 },
536 { 0x5fffc, 0x840010e },
537 { 0x50350, 0x33800002 },
538 { 0x5fffc, 0x9800114 },
539 { 0x50354, 0x31400000 },
540 { 0x5fffc, 0xac00119 },
541 { 0x50358, 0x2f4003fe },
542 { 0x5fffc, 0xc40011e },
543 { 0x5035c, 0x2d0003fc },
544 { 0x5fffc, 0xdc00121 },
545 { 0x50360, 0x2b0003fb },
546 { 0x5fffc, 0xf400125 },
547 { 0x50364, 0x28c003fa },
548 { 0x5fffc, 0x11000128 },
549 { 0x50368, 0x268003f9 },
550 { 0x5fffc, 0x12c0012a },
551 { 0x5036c, 0x244003f9 },
552 { 0x5fffc, 0x1480012c },
553 { 0x50370, 0x224003f8 },
554 { 0x5fffc, 0x1640012e },
555 { 0x50374, 0x200003f8 },
556 { 0x5fffc, 0x1800012f },
557 { 0x50378, 0x1e0003f8 },
558 { 0x5fffc, 0x1a00012f },
559 { 0x5037c, 0x1c0003f8 },
560};
561
562static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = {
563 { 0x5fffc, 0x0 },
564 { 0x50300, 0x7fc00000 },
565 { 0x5fffc, 0xff80000d },
566 { 0x50304, 0x7ec003f9 },
567 { 0x5fffc, 0xfec0001c },
568 { 0x50308, 0x7d4003f3 },
569 { 0x5fffc, 0xfe40002b },
570 { 0x5030c, 0x7b8003ed },
571 { 0x5fffc, 0xfd80003c },
572 { 0x50310, 0x794003e8 },
573 { 0x5fffc, 0xfcc0004d },
574 { 0x50314, 0x76c003e4 },
575 { 0x5fffc, 0xfc40005f },
576 { 0x50318, 0x73c003e0 },
577 { 0x5fffc, 0xfb800071 },
578 { 0x5031c, 0x708003de },
579 { 0x5fffc, 0xfac00085 },
580 { 0x50320, 0x6d0003db },
581 { 0x5fffc, 0xfa000098 },
582 { 0x50324, 0x698003d9 },
583 { 0x5fffc, 0xf98000ac },
584 { 0x50328, 0x654003d8 },
585 { 0x5fffc, 0xf8c000c1 },
586 { 0x5032c, 0x610003d7 },
587 { 0x5fffc, 0xf84000d5 },
588 { 0x50330, 0x5c8003d7 },
589 { 0x5fffc, 0xf7c000e9 },
590 { 0x50334, 0x580003d7 },
591 { 0x5fffc, 0xf74000fd },
592 { 0x50338, 0x534003d8 },
593 { 0x5fffc, 0xf6c00112 },
594 { 0x5033c, 0x4e8003d8 },
595 { 0x5fffc, 0xf6800126 },
596 { 0x50340, 0x494003da },
597 { 0x5fffc, 0xf600013a },
598 { 0x50344, 0x448003db },
599 { 0x5fffc, 0xf600014d },
600 { 0x50348, 0x3f4003dd },
601 { 0x5fffc, 0xf5c00160 },
602 { 0x5034c, 0x3a4003df },
603 { 0x5fffc, 0xf5c00172 },
604 { 0x50350, 0x354003e1 },
605 { 0x5fffc, 0xf5c00184 },
606 { 0x50354, 0x304003e3 },
607 { 0x5fffc, 0xf6000195 },
608 { 0x50358, 0x2b0003e6 },
609 { 0x5fffc, 0xf64001a6 },
610 { 0x5035c, 0x260003e8 },
611 { 0x5fffc, 0xf6c001b4 },
612 { 0x50360, 0x214003eb },
613 { 0x5fffc, 0xf78001c2 },
614 { 0x50364, 0x1c4003ee },
615 { 0x5fffc, 0xf80001cf },
616 { 0x50368, 0x17c003f1 },
617 { 0x5fffc, 0xf90001db },
618 { 0x5036c, 0x134003f3 },
619 { 0x5fffc, 0xfa0001e5 },
620 { 0x50370, 0xf0003f6 },
621 { 0x5fffc, 0xfb4001ee },
622 { 0x50374, 0xac003f9 },
623 { 0x5fffc, 0xfcc001f5 },
624 { 0x50378, 0x70003fb },
625 { 0x5fffc, 0xfe4001fb },
626 { 0x5037c, 0x34003fe },
627};
628
629struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = {
630 [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4,
631 [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6,
632 [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8,
633 [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_y_table_PT8TO1,
634};
635
636struct mdp_table_entry mdp_gaussian_blur_table[] = {
637 /* max variance */
638 { 0x5fffc, 0x20000080 },
639 { 0x50280, 0x20000080 },
640 { 0x5fffc, 0x20000080 },
641 { 0x50284, 0x20000080 },
642 { 0x5fffc, 0x20000080 },
643 { 0x50288, 0x20000080 },
644 { 0x5fffc, 0x20000080 },
645 { 0x5028c, 0x20000080 },
646 { 0x5fffc, 0x20000080 },
647 { 0x50290, 0x20000080 },
648 { 0x5fffc, 0x20000080 },
649 { 0x50294, 0x20000080 },
650 { 0x5fffc, 0x20000080 },
651 { 0x50298, 0x20000080 },
652 { 0x5fffc, 0x20000080 },
653 { 0x5029c, 0x20000080 },
654 { 0x5fffc, 0x20000080 },
655 { 0x502a0, 0x20000080 },
656 { 0x5fffc, 0x20000080 },
657 { 0x502a4, 0x20000080 },
658 { 0x5fffc, 0x20000080 },
659 { 0x502a8, 0x20000080 },
660 { 0x5fffc, 0x20000080 },
661 { 0x502ac, 0x20000080 },
662 { 0x5fffc, 0x20000080 },
663 { 0x502b0, 0x20000080 },
664 { 0x5fffc, 0x20000080 },
665 { 0x502b4, 0x20000080 },
666 { 0x5fffc, 0x20000080 },
667 { 0x502b8, 0x20000080 },
668 { 0x5fffc, 0x20000080 },
669 { 0x502bc, 0x20000080 },
670 { 0x5fffc, 0x20000080 },
671 { 0x502c0, 0x20000080 },
672 { 0x5fffc, 0x20000080 },
673 { 0x502c4, 0x20000080 },
674 { 0x5fffc, 0x20000080 },
675 { 0x502c8, 0x20000080 },
676 { 0x5fffc, 0x20000080 },
677 { 0x502cc, 0x20000080 },
678 { 0x5fffc, 0x20000080 },
679 { 0x502d0, 0x20000080 },
680 { 0x5fffc, 0x20000080 },
681 { 0x502d4, 0x20000080 },
682 { 0x5fffc, 0x20000080 },
683 { 0x502d8, 0x20000080 },
684 { 0x5fffc, 0x20000080 },
685 { 0x502dc, 0x20000080 },
686 { 0x5fffc, 0x20000080 },
687 { 0x502e0, 0x20000080 },
688 { 0x5fffc, 0x20000080 },
689 { 0x502e4, 0x20000080 },
690 { 0x5fffc, 0x20000080 },
691 { 0x502e8, 0x20000080 },
692 { 0x5fffc, 0x20000080 },
693 { 0x502ec, 0x20000080 },
694 { 0x5fffc, 0x20000080 },
695 { 0x502f0, 0x20000080 },
696 { 0x5fffc, 0x20000080 },
697 { 0x502f4, 0x20000080 },
698 { 0x5fffc, 0x20000080 },
699 { 0x502f8, 0x20000080 },
700 { 0x5fffc, 0x20000080 },
701 { 0x502fc, 0x20000080 },
702 { 0x5fffc, 0x20000080 },
703 { 0x50300, 0x20000080 },
704 { 0x5fffc, 0x20000080 },
705 { 0x50304, 0x20000080 },
706 { 0x5fffc, 0x20000080 },
707 { 0x50308, 0x20000080 },
708 { 0x5fffc, 0x20000080 },
709 { 0x5030c, 0x20000080 },
710 { 0x5fffc, 0x20000080 },
711 { 0x50310, 0x20000080 },
712 { 0x5fffc, 0x20000080 },
713 { 0x50314, 0x20000080 },
714 { 0x5fffc, 0x20000080 },
715 { 0x50318, 0x20000080 },
716 { 0x5fffc, 0x20000080 },
717 { 0x5031c, 0x20000080 },
718 { 0x5fffc, 0x20000080 },
719 { 0x50320, 0x20000080 },
720 { 0x5fffc, 0x20000080 },
721 { 0x50324, 0x20000080 },
722 { 0x5fffc, 0x20000080 },
723 { 0x50328, 0x20000080 },
724 { 0x5fffc, 0x20000080 },
725 { 0x5032c, 0x20000080 },
726 { 0x5fffc, 0x20000080 },
727 { 0x50330, 0x20000080 },
728 { 0x5fffc, 0x20000080 },
729 { 0x50334, 0x20000080 },
730 { 0x5fffc, 0x20000080 },
731 { 0x50338, 0x20000080 },
732 { 0x5fffc, 0x20000080 },
733 { 0x5033c, 0x20000080 },
734 { 0x5fffc, 0x20000080 },
735 { 0x50340, 0x20000080 },
736 { 0x5fffc, 0x20000080 },
737 { 0x50344, 0x20000080 },
738 { 0x5fffc, 0x20000080 },
739 { 0x50348, 0x20000080 },
740 { 0x5fffc, 0x20000080 },
741 { 0x5034c, 0x20000080 },
742 { 0x5fffc, 0x20000080 },
743 { 0x50350, 0x20000080 },
744 { 0x5fffc, 0x20000080 },
745 { 0x50354, 0x20000080 },
746 { 0x5fffc, 0x20000080 },
747 { 0x50358, 0x20000080 },
748 { 0x5fffc, 0x20000080 },
749 { 0x5035c, 0x20000080 },
750 { 0x5fffc, 0x20000080 },
751 { 0x50360, 0x20000080 },
752 { 0x5fffc, 0x20000080 },
753 { 0x50364, 0x20000080 },
754 { 0x5fffc, 0x20000080 },
755 { 0x50368, 0x20000080 },
756 { 0x5fffc, 0x20000080 },
757 { 0x5036c, 0x20000080 },
758 { 0x5fffc, 0x20000080 },
759 { 0x50370, 0x20000080 },
760 { 0x5fffc, 0x20000080 },
761 { 0x50374, 0x20000080 },
762 { 0x5fffc, 0x20000080 },
763 { 0x50378, 0x20000080 },
764 { 0x5fffc, 0x20000080 },
765 { 0x5037c, 0x20000080 },
766};
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h
new file mode 100644
index 000000000000..34077b1af603
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.h
@@ -0,0 +1,38 @@
1/* drivers/video/msm_fb/mdp_scale_tables.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MDP_SCALE_TABLES_H_
16#define _MDP_SCALE_TABLES_H_
17
18#include <linux/types.h>
19struct mdp_table_entry {
20 uint32_t reg;
21 uint32_t val;
22};
23
24extern struct mdp_table_entry mdp_upscale_table[64];
25
26enum {
27 MDP_DOWNSCALE_PT2TOPT4,
28 MDP_DOWNSCALE_PT4TOPT6,
29 MDP_DOWNSCALE_PT6TOPT8,
30 MDP_DOWNSCALE_PT8TO1,
31 MDP_DOWNSCALE_MAX,
32};
33
34extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
35extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
36extern struct mdp_table_entry mdp_gaussian_blur_table[];
37
38#endif
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
new file mode 100644
index 000000000000..49101dda45ee
--- /dev/null
+++ b/drivers/video/msm/msm_fb.c
@@ -0,0 +1,636 @@
1/* drivers/video/msm/msm_fb.c
2 *
3 * Core MSM framebuffer driver.
4 *
5 * Copyright (C) 2007 Google Incorporated
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/platform_device.h>
18#include <linux/module.h>
19#include <linux/fb.h>
20#include <linux/delay.h>
21
22#include <linux/freezer.h>
23#include <linux/wait.h>
24#include <linux/msm_mdp.h>
25#include <linux/io.h>
26#include <linux/uaccess.h>
27#include <mach/msm_fb.h>
28#include <mach/board.h>
29#include <linux/workqueue.h>
30#include <linux/clk.h>
31#include <linux/debugfs.h>
32#include <linux/dma-mapping.h>
33
34#define PRINT_FPS 0
35#define PRINT_BLIT_TIME 0
36
37#define SLEEPING 0x4
38#define UPDATING 0x3
39#define FULL_UPDATE_DONE 0x2
40#define WAKING 0x1
41#define AWAKE 0x0
42
43#define NONE 0
44#define SUSPEND_RESUME 0x1
45#define FPS 0x2
46#define BLIT_TIME 0x4
47#define SHOW_UPDATES 0x8
48
49#define DLOG(mask, fmt, args...) \
50do { \
51 if (msmfb_debug_mask & mask) \
52 printk(KERN_INFO "msmfb: "fmt, ##args); \
53} while (0)
54
55static int msmfb_debug_mask;
56module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
57 S_IRUGO | S_IWUSR | S_IWGRP);
58
59struct mdp_device *mdp;
60
61struct msmfb_info {
62 struct fb_info *fb;
63 struct msm_panel_data *panel;
64 int xres;
65 int yres;
66 unsigned output_format;
67 unsigned yoffset;
68 unsigned frame_requested;
69 unsigned frame_done;
70 int sleeping;
71 unsigned update_frame;
72 struct {
73 int left;
74 int top;
75 int eright; /* exclusive */
76 int ebottom; /* exclusive */
77 } update_info;
78 char *black;
79
80 spinlock_t update_lock;
81 struct mutex panel_init_lock;
82 wait_queue_head_t frame_wq;
83 struct workqueue_struct *resume_workqueue;
84 struct work_struct resume_work;
85 struct msmfb_callback dma_callback;
86 struct msmfb_callback vsync_callback;
87 struct hrtimer fake_vsync;
88 ktime_t vsync_request_time;
89};
90
91static int msmfb_open(struct fb_info *info, int user)
92{
93 return 0;
94}
95
96static int msmfb_release(struct fb_info *info, int user)
97{
98 return 0;
99}
100
101/* Called from dma interrupt handler, must not sleep */
102static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
103{
104 unsigned long irq_flags;
105 struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
106 dma_callback);
107
108 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
109 msmfb->frame_done = msmfb->frame_requested;
110 if (msmfb->sleeping == UPDATING &&
111 msmfb->frame_done == msmfb->update_frame) {
112 DLOG(SUSPEND_RESUME, "full update completed\n");
113 queue_work(msmfb->resume_workqueue, &msmfb->resume_work);
114 }
115 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
116 wake_up(&msmfb->frame_wq);
117}
118
119static int msmfb_start_dma(struct msmfb_info *msmfb)
120{
121 uint32_t x, y, w, h;
122 unsigned addr;
123 unsigned long irq_flags;
124 uint32_t yoffset;
125 s64 time_since_request;
126 struct msm_panel_data *panel = msmfb->panel;
127
128 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
129 time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
130 msmfb->vsync_request_time));
131 if (time_since_request > 20 * NSEC_PER_MSEC) {
132 uint32_t us;
133 us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
134 printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
135 "request\n", time_since_request, us);
136 }
137 if (msmfb->frame_done == msmfb->frame_requested) {
138 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
139 return -1;
140 }
141 if (msmfb->sleeping == SLEEPING) {
142 DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
143 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
144 return -1;
145 }
146 x = msmfb->update_info.left;
147 y = msmfb->update_info.top;
148 w = msmfb->update_info.eright - x;
149 h = msmfb->update_info.ebottom - y;
150 yoffset = msmfb->yoffset;
151 msmfb->update_info.left = msmfb->xres + 1;
152 msmfb->update_info.top = msmfb->yres + 1;
153 msmfb->update_info.eright = 0;
154 msmfb->update_info.ebottom = 0;
155 if (unlikely(w > msmfb->xres || h > msmfb->yres ||
156 w == 0 || h == 0)) {
157 printk(KERN_INFO "invalid update: %d %d %d "
158 "%d\n", x, y, w, h);
159 msmfb->frame_done = msmfb->frame_requested;
160 goto error;
161 }
162 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
163
164 addr = ((msmfb->xres * (yoffset + y) + x) * 2);
165 mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
166 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
167 panel->interface_type);
168 return 0;
169error:
170 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
171 /* some clients need to clear their vsync interrupt */
172 if (panel->clear_vsync)
173 panel->clear_vsync(panel);
174 wake_up(&msmfb->frame_wq);
175 return 0;
176}
177
178/* Called from esync interrupt handler, must not sleep */
179static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
180{
181 struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
182 vsync_callback);
183 msmfb_start_dma(msmfb);
184}
185
186static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
187{
188 struct msmfb_info *msmfb = container_of(timer, struct msmfb_info,
189 fake_vsync);
190 msmfb_start_dma(msmfb);
191 return HRTIMER_NORESTART;
192}
193
194static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
195 uint32_t eright, uint32_t ebottom,
196 uint32_t yoffset, int pan_display)
197{
198 struct msmfb_info *msmfb = info->par;
199 struct msm_panel_data *panel = msmfb->panel;
200 unsigned long irq_flags;
201 int sleeping;
202 int retry = 1;
203
204 DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
205 left, top, eright, ebottom, yoffset, pan_display);
206restart:
207 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
208
209 /* if we are sleeping, on a pan_display wait 10ms (to throttle back
210 * drawing otherwise return */
211 if (msmfb->sleeping == SLEEPING) {
212 DLOG(SUSPEND_RESUME, "drawing while asleep\n");
213 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
214 if (pan_display)
215 wait_event_interruptible_timeout(msmfb->frame_wq,
216 msmfb->sleeping != SLEEPING, HZ/10);
217 return;
218 }
219
220 sleeping = msmfb->sleeping;
221 /* on a full update, if the last frame has not completed, wait for it */
222 if (pan_display && (msmfb->frame_requested != msmfb->frame_done ||
223 sleeping == UPDATING)) {
224 int ret;
225 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
226 ret = wait_event_interruptible_timeout(msmfb->frame_wq,
227 msmfb->frame_done == msmfb->frame_requested &&
228 msmfb->sleeping != UPDATING, 5 * HZ);
229 if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
230 msmfb->sleeping == UPDATING)) {
231 if (retry && panel->request_vsync &&
232 (sleeping == AWAKE)) {
233 panel->request_vsync(panel,
234 &msmfb->vsync_callback);
235 retry = 0;
236 printk(KERN_WARNING "msmfb_pan_display timeout "
237 "rerequest vsync\n");
238 } else {
239 printk(KERN_WARNING "msmfb_pan_display timeout "
240 "waiting for frame start, %d %d\n",
241 msmfb->frame_requested,
242 msmfb->frame_done);
243 return;
244 }
245 }
246 goto restart;
247 }
248
249
250 msmfb->frame_requested++;
251 /* if necessary, update the y offset, if this is the
252 * first full update on resume, set the sleeping state */
253 if (pan_display) {
254 msmfb->yoffset = yoffset;
255 if (left == 0 && top == 0 && eright == info->var.xres &&
256 ebottom == info->var.yres) {
257 if (sleeping == WAKING) {
258 msmfb->update_frame = msmfb->frame_requested;
259 DLOG(SUSPEND_RESUME, "full update starting\n");
260 msmfb->sleeping = UPDATING;
261 }
262 }
263 }
264
265 /* set the update request */
266 if (left < msmfb->update_info.left)
267 msmfb->update_info.left = left;
268 if (top < msmfb->update_info.top)
269 msmfb->update_info.top = top;
270 if (eright > msmfb->update_info.eright)
271 msmfb->update_info.eright = eright;
272 if (ebottom > msmfb->update_info.ebottom)
273 msmfb->update_info.ebottom = ebottom;
274 DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
275 msmfb->update_info.left, msmfb->update_info.top,
276 msmfb->update_info.eright, msmfb->update_info.ebottom,
277 msmfb->yoffset);
278 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
279
280 /* if the panel is all the way on wait for vsync, otherwise sleep
281 * for 16 ms (long enough for the dma to panel) and then begin dma */
282 msmfb->vsync_request_time = ktime_get();
283 if (panel->request_vsync && (sleeping == AWAKE)) {
284 panel->request_vsync(panel, &msmfb->vsync_callback);
285 } else {
286 if (!hrtimer_active(&msmfb->fake_vsync)) {
287 hrtimer_start(&msmfb->fake_vsync,
288 ktime_set(0, NSEC_PER_SEC/60),
289 HRTIMER_MODE_REL);
290 }
291 }
292}
293
294static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
295 uint32_t eright, uint32_t ebottom)
296{
297 msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
298}
299
300static void power_on_panel(struct work_struct *work)
301{
302 struct msmfb_info *msmfb =
303 container_of(work, struct msmfb_info, resume_work);
304 struct msm_panel_data *panel = msmfb->panel;
305 unsigned long irq_flags;
306
307 mutex_lock(&msmfb->panel_init_lock);
308 DLOG(SUSPEND_RESUME, "turning on panel\n");
309 if (msmfb->sleeping == UPDATING) {
310 if (panel->unblank(panel)) {
311 printk(KERN_INFO "msmfb: panel unblank failed,"
312 "not starting drawing\n");
313 goto error;
314 }
315 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
316 msmfb->sleeping = AWAKE;
317 wake_up(&msmfb->frame_wq);
318 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
319 }
320error:
321 mutex_unlock(&msmfb->panel_init_lock);
322}
323
324
325static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
326{
327 if ((var->xres != info->var.xres) ||
328 (var->yres != info->var.yres) ||
329 (var->xres_virtual != info->var.xres_virtual) ||
330 (var->yres_virtual != info->var.yres_virtual) ||
331 (var->xoffset != info->var.xoffset) ||
332 (var->bits_per_pixel != info->var.bits_per_pixel) ||
333 (var->grayscale != info->var.grayscale))
334 return -EINVAL;
335 return 0;
336}
337
338int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
339{
340 struct msmfb_info *msmfb = info->par;
341 struct msm_panel_data *panel = msmfb->panel;
342
343 /* "UPDT" */
344 if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
345 (var->reserved[0] == 0x54445055)) {
346 msmfb_pan_update(info, var->reserved[1] & 0xffff,
347 var->reserved[1] >> 16,
348 var->reserved[2] & 0xffff,
349 var->reserved[2] >> 16, var->yoffset, 1);
350 } else {
351 msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
352 var->yoffset, 1);
353 }
354 return 0;
355}
356
357static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
358{
359 cfb_fillrect(p, rect);
360 msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
361 rect->dy + rect->height);
362}
363
364static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
365{
366 cfb_copyarea(p, area);
367 msmfb_update(p, area->dx, area->dy, area->dx + area->width,
368 area->dy + area->height);
369}
370
371static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
372{
373 cfb_imageblit(p, image);
374 msmfb_update(p, image->dx, image->dy, image->dx + image->width,
375 image->dy + image->height);
376}
377
378
379static int msmfb_blit(struct fb_info *info,
380 void __user *p)
381{
382 struct mdp_blit_req req;
383 struct mdp_blit_req_list req_list;
384 int i;
385 int ret;
386
387 if (copy_from_user(&req_list, p, sizeof(req_list)))
388 return -EFAULT;
389
390 for (i = 0; i < req_list.count; i++) {
391 struct mdp_blit_req_list *list =
392 (struct mdp_blit_req_list *)p;
393 if (copy_from_user(&req, &list->req[i], sizeof(req)))
394 return -EFAULT;
395 ret = mdp->blit(mdp, info, &req);
396 if (ret)
397 return ret;
398 }
399 return 0;
400}
401
402
403DEFINE_MUTEX(mdp_ppp_lock);
404
405static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
406{
407 void __user *argp = (void __user *)arg;
408 int ret;
409
410 switch (cmd) {
411 case MSMFB_GRP_DISP:
412 mdp->set_grp_disp(mdp, arg);
413 break;
414 case MSMFB_BLIT:
415 ret = msmfb_blit(p, argp);
416 if (ret)
417 return ret;
418 break;
419 default:
420 printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
421 return -EINVAL;
422 }
423 return 0;
424}
425
426static struct fb_ops msmfb_ops = {
427 .owner = THIS_MODULE,
428 .fb_open = msmfb_open,
429 .fb_release = msmfb_release,
430 .fb_check_var = msmfb_check_var,
431 .fb_pan_display = msmfb_pan_display,
432 .fb_fillrect = msmfb_fillrect,
433 .fb_copyarea = msmfb_copyarea,
434 .fb_imageblit = msmfb_imageblit,
435 .fb_ioctl = msmfb_ioctl,
436};
437
438static unsigned PP[16];
439
440
441
442#define BITS_PER_PIXEL 16
443
444static void setup_fb_info(struct msmfb_info *msmfb)
445{
446 struct fb_info *fb_info = msmfb->fb;
447 int r;
448
449 /* finish setting up the fb_info struct */
450 strncpy(fb_info->fix.id, "msmfb", 16);
451 fb_info->fix.ypanstep = 1;
452
453 fb_info->fbops = &msmfb_ops;
454 fb_info->flags = FBINFO_DEFAULT;
455
456 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
457 fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
458 fb_info->fix.line_length = msmfb->xres * 2;
459
460 fb_info->var.xres = msmfb->xres;
461 fb_info->var.yres = msmfb->yres;
462 fb_info->var.width = msmfb->panel->fb_data->width;
463 fb_info->var.height = msmfb->panel->fb_data->height;
464 fb_info->var.xres_virtual = msmfb->xres;
465 fb_info->var.yres_virtual = msmfb->yres * 2;
466 fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
467 fb_info->var.accel_flags = 0;
468
469 fb_info->var.yoffset = 0;
470
471 if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
472 fb_info->var.reserved[0] = 0x54445055;
473 fb_info->var.reserved[1] = 0;
474 fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
475 ((uint32_t)msmfb->yres << 16);
476 }
477
478 fb_info->var.red.offset = 11;
479 fb_info->var.red.length = 5;
480 fb_info->var.red.msb_right = 0;
481 fb_info->var.green.offset = 5;
482 fb_info->var.green.length = 6;
483 fb_info->var.green.msb_right = 0;
484 fb_info->var.blue.offset = 0;
485 fb_info->var.blue.length = 5;
486 fb_info->var.blue.msb_right = 0;
487
488 r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
489 fb_info->pseudo_palette = PP;
490
491 PP[0] = 0;
492 for (r = 1; r < 16; r++)
493 PP[r] = 0xffffffff;
494}
495
496static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
497{
498 struct fb_info *fb = msmfb->fb;
499 struct resource *resource;
500 unsigned long size = msmfb->xres * msmfb->yres *
501 (BITS_PER_PIXEL >> 3) * 2;
502 unsigned char *fbram;
503
504 /* board file might have attached a resource describing an fb */
505 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
506 if (!resource)
507 return -EINVAL;
508
509 /* check the resource is large enough to fit the fb */
510 if (resource->end - resource->start < size) {
511 printk(KERN_ERR "allocated resource is too small for "
512 "fb\n");
513 return -ENOMEM;
514 }
515 fb->fix.smem_start = resource->start;
516 fb->fix.smem_len = resource->end - resource->start;
517 fbram = ioremap(resource->start,
518 resource->end - resource->start);
519 if (fbram == 0) {
520 printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
521 return -ENOMEM;
522 }
523 fb->screen_base = fbram;
524 return 0;
525}
526
527static int msmfb_probe(struct platform_device *pdev)
528{
529 struct fb_info *fb;
530 struct msmfb_info *msmfb;
531 struct msm_panel_data *panel = pdev->dev.platform_data;
532 int ret;
533
534 if (!panel) {
535 pr_err("msmfb_probe: no platform data\n");
536 return -EINVAL;
537 }
538 if (!panel->fb_data) {
539 pr_err("msmfb_probe: no fb_data\n");
540 return -EINVAL;
541 }
542
543 fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
544 if (!fb)
545 return -ENOMEM;
546 msmfb = fb->par;
547 msmfb->fb = fb;
548 msmfb->panel = panel;
549 msmfb->xres = panel->fb_data->xres;
550 msmfb->yres = panel->fb_data->yres;
551
552 ret = setup_fbmem(msmfb, pdev);
553 if (ret)
554 goto error_setup_fbmem;
555
556 setup_fb_info(msmfb);
557
558 spin_lock_init(&msmfb->update_lock);
559 mutex_init(&msmfb->panel_init_lock);
560 init_waitqueue_head(&msmfb->frame_wq);
561 msmfb->resume_workqueue = create_workqueue("panel_on");
562 if (msmfb->resume_workqueue == NULL) {
563 printk(KERN_ERR "failed to create panel_on workqueue\n");
564 ret = -ENOMEM;
565 goto error_create_workqueue;
566 }
567 INIT_WORK(&msmfb->resume_work, power_on_panel);
568 msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
569 GFP_KERNEL);
570
571 printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
572 msmfb->xres, msmfb->yres);
573
574 msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
575 msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
576 hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
577 HRTIMER_MODE_REL);
578
579
580 msmfb->fake_vsync.function = msmfb_fake_vsync;
581
582 ret = register_framebuffer(fb);
583 if (ret)
584 goto error_register_framebuffer;
585
586 msmfb->sleeping = WAKING;
587
588 return 0;
589
590error_register_framebuffer:
591 destroy_workqueue(msmfb->resume_workqueue);
592error_create_workqueue:
593 iounmap(fb->screen_base);
594error_setup_fbmem:
595 framebuffer_release(msmfb->fb);
596 return ret;
597}
598
599static struct platform_driver msm_panel_driver = {
600 /* need to write remove */
601 .probe = msmfb_probe,
602 .driver = {.name = "msm_panel"},
603};
604
605
606static int msmfb_add_mdp_device(struct device *dev,
607 struct class_interface *class_intf)
608{
609 /* might need locking if mulitple mdp devices */
610 if (mdp)
611 return 0;
612 mdp = container_of(dev, struct mdp_device, dev);
613 return platform_driver_register(&msm_panel_driver);
614}
615
616static void msmfb_remove_mdp_device(struct device *dev,
617 struct class_interface *class_intf)
618{
619 /* might need locking if mulitple mdp devices */
620 if (dev != &mdp->dev)
621 return;
622 platform_driver_unregister(&msm_panel_driver);
623 mdp = NULL;
624}
625
626static struct class_interface msm_fb_interface = {
627 .add_dev = &msmfb_add_mdp_device,
628 .remove_dev = &msmfb_remove_mdp_device,
629};
630
631static int __init msmfb_init(void)
632{
633 return register_mdp_client(&msm_fb_interface);
634}
635
636module_init(msmfb_init);