mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
drm: bridge: dw-hdmi: add debugfs node
Create two debugfs node to debug hdmi controller and phy. Use following command to debug: Read hdmi controller register: cat /d/dw-hdmi/ctrl Read hdmi phy register: cat /d/dw-hdmi/phy Write hdmi controller register: echo <reg> <val> > /d/dw-hdmi/ctrl Write hdmi phy register: echo <reg> <val> > /d/dw-hdmi/phy <reg> and <val> is hexadecimal. Change-Id: I02e40cc94aa651ff0734feddbfa7d816edcf222f Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
This commit is contained in:
@@ -1383,6 +1383,23 @@ static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int hdmi_phy_i2c_read(struct dw_hdmi *hdmi, unsigned char addr)
|
||||
{
|
||||
int val;
|
||||
|
||||
hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
|
||||
hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
|
||||
hdmi_writeb(hdmi, 0, HDMI_PHY_I2CM_DATAI_1_ADDR);
|
||||
hdmi_writeb(hdmi, 0, HDMI_PHY_I2CM_DATAI_0_ADDR);
|
||||
hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_READ,
|
||||
HDMI_PHY_I2CM_OPERATION_ADDR);
|
||||
hdmi_phy_wait_i2c_done(hdmi, 1000);
|
||||
val = hdmi_readb(hdmi, HDMI_PHY_I2CM_DATAI_1_ADDR);
|
||||
val = (val & 0xff) << 8;
|
||||
val += hdmi_readb(hdmi, HDMI_PHY_I2CM_DATAI_0_ADDR) & 0xff;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* HDMI2.0 Specifies the following procedure for High TMDS Bit Rates:
|
||||
* - The Source shall suspend transmission of the TMDS clock and data
|
||||
@@ -3407,6 +3424,158 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
|
||||
hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
struct dw_hdmi_reg_table {
|
||||
int reg_base;
|
||||
int reg_end;
|
||||
};
|
||||
|
||||
static const struct dw_hdmi_reg_table hdmi_reg_table[] = {
|
||||
{HDMI_DESIGN_ID, HDMI_CONFIG3_ID},
|
||||
{HDMI_IH_FC_STAT0, HDMI_IH_MUTE},
|
||||
{HDMI_TX_INVID0, HDMI_TX_BCBDATA1},
|
||||
{HDMI_VP_STATUS, HDMI_VP_POL},
|
||||
{HDMI_FC_INVIDCONF, HDMI_FC_DBGTMDS2},
|
||||
{HDMI_PHY_CONF0, HDMI_PHY_POL0},
|
||||
{HDMI_PHY_I2CM_SLAVE_ADDR, HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR},
|
||||
{HDMI_AUD_CONF0, 0x3624},
|
||||
{HDMI_MC_SFRDIV, HDMI_MC_HEACPHY_RST},
|
||||
{HDMI_CSC_CFG, HDMI_CSC_COEF_C4_LSB},
|
||||
{HDMI_A_HDCPCFG0, 0x52bb},
|
||||
{0x7800, 0x7818},
|
||||
{0x7900, 0x790e},
|
||||
{HDMI_CEC_CTRL, HDMI_CEC_WKUPCTRL},
|
||||
{HDMI_I2CM_SLAVE, 0x7e31},
|
||||
};
|
||||
|
||||
static int dw_hdmi_ctrl_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct dw_hdmi *hdmi = s->private;
|
||||
u32 i = 0, j = 0, val = 0;
|
||||
|
||||
seq_puts(s, "\n>>>hdmi_ctl reg ");
|
||||
for (i = 0; i < 16; i++)
|
||||
seq_printf(s, " %2x", i);
|
||||
seq_puts(s, "\n---------------------------------------------------");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
|
||||
for (j = hdmi_reg_table[i].reg_base;
|
||||
j <= hdmi_reg_table[i].reg_end; j++) {
|
||||
val = hdmi_readb(hdmi, j);
|
||||
if ((j - hdmi_reg_table[i].reg_base) % 16 == 0)
|
||||
seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
|
||||
seq_printf(s, " %02x", val);
|
||||
}
|
||||
}
|
||||
seq_puts(s, "\n---------------------------------------------------\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_hdmi_ctrl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dw_hdmi_ctrl_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dw_hdmi_ctrl_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct dw_hdmi *hdmi =
|
||||
((struct seq_file *)file->private_data)->private;
|
||||
u32 reg, val;
|
||||
char kbuf[25];
|
||||
|
||||
if (copy_from_user(kbuf, buf, count))
|
||||
return -EFAULT;
|
||||
if (sscanf(kbuf, "%x%x", ®, &val) == -1)
|
||||
return -EFAULT;
|
||||
if (reg > HDMI_I2CM_FS_SCL_LCNT_0_ADDR) {
|
||||
dev_err(hdmi->dev, "it is no a hdmi register\n");
|
||||
return count;
|
||||
}
|
||||
dev_info(hdmi->dev, "/**********hdmi register config******/");
|
||||
dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val);
|
||||
hdmi_writeb(hdmi, val, reg);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations dw_hdmi_ctrl_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dw_hdmi_ctrl_open,
|
||||
.read = seq_read,
|
||||
.write = dw_hdmi_ctrl_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int dw_hdmi_phy_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct dw_hdmi *hdmi = s->private;
|
||||
u32 i;
|
||||
|
||||
seq_puts(s, "\n>>>hdmi_phy reg ");
|
||||
for (i = 0; i < 0x28; i++)
|
||||
seq_printf(s, "regs %02x val %04x\n",
|
||||
i, hdmi_phy_i2c_read(hdmi, i));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_hdmi_phy_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dw_hdmi_phy_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dw_hdmi_phy_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct dw_hdmi *hdmi =
|
||||
((struct seq_file *)file->private_data)->private;
|
||||
u32 reg, val;
|
||||
char kbuf[25];
|
||||
|
||||
if (copy_from_user(kbuf, buf, count))
|
||||
return -EFAULT;
|
||||
if (sscanf(kbuf, "%x%x", ®, &val) == -1)
|
||||
return -EFAULT;
|
||||
if (reg > 0x28) {
|
||||
dev_err(hdmi->dev, "it is not a hdmi phy register\n");
|
||||
return count;
|
||||
}
|
||||
dev_info(hdmi->dev, "/*******hdmi phy register config******/");
|
||||
dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val);
|
||||
dw_hdmi_phy_i2c_write(hdmi, val, reg);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations dw_hdmi_phy_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dw_hdmi_phy_open,
|
||||
.read = seq_read,
|
||||
.write = dw_hdmi_phy_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void dw_hdmi_register_debugfs(struct device *dev, struct dw_hdmi *hdmi)
|
||||
{
|
||||
struct dentry *debugfs_dir;
|
||||
|
||||
debugfs_dir = debugfs_create_dir("dw-hdmi", NULL);
|
||||
if (IS_ERR(debugfs_dir)) {
|
||||
dev_err(dev, "failed to create debugfs dir!\n");
|
||||
return;
|
||||
}
|
||||
debugfs_create_file("ctrl", 0400, debugfs_dir,
|
||||
hdmi, &dw_hdmi_ctrl_fops);
|
||||
debugfs_create_file("phy", 0400, debugfs_dir,
|
||||
hdmi, &dw_hdmi_phy_fops);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Probe/remove API, used from platforms based on the DRM bridge API.
|
||||
*/
|
||||
@@ -3671,6 +3840,8 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
|
||||
drm_bridge_add(&hdmi->bridge);
|
||||
|
||||
dw_hdmi_register_debugfs(dev, hdmi);
|
||||
|
||||
return hdmi;
|
||||
|
||||
err_iahb:
|
||||
|
||||
@@ -509,6 +509,51 @@
|
||||
#define HDMI_A_PRESETUP 0x501A
|
||||
#define HDMI_A_SRM_BASE 0x5020
|
||||
|
||||
/* CEC Engine Registers */
|
||||
#define HDMI_CEC_CTRL 0x7D00
|
||||
#define HDMI_CEC_STAT 0x7D01
|
||||
#define HDMI_CEC_MASK 0x7D02
|
||||
#define HDMI_CEC_POLARITY 0x7D03
|
||||
#define HDMI_CEC_INT 0x7D04
|
||||
#define HDMI_CEC_ADDR_L 0x7D05
|
||||
#define HDMI_CEC_ADDR_H 0x7D06
|
||||
#define HDMI_CEC_TX_CNT 0x7D07
|
||||
#define HDMI_CEC_RX_CNT 0x7D08
|
||||
#define HDMI_CEC_TX_DATA0 0x7D10
|
||||
#define HDMI_CEC_TX_DATA1 0x7D11
|
||||
#define HDMI_CEC_TX_DATA2 0x7D12
|
||||
#define HDMI_CEC_TX_DATA3 0x7D13
|
||||
#define HDMI_CEC_TX_DATA4 0x7D14
|
||||
#define HDMI_CEC_TX_DATA5 0x7D15
|
||||
#define HDMI_CEC_TX_DATA6 0x7D16
|
||||
#define HDMI_CEC_TX_DATA7 0x7D17
|
||||
#define HDMI_CEC_TX_DATA8 0x7D18
|
||||
#define HDMI_CEC_TX_DATA9 0x7D19
|
||||
#define HDMI_CEC_TX_DATA10 0x7D1a
|
||||
#define HDMI_CEC_TX_DATA11 0x7D1b
|
||||
#define HDMI_CEC_TX_DATA12 0x7D1c
|
||||
#define HDMI_CEC_TX_DATA13 0x7D1d
|
||||
#define HDMI_CEC_TX_DATA14 0x7D1e
|
||||
#define HDMI_CEC_TX_DATA15 0x7D1f
|
||||
#define HDMI_CEC_RX_DATA0 0x7D20
|
||||
#define HDMI_CEC_RX_DATA1 0x7D21
|
||||
#define HDMI_CEC_RX_DATA2 0x7D22
|
||||
#define HDMI_CEC_RX_DATA3 0x7D23
|
||||
#define HDMI_CEC_RX_DATA4 0x7D24
|
||||
#define HDMI_CEC_RX_DATA5 0x7D25
|
||||
#define HDMI_CEC_RX_DATA6 0x7D26
|
||||
#define HDMI_CEC_RX_DATA7 0x7D27
|
||||
#define HDMI_CEC_RX_DATA8 0x7D28
|
||||
#define HDMI_CEC_RX_DATA9 0x7D29
|
||||
#define HDMI_CEC_RX_DATA10 0x7D2a
|
||||
#define HDMI_CEC_RX_DATA11 0x7D2b
|
||||
#define HDMI_CEC_RX_DATA12 0x7D2c
|
||||
#define HDMI_CEC_RX_DATA13 0x7D2d
|
||||
#define HDMI_CEC_RX_DATA14 0x7D2e
|
||||
#define HDMI_CEC_RX_DATA15 0x7D2f
|
||||
#define HDMI_CEC_LOCK 0x7D30
|
||||
#define HDMI_CEC_WKUPCTRL 0x7D31
|
||||
|
||||
/* I2C Master Registers (E-DDC) */
|
||||
#define HDMI_I2CM_SLAVE 0x7E00
|
||||
#define HDMI_I2CM_ADDRESS 0x7E01
|
||||
|
||||
Reference in New Issue
Block a user