diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 19c0d34b3228..d29d417e31ac 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -382,6 +382,8 @@ struct mdss_data_type { int iommu_attached; struct mdss_iommu_map_type *iommu_map; + struct debug_bus *dbg_bus; + u32 dbg_bus_size; struct mdss_debug_inf debug_inf; bool mixer_switched; struct mdss_panel_cfg pan_cfg; diff --git a/drivers/video/fbdev/msm/mdss_debug.h b/drivers/video/fbdev/msm/mdss_debug.h index 3e16ec59c3f9..bb69a7897754 100644 --- a/drivers/video/fbdev/msm/mdss_debug.h +++ b/drivers/video/fbdev/msm/mdss_debug.h @@ -32,8 +32,8 @@ #define MDSS_REG_BLOCK_NAME_LEN (5) enum mdss_dbg_reg_dump_flag { - MDSS_REG_DUMP_IN_LOG = BIT(0), - MDSS_REG_DUMP_IN_MEM = BIT(1), + MDSS_DBG_DUMP_IN_LOG = BIT(0), + MDSS_DBG_DUMP_IN_MEM = BIT(1), }; enum mdss_dbg_xlog_flag { @@ -43,6 +43,13 @@ enum mdss_dbg_xlog_flag { MDSS_XLOG_ALL = BIT(7) }; +#define TEST_MASK(id, tp) ((id << 4) | (tp << 1) | BIT(0)) +struct debug_bus { + u32 wr_addr; + u32 block_id; + u32 test_id; +}; + #define MDSS_XLOG(...) mdss_xlog(__func__, __LINE__, MDSS_XLOG_DEFAULT, \ ##__VA_ARGS__, DATA_LIMITER) diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c index e92464f78b4f..2d23d074cf70 100644 --- a/drivers/video/fbdev/msm/mdss_debug_xlog.c +++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c @@ -30,6 +30,7 @@ #define XLOG_DEFAULT_PANIC 1 #define XLOG_DEFAULT_REGDUMP 0x2 /* dump in RAM */ +#define XLOG_DEFAULT_DBGBUSDUMP 0x3 /* dump in LOG & RAM */ #define MDSS_XLOG_ENTRY 256 #define MDSS_XLOG_MAX_DATA 6 @@ -55,9 +56,12 @@ struct mdss_dbg_xlog { u32 xlog_enable; u32 panic_on_err; u32 enable_reg_dump; + u32 enable_dbgbus_dump; struct work_struct xlog_dump_work; struct mdss_debug_base *blk_arr[MDSS_DEBUG_BASE_MAX]; bool work_panic; + bool work_dbgbus; + u32 *dbgbus_dump; /* address for the debug bus dump */ } mdss_dbg_xlog; static inline bool mdss_xlog_is_enabled(u32 flag) @@ -203,6 +207,72 @@ u32 get_dump_range(struct dump_offset *range_node, size_t max_offset) return length; } +static void mdss_dump_debug_bus(u32 bus_dump_flag, + u32 **dump_mem) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + bool in_log, in_mem; + u32 *dump_addr = NULL; + u32 status = 0; + struct debug_bus *head; + phys_addr_t phys = 0; + int list_size = mdata->dbg_bus_size; + int i; + + if (!(mdata->dbg_bus && list_size)) + return; + + /* will keep in memory 4 entries of 4 bytes each */ + list_size = (list_size * 4 * 4); + + in_log = (bus_dump_flag & MDSS_DBG_DUMP_IN_LOG); + in_mem = (bus_dump_flag & MDSS_DBG_DUMP_IN_MEM); + + if (in_mem) { + if (!(*dump_mem)) + *dump_mem = dma_alloc_coherent(&mdata->pdev->dev, + list_size, &phys, GFP_KERNEL); + + if (*dump_mem) { + dump_addr = *dump_mem; + pr_info("bus dump_addr:%p size:%d\n", + dump_addr, list_size); + } else { + in_mem = false; + pr_err("dump_mem: allocation fails\n"); + } + } + + pr_info("======== Debug bus DUMP =========\n"); + + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); + for (i = 0; i < mdata->dbg_bus_size; i++) { + head = mdata->dbg_bus + i; + writel_relaxed(TEST_MASK(head->block_id, head->test_id), + mdss_res->mdp_base + head->wr_addr); + wmb(); /* make sure test bits were written */ + status = readl_relaxed(mdss_res->mdp_base + + head->wr_addr + 0x4); + + if (in_log) + pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n", + head->wr_addr, head->block_id, head->test_id, + status); + + if (dump_addr && in_mem) { + dump_addr[i*4] = head->wr_addr; + dump_addr[i*4 + 1] = head->block_id; + dump_addr[i*4 + 2] = head->test_id; + dump_addr[i*4 + 3] = status; + } + + } + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); + + pr_info("========End Debug bus=========\n"); + +} + static void mdss_dump_reg(u32 reg_dump_flag, char *addr, int len, u32 **dump_mem) { @@ -212,8 +282,8 @@ static void mdss_dump_reg(u32 reg_dump_flag, phys_addr_t phys = 0; int i; - in_log = (reg_dump_flag & MDSS_REG_DUMP_IN_LOG); - in_mem = (reg_dump_flag & MDSS_REG_DUMP_IN_MEM); + in_log = (reg_dump_flag & MDSS_DBG_DUMP_IN_LOG); + in_mem = (reg_dump_flag & MDSS_DBG_DUMP_IN_MEM); pr_info("reg_dump_flag=%d in_log=%d in_mem=%d\n", reg_dump_flag, in_log, in_mem); @@ -363,7 +433,7 @@ struct mdss_debug_base *get_dump_blk_addr(const char *blk_name) } static void mdss_xlog_dump_array(struct mdss_debug_base *blk_arr[], - u32 len, bool dead, const char *name) + u32 len, bool dead, const char *name, bool dump_dbgbus) { int i; @@ -375,6 +445,10 @@ static void mdss_xlog_dump_array(struct mdss_debug_base *blk_arr[], mdss_xlog_dump_all(); + if (dump_dbgbus) + mdss_dump_debug_bus(mdss_dbg_xlog.enable_dbgbus_dump, + &mdss_dbg_xlog.dbgbus_dump); + if (dead && mdss_dbg_xlog.panic_on_err) panic(name); } @@ -384,13 +458,15 @@ static void xlog_debug_work(struct work_struct *work) mdss_xlog_dump_array(mdss_dbg_xlog.blk_arr, ARRAY_SIZE(mdss_dbg_xlog.blk_arr), - mdss_dbg_xlog.work_panic, "xlog_workitem"); + mdss_dbg_xlog.work_panic, "xlog_workitem", + mdss_dbg_xlog.work_dbgbus); } void mdss_xlog_tout_handler_default(bool queue, const char *name, ...) { int i, index = 0; bool dead = false; + bool dump_dbgbus = false; va_list args; char *blk_name = NULL; struct mdss_debug_base *blk_base = NULL; @@ -420,6 +496,9 @@ void mdss_xlog_tout_handler_default(bool queue, const char *name, ...) index++; } + if (!strcmp(blk_name, "dbg_bus")) + dump_dbgbus = true; + if (!strcmp(blk_name, "panic")) dead = true; } @@ -428,9 +507,10 @@ void mdss_xlog_tout_handler_default(bool queue, const char *name, ...) if (queue) { /* schedule work to dump later */ mdss_dbg_xlog.work_panic = dead; + mdss_dbg_xlog.work_dbgbus = dump_dbgbus; schedule_work(&mdss_dbg_xlog.xlog_dump_work); } else { - mdss_xlog_dump_array(blk_arr, blk_len, dead, name); + mdss_xlog_dump_array(blk_arr, blk_len, dead, name, dump_dbgbus); } } @@ -499,10 +579,13 @@ int mdss_create_xlog_debug(struct mdss_debug_data *mdd) &mdss_dbg_xlog.panic_on_err); debugfs_create_u32("reg_dump", 0644, mdss_dbg_xlog.xlog, &mdss_dbg_xlog.enable_reg_dump); + debugfs_create_u32("dbgbus_dump", 0644, mdss_dbg_xlog.xlog, + &mdss_dbg_xlog.enable_dbgbus_dump); mdss_dbg_xlog.xlog_enable = XLOG_DEFAULT_ENABLE; mdss_dbg_xlog.panic_on_err = XLOG_DEFAULT_PANIC; mdss_dbg_xlog.enable_reg_dump = XLOG_DEFAULT_REGDUMP; + mdss_dbg_xlog.enable_dbgbus_dump = XLOG_DEFAULT_DBGBUSDUMP; pr_info("xlog_status: enable:%d, panic:%d, dump:%d\n", mdss_dbg_xlog.xlog_enable, mdss_dbg_xlog.panic_on_err, diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index bd7e1d8cfd0c..8714c9f8ab29 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1061,6 +1061,8 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) /* prevent disable of prefill calculations */ mdata->min_prefill_lines = 0xffff; + mdss_mdp_hw_rev_debug_caps_init(mdata); + switch (mdata->mdp_rev) { case MDSS_MDP_HW_REV_107: mdss_set_quirk(mdata, MDSS_QUIRK_ROTCDP); diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c index 18ed1b930c3d..dacaf2fca800 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_debug.c +++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c @@ -22,6 +22,123 @@ #define BUF_DUMP_LAST_N 10 +static struct debug_bus dbg_bus_8994[] = { + /* VIG QSEED */ + { 0x298, 4, 0}, + { 0x298, 4, 1}, + { 0x298, 24, 0}, + { 0x298, 24, 1}, + { 0x298, 42, 0}, + { 0x298, 42, 1}, + { 0x298, 88, 0}, + { 0x298, 88, 1}, + /* RGB SCALE */ + { 0x298, 12, 0}, + { 0x298, 12, 1}, + { 0x298, 34, 0}, + { 0x298, 34, 1}, + { 0x298, 52, 0}, + { 0x298, 52, 1}, + { 0x298, 96, 0}, + { 0x298, 96, 1}, + /* VIG CSC */ + { 0x298, 5, 0}, + { 0x298, 5, 1}, + { 0x298, 25, 0}, + { 0x298, 25, 1}, + { 0x298, 43, 0}, + { 0x298, 43, 1}, + { 0x298, 89, 0}, + { 0x298, 89, 1}, + /* VIG SPA */ + { 0x298, 6, 0}, + { 0x298, 26, 0}, + { 0x298, 44, 0}, + { 0x298, 90, 0}, + /* DSPP_PA */ + { 0x348, 13, 0}, + { 0x348, 19, 0}, + { 0x348, 25, 0}, + { 0x348, 3, 0}, + /* VIG ISC */ + { 0x298, 7, 0}, + { 0x298, 7, 1}, + { 0x298, 7, 3}, + { 0x298, 27, 0}, + { 0x298, 27, 1}, + { 0x298, 27, 3}, + { 0x298, 45, 0}, + { 0x298, 45, 1}, + { 0x298, 45, 3}, + { 0x298, 91, 0}, + { 0x298, 91, 1}, + { 0x298, 91, 3}, + /* RGB IGC */ + { 0x298, 13, 0}, + { 0x298, 13, 1}, + { 0x298, 13, 3}, + { 0x298, 35, 0}, + { 0x298, 35, 1}, + { 0x298, 35, 3}, + { 0x298, 53, 0}, + { 0x298, 53, 1}, + { 0x298, 53, 3}, + { 0x298, 97, 0}, + { 0x298, 97, 1}, + { 0x298, 97, 3}, + /* DMA IGC */ + { 0x298, 58, 0}, + { 0x298, 58, 1}, + { 0x298, 58, 3}, + { 0x298, 65, 0}, + { 0x298, 65, 1}, + { 0x298, 65, 3}, + /* DSPP IGC */ + { 0x348, 14, 0}, + { 0x348, 14, 1}, + { 0x348, 14, 3}, + { 0x348, 20, 0}, + { 0x348, 20, 1}, + { 0x348, 20, 3}, + { 0x348, 26, 0}, + { 0x348, 26, 1}, + { 0x348, 26, 3}, + { 0x348, 4, 0}, + { 0x348, 4, 1}, + { 0x348, 4, 3}, + /* DSPP DITHER */ + { 0x348, 18, 1}, + { 0x348, 24, 1}, + { 0x348, 30, 1}, + { 0x348, 8, 1}, + /*PPB 0*/ + { 0x348, 31, 0}, + { 0x348, 33, 0}, + { 0x348, 35, 0}, + { 0x348, 42, 0}, + /*PPB 1*/ + { 0x348, 32, 0}, + { 0x348, 34, 0}, + { 0x348, 36, 0}, + { 0x348, 43, 0}, +}; + +void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata) +{ + mdata->dbg_bus = NULL; + mdata->dbg_bus_size = 0; + + switch (mdata->mdp_rev) { + case MDSS_MDP_HW_REV_105: + case MDSS_MDP_HW_REV_109: + mdata->dbg_bus = dbg_bus_8994; + mdata->dbg_bus_size = ARRAY_SIZE(dbg_bus_8994); + break; + default: + break; + } +} + static void __print_time(char *buf, u32 size, u64 ts) { unsigned long rem_ns = do_div(ts, NSEC_PER_SEC); diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.h b/drivers/video/fbdev/msm/mdss_mdp_debug.h index db527ad6abd6..05d310e6fd50 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_debug.h +++ b/drivers/video/fbdev/msm/mdss_mdp_debug.h @@ -73,6 +73,8 @@ static inline const char *mdss_mdp_format2str(u32 format) return strings[format]; } void mdss_mdp_dump(struct mdss_data_type *mdata); +void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata); + #ifdef CONFIG_DEBUG_FS int mdss_mdp_debugfs_init(struct mdss_data_type *mdata);