blob: 2eb9257bc3e0e755ab2ac3f009b854fedf1ac53e [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/time.h>
17#include <linux/init.h>
18#include <linux/interrupt.h>
19#include <linux/spinlock.h>
20#include <linux/hrtimer.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23#include <linux/debugfs.h>
24#include <linux/semaphore.h>
25#include <linux/uaccess.h>
26#include <asm/system.h>
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29
30#include "mdp.h"
31#include "msm_fb.h"
32#ifdef CONFIG_FB_MSM_MDP40
33#include "mdp4.h"
34#endif
35#include "mddihosti.h"
36#include "tvenc.h"
37#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
38#include "hdmi_msm.h"
39#endif
40
41#define MDP_DEBUG_BUF 2048
42
43static uint32 mdp_offset;
44static uint32 mdp_count;
45
46static char debug_buf[MDP_DEBUG_BUF];
47
48/*
49 * MDP4
50 *
51 */
52
53static int mdp_offset_open(struct inode *inode, struct file *file)
54{
55 /* non-seekable */
56 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
57 return 0;
58}
59
60static int mdp_offset_release(struct inode *inode, struct file *file)
61{
62 return 0;
63}
64
65static ssize_t mdp_offset_write(
66 struct file *file,
67 const char __user *buff,
68 size_t count,
69 loff_t *ppos)
70{
71 uint32 off, cnt;
72
73 if (count >= sizeof(debug_buf))
74 return -EFAULT;
75
76 if (copy_from_user(debug_buf, buff, count))
77 return -EFAULT;
78
79 debug_buf[count] = 0; /* end of string */
80
81 sscanf(debug_buf, "%x %d", &off, &cnt);
82
83 if (cnt <= 0)
84 cnt = 1;
85
86 mdp_offset = off;
87 mdp_count = cnt;
88
89 printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
90 mdp_offset, mdp_count);
91
92 return count;
93}
94
95static ssize_t mdp_offset_read(
96 struct file *file,
97 char __user *buff,
98 size_t count,
99 loff_t *ppos)
100{
101 int len = 0;
102
103
104 if (*ppos)
105 return 0; /* the end */
106
107 len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
108 mdp_offset, mdp_count);
109 if (len < 0)
110 return 0;
111
112 if (copy_to_user(buff, debug_buf, len))
113 return -EFAULT;
114
115 *ppos += len; /* increase offset */
116
117 return len;
118}
119
120static const struct file_operations mdp_off_fops = {
121 .open = mdp_offset_open,
122 .release = mdp_offset_release,
123 .read = mdp_offset_read,
124 .write = mdp_offset_write,
125};
126
127static int mdp_reg_open(struct inode *inode, struct file *file)
128{
129 /* non-seekable */
130 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
131 return 0;
132}
133
134static int mdp_reg_release(struct inode *inode, struct file *file)
135{
136 return 0;
137}
138
139static ssize_t mdp_reg_write(
140 struct file *file,
141 const char __user *buff,
142 size_t count,
143 loff_t *ppos)
144{
145 uint32 off, data;
146 int cnt;
147
148 if (count >= sizeof(debug_buf))
149 return -EFAULT;
150
151 if (copy_from_user(debug_buf, buff, count))
152 return -EFAULT;
153
154 debug_buf[count] = 0; /* end of string */
155
156 cnt = sscanf(debug_buf, "%x %x", &off, &data);
157
158 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
159 outpdw(MDP_BASE + off, data);
160 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
161
162 printk(KERN_INFO "%s: addr=%x data=%x\n", __func__, off, data);
163
164 return count;
165}
166
167static ssize_t mdp_reg_read(
168 struct file *file,
169 char __user *buff,
170 size_t count,
171 loff_t *ppos)
172{
173 int len = 0;
174 uint32 data;
175 int i, j, off, dlen, num;
176 char *bp, *cp;
177 int tot = 0;
178
179
180 if (*ppos)
181 return 0; /* the end */
182
183 j = 0;
184 num = 0;
185 bp = debug_buf;
186 cp = MDP_BASE + mdp_offset;
187 dlen = sizeof(debug_buf);
188 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
189 while (j++ < 8) {
190 len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
191 tot += len;
192 bp += len;
193 dlen -= len;
194 off = 0;
195 i = 0;
196 while (i++ < 4) {
197 data = inpdw(cp + off);
198 len = snprintf(bp, dlen, "%08x ", data);
199 tot += len;
200 bp += len;
201 dlen -= len;
202 off += 4;
203 num++;
204 if (num >= mdp_count)
205 break;
206 }
207 *bp++ = '\n';
208 --dlen;
209 tot++;
210 cp += off;
211 if (num >= mdp_count)
212 break;
213 }
214 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
215 *bp = 0;
216 tot++;
217
218 if (copy_to_user(buff, debug_buf, tot))
219 return -EFAULT;
220
221 *ppos += tot; /* increase offset */
222
223 return tot;
224}
225
226
227static const struct file_operations mdp_reg_fops = {
228 .open = mdp_reg_open,
229 .release = mdp_reg_release,
230 .read = mdp_reg_read,
231 .write = mdp_reg_write,
232};
233
234#ifdef CONFIG_FB_MSM_MDP40
235static int mdp_stat_open(struct inode *inode, struct file *file)
236{
237 /* non-seekable */
238 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
239 return 0;
240}
241
242static int mdp_stat_release(struct inode *inode, struct file *file)
243{
244 return 0;
245}
246
247static ssize_t mdp_stat_write(
248 struct file *file,
249 const char __user *buff,
250 size_t count,
251 loff_t *ppos)
252{
253 unsigned long flag;
254
255 if (count > sizeof(debug_buf))
256 return -EFAULT;
257
258 spin_lock_irqsave(&mdp_spin_lock, flag);
259 memset((char *)&mdp4_stat, 0 , sizeof(mdp4_stat)); /* reset */
260 spin_unlock_irqrestore(&mdp_spin_lock, flag);
261
262 return count;
263}
264
265static ssize_t mdp_stat_read(
266 struct file *file,
267 char __user *buff,
268 size_t count,
269 loff_t *ppos)
270{
271 int len = 0;
272 int tot = 0;
273 int dlen;
274 char *bp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275
276
277 if (*ppos)
278 return 0; /* the end */
279
280 bp = debug_buf;
281 dlen = sizeof(debug_buf);
282
kuogee hsieh0948c682011-10-31 16:50:43 -0700283 len = snprintf(bp, dlen, "\nmdp:\n");
284 bp += len;
285 dlen -= len;
286
287 len = snprintf(bp, dlen, "int_total: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288 mdp4_stat.intr_tot);
289 bp += len;
290 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700291
292 len = snprintf(bp, dlen, "int_overlay0: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 mdp4_stat.intr_overlay0);
294 bp += len;
295 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700296 len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297 mdp4_stat.intr_overlay1);
298 bp += len;
299 dlen -= len;
Rajesh Sastrulab52368b2011-12-22 12:09:17 -0800300 len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
301 mdp4_stat.intr_overlay2);
302 bp += len;
303 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700304
305 len = snprintf(bp, dlen, "int_dmap: %08lu\t",
306 mdp4_stat.intr_dma_p);
307 bp += len;
308 dlen -= len;
309 len = snprintf(bp, dlen, "int_dmas: %08lu\t",
310 mdp4_stat.intr_dma_s);
311 bp += len;
312 dlen -= len;
313 len = snprintf(bp, dlen, "int_dmae: %08lu\n",
314 mdp4_stat.intr_dma_e);
315 bp += len;
316 dlen -= len;
317
318 len = snprintf(bp, dlen, "primary: vsync: %08lu\t",
319 mdp4_stat.intr_vsync_p);
320 bp += len;
321 dlen -= len;
322 len = snprintf(bp, dlen, "underrun: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700323 mdp4_stat.intr_underrun_p);
324 bp += len;
325 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700326 len = snprintf(bp, dlen, "external: vsync: %08lu\t",
327 mdp4_stat.intr_vsync_e);
328 bp += len;
329 dlen -= len;
330 len = snprintf(bp, dlen, "underrun: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331 mdp4_stat.intr_underrun_e);
332
333 bp += len;
334 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700335 len = snprintf(bp, dlen, "histogram: %08lu\t",
336 mdp4_stat.intr_histogram);
337 bp += len;
338 dlen -= len;
339 len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
340 mdp4_stat.intr_rd_ptr);
341 bp += len;
342 dlen -= len;
343 len = snprintf(bp, dlen, "dsi:\n");
344 bp += len;
345 dlen -= len;
346 len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
347 mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
348 bp += len;
349 dlen -= len;
350 len = snprintf(bp, dlen, "int_cmd: %08lu\t",
351 mdp4_stat.intr_dsi_cmd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352
353 bp += len;
354 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700355 len = snprintf(bp, dlen, "int_mdp: %08lu\t",
356 mdp4_stat.intr_dsi_mdp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700357
358 bp += len;
359 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700360
361 len = snprintf(bp, dlen, "int_err: %08lu\n",
362 mdp4_stat.intr_dsi_err);
363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 bp += len;
365 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700366 len = snprintf(bp, dlen, "clk_on : %08lu\t",
367 mdp4_stat.dsi_clk_on);
368
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 bp += len;
370 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700371 len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
372 mdp4_stat.dsi_clk_off);
373
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 bp += len;
375 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700376 len = snprintf(bp, dlen, "kickoff:\n");
377 bp += len;
378 dlen -= len;
379
380 len = snprintf(bp, dlen, "overlay0: %08lu\t",
381 mdp4_stat.kickoff_ov0);
382 bp += len;
383 dlen -= len;
384 len = snprintf(bp, dlen, "dmap: %08lu\t",
385 mdp4_stat.kickoff_dmap);
386 bp += len;
387 dlen -= len;
388 len = snprintf(bp, dlen, "dmas: %08lu\n",
389 mdp4_stat.kickoff_dmas);
390
391 bp += len;
392 dlen -= len;
393 len = snprintf(bp, dlen, "overlay1: %08lu\t",
394 mdp4_stat.kickoff_ov1);
395 bp += len;
396 dlen -= len;
397 len = snprintf(bp, dlen, "dmae: %08lu\n\n",
398 mdp4_stat.kickoff_dmae);
399
400 bp += len;
401 dlen -= len;
402
403 len = snprintf(bp, dlen, "overlay0_play:\n");
404 bp += len;
405 dlen -= len;
406
407 len = snprintf(bp, dlen, "set: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408 mdp4_stat.overlay_set[0]);
409 bp += len;
410 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700411 len = snprintf(bp, dlen, "unset: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 mdp4_stat.overlay_unset[0]);
413 bp += len;
414 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700415 len = snprintf(bp, dlen, "play: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416 mdp4_stat.overlay_play[0]);
417 bp += len;
418 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700419
420 len = snprintf(bp, dlen, "overlay1_play:\n");
421 bp += len;
422 dlen -= len;
423 len = snprintf(bp, dlen, "set: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 mdp4_stat.overlay_set[1]);
425 bp += len;
426 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700427 len = snprintf(bp, dlen, "unset: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 mdp4_stat.overlay_unset[1]);
429 bp += len;
430 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700431 len = snprintf(bp, dlen, "play: %08lu\n\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 mdp4_stat.overlay_play[1]);
433
434 bp += len;
435 dlen -= len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436
kuogee hsieh0948c682011-10-31 16:50:43 -0700437 len = snprintf(bp, dlen, "frame_push:\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438 bp += len;
439 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700440 len = snprintf(bp, dlen, "rgb1: %08lu\t\t", mdp4_stat.pipe[0]);
441 bp += len;
442 dlen -= len;
443 len = snprintf(bp, dlen, "rgb2: %08lu\n", mdp4_stat.pipe[1]);
444 bp += len;
445 dlen -= len;
446 len = snprintf(bp, dlen, "vg1: %08lu\t\t", mdp4_stat.pipe[2]);
447 bp += len;
448 dlen -= len;
449 len = snprintf(bp, dlen, "vg2: %08lu\n", mdp4_stat.pipe[3]);
450 bp += len;
451 dlen -= len;
452 len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
453 bp += len;
454 dlen -= len;
455 len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
456 bp += len;
457 dlen -= len;
458 len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
459 bp += len;
460 dlen -= len;
461 len = snprintf(bp, dlen, "err_format: %08lu\n\n", mdp4_stat.err_format);
462 bp += len;
463 dlen -= len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700464
kuogee hsieh0948c682011-10-31 16:50:43 -0700465 len = snprintf(bp, dlen, "writeback:\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700466 bp += len;
467 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700468
469 len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
470 mdp4_stat.blt_dsi_cmd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 bp += len;
472 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700473
474 len = snprintf(bp, dlen, "dsi_video: %08lu\n",
475 mdp4_stat.blt_dsi_video);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700476 bp += len;
477 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700478
479 len = snprintf(bp, dlen, "lcdc: %08lu\t",
480 mdp4_stat.blt_lcdc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700481 bp += len;
482 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700483
484 len = snprintf(bp, dlen, "dtv: %08lu\t",
485 mdp4_stat.blt_dtv);
486 bp += len;
487 dlen -= len;
488
489 len = snprintf(bp, dlen, "mddi: %08lu\n\n",
490 mdp4_stat.blt_mddi);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 bp += len;
492 dlen -= len;
493
494 tot = (uint32)bp - (uint32)debug_buf;
495 *bp = 0;
496 tot++;
497
498 if (tot < 0)
499 return 0;
500 if (copy_to_user(buff, debug_buf, tot))
501 return -EFAULT;
502
503 *ppos += tot; /* increase offset */
504
505 return tot;
506}
507
508static const struct file_operations mdp_stat_fops = {
509 .open = mdp_stat_open,
510 .release = mdp_stat_release,
511 .read = mdp_stat_read,
512 .write = mdp_stat_write,
513};
514#endif
515
516/*
517 * MDDI
518 *
519 */
520
521struct mddi_reg {
522 char *name;
523 int off;
524};
525
526static struct mddi_reg mddi_regs_list[] = {
527 {"MDDI_CMD", MDDI_CMD}, /* 0x0000 */
528 {"MDDI_VERSION", MDDI_VERSION}, /* 0x0004 */
529 {"MDDI_PRI_PTR", MDDI_PRI_PTR}, /* 0x0008 */
530 {"MDDI_BPS", MDDI_BPS}, /* 0x0010 */
531 {"MDDI_SPM", MDDI_SPM}, /* 0x0014 */
532 {"MDDI_INT", MDDI_INT}, /* 0x0018 */
533 {"MDDI_INTEN", MDDI_INTEN}, /* 0x001c */
534 {"MDDI_REV_PTR", MDDI_REV_PTR}, /* 0x0020 */
535 {"MDDI_ REV_SIZE", MDDI_REV_SIZE},/* 0x0024 */
536 {"MDDI_STAT", MDDI_STAT}, /* 0x0028 */
537 {"MDDI_REV_RATE_DIV", MDDI_REV_RATE_DIV}, /* 0x002c */
538 {"MDDI_REV_CRC_ERR", MDDI_REV_CRC_ERR}, /* 0x0030 */
539 {"MDDI_TA1_LEN", MDDI_TA1_LEN}, /* 0x0034 */
540 {"MDDI_TA2_LEN", MDDI_TA2_LEN}, /* 0x0038 */
541 {"MDDI_TEST", MDDI_TEST}, /* 0x0040 */
542 {"MDDI_REV_PKT_CNT", MDDI_REV_PKT_CNT}, /* 0x0044 */
543 {"MDDI_DRIVE_HI", MDDI_DRIVE_HI},/* 0x0048 */
544 {"MDDI_DRIVE_LO", MDDI_DRIVE_LO}, /* 0x004c */
545 {"MDDI_DISP_WAKE", MDDI_DISP_WAKE},/* 0x0050 */
546 {"MDDI_REV_ENCAP_SZ", MDDI_REV_ENCAP_SZ}, /* 0x0054 */
547 {"MDDI_RTD_VAL", MDDI_RTD_VAL}, /* 0x0058 */
548 {"MDDI_PAD_CTL", MDDI_PAD_CTL}, /* 0x0068 */
549 {"MDDI_DRIVER_START_CNT", MDDI_DRIVER_START_CNT}, /* 0x006c */
550 {"MDDI_CORE_VER", MDDI_CORE_VER}, /* 0x008c */
551 {"MDDI_FIFO_ALLOC", MDDI_FIFO_ALLOC}, /* 0x0090 */
552 {"MDDI_PAD_IO_CTL", MDDI_PAD_IO_CTL}, /* 0x00a0 */
553 {"MDDI_PAD_CAL", MDDI_PAD_CAL}, /* 0x00a4 */
554 {0, 0}
555};
556
557static int mddi_reg_open(struct inode *inode, struct file *file)
558{
559 /* non-seekable */
560 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
561 return 0;
562}
563
564static int mddi_reg_release(struct inode *inode, struct file *file)
565{
566 return 0;
567}
568
569static void mddi_reg_write(int ndx, uint32 off, uint32 data)
570{
571 char *base;
572
573 if (ndx)
574 base = (char *)msm_emdh_base;
575 else
576 base = (char *)msm_pmdh_base;
577
578 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
579 writel(data, base + off);
580 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
581
582 printk(KERN_INFO "%s: addr=%x data=%x\n",
583 __func__, (int)(base+off), (int)data);
584}
585
586static int mddi_reg_read(int ndx)
587{
588 struct mddi_reg *reg;
589 unsigned char *base;
590 int data;
591 char *bp;
592 int len = 0;
593 int tot = 0;
594 int dlen;
595
596 if (ndx)
597 base = msm_emdh_base;
598 else
599 base = msm_pmdh_base;
600
601 reg = mddi_regs_list;
602 bp = debug_buf;
603 dlen = sizeof(debug_buf);
604
605 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
606 while (reg->name) {
607 data = readl((u32)base + reg->off);
608 len = snprintf(bp, dlen, "%s:0x%08x\t\t= 0x%08x\n",
609 reg->name, reg->off, data);
610 tot += len;
611 bp += len;
612 dlen -= len;
613 reg++;
614 }
615 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
616 *bp = 0;
617 tot++;
618
619 return tot;
620}
621
622static ssize_t pmdh_reg_write(
623 struct file *file,
624 const char __user *buff,
625 size_t count,
626 loff_t *ppos)
627{
628 uint32 off, data;
629 int cnt;
630
631 if (count >= sizeof(debug_buf))
632 return -EFAULT;
633
634 if (copy_from_user(debug_buf, buff, count))
635 return -EFAULT;
636
637 debug_buf[count] = 0; /* end of string */
638
639 cnt = sscanf(debug_buf, "%x %x", &off, &data);
640
641 mddi_reg_write(0, off, data);
642
643 return count;
644}
645
646static ssize_t pmdh_reg_read(
647 struct file *file,
648 char __user *buff,
649 size_t count,
650 loff_t *ppos)
651{
652 int tot = 0;
653
654 if (*ppos)
655 return 0; /* the end */
656
657 tot = mddi_reg_read(0); /* pmdh */
658
659 if (tot < 0)
660 return 0;
661 if (copy_to_user(buff, debug_buf, tot))
662 return -EFAULT;
663
664 *ppos += tot; /* increase offset */
665
666 return tot;
667}
668
669
670static const struct file_operations pmdh_fops = {
671 .open = mddi_reg_open,
672 .release = mddi_reg_release,
673 .read = pmdh_reg_read,
674 .write = pmdh_reg_write,
675};
676
677
678
679#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
680static int vsync_reg_open(struct inode *inode, struct file *file)
681{
682 /* non-seekable */
683 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
684 return 0;
685}
686
687static int vsync_reg_release(struct inode *inode, struct file *file)
688{
689 return 0;
690}
691
692static ssize_t vsync_reg_write(
693 struct file *file,
694 const char __user *buff,
695 size_t count,
696 loff_t *ppos)
697{
698 uint32 enable;
699 int cnt;
700
701 if (count >= sizeof(debug_buf))
702 return -EFAULT;
703
704 if (copy_from_user(debug_buf, buff, count))
705 return -EFAULT;
706
707 debug_buf[count] = 0; /* end of string */
708
709 cnt = sscanf(debug_buf, "%x", &enable);
710
711 mdp_dmap_vsync_set(enable);
712
713 return count;
714}
715
716static ssize_t vsync_reg_read(
717 struct file *file,
718 char __user *buff,
719 size_t count,
720 loff_t *ppos)
721{
722 char *bp;
723 int len = 0;
724 int tot = 0;
725 int dlen;
726
727 if (*ppos)
728 return 0; /* the end */
729
730 bp = debug_buf;
731 dlen = sizeof(debug_buf);
732 len = snprintf(bp, dlen, "%x\n", mdp_dmap_vsync_get());
733 tot += len;
734 bp += len;
735 *bp = 0;
736 tot++;
737
738 if (copy_to_user(buff, debug_buf, tot))
739 return -EFAULT;
740
741 *ppos += tot; /* increase offset */
742
743 return tot;
744}
745
746
747static const struct file_operations vsync_fops = {
748 .open = vsync_reg_open,
749 .release = vsync_reg_release,
750 .read = vsync_reg_read,
751 .write = vsync_reg_write,
752};
753#endif
754
755static ssize_t emdh_reg_write(
756 struct file *file,
757 const char __user *buff,
758 size_t count,
759 loff_t *ppos)
760{
761 uint32 off, data;
762 int cnt;
763
764 if (count >= sizeof(debug_buf))
765 return -EFAULT;
766
767 if (copy_from_user(debug_buf, buff, count))
768 return -EFAULT;
769
770 debug_buf[count] = 0; /* end of string */
771
772 cnt = sscanf(debug_buf, "%x %x", &off, &data);
773
774 mddi_reg_write(1, off, data);
775
776 return count;
777}
778
779static ssize_t emdh_reg_read(
780 struct file *file,
781 char __user *buff,
782 size_t count,
783 loff_t *ppos)
784{
785 int tot = 0;
786
787 if (*ppos)
788 return 0; /* the end */
789
790 tot = mddi_reg_read(1); /* emdh */
791
792 if (tot < 0)
793 return 0;
794 if (copy_to_user(buff, debug_buf, tot))
795 return -EFAULT;
796
797 *ppos += tot; /* increase offset */
798
799 return tot;
800}
801
802static const struct file_operations emdh_fops = {
803 .open = mddi_reg_open,
804 .release = mddi_reg_release,
805 .read = emdh_reg_read,
806 .write = emdh_reg_write,
807};
808
809
810uint32 dbg_offset;
811uint32 dbg_count;
812char *dbg_base;
813
814
815static int dbg_open(struct inode *inode, struct file *file)
816{
817 /* non-seekable */
818 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
819 return 0;
820}
821
822static int dbg_release(struct inode *inode, struct file *file)
823{
824 return 0;
825}
826
827static ssize_t dbg_base_write(
828 struct file *file,
829 const char __user *buff,
830 size_t count,
831 loff_t *ppos)
832{
833 return count;
834}
835
836static ssize_t dbg_base_read(
837 struct file *file,
838 char __user *buff,
839 size_t count,
840 loff_t *ppos)
841{
842 int len = 0;
843 int tot = 0;
844 int dlen;
845 char *bp;
846
847
848 if (*ppos)
849 return 0; /* the end */
850
851
852 bp = debug_buf;
853 dlen = sizeof(debug_buf);
854
855 len = snprintf(bp, dlen, "mdp_base : %08x\n",
856 (int)msm_mdp_base);
857 bp += len;
858 dlen -= len;
859 len = snprintf(bp, dlen, "mddi_base : %08x\n",
860 (int)msm_pmdh_base);
861 bp += len;
862 dlen -= len;
863 len = snprintf(bp, dlen, "emdh_base : %08x\n",
864 (int)msm_emdh_base);
865 bp += len;
866 dlen -= len;
867#ifdef CONFIG_FB_MSM_TVOUT
868 len = snprintf(bp, dlen, "tvenv_base: %08x\n",
869 (int)tvenc_base);
870 bp += len;
871 dlen -= len;
872#endif
873
874#ifdef CONFIG_FB_MSM_MIPI_DSI
875 len = snprintf(bp, dlen, "mipi_dsi_base: %08x\n",
876 (int)mipi_dsi_base);
877 bp += len;
878 dlen -= len;
879#endif
880
881 tot = (uint32)bp - (uint32)debug_buf;
882 *bp = 0;
883 tot++;
884
885 if (tot < 0)
886 return 0;
887 if (copy_to_user(buff, debug_buf, tot))
888 return -EFAULT;
889
890 *ppos += tot; /* increase offset */
891
892 return tot;
893}
894
895static const struct file_operations dbg_base_fops = {
896 .open = dbg_open,
897 .release = dbg_release,
898 .read = dbg_base_read,
899 .write = dbg_base_write,
900};
901
902static ssize_t dbg_offset_write(
903 struct file *file,
904 const char __user *buff,
905 size_t count,
906 loff_t *ppos)
907{
908 uint32 off, cnt, num, base;
909
910 if (count >= sizeof(debug_buf))
911 return -EFAULT;
912
913 if (copy_from_user(debug_buf, buff, count))
914 return -EFAULT;
915
916 debug_buf[count] = 0; /* end of string */
917
918 cnt = sscanf(debug_buf, "%x %d %x", &off, &num, &base);
919
920 if (cnt < 0)
921 cnt = 0;
922
923 if (cnt >= 1)
924 dbg_offset = off;
925 if (cnt >= 2)
926 dbg_count = num;
927 if (cnt >= 3)
928 dbg_base = (char *)base;
929
930 printk(KERN_INFO "%s: offset=%x cnt=%d base=%x\n", __func__,
931 dbg_offset, dbg_count, (int)dbg_base);
932
933 return count;
934}
935
936static ssize_t dbg_offset_read(
937 struct file *file,
938 char __user *buff,
939 size_t count,
940 loff_t *ppos)
941{
942 int len = 0;
943
944
945 if (*ppos)
946 return 0; /* the end */
947
948 len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d 0x%08x\n",
949 dbg_offset, dbg_count, (int)dbg_base);
950 if (len < 0)
951 return 0;
952
953 if (copy_to_user(buff, debug_buf, len))
954 return -EFAULT;
955
956 *ppos += len; /* increase offset */
957
958 return len;
959}
960
961static const struct file_operations dbg_off_fops = {
962 .open = dbg_open,
963 .release = dbg_release,
964 .read = dbg_offset_read,
965 .write = dbg_offset_write,
966};
967
968
969static ssize_t dbg_reg_write(
970 struct file *file,
971 const char __user *buff,
972 size_t count,
973 loff_t *ppos)
974{
975 uint32 off, data;
976 int cnt;
977
978 if (count >= sizeof(debug_buf))
979 return -EFAULT;
980
981 if (copy_from_user(debug_buf, buff, count))
982 return -EFAULT;
983
984 debug_buf[count] = 0; /* end of string */
985
986 cnt = sscanf(debug_buf, "%x %x", &off, &data);
987
988 writel(data, dbg_base + off);
989
990 printk(KERN_INFO "%s: addr=%x data=%x\n",
991 __func__, (int)(dbg_base+off), (int)data);
992
993 return count;
994}
995
996static ssize_t dbg_reg_read(
997 struct file *file,
998 char __user *buff,
999 size_t count,
1000 loff_t *ppos)
1001{
1002 int len = 0;
1003 uint32 data;
1004 int i, j, off, dlen, num;
1005 char *bp, *cp;
1006 int tot = 0;
1007
1008
1009 if (*ppos)
1010 return 0; /* the end */
1011
1012 if (dbg_base == 0)
1013 return 0; /* nothing to read */
1014
1015 j = 0;
1016 num = 0;
1017 bp = debug_buf;
1018 cp = (char *)(dbg_base + dbg_offset);
1019 dlen = sizeof(debug_buf);
1020 while (j++ < 16) {
1021 len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
1022 tot += len;
1023 bp += len;
1024 dlen -= len;
1025 off = 0;
1026 i = 0;
1027 while (i++ < 4) {
1028 data = readl(cp + off);
1029 len = snprintf(bp, dlen, "%08x ", data);
1030 tot += len;
1031 bp += len;
1032 dlen -= len;
1033 off += 4;
1034 num++;
1035 if (num >= dbg_count)
1036 break;
1037 }
1038 data = readl((u32)cp + off);
1039 *bp++ = '\n';
1040 --dlen;
1041 tot++;
1042 cp += off;
1043 if (num >= dbg_count)
1044 break;
1045 }
1046 *bp = 0;
1047 tot++;
1048
1049 if (copy_to_user(buff, debug_buf, tot))
1050 return -EFAULT;
1051
1052 *ppos += tot; /* increase offset */
1053
1054 return tot;
1055}
1056
1057
1058static const struct file_operations dbg_reg_fops = {
1059 .open = dbg_open,
1060 .release = dbg_release,
1061 .read = dbg_reg_read,
1062 .write = dbg_reg_write,
1063};
1064
1065#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1066static uint32 hdmi_offset;
1067static uint32 hdmi_count;
1068
1069static int hdmi_open(struct inode *inode, struct file *file)
1070{
1071 /* non-seekable */
1072 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
1073 return 0;
1074}
1075
1076static int hdmi_release(struct inode *inode, struct file *file)
1077{
1078 return 0;
1079}
1080
1081static ssize_t hdmi_offset_write(
1082 struct file *file,
1083 const char __user *buff,
1084 size_t count,
1085 loff_t *ppos)
1086{
1087 uint32 off, cnt, num;
1088
1089 if (count >= sizeof(debug_buf))
1090 return -EFAULT;
1091
1092 if (copy_from_user(debug_buf, buff, count))
1093 return -EFAULT;
1094
1095 debug_buf[count] = 0; /* end of string */
1096
1097 cnt = sscanf(debug_buf, "%x %d", &off, &num);
1098
1099 if (cnt < 0)
1100 cnt = 0;
1101
1102 if (cnt >= 1)
1103 hdmi_offset = off;
1104 if (cnt >= 2)
1105 hdmi_count = num;
1106
1107 printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
1108 hdmi_offset, hdmi_count);
1109
1110 return count;
1111}
1112
1113static ssize_t hdmi_offset_read(
1114 struct file *file,
1115 char __user *buff,
1116 size_t count,
1117 loff_t *ppos)
1118{
1119 int len = 0;
1120
1121
1122 if (*ppos)
1123 return 0; /* the end */
1124
1125 len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
1126 hdmi_offset, hdmi_count);
1127 if (len < 0)
1128 return 0;
1129
1130 if (copy_to_user(buff, debug_buf, len))
1131 return -EFAULT;
1132
1133 *ppos += len; /* increase offset */
1134
1135 return len;
1136}
1137
1138static const struct file_operations hdmi_off_fops = {
1139 .open = hdmi_open,
1140 .release = hdmi_release,
1141 .read = hdmi_offset_read,
1142 .write = hdmi_offset_write,
1143};
1144
1145
1146static ssize_t hdmi_reg_write(
1147 struct file *file,
1148 const char __user *buff,
1149 size_t count,
1150 loff_t *ppos)
1151{
1152 uint32 off, data, base;
1153 int cnt;
1154
1155 if (count >= sizeof(debug_buf))
1156 return -EFAULT;
1157
1158 if (copy_from_user(debug_buf, buff, count))
1159 return -EFAULT;
1160
1161 base = hdmi_msm_get_io_base();
1162 if (base == 0)
1163 return -EFAULT;
1164
1165 debug_buf[count] = 0; /* end of string */
1166
1167 cnt = sscanf(debug_buf, "%x %x", &off, &data);
1168
1169 writel(data, base + off);
1170
1171 printk(KERN_INFO "%s: addr=%x data=%x\n",
1172 __func__, (int)(base+off), (int)data);
1173
1174 return count;
1175}
1176
1177static ssize_t hdmi_reg_read(
1178 struct file *file,
1179 char __user *buff,
1180 size_t count,
1181 loff_t *ppos)
1182{
1183 int len = 0;
1184 uint32 data;
1185 int i, j, off, dlen, num;
1186 char *bp, *cp;
1187 int tot = 0;
1188
1189
1190 if (*ppos)
1191 return 0; /* the end */
1192
1193 if (hdmi_msm_get_io_base() == 0)
1194 return 0; /* nothing to read */
1195
1196 j = 0;
1197 num = 0;
1198 bp = debug_buf;
1199 cp = (char *)(hdmi_msm_get_io_base() + hdmi_offset);
1200 dlen = sizeof(debug_buf);
1201 while (j++ < 16) {
1202 len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
1203 tot += len;
1204 bp += len;
1205 dlen -= len;
1206 off = 0;
1207 i = 0;
1208 while (i++ < 4) {
1209 data = readl(cp + off);
1210 len = snprintf(bp, dlen, "%08x ", data);
1211 tot += len;
1212 bp += len;
1213 dlen -= len;
1214 off += 4;
1215 num++;
1216 if (num >= hdmi_count)
1217 break;
1218 }
1219 data = readl((u32)cp + off);
1220 *bp++ = '\n';
1221 --dlen;
1222 tot++;
1223 cp += off;
1224 if (num >= hdmi_count)
1225 break;
1226 }
1227 *bp = 0;
1228 tot++;
1229
1230 if (copy_to_user(buff, debug_buf, tot))
1231 return -EFAULT;
1232
1233 *ppos += tot; /* increase offset */
1234
1235 return tot;
1236}
1237
1238
1239static const struct file_operations hdmi_reg_fops = {
1240 .open = hdmi_open,
1241 .release = hdmi_release,
1242 .read = hdmi_reg_read,
1243 .write = hdmi_reg_write,
1244};
1245#endif
1246
1247/*
1248 * debugfs
1249 *
1250 */
1251
1252int mdp_debugfs_init(void)
1253{
1254 struct dentry *dent = debugfs_create_dir("mdp", NULL);
1255
1256 if (IS_ERR(dent)) {
1257 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1258 __FILE__, __LINE__, PTR_ERR(dent));
1259 return -1;
1260 }
1261
1262 if (debugfs_create_file("off", 0644, dent, 0, &mdp_off_fops)
1263 == NULL) {
1264 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1265 __FILE__, __LINE__);
1266 return -1;
1267 }
1268
1269 if (debugfs_create_file("reg", 0644, dent, 0, &mdp_reg_fops)
1270 == NULL) {
1271 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1272 __FILE__, __LINE__);
1273 return -1;
1274 }
1275
1276#ifdef CONFIG_FB_MSM_MDP40
1277 if (debugfs_create_file("stat", 0644, dent, 0, &mdp_stat_fops)
1278 == NULL) {
1279 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1280 __FILE__, __LINE__);
1281 return -1;
1282 }
1283#endif
1284
1285 dent = debugfs_create_dir("mddi", NULL);
1286
1287 if (IS_ERR(dent)) {
1288 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1289 __FILE__, __LINE__, PTR_ERR(dent));
1290 return -1;
1291 }
1292
1293 if (debugfs_create_file("reg", 0644, dent, 0, &pmdh_fops)
1294 == NULL) {
1295 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1296 __FILE__, __LINE__);
1297 return -1;
1298 }
1299
1300#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
1301 if (debugfs_create_file("vsync", 0644, dent, 0, &vsync_fops)
1302 == NULL) {
1303 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1304 __FILE__, __LINE__);
1305 return -1;
1306 }
1307#endif
1308
1309 dent = debugfs_create_dir("emdh", NULL);
1310
1311 if (IS_ERR(dent)) {
1312 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1313 __FILE__, __LINE__, PTR_ERR(dent));
1314 return -1;
1315 }
1316
1317 if (debugfs_create_file("reg", 0644, dent, 0, &emdh_fops)
1318 == NULL) {
1319 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1320 __FILE__, __LINE__);
1321 return -1;
1322 }
1323
1324 dent = debugfs_create_dir("mdp-dbg", NULL);
1325
1326 if (IS_ERR(dent)) {
1327 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1328 __FILE__, __LINE__, PTR_ERR(dent));
1329 return -1;
1330 }
1331
1332 if (debugfs_create_file("base", 0644, dent, 0, &dbg_base_fops)
1333 == NULL) {
1334 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1335 __FILE__, __LINE__);
1336 return -1;
1337 }
1338
1339 if (debugfs_create_file("off", 0644, dent, 0, &dbg_off_fops)
1340 == NULL) {
1341 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1342 __FILE__, __LINE__);
1343 return -1;
1344 }
1345
1346 if (debugfs_create_file("reg", 0644, dent, 0, &dbg_reg_fops)
1347 == NULL) {
1348 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1349 __FILE__, __LINE__);
1350 return -1;
1351 }
1352
1353#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1354 dent = debugfs_create_dir("hdmi", NULL);
1355
1356 if (IS_ERR(dent)) {
1357 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1358 __FILE__, __LINE__, PTR_ERR(dent));
1359 return PTR_ERR(dent);
1360 }
1361
1362 if (debugfs_create_file("off", 0644, dent, 0, &hdmi_off_fops)
1363 == NULL) {
1364 printk(KERN_ERR "%s(%d): debugfs_create_file: 'off' fail\n",
1365 __FILE__, __LINE__);
1366 return -ENOENT;
1367 }
1368
1369 if (debugfs_create_file("reg", 0644, dent, 0, &hdmi_reg_fops)
1370 == NULL) {
1371 printk(KERN_ERR "%s(%d): debugfs_create_file: 'reg' fail\n",
1372 __FILE__, __LINE__);
1373 return -ENOENT;
1374 }
1375#endif
1376
1377 return 0;
1378}