blob: 9ae1d9c5b96e0789b4b1c6e249a80db475c652a2 [file] [log] [blame]
/* 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;
if (*ppos)
return 0; /* the end */
bp = debug_buf;
dlen = sizeof(debug_buf);
len = snprintf(bp, dlen, "\nmdp:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_total: %08lu\t",
mdp4_stat.intr_tot);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_overlay0: %08lu\t",
mdp4_stat.intr_overlay0);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
mdp4_stat.intr_overlay1);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_dmap: %08lu\t",
mdp4_stat.intr_dma_p);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_dmas: %08lu\t",
mdp4_stat.intr_dma_s);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_dmae: %08lu\n",
mdp4_stat.intr_dma_e);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "primary: vsync: %08lu\t",
mdp4_stat.intr_vsync_p);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "underrun: %08lu\n",
mdp4_stat.intr_underrun_p);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "external: vsync: %08lu\t",
mdp4_stat.intr_vsync_e);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "underrun: %08lu\n",
mdp4_stat.intr_underrun_e);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "histogram: %08lu\t",
mdp4_stat.intr_histogram);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
mdp4_stat.intr_rd_ptr);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dsi:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_cmd: %08lu\t",
mdp4_stat.intr_dsi_cmd);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_mdp: %08lu\t",
mdp4_stat.intr_dsi_mdp);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "int_err: %08lu\n",
mdp4_stat.intr_dsi_err);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "clk_on : %08lu\t",
mdp4_stat.dsi_clk_on);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
mdp4_stat.dsi_clk_off);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "kickoff:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "overlay0: %08lu\t",
mdp4_stat.kickoff_ov0);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dmap: %08lu\t",
mdp4_stat.kickoff_dmap);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dmas: %08lu\n",
mdp4_stat.kickoff_dmas);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "overlay1: %08lu\t",
mdp4_stat.kickoff_ov1);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dmae: %08lu\n\n",
mdp4_stat.kickoff_dmae);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "overlay0_play:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "set: %08lu\t",
mdp4_stat.overlay_set[0]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "unset: %08lu\t",
mdp4_stat.overlay_unset[0]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "play: %08lu\n",
mdp4_stat.overlay_play[0]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "overlay1_play:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "set: %08lu\t",
mdp4_stat.overlay_set[1]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "unset: %08lu\t",
mdp4_stat.overlay_unset[1]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "play: %08lu\n\n",
mdp4_stat.overlay_play[1]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "frame_push:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "rgb1: %08lu\t\t", mdp4_stat.pipe[0]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "rgb2: %08lu\n", mdp4_stat.pipe[1]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "vg1: %08lu\t\t", mdp4_stat.pipe[2]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "vg2: %08lu\n", mdp4_stat.pipe[3]);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "err_mixer: %08lu\t", 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\t", mdp4_stat.err_scale);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "err_format: %08lu\n\n", mdp4_stat.err_format);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "writeback:\n");
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
mdp4_stat.blt_dsi_cmd);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dsi_video: %08lu\n",
mdp4_stat.blt_dsi_video);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "lcdc: %08lu\t",
mdp4_stat.blt_lcdc);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "dtv: %08lu\t",
mdp4_stat.blt_dtv);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "mddi: %08lu\n\n",
mdp4_stat.blt_mddi);
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;
}