Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
new file mode 100644
index 0000000..b89e8c7
--- /dev/null
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -0,0 +1,1289 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+#include "mddihosti.h"
+#include "tvenc.h"
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#include "hdmi_msm.h"
+#endif
+
+#define MDP_DEBUG_BUF 2048
+
+static uint32 mdp_offset;
+static uint32 mdp_count;
+
+static char debug_buf[MDP_DEBUG_BUF];
+
+/*
+ * MDP4
+ *
+ */
+
+static int mdp_offset_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_offset_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ sscanf(debug_buf, "%x %d", &off, &cnt);
+
+ if (cnt <= 0)
+ cnt = 1;
+
+ mdp_offset = off;
+ mdp_count = cnt;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
+ mdp_offset, mdp_count);
+
+ return count;
+}
+
+static ssize_t mdp_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
+ mdp_offset, mdp_count);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations mdp_off_fops = {
+ .open = mdp_offset_open,
+ .release = mdp_offset_release,
+ .read = mdp_offset_read,
+ .write = mdp_offset_write,
+};
+
+static int mdp_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + off, data);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n", __func__, off, data);
+
+ return count;
+}
+
+static ssize_t mdp_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = MDP_BASE + mdp_offset;
+ dlen = sizeof(debug_buf);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ while (j++ < 8) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = inpdw(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= mdp_count)
+ break;
+ }
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= mdp_count)
+ break;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations mdp_reg_fops = {
+ .open = mdp_reg_open,
+ .release = mdp_reg_release,
+ .read = mdp_reg_read,
+ .write = mdp_reg_write,
+};
+
+#ifdef CONFIG_FB_MSM_MDP40
+static int mdp_stat_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp_stat_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp_stat_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ unsigned long flag;
+
+ if (count > sizeof(debug_buf))
+ return -EFAULT;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ memset((char *)&mdp4_stat, 0 , sizeof(mdp4_stat)); /* reset */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ return count;
+}
+
+static ssize_t mdp_stat_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ int tot = 0;
+ int dlen;
+ char *bp;
+ unsigned long flag;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ len = snprintf(bp, dlen, "intr_total: %08lu\n",
+ mdp4_stat.intr_tot);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_p: %08lu\n",
+ mdp4_stat.intr_dma_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_s: %08lu\n",
+ mdp4_stat.intr_dma_s);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dma_e: %08lu\n",
+ mdp4_stat.intr_dma_e);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_overlay0: %08lu\n",
+ mdp4_stat.intr_overlay0);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_overlay1: %08lu\n",
+ mdp4_stat.intr_overlay1);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unerrun_primary: %08lu\n",
+ mdp4_stat.intr_underrun_p);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "unerrun_external: %08lu\n\n",
+ mdp4_stat.intr_underrun_e);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "intr_dsi : %08lu\n\n",
+ mdp4_stat.intr_dsi);
+
+ bp += len;
+ dlen -= len;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ len = snprintf(bp, dlen, "kickoff_mddi: %08lu\n",
+ mdp4_stat.kickoff_mddi);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_lcdc: %08lu\n",
+ mdp4_stat.kickoff_lcdc);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_dtv: %08lu\n",
+ mdp4_stat.kickoff_dtv);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_atv: %08lu\n",
+ mdp4_stat.kickoff_atv);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "kickoff_dsi: %08lu\n\n",
+ mdp4_stat.kickoff_dsi);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "writeback: %08lu\n",
+ mdp4_stat.writeback);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_set: %08lu\n",
+ mdp4_stat.overlay_set[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_unset: %08lu\n",
+ mdp4_stat.overlay_unset[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay0_play: %08lu\n",
+ mdp4_stat.overlay_play[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_set: %08lu\n",
+ mdp4_stat.overlay_set[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_unset: %08lu\n",
+ mdp4_stat.overlay_unset[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "overlay1_play: %08lu\n\n",
+ mdp4_stat.overlay_play[1]);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_rgb1: %08lu\n", mdp4_stat.pipe[0]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_rgb2: %08lu\n", mdp4_stat.pipe[1]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_vg1: %08lu\n", mdp4_stat.pipe[2]);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "pipe_vg2: %08lu\n\n", mdp4_stat.pipe[3]);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "dsi_clkoff: %08lu\n\n", mdp4_stat.dsi_clkoff);
+
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_mixer: %08lu\n", mdp4_stat.err_mixer);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_size: %08lu\n", mdp4_stat.err_size);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_scale: %08lu\n", mdp4_stat.err_scale);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
+ bp += len;
+ dlen -= len;
+
+ tot = (uint32)bp - (uint32)debug_buf;
+ *bp = 0;
+ tot++;
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations mdp_stat_fops = {
+ .open = mdp_stat_open,
+ .release = mdp_stat_release,
+ .read = mdp_stat_read,
+ .write = mdp_stat_write,
+};
+#endif
+
+/*
+ * MDDI
+ *
+ */
+
+struct mddi_reg {
+ char *name;
+ int off;
+};
+
+static struct mddi_reg mddi_regs_list[] = {
+ {"MDDI_CMD", MDDI_CMD}, /* 0x0000 */
+ {"MDDI_VERSION", MDDI_VERSION}, /* 0x0004 */
+ {"MDDI_PRI_PTR", MDDI_PRI_PTR}, /* 0x0008 */
+ {"MDDI_BPS", MDDI_BPS}, /* 0x0010 */
+ {"MDDI_SPM", MDDI_SPM}, /* 0x0014 */
+ {"MDDI_INT", MDDI_INT}, /* 0x0018 */
+ {"MDDI_INTEN", MDDI_INTEN}, /* 0x001c */
+ {"MDDI_REV_PTR", MDDI_REV_PTR}, /* 0x0020 */
+ {"MDDI_ REV_SIZE", MDDI_REV_SIZE},/* 0x0024 */
+ {"MDDI_STAT", MDDI_STAT}, /* 0x0028 */
+ {"MDDI_REV_RATE_DIV", MDDI_REV_RATE_DIV}, /* 0x002c */
+ {"MDDI_REV_CRC_ERR", MDDI_REV_CRC_ERR}, /* 0x0030 */
+ {"MDDI_TA1_LEN", MDDI_TA1_LEN}, /* 0x0034 */
+ {"MDDI_TA2_LEN", MDDI_TA2_LEN}, /* 0x0038 */
+ {"MDDI_TEST", MDDI_TEST}, /* 0x0040 */
+ {"MDDI_REV_PKT_CNT", MDDI_REV_PKT_CNT}, /* 0x0044 */
+ {"MDDI_DRIVE_HI", MDDI_DRIVE_HI},/* 0x0048 */
+ {"MDDI_DRIVE_LO", MDDI_DRIVE_LO}, /* 0x004c */
+ {"MDDI_DISP_WAKE", MDDI_DISP_WAKE},/* 0x0050 */
+ {"MDDI_REV_ENCAP_SZ", MDDI_REV_ENCAP_SZ}, /* 0x0054 */
+ {"MDDI_RTD_VAL", MDDI_RTD_VAL}, /* 0x0058 */
+ {"MDDI_PAD_CTL", MDDI_PAD_CTL}, /* 0x0068 */
+ {"MDDI_DRIVER_START_CNT", MDDI_DRIVER_START_CNT}, /* 0x006c */
+ {"MDDI_CORE_VER", MDDI_CORE_VER}, /* 0x008c */
+ {"MDDI_FIFO_ALLOC", MDDI_FIFO_ALLOC}, /* 0x0090 */
+ {"MDDI_PAD_IO_CTL", MDDI_PAD_IO_CTL}, /* 0x00a0 */
+ {"MDDI_PAD_CAL", MDDI_PAD_CAL}, /* 0x00a4 */
+ {0, 0}
+};
+
+static int mddi_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mddi_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static void mddi_reg_write(int ndx, uint32 off, uint32 data)
+{
+ char *base;
+
+ if (ndx)
+ base = (char *)msm_emdh_base;
+ else
+ base = (char *)msm_pmdh_base;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ writel(data, base + off);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(base+off), (int)data);
+}
+
+static int mddi_reg_read(int ndx)
+{
+ struct mddi_reg *reg;
+ unsigned char *base;
+ int data;
+ char *bp;
+ int len = 0;
+ int tot = 0;
+ int dlen;
+
+ if (ndx)
+ base = msm_emdh_base;
+ else
+ base = msm_pmdh_base;
+
+ reg = mddi_regs_list;
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ while (reg->name) {
+ data = readl((u32)base + reg->off);
+ len = snprintf(bp, dlen, "%s:0x%08x\t\t= 0x%08x\n",
+ reg->name, reg->off, data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ reg++;
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ *bp = 0;
+ tot++;
+
+ return tot;
+}
+
+static ssize_t pmdh_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mddi_reg_write(0, off, data);
+
+ return count;
+}
+
+static ssize_t pmdh_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int tot = 0;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ tot = mddi_reg_read(0); /* pmdh */
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations pmdh_fops = {
+ .open = mddi_reg_open,
+ .release = mddi_reg_release,
+ .read = pmdh_reg_read,
+ .write = pmdh_reg_write,
+};
+
+
+
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+static int vsync_reg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int vsync_reg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t vsync_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 enable;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x", &enable);
+
+ mdp_dmap_vsync_set(enable);
+
+ return count;
+}
+
+static ssize_t vsync_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ char *bp;
+ int len = 0;
+ int tot = 0;
+ int dlen;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+ len = snprintf(bp, dlen, "%x\n", mdp_dmap_vsync_get());
+ tot += len;
+ bp += len;
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations vsync_fops = {
+ .open = vsync_reg_open,
+ .release = vsync_reg_release,
+ .read = vsync_reg_read,
+ .write = vsync_reg_write,
+};
+#endif
+
+static ssize_t emdh_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ mddi_reg_write(1, off, data);
+
+ return count;
+}
+
+static ssize_t emdh_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int tot = 0;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ tot = mddi_reg_read(1); /* emdh */
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations emdh_fops = {
+ .open = mddi_reg_open,
+ .release = mddi_reg_release,
+ .read = emdh_reg_read,
+ .write = emdh_reg_write,
+};
+
+
+uint32 dbg_offset;
+uint32 dbg_count;
+char *dbg_base;
+
+
+static int dbg_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int dbg_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t dbg_base_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ return count;
+}
+
+static ssize_t dbg_base_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ int tot = 0;
+ int dlen;
+ char *bp;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+
+ bp = debug_buf;
+ dlen = sizeof(debug_buf);
+
+ len = snprintf(bp, dlen, "mdp_base : %08x\n",
+ (int)msm_mdp_base);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "mddi_base : %08x\n",
+ (int)msm_pmdh_base);
+ bp += len;
+ dlen -= len;
+ len = snprintf(bp, dlen, "emdh_base : %08x\n",
+ (int)msm_emdh_base);
+ bp += len;
+ dlen -= len;
+#ifdef CONFIG_FB_MSM_TVOUT
+ len = snprintf(bp, dlen, "tvenv_base: %08x\n",
+ (int)tvenc_base);
+ bp += len;
+ dlen -= len;
+#endif
+
+#ifdef CONFIG_FB_MSM_MIPI_DSI
+ len = snprintf(bp, dlen, "mipi_dsi_base: %08x\n",
+ (int)mipi_dsi_base);
+ bp += len;
+ dlen -= len;
+#endif
+
+ tot = (uint32)bp - (uint32)debug_buf;
+ *bp = 0;
+ tot++;
+
+ if (tot < 0)
+ return 0;
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations dbg_base_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_base_read,
+ .write = dbg_base_write,
+};
+
+static ssize_t dbg_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt, num, base;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %d %x", &off, &num, &base);
+
+ if (cnt < 0)
+ cnt = 0;
+
+ if (cnt >= 1)
+ dbg_offset = off;
+ if (cnt >= 2)
+ dbg_count = num;
+ if (cnt >= 3)
+ dbg_base = (char *)base;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d base=%x\n", __func__,
+ dbg_offset, dbg_count, (int)dbg_base);
+
+ return count;
+}
+
+static ssize_t dbg_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d 0x%08x\n",
+ dbg_offset, dbg_count, (int)dbg_base);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations dbg_off_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_offset_read,
+ .write = dbg_offset_write,
+};
+
+
+static ssize_t dbg_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ writel(data, dbg_base + off);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(dbg_base+off), (int)data);
+
+ return count;
+}
+
+static ssize_t dbg_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ if (dbg_base == 0)
+ return 0; /* nothing to read */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = (char *)(dbg_base + dbg_offset);
+ dlen = sizeof(debug_buf);
+ while (j++ < 16) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = readl(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= dbg_count)
+ break;
+ }
+ data = readl((u32)cp + off);
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= dbg_count)
+ break;
+ }
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations dbg_reg_fops = {
+ .open = dbg_open,
+ .release = dbg_release,
+ .read = dbg_reg_read,
+ .write = dbg_reg_write,
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static uint32 hdmi_offset;
+static uint32 hdmi_count;
+
+static int hdmi_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int hdmi_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t hdmi_offset_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, cnt, num;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %d", &off, &num);
+
+ if (cnt < 0)
+ cnt = 0;
+
+ if (cnt >= 1)
+ hdmi_offset = off;
+ if (cnt >= 2)
+ hdmi_count = num;
+
+ printk(KERN_INFO "%s: offset=%x cnt=%d\n", __func__,
+ hdmi_offset, hdmi_count);
+
+ return count;
+}
+
+static ssize_t hdmi_offset_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(debug_buf, sizeof(debug_buf), "0x%08x %d\n",
+ hdmi_offset, hdmi_count);
+ if (len < 0)
+ return 0;
+
+ if (copy_to_user(buff, debug_buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations hdmi_off_fops = {
+ .open = hdmi_open,
+ .release = hdmi_release,
+ .read = hdmi_offset_read,
+ .write = hdmi_offset_write,
+};
+
+
+static ssize_t hdmi_reg_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ uint32 off, data, base;
+ int cnt;
+
+ if (count >= sizeof(debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(debug_buf, buff, count))
+ return -EFAULT;
+
+ base = hdmi_msm_get_io_base();
+ if (base == 0)
+ return -EFAULT;
+
+ debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(debug_buf, "%x %x", &off, &data);
+
+ writel(data, base + off);
+
+ printk(KERN_INFO "%s: addr=%x data=%x\n",
+ __func__, (int)(base+off), (int)data);
+
+ return count;
+}
+
+static ssize_t hdmi_reg_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ uint32 data;
+ int i, j, off, dlen, num;
+ char *bp, *cp;
+ int tot = 0;
+
+
+ if (*ppos)
+ return 0; /* the end */
+
+ if (hdmi_msm_get_io_base() == 0)
+ return 0; /* nothing to read */
+
+ j = 0;
+ num = 0;
+ bp = debug_buf;
+ cp = (char *)(hdmi_msm_get_io_base() + hdmi_offset);
+ dlen = sizeof(debug_buf);
+ while (j++ < 16) {
+ len = snprintf(bp, dlen, "0x%08x: ", (int)cp);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off = 0;
+ i = 0;
+ while (i++ < 4) {
+ data = readl(cp + off);
+ len = snprintf(bp, dlen, "%08x ", data);
+ tot += len;
+ bp += len;
+ dlen -= len;
+ off += 4;
+ num++;
+ if (num >= hdmi_count)
+ break;
+ }
+ data = readl((u32)cp + off);
+ *bp++ = '\n';
+ --dlen;
+ tot++;
+ cp += off;
+ if (num >= hdmi_count)
+ break;
+ }
+ *bp = 0;
+ tot++;
+
+ if (copy_to_user(buff, debug_buf, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+
+static const struct file_operations hdmi_reg_fops = {
+ .open = hdmi_open,
+ .release = hdmi_release,
+ .read = hdmi_reg_read,
+ .write = hdmi_reg_write,
+};
+#endif
+
+/*
+ * debugfs
+ *
+ */
+
+int mdp_debugfs_init(void)
+{
+ struct dentry *dent = debugfs_create_dir("mdp", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &mdp_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &mdp_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (debugfs_create_file("stat", 0644, dent, 0, &mdp_stat_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+#endif
+
+ dent = debugfs_create_dir("mddi", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &pmdh_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#if defined(CONFIG_FB_MSM_OVERLAY) && defined(CONFIG_FB_MSM_MDDI)
+ if (debugfs_create_file("vsync", 0644, dent, 0, &vsync_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+#endif
+
+ dent = debugfs_create_dir("emdh", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &emdh_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ dent = debugfs_create_dir("mdp-dbg", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("base", 0644, dent, 0, &dbg_base_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &dbg_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: index fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &dbg_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: debug fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ dent = debugfs_create_dir("hdmi", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return PTR_ERR(dent);
+ }
+
+ if (debugfs_create_file("off", 0644, dent, 0, &hdmi_off_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: 'off' fail\n",
+ __FILE__, __LINE__);
+ return -ENOENT;
+ }
+
+ if (debugfs_create_file("reg", 0644, dent, 0, &hdmi_reg_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: 'reg' fail\n",
+ __FILE__, __LINE__);
+ return -ENOENT;
+ }
+#endif
+
+ return 0;
+}