blob: 9ae1d9c5b96e0789b4b1c6e249a80db475c652a2 [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;
kuogee hsieh0948c682011-10-31 16:50:43 -0700300
301 len = snprintf(bp, dlen, "int_dmap: %08lu\t",
302 mdp4_stat.intr_dma_p);
303 bp += len;
304 dlen -= len;
305 len = snprintf(bp, dlen, "int_dmas: %08lu\t",
306 mdp4_stat.intr_dma_s);
307 bp += len;
308 dlen -= len;
309 len = snprintf(bp, dlen, "int_dmae: %08lu\n",
310 mdp4_stat.intr_dma_e);
311 bp += len;
312 dlen -= len;
313
314 len = snprintf(bp, dlen, "primary: vsync: %08lu\t",
315 mdp4_stat.intr_vsync_p);
316 bp += len;
317 dlen -= len;
318 len = snprintf(bp, dlen, "underrun: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319 mdp4_stat.intr_underrun_p);
320 bp += len;
321 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700322 len = snprintf(bp, dlen, "external: vsync: %08lu\t",
323 mdp4_stat.intr_vsync_e);
324 bp += len;
325 dlen -= len;
326 len = snprintf(bp, dlen, "underrun: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700327 mdp4_stat.intr_underrun_e);
328
329 bp += len;
330 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700331 len = snprintf(bp, dlen, "histogram: %08lu\t",
332 mdp4_stat.intr_histogram);
333 bp += len;
334 dlen -= len;
335 len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
336 mdp4_stat.intr_rd_ptr);
337 bp += len;
338 dlen -= len;
339 len = snprintf(bp, dlen, "dsi:\n");
340 bp += len;
341 dlen -= len;
342 len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
343 mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
344 bp += len;
345 dlen -= len;
346 len = snprintf(bp, dlen, "int_cmd: %08lu\t",
347 mdp4_stat.intr_dsi_cmd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700348
349 bp += len;
350 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700351 len = snprintf(bp, dlen, "int_mdp: %08lu\t",
352 mdp4_stat.intr_dsi_mdp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353
354 bp += len;
355 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700356
357 len = snprintf(bp, dlen, "int_err: %08lu\n",
358 mdp4_stat.intr_dsi_err);
359
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700360 bp += len;
361 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700362 len = snprintf(bp, dlen, "clk_on : %08lu\t",
363 mdp4_stat.dsi_clk_on);
364
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 bp += len;
366 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700367 len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
368 mdp4_stat.dsi_clk_off);
369
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700370 bp += len;
371 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700372 len = snprintf(bp, dlen, "kickoff:\n");
373 bp += len;
374 dlen -= len;
375
376 len = snprintf(bp, dlen, "overlay0: %08lu\t",
377 mdp4_stat.kickoff_ov0);
378 bp += len;
379 dlen -= len;
380 len = snprintf(bp, dlen, "dmap: %08lu\t",
381 mdp4_stat.kickoff_dmap);
382 bp += len;
383 dlen -= len;
384 len = snprintf(bp, dlen, "dmas: %08lu\n",
385 mdp4_stat.kickoff_dmas);
386
387 bp += len;
388 dlen -= len;
389 len = snprintf(bp, dlen, "overlay1: %08lu\t",
390 mdp4_stat.kickoff_ov1);
391 bp += len;
392 dlen -= len;
393 len = snprintf(bp, dlen, "dmae: %08lu\n\n",
394 mdp4_stat.kickoff_dmae);
395
396 bp += len;
397 dlen -= len;
398
399 len = snprintf(bp, dlen, "overlay0_play:\n");
400 bp += len;
401 dlen -= len;
402
403 len = snprintf(bp, dlen, "set: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 mdp4_stat.overlay_set[0]);
405 bp += len;
406 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700407 len = snprintf(bp, dlen, "unset: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408 mdp4_stat.overlay_unset[0]);
409 bp += len;
410 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700411 len = snprintf(bp, dlen, "play: %08lu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 mdp4_stat.overlay_play[0]);
413 bp += len;
414 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700415
416 len = snprintf(bp, dlen, "overlay1_play:\n");
417 bp += len;
418 dlen -= len;
419 len = snprintf(bp, dlen, "set: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 mdp4_stat.overlay_set[1]);
421 bp += len;
422 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700423 len = snprintf(bp, dlen, "unset: %08lu\t",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 mdp4_stat.overlay_unset[1]);
425 bp += len;
426 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700427 len = snprintf(bp, dlen, "play: %08lu\n\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 mdp4_stat.overlay_play[1]);
429
430 bp += len;
431 dlen -= len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432
kuogee hsieh0948c682011-10-31 16:50:43 -0700433 len = snprintf(bp, dlen, "frame_push:\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 bp += len;
435 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700436 len = snprintf(bp, dlen, "rgb1: %08lu\t\t", mdp4_stat.pipe[0]);
437 bp += len;
438 dlen -= len;
439 len = snprintf(bp, dlen, "rgb2: %08lu\n", mdp4_stat.pipe[1]);
440 bp += len;
441 dlen -= len;
442 len = snprintf(bp, dlen, "vg1: %08lu\t\t", mdp4_stat.pipe[2]);
443 bp += len;
444 dlen -= len;
445 len = snprintf(bp, dlen, "vg2: %08lu\n", mdp4_stat.pipe[3]);
446 bp += len;
447 dlen -= len;
448 len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
449 bp += len;
450 dlen -= len;
451 len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
452 bp += len;
453 dlen -= len;
454 len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
455 bp += len;
456 dlen -= len;
457 len = snprintf(bp, dlen, "err_format: %08lu\n\n", mdp4_stat.err_format);
458 bp += len;
459 dlen -= len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460
kuogee hsieh0948c682011-10-31 16:50:43 -0700461 len = snprintf(bp, dlen, "writeback:\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700462 bp += len;
463 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700464
465 len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
466 mdp4_stat.blt_dsi_cmd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700467 bp += len;
468 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700469
470 len = snprintf(bp, dlen, "dsi_video: %08lu\n",
471 mdp4_stat.blt_dsi_video);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700472 bp += len;
473 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700474
475 len = snprintf(bp, dlen, "lcdc: %08lu\t",
476 mdp4_stat.blt_lcdc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477 bp += len;
478 dlen -= len;
kuogee hsieh0948c682011-10-31 16:50:43 -0700479
480 len = snprintf(bp, dlen, "dtv: %08lu\t",
481 mdp4_stat.blt_dtv);
482 bp += len;
483 dlen -= len;
484
485 len = snprintf(bp, dlen, "mddi: %08lu\n\n",
486 mdp4_stat.blt_mddi);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700487 bp += len;
488 dlen -= len;
489
490 tot = (uint32)bp - (uint32)debug_buf;
491 *bp = 0;
492 tot++;
493
494 if (tot < 0)
495 return 0;
496 if (copy_to_user(buff, debug_buf, tot))
497 return -EFAULT;
498
499 *ppos += tot; /* increase offset */
500
501 return tot;
502}
503
504static const struct file_operations mdp_stat_fops = {
505 .open = mdp_stat_open,
506 .release = mdp_stat_release,
507 .read = mdp_stat_read,
508 .write = mdp_stat_write,
509};
510#endif
511
512/*
513 * MDDI
514 *
515 */
516
517struct mddi_reg {
518 char *name;
519 int off;
520};
521
522static struct mddi_reg mddi_regs_list[] = {
523 {"MDDI_CMD", MDDI_CMD}, /* 0x0000 */
524 {"MDDI_VERSION", MDDI_VERSION}, /* 0x0004 */
525 {"MDDI_PRI_PTR", MDDI_PRI_PTR}, /* 0x0008 */
526 {"MDDI_BPS", MDDI_BPS}, /* 0x0010 */
527 {"MDDI_SPM", MDDI_SPM}, /* 0x0014 */
528 {"MDDI_INT", MDDI_INT}, /* 0x0018 */
529 {"MDDI_INTEN", MDDI_INTEN}, /* 0x001c */
530 {"MDDI_REV_PTR", MDDI_REV_PTR}, /* 0x0020 */
531 {"MDDI_ REV_SIZE", MDDI_REV_SIZE},/* 0x0024 */
532 {"MDDI_STAT", MDDI_STAT}, /* 0x0028 */
533 {"MDDI_REV_RATE_DIV", MDDI_REV_RATE_DIV}, /* 0x002c */
534 {"MDDI_REV_CRC_ERR", MDDI_REV_CRC_ERR}, /* 0x0030 */
535 {"MDDI_TA1_LEN", MDDI_TA1_LEN}, /* 0x0034 */
536 {"MDDI_TA2_LEN", MDDI_TA2_LEN}, /* 0x0038 */
537 {"MDDI_TEST", MDDI_TEST}, /* 0x0040 */
538 {"MDDI_REV_PKT_CNT", MDDI_REV_PKT_CNT}, /* 0x0044 */
539 {"MDDI_DRIVE_HI", MDDI_DRIVE_HI},/* 0x0048 */
540 {"MDDI_DRIVE_LO", MDDI_DRIVE_LO}, /* 0x004c */
541 {"MDDI_DISP_WAKE", MDDI_DISP_WAKE},/* 0x0050 */
542 {"MDDI_REV_ENCAP_SZ", MDDI_REV_ENCAP_SZ}, /* 0x0054 */
543 {"MDDI_RTD_VAL", MDDI_RTD_VAL}, /* 0x0058 */
544 {"MDDI_PAD_CTL", MDDI_PAD_CTL}, /* 0x0068 */
545 {"MDDI_DRIVER_START_CNT", MDDI_DRIVER_START_CNT}, /* 0x006c */
546 {"MDDI_CORE_VER", MDDI_CORE_VER}, /* 0x008c */
547 {"MDDI_FIFO_ALLOC", MDDI_FIFO_ALLOC}, /* 0x0090 */
548 {"MDDI_PAD_IO_CTL", MDDI_PAD_IO_CTL}, /* 0x00a0 */
549 {"MDDI_PAD_CAL", MDDI_PAD_CAL}, /* 0x00a4 */
550 {0, 0}
551};
552
553static int mddi_reg_open(struct inode *inode, struct file *file)
554{
555 /* non-seekable */
556 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
557 return 0;
558}
559
560static int mddi_reg_release(struct inode *inode, struct file *file)
561{
562 return 0;
563}
564
565static void mddi_reg_write(int ndx, uint32 off, uint32 data)
566{
567 char *base;
568
569 if (ndx)
570 base = (char *)msm_emdh_base;
571 else
572 base = (char *)msm_pmdh_base;
573
574 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
575 writel(data, base + off);
576 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
577
578 printk(KERN_INFO "%s: addr=%x data=%x\n",
579 __func__, (int)(base+off), (int)data);
580}
581
582static int mddi_reg_read(int ndx)
583{
584 struct mddi_reg *reg;
585 unsigned char *base;
586 int data;
587 char *bp;
588 int len = 0;
589 int tot = 0;
590 int dlen;
591
592 if (ndx)
593 base = msm_emdh_base;
594 else
595 base = msm_pmdh_base;
596
597 reg = mddi_regs_list;
598 bp = debug_buf;
599 dlen = sizeof(debug_buf);
600
601 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
602 while (reg->name) {
603 data = readl((u32)base + reg->off);
604 len = snprintf(bp, dlen, "%s:0x%08x\t\t= 0x%08x\n",
605 reg->name, reg->off, data);
606 tot += len;
607 bp += len;
608 dlen -= len;
609 reg++;
610 }
611 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
612 *bp = 0;
613 tot++;
614
615 return tot;
616}
617
618static ssize_t pmdh_reg_write(
619 struct file *file,
620 const char __user *buff,
621 size_t count,
622 loff_t *ppos)
623{
624 uint32 off, data;
625 int cnt;
626
627 if (count >= sizeof(debug_buf))
628 return -EFAULT;
629
630 if (copy_from_user(debug_buf, buff, count))
631 return -EFAULT;
632
633 debug_buf[count] = 0; /* end of string */
634
635 cnt = sscanf(debug_buf, "%x %x", &off, &data);
636
637 mddi_reg_write(0, off, data);
638
639 return count;
640}
641
642static ssize_t pmdh_reg_read(
643 struct file *file,
644 char __user *buff,
645 size_t count,
646 loff_t *ppos)
647{
648 int tot = 0;
649
650 if (*ppos)
651 return 0; /* the end */
652
653 tot = mddi_reg_read(0); /* pmdh */
654
655 if (tot < 0)
656 return 0;
657 if (copy_to_user(buff, debug_buf, tot))
658 return -EFAULT;
659
660 *ppos += tot; /* increase offset */
661
662 return tot;
663}
664
665
666static const struct file_operations pmdh_fops = {
667 .open = mddi_reg_open,
668 .release = mddi_reg_release,
669 .read = pmdh_reg_read,
670 .write = pmdh_reg_write,
671};
672
673
674
675#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
676static int vsync_reg_open(struct inode *inode, struct file *file)
677{
678 /* non-seekable */
679 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
680 return 0;
681}
682
683static int vsync_reg_release(struct inode *inode, struct file *file)
684{
685 return 0;
686}
687
688static ssize_t vsync_reg_write(
689 struct file *file,
690 const char __user *buff,
691 size_t count,
692 loff_t *ppos)
693{
694 uint32 enable;
695 int cnt;
696
697 if (count >= sizeof(debug_buf))
698 return -EFAULT;
699
700 if (copy_from_user(debug_buf, buff, count))
701 return -EFAULT;
702
703 debug_buf[count] = 0; /* end of string */
704
705 cnt = sscanf(debug_buf, "%x", &enable);
706
707 mdp_dmap_vsync_set(enable);
708
709 return count;
710}
711
712static ssize_t vsync_reg_read(
713 struct file *file,
714 char __user *buff,
715 size_t count,
716 loff_t *ppos)
717{
718 char *bp;
719 int len = 0;
720 int tot = 0;
721 int dlen;
722
723 if (*ppos)
724 return 0; /* the end */
725
726 bp = debug_buf;
727 dlen = sizeof(debug_buf);
728 len = snprintf(bp, dlen, "%x\n", mdp_dmap_vsync_get());
729 tot += len;
730 bp += len;
731 *bp = 0;
732 tot++;
733
734 if (copy_to_user(buff, debug_buf, tot))
735 return -EFAULT;
736
737 *ppos += tot; /* increase offset */
738
739 return tot;
740}
741
742
743static const struct file_operations vsync_fops = {
744 .open = vsync_reg_open,
745 .release = vsync_reg_release,
746 .read = vsync_reg_read,
747 .write = vsync_reg_write,
748};
749#endif
750
751static ssize_t emdh_reg_write(
752 struct file *file,
753 const char __user *buff,
754 size_t count,
755 loff_t *ppos)
756{
757 uint32 off, data;
758 int cnt;
759
760 if (count >= sizeof(debug_buf))
761 return -EFAULT;
762
763 if (copy_from_user(debug_buf, buff, count))
764 return -EFAULT;
765
766 debug_buf[count] = 0; /* end of string */
767
768 cnt = sscanf(debug_buf, "%x %x", &off, &data);
769
770 mddi_reg_write(1, off, data);
771
772 return count;
773}
774
775static ssize_t emdh_reg_read(
776 struct file *file,
777 char __user *buff,
778 size_t count,
779 loff_t *ppos)
780{
781 int tot = 0;
782
783 if (*ppos)
784 return 0; /* the end */
785
786 tot = mddi_reg_read(1); /* emdh */
787
788 if (tot < 0)
789 return 0;
790 if (copy_to_user(buff, debug_buf, tot))
791 return -EFAULT;
792
793 *ppos += tot; /* increase offset */
794
795 return tot;
796}
797
798static const struct file_operations emdh_fops = {
799 .open = mddi_reg_open,
800 .release = mddi_reg_release,
801 .read = emdh_reg_read,
802 .write = emdh_reg_write,
803};
804
805
806uint32 dbg_offset;
807uint32 dbg_count;
808char *dbg_base;
809
810
811static int dbg_open(struct inode *inode, struct file *file)
812{
813 /* non-seekable */
814 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
815 return 0;
816}
817
818static int dbg_release(struct inode *inode, struct file *file)
819{
820 return 0;
821}
822
823static ssize_t dbg_base_write(
824 struct file *file,
825 const char __user *buff,
826 size_t count,
827 loff_t *ppos)
828{
829 return count;
830}
831
832static ssize_t dbg_base_read(
833 struct file *file,
834 char __user *buff,
835 size_t count,
836 loff_t *ppos)
837{
838 int len = 0;
839 int tot = 0;
840 int dlen;
841 char *bp;
842
843
844 if (*ppos)
845 return 0; /* the end */
846
847
848 bp = debug_buf;
849 dlen = sizeof(debug_buf);
850
851 len = snprintf(bp, dlen, "mdp_base : %08x\n",
852 (int)msm_mdp_base);
853 bp += len;
854 dlen -= len;
855 len = snprintf(bp, dlen, "mddi_base : %08x\n",
856 (int)msm_pmdh_base);
857 bp += len;
858 dlen -= len;
859 len = snprintf(bp, dlen, "emdh_base : %08x\n",
860 (int)msm_emdh_base);
861 bp += len;
862 dlen -= len;
863#ifdef CONFIG_FB_MSM_TVOUT
864 len = snprintf(bp, dlen, "tvenv_base: %08x\n",
865 (int)tvenc_base);
866 bp += len;
867 dlen -= len;
868#endif
869
870#ifdef CONFIG_FB_MSM_MIPI_DSI
871 len = snprintf(bp, dlen, "mipi_dsi_base: %08x\n",
872 (int)mipi_dsi_base);
873 bp += len;
874 dlen -= len;
875#endif
876
877 tot = (uint32)bp - (uint32)debug_buf;
878 *bp = 0;
879 tot++;
880
881 if (tot < 0)
882 return 0;
883 if (copy_to_user(buff, debug_buf, tot))
884 return -EFAULT;
885
886 *ppos += tot; /* increase offset */
887
888 return tot;
889}
890
891static const struct file_operations dbg_base_fops = {
892 .open = dbg_open,
893 .release = dbg_release,
894 .read = dbg_base_read,
895 .write = dbg_base_write,
896};
897
898static ssize_t dbg_offset_write(
899 struct file *file,
900 const char __user *buff,
901 size_t count,
902 loff_t *ppos)
903{
904 uint32 off, cnt, num, base;
905
906 if (count >= sizeof(debug_buf))
907 return -EFAULT;
908
909 if (copy_from_user(debug_buf, buff, count))
910 return -EFAULT;
911
912 debug_buf[count] = 0; /* end of string */
913
914 cnt = sscanf(debug_buf, "%x %d %x", &off, &num, &base);
915
916 if (cnt < 0)
917 cnt = 0;
918
919 if (cnt >= 1)
920 dbg_offset = off;
921 if (cnt >= 2)
922 dbg_count = num;
923 if (cnt >= 3)
924 dbg_base = (char *)base;
925
926 printk(KERN_INFO "%s: offset=%x cnt=%d base=%x\n", __func__,
927 dbg_offset, dbg_count, (int)dbg_base);
928
929 return count;
930}
931
932static ssize_t dbg_offset_read(
933 struct file *file,
934 char __user *buff,
935 size_t count,
936 loff_t *ppos)
937{
938 int len = 0;
939
940
941 if (*ppos)
942 return 0; /* the end */
943
944 len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d 0x%08x\n",
945 dbg_offset, dbg_count, (int)dbg_base);
946 if (len < 0)
947 return 0;
948
949 if (copy_to_user(buff, debug_buf, len))
950 return -EFAULT;
951
952 *ppos += len; /* increase offset */
953
954 return len;
955}
956
957static const struct file_operations dbg_off_fops = {
958 .open = dbg_open,
959 .release = dbg_release,
960 .read = dbg_offset_read,
961 .write = dbg_offset_write,
962};
963
964
965static ssize_t dbg_reg_write(
966 struct file *file,
967 const char __user *buff,
968 size_t count,
969 loff_t *ppos)
970{
971 uint32 off, data;
972 int cnt;
973
974 if (count >= sizeof(debug_buf))
975 return -EFAULT;
976
977 if (copy_from_user(debug_buf, buff, count))
978 return -EFAULT;
979
980 debug_buf[count] = 0; /* end of string */
981
982 cnt = sscanf(debug_buf, "%x %x", &off, &data);
983
984 writel(data, dbg_base + off);
985
986 printk(KERN_INFO "%s: addr=%x data=%x\n",
987 __func__, (int)(dbg_base+off), (int)data);
988
989 return count;
990}
991
992static ssize_t dbg_reg_read(
993 struct file *file,
994 char __user *buff,
995 size_t count,
996 loff_t *ppos)
997{
998 int len = 0;
999 uint32 data;
1000 int i, j, off, dlen, num;
1001 char *bp, *cp;
1002 int tot = 0;
1003
1004
1005 if (*ppos)
1006 return 0; /* the end */
1007
1008 if (dbg_base == 0)
1009 return 0; /* nothing to read */
1010
1011 j = 0;
1012 num = 0;
1013 bp = debug_buf;
1014 cp = (char *)(dbg_base + dbg_offset);
1015 dlen = sizeof(debug_buf);
1016 while (j++ < 16) {
1017 len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
1018 tot += len;
1019 bp += len;
1020 dlen -= len;
1021 off = 0;
1022 i = 0;
1023 while (i++ < 4) {
1024 data = readl(cp + off);
1025 len = snprintf(bp, dlen, "%08x ", data);
1026 tot += len;
1027 bp += len;
1028 dlen -= len;
1029 off += 4;
1030 num++;
1031 if (num >= dbg_count)
1032 break;
1033 }
1034 data = readl((u32)cp + off);
1035 *bp++ = '\n';
1036 --dlen;
1037 tot++;
1038 cp += off;
1039 if (num >= dbg_count)
1040 break;
1041 }
1042 *bp = 0;
1043 tot++;
1044
1045 if (copy_to_user(buff, debug_buf, tot))
1046 return -EFAULT;
1047
1048 *ppos += tot; /* increase offset */
1049
1050 return tot;
1051}
1052
1053
1054static const struct file_operations dbg_reg_fops = {
1055 .open = dbg_open,
1056 .release = dbg_release,
1057 .read = dbg_reg_read,
1058 .write = dbg_reg_write,
1059};
1060
1061#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1062static uint32 hdmi_offset;
1063static uint32 hdmi_count;
1064
1065static int hdmi_open(struct inode *inode, struct file *file)
1066{
1067 /* non-seekable */
1068 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
1069 return 0;
1070}
1071
1072static int hdmi_release(struct inode *inode, struct file *file)
1073{
1074 return 0;
1075}
1076
1077static ssize_t hdmi_offset_write(
1078 struct file *file,
1079 const char __user *buff,
1080 size_t count,
1081 loff_t *ppos)
1082{
1083 uint32 off, cnt, num;
1084
1085 if (count >= sizeof(debug_buf))
1086 return -EFAULT;
1087
1088 if (copy_from_user(debug_buf, buff, count))
1089 return -EFAULT;
1090
1091 debug_buf[count] = 0; /* end of string */
1092
1093 cnt = sscanf(debug_buf, "%x %d", &off, &num);
1094
1095 if (cnt < 0)
1096 cnt = 0;
1097
1098 if (cnt >= 1)
1099 hdmi_offset = off;
1100 if (cnt >= 2)
1101 hdmi_count = num;
1102
1103 printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
1104 hdmi_offset, hdmi_count);
1105
1106 return count;
1107}
1108
1109static ssize_t hdmi_offset_read(
1110 struct file *file,
1111 char __user *buff,
1112 size_t count,
1113 loff_t *ppos)
1114{
1115 int len = 0;
1116
1117
1118 if (*ppos)
1119 return 0; /* the end */
1120
1121 len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
1122 hdmi_offset, hdmi_count);
1123 if (len < 0)
1124 return 0;
1125
1126 if (copy_to_user(buff, debug_buf, len))
1127 return -EFAULT;
1128
1129 *ppos += len; /* increase offset */
1130
1131 return len;
1132}
1133
1134static const struct file_operations hdmi_off_fops = {
1135 .open = hdmi_open,
1136 .release = hdmi_release,
1137 .read = hdmi_offset_read,
1138 .write = hdmi_offset_write,
1139};
1140
1141
1142static ssize_t hdmi_reg_write(
1143 struct file *file,
1144 const char __user *buff,
1145 size_t count,
1146 loff_t *ppos)
1147{
1148 uint32 off, data, base;
1149 int cnt;
1150
1151 if (count >= sizeof(debug_buf))
1152 return -EFAULT;
1153
1154 if (copy_from_user(debug_buf, buff, count))
1155 return -EFAULT;
1156
1157 base = hdmi_msm_get_io_base();
1158 if (base == 0)
1159 return -EFAULT;
1160
1161 debug_buf[count] = 0; /* end of string */
1162
1163 cnt = sscanf(debug_buf, "%x %x", &off, &data);
1164
1165 writel(data, base + off);
1166
1167 printk(KERN_INFO "%s: addr=%x data=%x\n",
1168 __func__, (int)(base+off), (int)data);
1169
1170 return count;
1171}
1172
1173static ssize_t hdmi_reg_read(
1174 struct file *file,
1175 char __user *buff,
1176 size_t count,
1177 loff_t *ppos)
1178{
1179 int len = 0;
1180 uint32 data;
1181 int i, j, off, dlen, num;
1182 char *bp, *cp;
1183 int tot = 0;
1184
1185
1186 if (*ppos)
1187 return 0; /* the end */
1188
1189 if (hdmi_msm_get_io_base() == 0)
1190 return 0; /* nothing to read */
1191
1192 j = 0;
1193 num = 0;
1194 bp = debug_buf;
1195 cp = (char *)(hdmi_msm_get_io_base() + hdmi_offset);
1196 dlen = sizeof(debug_buf);
1197 while (j++ < 16) {
1198 len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
1199 tot += len;
1200 bp += len;
1201 dlen -= len;
1202 off = 0;
1203 i = 0;
1204 while (i++ < 4) {
1205 data = readl(cp + off);
1206 len = snprintf(bp, dlen, "%08x ", data);
1207 tot += len;
1208 bp += len;
1209 dlen -= len;
1210 off += 4;
1211 num++;
1212 if (num >= hdmi_count)
1213 break;
1214 }
1215 data = readl((u32)cp + off);
1216 *bp++ = '\n';
1217 --dlen;
1218 tot++;
1219 cp += off;
1220 if (num >= hdmi_count)
1221 break;
1222 }
1223 *bp = 0;
1224 tot++;
1225
1226 if (copy_to_user(buff, debug_buf, tot))
1227 return -EFAULT;
1228
1229 *ppos += tot; /* increase offset */
1230
1231 return tot;
1232}
1233
1234
1235static const struct file_operations hdmi_reg_fops = {
1236 .open = hdmi_open,
1237 .release = hdmi_release,
1238 .read = hdmi_reg_read,
1239 .write = hdmi_reg_write,
1240};
1241#endif
1242
1243/*
1244 * debugfs
1245 *
1246 */
1247
1248int mdp_debugfs_init(void)
1249{
1250 struct dentry *dent = debugfs_create_dir("mdp", NULL);
1251
1252 if (IS_ERR(dent)) {
1253 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1254 __FILE__, __LINE__, PTR_ERR(dent));
1255 return -1;
1256 }
1257
1258 if (debugfs_create_file("off", 0644, dent, 0, &mdp_off_fops)
1259 == NULL) {
1260 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1261 __FILE__, __LINE__);
1262 return -1;
1263 }
1264
1265 if (debugfs_create_file("reg", 0644, dent, 0, &mdp_reg_fops)
1266 == NULL) {
1267 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1268 __FILE__, __LINE__);
1269 return -1;
1270 }
1271
1272#ifdef CONFIG_FB_MSM_MDP40
1273 if (debugfs_create_file("stat", 0644, dent, 0, &mdp_stat_fops)
1274 == NULL) {
1275 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1276 __FILE__, __LINE__);
1277 return -1;
1278 }
1279#endif
1280
1281 dent = debugfs_create_dir("mddi", NULL);
1282
1283 if (IS_ERR(dent)) {
1284 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1285 __FILE__, __LINE__, PTR_ERR(dent));
1286 return -1;
1287 }
1288
1289 if (debugfs_create_file("reg", 0644, dent, 0, &pmdh_fops)
1290 == NULL) {
1291 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1292 __FILE__, __LINE__);
1293 return -1;
1294 }
1295
1296#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
1297 if (debugfs_create_file("vsync", 0644, dent, 0, &vsync_fops)
1298 == NULL) {
1299 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1300 __FILE__, __LINE__);
1301 return -1;
1302 }
1303#endif
1304
1305 dent = debugfs_create_dir("emdh", NULL);
1306
1307 if (IS_ERR(dent)) {
1308 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1309 __FILE__, __LINE__, PTR_ERR(dent));
1310 return -1;
1311 }
1312
1313 if (debugfs_create_file("reg", 0644, dent, 0, &emdh_fops)
1314 == NULL) {
1315 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1316 __FILE__, __LINE__);
1317 return -1;
1318 }
1319
1320 dent = debugfs_create_dir("mdp-dbg", NULL);
1321
1322 if (IS_ERR(dent)) {
1323 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1324 __FILE__, __LINE__, PTR_ERR(dent));
1325 return -1;
1326 }
1327
1328 if (debugfs_create_file("base", 0644, dent, 0, &dbg_base_fops)
1329 == NULL) {
1330 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1331 __FILE__, __LINE__);
1332 return -1;
1333 }
1334
1335 if (debugfs_create_file("off", 0644, dent, 0, &dbg_off_fops)
1336 == NULL) {
1337 printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
1338 __FILE__, __LINE__);
1339 return -1;
1340 }
1341
1342 if (debugfs_create_file("reg", 0644, dent, 0, &dbg_reg_fops)
1343 == NULL) {
1344 printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
1345 __FILE__, __LINE__);
1346 return -1;
1347 }
1348
1349#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
1350 dent = debugfs_create_dir("hdmi", NULL);
1351
1352 if (IS_ERR(dent)) {
1353 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
1354 __FILE__, __LINE__, PTR_ERR(dent));
1355 return PTR_ERR(dent);
1356 }
1357
1358 if (debugfs_create_file("off", 0644, dent, 0, &hdmi_off_fops)
1359 == NULL) {
1360 printk(KERN_ERR "%s(%d): debugfs_create_file: 'off' fail\n",
1361 __FILE__, __LINE__);
1362 return -ENOENT;
1363 }
1364
1365 if (debugfs_create_file("reg", 0644, dent, 0, &hdmi_reg_fops)
1366 == NULL) {
1367 printk(KERN_ERR "%s(%d): debugfs_create_file: 'reg' fail\n",
1368 __FILE__, __LINE__);
1369 return -ENOENT;
1370 }
1371#endif
1372
1373 return 0;
1374}