Loading drivers/video/msm/mdss/mdss_debug.c +278 −0 Original line number Diff line number Diff line Loading @@ -25,12 +25,290 @@ #include "mdss_mdp.h" #include "mdss_mdp_hwio.h" #include "mdss_debug.h" #include "mdss_dsi.h" #define DEFAULT_BASE_REG_CNT 0x100 #define GROUP_BYTES 4 #define ROW_BYTES 16 #define MAX_VSYNC_COUNT 0xFFFFFFF #define DEFAULT_READ_PANEL_POWER_MODE_REG 0x0A #define PANEL_RX_MAX_BUF 128 #define PANEL_TX_MAX_BUF 64 #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; static int panel_debug_base_open(struct inode *inode, struct file *file) { /* non-seekable */ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); file->private_data = inode->i_private; return 0; } static int panel_debug_base_release(struct inode *inode, struct file *file) { struct mdss_debug_base *dbg = file->private_data; if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } return 0; } static ssize_t panel_debug_base_offset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; u32 off = 0; u32 cnt = DEFAULT_BASE_REG_CNT; char buf[PANEL_RX_MAX_BUF] = {0x0}; if (!dbg) return -ENODEV; if (count >= sizeof(buf)) return -EFAULT; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] = 0; /* end of string */ if (sscanf(buf, "%x %x", &off, &cnt) != 2) return -EFAULT; if (off > dbg->max_offset) return -EINVAL; if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; dbg->off = off; dbg->cnt = cnt; pr_debug("offset=%x cnt=%x\n", off, cnt); return count; } static ssize_t panel_debug_base_offset_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; int len = 0; char buf[PANEL_RX_MAX_BUF] = {0x0}; if (!dbg) return -ENODEV; if (*ppos) return 0; /* the end */ len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); if (len < 0) return 0; if (copy_to_user(buff, buf, len)) return -EFAULT; *ppos += len; /* increase offset */ return len; } static ssize_t panel_debug_base_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; u32 cnt, tmp, i; u32 len = 0; char buf[PANEL_TX_MAX_BUF] = {0x0}; char *p = NULL; char reg[PANEL_TX_MAX_BUF] = {0x0}; struct mdss_data_type *mdata = mdss_res; struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; struct mdss_panel_data *panel_data = ctl->panel_data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); struct dsi_cmd_desc dsi_write_cmd = { {DTYPE_GEN_LWRITE, 1, 0, 0, 0, 0/*len*/}, reg}; struct dcs_cmd_req cmdreq; cmdreq.cmds = &dsi_write_cmd; cmdreq.cmds_cnt = 1; cmdreq.flags = CMD_REQ_COMMIT; cmdreq.rlen = 0; cmdreq.cb = NULL; if (!dbg || !mdata) return -ENODEV; if (count >= sizeof(buf)) return -EFAULT; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] = 0; /* end of string */ len = count / 3; if (len < PANEL_CMD_MIN_TX_COUNT) { pr_err("wrong input reg len\n"); return -EFAULT; } for (i = 0; i < len; i++) { p = buf + i * 3; p[2] = 0; pr_debug("p[%d] = %p:%s\n", i, p, p); cnt = sscanf(p, "%x", &tmp); reg[i] = tmp; pr_debug("reg[%d] = %x\n", i, (int)reg[i]); } if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); dsi_write_cmd.dchdr.dlen = len; mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(0); return count; } static ssize_t panel_debug_base_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; int len = 0; int rx_len = 0; int i, lx = 0; char to_user_buf[PANEL_RX_MAX_BUF] = {0x0}; char panel_reg_buf[PANEL_RX_MAX_BUF] = {0x0}; char rx_buf[PANEL_RX_MAX_BUF] = {0x0}; struct mdss_data_type *mdata = mdss_res; struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; struct mdss_panel_data *panel_data = ctl->panel_data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); if (!dbg) return -ENODEV; if (*ppos) return 0; /* the end */ if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); panel_reg[0] = dbg->off; mdss_dsi_panel_cmd_read(ctrl_pdata, panel_reg[0], panel_reg[1], NULL, rx_buf, dbg->cnt); rx_len = ctrl_pdata->rx_len; for (i = 0; i < rx_len; i++) { lx += snprintf(panel_reg_buf + lx, sizeof(panel_reg_buf), "%s%02x", " 0x", rx_buf[i]); } pr_debug("%s:lx =%d,panel_reg_buf= %s,data[%d]=%x\n", __func__, lx, panel_reg_buf, i, rx_buf[i]); len = snprintf(to_user_buf, sizeof(to_user_buf), "0x%02zx:%s\n", dbg->off, panel_reg_buf); if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(0); if (len < 0) return 0; if (copy_to_user(user_buf, to_user_buf, len)) return -EFAULT; *ppos += len; /* increase offset */ return len; } static const struct file_operations panel_off_fops = { .open = panel_debug_base_open, .release = panel_debug_base_release, .read = panel_debug_base_offset_read, .write = panel_debug_base_offset_write, }; static const struct file_operations panel_reg_fops = { .open = panel_debug_base_open, .release = panel_debug_base_release, .read = panel_debug_base_reg_read, .write = panel_debug_base_reg_write, }; int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { struct mdss_data_type *mdata = mdss_res; struct mdss_debug_data *mdd; struct mdss_debug_base *dbg; struct dentry *ent_off, *ent_reg; char dn[PANEL_DATA_NODE_LEN] = ""; int prefix_len = 0; if (!mdata || !mdata->debug_inf.debug_data) return -ENODEV; mdd = mdata->debug_inf.debug_data; dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); if (!dbg) return -ENOMEM; dbg->base = base; dbg->max_offset = max_offset; dbg->off = 0x0a; dbg->cnt = 0x01; if (name) prefix_len = snprintf(dn, sizeof(dn), "%s_", name); strlcpy(dn + prefix_len, "off", sizeof(dn) - prefix_len); ent_off = debugfs_create_file(dn, 0644, mdd->root, dbg, &panel_off_fops); if (IS_ERR_OR_NULL(ent_off)) { pr_err("debugfs_create_file: offset fail\n"); goto off_fail; } strlcpy(dn + prefix_len, "reg", sizeof(dn) - prefix_len); ent_reg = debugfs_create_file(dn, 0644, mdd->root, dbg, &panel_reg_fops); if (IS_ERR_OR_NULL(ent_reg)) { pr_err("debugfs_create_file: reg fail\n"); goto reg_fail; } list_add(&dbg->head, &mdd->base_list); return 0; reg_fail: debugfs_remove(ent_off); off_fail: kfree(dbg); return -ENODEV; } static int mdss_debug_base_open(struct inode *inode, struct file *file) { /* non-seekable */ Loading drivers/video/msm/mdss/mdss_debug.h +6 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ int mdss_debug_register_base(const char *name, void __iomem *base, void mdss_debug_register_dump_range(struct platform_device *pdev, struct mdss_debug_base *blk_base, const char *ranges_prop, const char *name_prop); int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset); int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl); int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, Loading @@ -148,6 +150,10 @@ static inline int mdss_debug_register_base(const char *name, void __iomem *base, static inline void mdss_debug_register_dump_range(struct platform_device *pdev, struct mdss_debug_base *blk_base, const char *ranges_prop, const char *name_prop) { return 0; } static inline int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { return 0; } static inline int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) Loading drivers/video/msm/mdss/mdss_dsi.c +3 −0 Original line number Diff line number Diff line Loading @@ -2074,6 +2074,9 @@ int dsi_panel_device_register(struct device_node *pan_node, ctrl_pdata->ndx = 1; } panel_debug_register_base("panel", ctrl_pdata->ctrl_base, ctrl_pdata->reg_size); pr_debug("%s: Panel data initialized\n", __func__); return 0; } Loading drivers/video/msm/mdss/mdss_dsi.h +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. 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 Loading Loading @@ -393,6 +393,7 @@ struct mdss_dsi_ctrl_pdata { struct dsi_buf rx_buf; struct dsi_buf status_buf; int status_mode; int rx_len; struct dsi_pinctrl_res pin_res; Loading Loading @@ -477,7 +478,8 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, char cmd1, void (*fxn)(int), char *rbuf, int len); int mdss_dsi_panel_init(struct device_node *node, struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool cmd_cfg_cont_splash); Loading drivers/video/msm/mdss/mdss_dsi_host.c +1 −0 Original line number Diff line number Diff line Loading @@ -1929,6 +1929,7 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, rp = &ctrl->rx_buf; len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen); memcpy(req->rbuf, rp->data, rp->len); ctrl->rx_len = len; } else { pr_err("%s: No rx buffer provided\n", __func__); } Loading Loading
drivers/video/msm/mdss/mdss_debug.c +278 −0 Original line number Diff line number Diff line Loading @@ -25,12 +25,290 @@ #include "mdss_mdp.h" #include "mdss_mdp_hwio.h" #include "mdss_debug.h" #include "mdss_dsi.h" #define DEFAULT_BASE_REG_CNT 0x100 #define GROUP_BYTES 4 #define ROW_BYTES 16 #define MAX_VSYNC_COUNT 0xFFFFFFF #define DEFAULT_READ_PANEL_POWER_MODE_REG 0x0A #define PANEL_RX_MAX_BUF 128 #define PANEL_TX_MAX_BUF 64 #define PANEL_CMD_MIN_TX_COUNT 2 #define PANEL_DATA_NODE_LEN 80 static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; static int panel_debug_base_open(struct inode *inode, struct file *file) { /* non-seekable */ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); file->private_data = inode->i_private; return 0; } static int panel_debug_base_release(struct inode *inode, struct file *file) { struct mdss_debug_base *dbg = file->private_data; if (dbg && dbg->buf) { kfree(dbg->buf); dbg->buf_len = 0; dbg->buf = NULL; } return 0; } static ssize_t panel_debug_base_offset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; u32 off = 0; u32 cnt = DEFAULT_BASE_REG_CNT; char buf[PANEL_RX_MAX_BUF] = {0x0}; if (!dbg) return -ENODEV; if (count >= sizeof(buf)) return -EFAULT; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] = 0; /* end of string */ if (sscanf(buf, "%x %x", &off, &cnt) != 2) return -EFAULT; if (off > dbg->max_offset) return -EINVAL; if (cnt > (dbg->max_offset - off)) cnt = dbg->max_offset - off; dbg->off = off; dbg->cnt = cnt; pr_debug("offset=%x cnt=%x\n", off, cnt); return count; } static ssize_t panel_debug_base_offset_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; int len = 0; char buf[PANEL_RX_MAX_BUF] = {0x0}; if (!dbg) return -ENODEV; if (*ppos) return 0; /* the end */ len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); if (len < 0) return 0; if (copy_to_user(buff, buf, len)) return -EFAULT; *ppos += len; /* increase offset */ return len; } static ssize_t panel_debug_base_reg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; u32 cnt, tmp, i; u32 len = 0; char buf[PANEL_TX_MAX_BUF] = {0x0}; char *p = NULL; char reg[PANEL_TX_MAX_BUF] = {0x0}; struct mdss_data_type *mdata = mdss_res; struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; struct mdss_panel_data *panel_data = ctl->panel_data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); struct dsi_cmd_desc dsi_write_cmd = { {DTYPE_GEN_LWRITE, 1, 0, 0, 0, 0/*len*/}, reg}; struct dcs_cmd_req cmdreq; cmdreq.cmds = &dsi_write_cmd; cmdreq.cmds_cnt = 1; cmdreq.flags = CMD_REQ_COMMIT; cmdreq.rlen = 0; cmdreq.cb = NULL; if (!dbg || !mdata) return -ENODEV; if (count >= sizeof(buf)) return -EFAULT; if (copy_from_user(buf, user_buf, count)) return -EFAULT; buf[count] = 0; /* end of string */ len = count / 3; if (len < PANEL_CMD_MIN_TX_COUNT) { pr_err("wrong input reg len\n"); return -EFAULT; } for (i = 0; i < len; i++) { p = buf + i * 3; p[2] = 0; pr_debug("p[%d] = %p:%s\n", i, p, p); cnt = sscanf(p, "%x", &tmp); reg[i] = tmp; pr_debug("reg[%d] = %x\n", i, (int)reg[i]); } if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); dsi_write_cmd.dchdr.dlen = len; mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(0); return count; } static ssize_t panel_debug_base_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct mdss_debug_base *dbg = file->private_data; int len = 0; int rx_len = 0; int i, lx = 0; char to_user_buf[PANEL_RX_MAX_BUF] = {0x0}; char panel_reg_buf[PANEL_RX_MAX_BUF] = {0x0}; char rx_buf[PANEL_RX_MAX_BUF] = {0x0}; struct mdss_data_type *mdata = mdss_res; struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; struct mdss_panel_data *panel_data = ctl->panel_data; struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); if (!dbg) return -ENODEV; if (*ppos) return 0; /* the end */ if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(1); panel_reg[0] = dbg->off; mdss_dsi_panel_cmd_read(ctrl_pdata, panel_reg[0], panel_reg[1], NULL, rx_buf, dbg->cnt); rx_len = ctrl_pdata->rx_len; for (i = 0; i < rx_len; i++) { lx += snprintf(panel_reg_buf + lx, sizeof(panel_reg_buf), "%s%02x", " 0x", rx_buf[i]); } pr_debug("%s:lx =%d,panel_reg_buf= %s,data[%d]=%x\n", __func__, lx, panel_reg_buf, i, rx_buf[i]); len = snprintf(to_user_buf, sizeof(to_user_buf), "0x%02zx:%s\n", dbg->off, panel_reg_buf); if (mdata->debug_inf.debug_enable_clock) mdata->debug_inf.debug_enable_clock(0); if (len < 0) return 0; if (copy_to_user(user_buf, to_user_buf, len)) return -EFAULT; *ppos += len; /* increase offset */ return len; } static const struct file_operations panel_off_fops = { .open = panel_debug_base_open, .release = panel_debug_base_release, .read = panel_debug_base_offset_read, .write = panel_debug_base_offset_write, }; static const struct file_operations panel_reg_fops = { .open = panel_debug_base_open, .release = panel_debug_base_release, .read = panel_debug_base_reg_read, .write = panel_debug_base_reg_write, }; int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { struct mdss_data_type *mdata = mdss_res; struct mdss_debug_data *mdd; struct mdss_debug_base *dbg; struct dentry *ent_off, *ent_reg; char dn[PANEL_DATA_NODE_LEN] = ""; int prefix_len = 0; if (!mdata || !mdata->debug_inf.debug_data) return -ENODEV; mdd = mdata->debug_inf.debug_data; dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); if (!dbg) return -ENOMEM; dbg->base = base; dbg->max_offset = max_offset; dbg->off = 0x0a; dbg->cnt = 0x01; if (name) prefix_len = snprintf(dn, sizeof(dn), "%s_", name); strlcpy(dn + prefix_len, "off", sizeof(dn) - prefix_len); ent_off = debugfs_create_file(dn, 0644, mdd->root, dbg, &panel_off_fops); if (IS_ERR_OR_NULL(ent_off)) { pr_err("debugfs_create_file: offset fail\n"); goto off_fail; } strlcpy(dn + prefix_len, "reg", sizeof(dn) - prefix_len); ent_reg = debugfs_create_file(dn, 0644, mdd->root, dbg, &panel_reg_fops); if (IS_ERR_OR_NULL(ent_reg)) { pr_err("debugfs_create_file: reg fail\n"); goto reg_fail; } list_add(&dbg->head, &mdd->base_list); return 0; reg_fail: debugfs_remove(ent_off); off_fail: kfree(dbg); return -ENODEV; } static int mdss_debug_base_open(struct inode *inode, struct file *file) { /* non-seekable */ Loading
drivers/video/msm/mdss/mdss_debug.h +6 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ int mdss_debug_register_base(const char *name, void __iomem *base, void mdss_debug_register_dump_range(struct platform_device *pdev, struct mdss_debug_base *blk_base, const char *ranges_prop, const char *name_prop); int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset); int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl); int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, Loading @@ -148,6 +150,10 @@ static inline int mdss_debug_register_base(const char *name, void __iomem *base, static inline void mdss_debug_register_dump_range(struct platform_device *pdev, struct mdss_debug_base *blk_base, const char *ranges_prop, const char *name_prop) { return 0; } static inline int panel_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { return 0; } static inline int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) Loading
drivers/video/msm/mdss/mdss_dsi.c +3 −0 Original line number Diff line number Diff line Loading @@ -2074,6 +2074,9 @@ int dsi_panel_device_register(struct device_node *pan_node, ctrl_pdata->ndx = 1; } panel_debug_register_base("panel", ctrl_pdata->ctrl_base, ctrl_pdata->reg_size); pr_debug("%s: Panel data initialized\n", __func__); return 0; } Loading
drivers/video/msm/mdss/mdss_dsi.h +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. 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 Loading Loading @@ -393,6 +393,7 @@ struct mdss_dsi_ctrl_pdata { struct dsi_buf rx_buf; struct dsi_buf status_buf; int status_mode; int rx_len; struct dsi_pinctrl_res pin_res; Loading Loading @@ -477,7 +478,8 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, char cmd1, void (*fxn)(int), char *rbuf, int len); int mdss_dsi_panel_init(struct device_node *node, struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool cmd_cfg_cont_splash); Loading
drivers/video/msm/mdss/mdss_dsi_host.c +1 −0 Original line number Diff line number Diff line Loading @@ -1929,6 +1929,7 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl, rp = &ctrl->rx_buf; len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen); memcpy(req->rbuf, rp->data, rp->len); ctrl->rx_len = len; } else { pr_err("%s: No rx buffer provided\n", __func__); } Loading