Loading drivers/video/msm/mdss/mdss_debug.c +190 −44 Original line number Diff line number Diff line Loading @@ -23,12 +23,13 @@ #include "mdss.h" #include "mdss_mdp.h" #include "mdss_mdp_hwio.h" #include "mdss_debug.h" #define DEFAULT_BASE_REG_CNT 0x100 #define GROUP_BYTES 4 #define ROW_BYTES 16 #define MAX_VSYNC_COUNT 0xFFFFFFF struct mdss_debug_data { struct dentry *root; struct list_head base_list; Loading Loading @@ -409,28 +410,63 @@ int mdss_debugfs_remove(struct mdss_data_type *mdata) return 0; } int vsync_count; static struct mdss_mdp_misr_map { u32 ctrl_reg; u32 value_reg; u32 crc_op_mode; u32 crc_index; u32 crc_value[MISR_CRC_BATCH_SIZE]; bool use_ping; bool is_ping_full; bool is_pong_full; struct mutex crc_lock; u32 crc_ping[MISR_CRC_BATCH_SIZE]; u32 crc_pong[MISR_CRC_BATCH_SIZE]; } mdss_mdp_misr_table[DISPLAY_MISR_MAX] = { [DISPLAY_MISR_DSI0] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI0, .value_reg = MDSS_MDP_LP_MISR_SIGN_DSI0, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_DSI1] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI1, .value_reg = MDSS_MDP_LP_MISR_SIGN_DSI1, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_EDP] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_EDP, .value_reg = MDSS_MDP_LP_MISR_SIGN_EDP, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_HDMI] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_HDMI, .value_reg = MDSS_MDP_LP_MISR_SIGN_HDMI, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_MDP] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_MDP, .value_reg = MDSS_MDP_LP_MISR_SIGN_MDP, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, }; Loading @@ -438,7 +474,7 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id) { struct mdss_mdp_misr_map *map; if (block_id > DISPLAY_MISR_LCDC) { if (block_id > DISPLAY_MISR_MDP) { pr_err("MISR Block id (%d) out of range\n", block_id); return NULL; } Loading @@ -452,23 +488,51 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id) return map; } int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req) int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) { struct mdss_mdp_misr_map *map; u32 config = 0; struct mdss_mdp_mixer *mixer; u32 config = 0, val = 0; u32 mixer_num = 0; bool is_valid_wb_mixer = true; map = mdss_misr_get_map(req->block_id); if (!map) { pr_err("Invalid MISR Block=%d\n", req->block_id); return -EINVAL; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (req->block_id == DISPLAY_MISR_MDP) { mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT); mixer_num = mixer->num; pr_debug("SET MDP MISR BLK to MDSS_MDP_LP_MISR_SEL_LMIX%d_GC\n", req->block_id); switch (mixer_num) { case MDSS_MDP_INTF_LAYERMIXER0: pr_debug("Use Layer Mixer 0 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX0_GC; break; case MDSS_MDP_INTF_LAYERMIXER1: pr_debug("Use Layer Mixer 1 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX1_GC; break; case MDSS_MDP_INTF_LAYERMIXER2: pr_debug("Use Layer Mixer 2 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX2_GC; break; default: pr_err("Invalid Layer Mixer %d selected for WB CRC\n", mixer_num); is_valid_wb_mixer = false; break; } if (is_valid_wb_mixer) writel_relaxed(val, mdata->mdp_base + MDSS_MDP_LP_MISR_SEL); } vsync_count = 0; map->crc_op_mode = req->crc_op_mode; memset(map->crc_value, 0, sizeof(map->crc_value)); pr_debug("MISR Config (BlockId %d) (Frame Count = %d)\n", req->block_id, req->frame_count); config = (MDSS_MDP_LP_MISR_CTRL_FRAME_COUNT_MASK & req->frame_count) | (MDSS_MDP_LP_MISR_CTRL_ENABLE); Loading @@ -476,24 +540,32 @@ int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req) mdata->mdp_base + map->ctrl_reg); /* ensure clear is done */ wmb(); if (MISR_OP_BM == map->crc_op_mode) { writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); } else { memset(map->crc_ping, 0, sizeof(map->crc_ping)); memset(map->crc_pong, 0, sizeof(map->crc_pong)); map->crc_index = 0; map->use_ping = true; map->is_ping_full = false; map->is_pong_full = false; if (MISR_OP_BM != map->crc_op_mode) { writel_relaxed(config, mdata->mdp_base + map->ctrl_reg); config = readl_relaxed(mdata->mdp_base + map->ctrl_reg); pr_debug("MISR_CTRL = 0x%x", config); pr_debug("MISR_CTRL = 0x%x", readl_relaxed(mdata->mdp_base + map->ctrl_reg)); } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); return 0; } int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, struct mdss_mdp_ctl *ctl) { struct mdss_mdp_misr_map *map; u32 status; int ret = 0; int ret = -1; int i; map = mdss_misr_get_map(resp->block_id); Loading @@ -501,35 +573,60 @@ int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) pr_err("Invalid MISR Block=%d\n", resp->block_id); return -EINVAL; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); switch (map->crc_op_mode) { case MISR_OP_SFM: case MISR_OP_MFM: ret = readl_poll_timeout(mdata->mdp_base + map->ctrl_reg, status, status & MDSS_MDP_LP_MISR_CTRL_STATUS, MISR_POLL_SLEEP, MISR_POLL_TIMEOUT); pr_debug("Status of Get MISR_CTRL = 0x%x", status); if (ret == 0) { resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); pr_debug("CRC %d=0x%x\n", resp->block_id, resp->crc_value[0]); writel_relaxed(0, mdata->mdp_base + map->ctrl_reg); } else { pr_warn("MISR %d busy with status 0x%x\n", resp->block_id, status); mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1); ret = readl_poll_timeout(mdata->mdp_base + map->ctrl_reg, status, status & MDSS_MDP_LP_MISR_CTRL_STATUS, MISR_POLL_SLEEP, MISR_POLL_TIMEOUT); if (ret == 0) { resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); } writel_relaxed(0, mdata->mdp_base + map->ctrl_reg); } break; case MISR_OP_BM: if (map->is_ping_full) { for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) resp->crc_value[i] = map->crc_value[i]; map->crc_index = 0; resp->crc_value[i] = map->crc_ping[i]; memset(map->crc_ping, 0, sizeof(map->crc_ping)); map->is_ping_full = false; ret = 0; } else if (map->is_pong_full) { for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) resp->crc_value[i] = map->crc_pong[i]; memset(map->crc_pong, 0, sizeof(map->crc_pong)); map->is_pong_full = false; ret = 0; } else { pr_debug("mdss_mdp_misr_crc_get PING BUF %s\n", map->is_ping_full ? "FULL" : "EMPTRY"); pr_debug("mdss_mdp_misr_crc_get PONG BUF %s\n", map->is_pong_full ? "FULL" : "EMPTRY"); } resp->crc_op_mode = map->crc_op_mode; break; default: ret = -ENOSYS; break; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); return ret; } Loading @@ -537,22 +634,71 @@ int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id) { struct mdss_mdp_misr_map *map; u32 status, config; u32 status = 0; u32 crc = 0x0BAD0BAD; bool crc_stored = false; map = mdss_misr_get_map(block_id); if (!map || (map->crc_op_mode != MISR_OP_BM)) return; config = MISR_CRC_BATCH_CFG; status = readl_relaxed(mdata->mdp_base + map->ctrl_reg); if (status & MDSS_MDP_LP_MISR_CTRL_STATUS) { map->crc_value[map->crc_index] = readl_relaxed(mdata->mdp_base + map->value_reg); map->crc_index++; if (map->crc_index == MISR_CRC_BATCH_SIZE) if (MDSS_MDP_LP_MISR_CTRL_STATUS & status) { crc = readl_relaxed(mdata->mdp_base + map->value_reg); if (map->use_ping) { if (map->is_ping_full) { pr_err("PING Buffer FULL\n"); } else { map->crc_ping[map->crc_index] = crc; crc_stored = true; } } else { if (map->is_pong_full) { pr_err("PONG Buffer FULL\n"); } else { map->crc_pong[map->crc_index] = crc; crc_stored = true; } } if (crc_stored) { map->crc_index = (map->crc_index + 1); if (map->crc_index == MISR_CRC_BATCH_SIZE) { map->crc_index = 0; config |= MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR; if (true == map->use_ping) { map->is_ping_full = true; map->use_ping = false; } else { map->is_pong_full = true; map->use_ping = true; } pr_debug("USE BUFF %s\n", map->use_ping ? "PING" : "PONG"); pr_debug("mdss_misr_crc_collect PING BUF %s\n", map->is_ping_full ? "FULL" : "EMPTRY"); pr_debug("mdss_misr_crc_collect PONG BUF %s\n", map->is_pong_full ? "FULL" : "EMPTRY"); } } else { pr_err("CRC(%d) Not saved\n", crc); } writel_relaxed(MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR, mdata->mdp_base + map->ctrl_reg); writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); } else if (0 == status) { writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); pr_debug("$$ Batch CRC Start $$\n"); } pr_debug("$$ Vsync Count = %d, CRC=0x%x Indx = %d$$\n", vsync_count, crc, map->crc_index); if (MAX_VSYNC_COUNT == vsync_count) { pr_err("RESET vsync_count(%d)\n", vsync_count); vsync_count = 0; } else { vsync_count += 1; } writel_relaxed(config, mdata->mdp_base + map->ctrl_reg); } drivers/video/msm/mdss/mdss_debug.h +17 −12 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ #define MISR_POLL_SLEEP 2000 #define MISR_POLL_TIMEOUT 32000 #define MISR_CRC_BATCH_SIZE 32 #define MISR_CRC_BATCH_CFG 0x101 #ifdef CONFIG_DEBUG_FS Loading @@ -26,8 +25,10 @@ int mdss_debugfs_init(struct mdss_data_type *mdata); int mdss_debugfs_remove(struct mdss_data_type *mdata); int mdss_debug_register_base(const char *name, void __iomem *base, size_t max_offset); int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req); int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp); 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, struct mdss_mdp_ctl *ctl); void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id); #else static inline int mdss_debugfs_init(struct mdss_data_type *mdata) { return 0; } Loading @@ -35,10 +36,14 @@ static inline int mdss_debugfs_remove(struct mdss_data_type *mdata) { return 0; } static inline int mdss_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { return 0; } static inline int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *reg) { return 0; } static inline int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) { return 0; } static inline int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) { return 0; } static inline int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, struct mdss_mdp_ctl *ctl) { return 0; } static inline void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id) { } #endif Loading drivers/video/msm/mdss/mdss_mdp_overlay.c +8 −2 Original line number Diff line number Diff line Loading @@ -1956,7 +1956,10 @@ static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd, struct msmfb_metadata *metadata) { struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; if (!ctl) return -EPERM; switch (metadata->op) { case metadata_op_vic: if (mfd->panel_info) Loading @@ -1968,7 +1971,7 @@ static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd, case metadata_op_crc: if (!mfd->panel_power_on) return -EPERM; ret = mdss_misr_crc_set(mdata, &metadata->data.misr_request); ret = mdss_misr_set(mdata, &metadata->data.misr_request, ctl); break; case metadata_op_wb_format: ret = mdss_mdp_wb_set_format(mfd, Loading Loading @@ -2001,7 +2004,10 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, struct msmfb_metadata *metadata) { struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; if (!ctl) return -EPERM; switch (metadata->op) { case metadata_op_frame_rate: metadata->data.panel_frame_rate = Loading @@ -2013,7 +2019,7 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, case metadata_op_crc: if (!mfd->panel_power_on) return -EPERM; ret = mdss_misr_crc_get(mdata, &metadata->data.misr_request); ret = mdss_misr_get(mdata, &metadata->data.misr_request, ctl); break; case metadata_op_wb_format: ret = mdss_mdp_wb_get_format(mfd, &metadata->data.mixer_cfg); Loading drivers/video/msm/mdss/mdss_mdp_util.c +9 −3 Original line number Diff line number Diff line Loading @@ -201,14 +201,20 @@ irqreturn_t mdss_mdp_isr(int irq, void *ptr) mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI); } if (isr & MDSS_MDP_INTR_WB_0_DONE) if (isr & MDSS_MDP_INTR_WB_0_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_0); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } if (isr & MDSS_MDP_INTR_WB_1_DONE) if (isr & MDSS_MDP_INTR_WB_1_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_1); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } if (isr & MDSS_MDP_INTR_WB_2_DONE) if (isr & MDSS_MDP_INTR_WB_2_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_2); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } mdp_isr_done: hist_isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_HIST_INTR_STATUS); Loading include/uapi/linux/msm_mdp.h +3 −1 Original line number Diff line number Diff line Loading @@ -468,12 +468,14 @@ struct mdp_histogram { uint32_t *b; }; #define MISR_CRC_BATCH_SIZE 32 enum { DISPLAY_MISR_EDP, DISPLAY_MISR_DSI0, DISPLAY_MISR_DSI1, DISPLAY_MISR_HDMI, DISPLAY_MISR_LCDC, DISPLAY_MISR_MDP, DISPLAY_MISR_ATV, DISPLAY_MISR_DSI_CMD, DISPLAY_MISR_MAX Loading @@ -491,7 +493,7 @@ struct mdp_misr { uint32_t block_id; uint32_t frame_count; uint32_t crc_op_mode; uint32_t crc_value[32]; uint32_t crc_value[MISR_CRC_BATCH_SIZE]; }; /* Loading Loading
drivers/video/msm/mdss/mdss_debug.c +190 −44 Original line number Diff line number Diff line Loading @@ -23,12 +23,13 @@ #include "mdss.h" #include "mdss_mdp.h" #include "mdss_mdp_hwio.h" #include "mdss_debug.h" #define DEFAULT_BASE_REG_CNT 0x100 #define GROUP_BYTES 4 #define ROW_BYTES 16 #define MAX_VSYNC_COUNT 0xFFFFFFF struct mdss_debug_data { struct dentry *root; struct list_head base_list; Loading Loading @@ -409,28 +410,63 @@ int mdss_debugfs_remove(struct mdss_data_type *mdata) return 0; } int vsync_count; static struct mdss_mdp_misr_map { u32 ctrl_reg; u32 value_reg; u32 crc_op_mode; u32 crc_index; u32 crc_value[MISR_CRC_BATCH_SIZE]; bool use_ping; bool is_ping_full; bool is_pong_full; struct mutex crc_lock; u32 crc_ping[MISR_CRC_BATCH_SIZE]; u32 crc_pong[MISR_CRC_BATCH_SIZE]; } mdss_mdp_misr_table[DISPLAY_MISR_MAX] = { [DISPLAY_MISR_DSI0] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI0, .value_reg = MDSS_MDP_LP_MISR_SIGN_DSI0, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_DSI1] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_DSI1, .value_reg = MDSS_MDP_LP_MISR_SIGN_DSI1, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_EDP] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_EDP, .value_reg = MDSS_MDP_LP_MISR_SIGN_EDP, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_HDMI] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_HDMI, .value_reg = MDSS_MDP_LP_MISR_SIGN_HDMI, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, [DISPLAY_MISR_MDP] = { .ctrl_reg = MDSS_MDP_LP_MISR_CTRL_MDP, .value_reg = MDSS_MDP_LP_MISR_SIGN_MDP, .crc_op_mode = 0, .crc_index = 0, .use_ping = true, .is_ping_full = false, .is_pong_full = false, }, }; Loading @@ -438,7 +474,7 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id) { struct mdss_mdp_misr_map *map; if (block_id > DISPLAY_MISR_LCDC) { if (block_id > DISPLAY_MISR_MDP) { pr_err("MISR Block id (%d) out of range\n", block_id); return NULL; } Loading @@ -452,23 +488,51 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id) return map; } int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req) int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) { struct mdss_mdp_misr_map *map; u32 config = 0; struct mdss_mdp_mixer *mixer; u32 config = 0, val = 0; u32 mixer_num = 0; bool is_valid_wb_mixer = true; map = mdss_misr_get_map(req->block_id); if (!map) { pr_err("Invalid MISR Block=%d\n", req->block_id); return -EINVAL; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); if (req->block_id == DISPLAY_MISR_MDP) { mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT); mixer_num = mixer->num; pr_debug("SET MDP MISR BLK to MDSS_MDP_LP_MISR_SEL_LMIX%d_GC\n", req->block_id); switch (mixer_num) { case MDSS_MDP_INTF_LAYERMIXER0: pr_debug("Use Layer Mixer 0 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX0_GC; break; case MDSS_MDP_INTF_LAYERMIXER1: pr_debug("Use Layer Mixer 1 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX1_GC; break; case MDSS_MDP_INTF_LAYERMIXER2: pr_debug("Use Layer Mixer 2 for WB CRC\n"); val = MDSS_MDP_LP_MISR_SEL_LMIX2_GC; break; default: pr_err("Invalid Layer Mixer %d selected for WB CRC\n", mixer_num); is_valid_wb_mixer = false; break; } if (is_valid_wb_mixer) writel_relaxed(val, mdata->mdp_base + MDSS_MDP_LP_MISR_SEL); } vsync_count = 0; map->crc_op_mode = req->crc_op_mode; memset(map->crc_value, 0, sizeof(map->crc_value)); pr_debug("MISR Config (BlockId %d) (Frame Count = %d)\n", req->block_id, req->frame_count); config = (MDSS_MDP_LP_MISR_CTRL_FRAME_COUNT_MASK & req->frame_count) | (MDSS_MDP_LP_MISR_CTRL_ENABLE); Loading @@ -476,24 +540,32 @@ int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req) mdata->mdp_base + map->ctrl_reg); /* ensure clear is done */ wmb(); if (MISR_OP_BM == map->crc_op_mode) { writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); } else { memset(map->crc_ping, 0, sizeof(map->crc_ping)); memset(map->crc_pong, 0, sizeof(map->crc_pong)); map->crc_index = 0; map->use_ping = true; map->is_ping_full = false; map->is_pong_full = false; if (MISR_OP_BM != map->crc_op_mode) { writel_relaxed(config, mdata->mdp_base + map->ctrl_reg); config = readl_relaxed(mdata->mdp_base + map->ctrl_reg); pr_debug("MISR_CTRL = 0x%x", config); pr_debug("MISR_CTRL = 0x%x", readl_relaxed(mdata->mdp_base + map->ctrl_reg)); } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); return 0; } int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, struct mdss_mdp_ctl *ctl) { struct mdss_mdp_misr_map *map; u32 status; int ret = 0; int ret = -1; int i; map = mdss_misr_get_map(resp->block_id); Loading @@ -501,35 +573,60 @@ int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) pr_err("Invalid MISR Block=%d\n", resp->block_id); return -EINVAL; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); switch (map->crc_op_mode) { case MISR_OP_SFM: case MISR_OP_MFM: ret = readl_poll_timeout(mdata->mdp_base + map->ctrl_reg, status, status & MDSS_MDP_LP_MISR_CTRL_STATUS, MISR_POLL_SLEEP, MISR_POLL_TIMEOUT); pr_debug("Status of Get MISR_CTRL = 0x%x", status); if (ret == 0) { resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); pr_debug("CRC %d=0x%x\n", resp->block_id, resp->crc_value[0]); writel_relaxed(0, mdata->mdp_base + map->ctrl_reg); } else { pr_warn("MISR %d busy with status 0x%x\n", resp->block_id, status); mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1); ret = readl_poll_timeout(mdata->mdp_base + map->ctrl_reg, status, status & MDSS_MDP_LP_MISR_CTRL_STATUS, MISR_POLL_SLEEP, MISR_POLL_TIMEOUT); if (ret == 0) { resp->crc_value[0] = readl_relaxed(mdata->mdp_base + map->value_reg); } writel_relaxed(0, mdata->mdp_base + map->ctrl_reg); } break; case MISR_OP_BM: if (map->is_ping_full) { for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) resp->crc_value[i] = map->crc_value[i]; map->crc_index = 0; resp->crc_value[i] = map->crc_ping[i]; memset(map->crc_ping, 0, sizeof(map->crc_ping)); map->is_ping_full = false; ret = 0; } else if (map->is_pong_full) { for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) resp->crc_value[i] = map->crc_pong[i]; memset(map->crc_pong, 0, sizeof(map->crc_pong)); map->is_pong_full = false; ret = 0; } else { pr_debug("mdss_mdp_misr_crc_get PING BUF %s\n", map->is_ping_full ? "FULL" : "EMPTRY"); pr_debug("mdss_mdp_misr_crc_get PONG BUF %s\n", map->is_pong_full ? "FULL" : "EMPTRY"); } resp->crc_op_mode = map->crc_op_mode; break; default: ret = -ENOSYS; break; } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false); return ret; } Loading @@ -537,22 +634,71 @@ int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id) { struct mdss_mdp_misr_map *map; u32 status, config; u32 status = 0; u32 crc = 0x0BAD0BAD; bool crc_stored = false; map = mdss_misr_get_map(block_id); if (!map || (map->crc_op_mode != MISR_OP_BM)) return; config = MISR_CRC_BATCH_CFG; status = readl_relaxed(mdata->mdp_base + map->ctrl_reg); if (status & MDSS_MDP_LP_MISR_CTRL_STATUS) { map->crc_value[map->crc_index] = readl_relaxed(mdata->mdp_base + map->value_reg); map->crc_index++; if (map->crc_index == MISR_CRC_BATCH_SIZE) if (MDSS_MDP_LP_MISR_CTRL_STATUS & status) { crc = readl_relaxed(mdata->mdp_base + map->value_reg); if (map->use_ping) { if (map->is_ping_full) { pr_err("PING Buffer FULL\n"); } else { map->crc_ping[map->crc_index] = crc; crc_stored = true; } } else { if (map->is_pong_full) { pr_err("PONG Buffer FULL\n"); } else { map->crc_pong[map->crc_index] = crc; crc_stored = true; } } if (crc_stored) { map->crc_index = (map->crc_index + 1); if (map->crc_index == MISR_CRC_BATCH_SIZE) { map->crc_index = 0; config |= MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR; if (true == map->use_ping) { map->is_ping_full = true; map->use_ping = false; } else { map->is_pong_full = true; map->use_ping = true; } pr_debug("USE BUFF %s\n", map->use_ping ? "PING" : "PONG"); pr_debug("mdss_misr_crc_collect PING BUF %s\n", map->is_ping_full ? "FULL" : "EMPTRY"); pr_debug("mdss_misr_crc_collect PONG BUF %s\n", map->is_pong_full ? "FULL" : "EMPTRY"); } } else { pr_err("CRC(%d) Not saved\n", crc); } writel_relaxed(MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR, mdata->mdp_base + map->ctrl_reg); writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); } else if (0 == status) { writel_relaxed(MISR_CRC_BATCH_CFG, mdata->mdp_base + map->ctrl_reg); pr_debug("$$ Batch CRC Start $$\n"); } pr_debug("$$ Vsync Count = %d, CRC=0x%x Indx = %d$$\n", vsync_count, crc, map->crc_index); if (MAX_VSYNC_COUNT == vsync_count) { pr_err("RESET vsync_count(%d)\n", vsync_count); vsync_count = 0; } else { vsync_count += 1; } writel_relaxed(config, mdata->mdp_base + map->ctrl_reg); }
drivers/video/msm/mdss/mdss_debug.h +17 −12 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ #define MISR_POLL_SLEEP 2000 #define MISR_POLL_TIMEOUT 32000 #define MISR_CRC_BATCH_SIZE 32 #define MISR_CRC_BATCH_CFG 0x101 #ifdef CONFIG_DEBUG_FS Loading @@ -26,8 +25,10 @@ int mdss_debugfs_init(struct mdss_data_type *mdata); int mdss_debugfs_remove(struct mdss_data_type *mdata); int mdss_debug_register_base(const char *name, void __iomem *base, size_t max_offset); int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *req); int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp); 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, struct mdss_mdp_ctl *ctl); void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id); #else static inline int mdss_debugfs_init(struct mdss_data_type *mdata) { return 0; } Loading @@ -35,10 +36,14 @@ static inline int mdss_debugfs_remove(struct mdss_data_type *mdata) { return 0; } static inline int mdss_debug_register_base(const char *name, void __iomem *base, size_t max_offset) { return 0; } static inline int mdss_misr_crc_set(struct mdss_data_type *mdata, struct mdp_misr *reg) { return 0; } static inline int mdss_misr_crc_get(struct mdss_data_type *mdata, struct mdp_misr *resp) { return 0; } static inline int mdss_misr_set(struct mdss_data_type *mdata, struct mdp_misr *req, struct mdss_mdp_ctl *ctl) { return 0; } static inline int mdss_misr_get(struct mdss_data_type *mdata, struct mdp_misr *resp, struct mdss_mdp_ctl *ctl) { return 0; } static inline void mdss_misr_crc_collect(struct mdss_data_type *mdata, int block_id) { } #endif Loading
drivers/video/msm/mdss/mdss_mdp_overlay.c +8 −2 Original line number Diff line number Diff line Loading @@ -1956,7 +1956,10 @@ static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd, struct msmfb_metadata *metadata) { struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; if (!ctl) return -EPERM; switch (metadata->op) { case metadata_op_vic: if (mfd->panel_info) Loading @@ -1968,7 +1971,7 @@ static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd, case metadata_op_crc: if (!mfd->panel_power_on) return -EPERM; ret = mdss_misr_crc_set(mdata, &metadata->data.misr_request); ret = mdss_misr_set(mdata, &metadata->data.misr_request, ctl); break; case metadata_op_wb_format: ret = mdss_mdp_wb_set_format(mfd, Loading Loading @@ -2001,7 +2004,10 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, struct msmfb_metadata *metadata) { struct mdss_data_type *mdata = mfd_to_mdata(mfd); struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); int ret = 0; if (!ctl) return -EPERM; switch (metadata->op) { case metadata_op_frame_rate: metadata->data.panel_frame_rate = Loading @@ -2013,7 +2019,7 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, case metadata_op_crc: if (!mfd->panel_power_on) return -EPERM; ret = mdss_misr_crc_get(mdata, &metadata->data.misr_request); ret = mdss_misr_get(mdata, &metadata->data.misr_request, ctl); break; case metadata_op_wb_format: ret = mdss_mdp_wb_get_format(mfd, &metadata->data.mixer_cfg); Loading
drivers/video/msm/mdss/mdss_mdp_util.c +9 −3 Original line number Diff line number Diff line Loading @@ -201,14 +201,20 @@ irqreturn_t mdss_mdp_isr(int irq, void *ptr) mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI); } if (isr & MDSS_MDP_INTR_WB_0_DONE) if (isr & MDSS_MDP_INTR_WB_0_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_0); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } if (isr & MDSS_MDP_INTR_WB_1_DONE) if (isr & MDSS_MDP_INTR_WB_1_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_1); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } if (isr & MDSS_MDP_INTR_WB_2_DONE) if (isr & MDSS_MDP_INTR_WB_2_DONE) { mdss_mdp_intr_done(MDP_INTR_WB_2); mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP); } mdp_isr_done: hist_isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_HIST_INTR_STATUS); Loading
include/uapi/linux/msm_mdp.h +3 −1 Original line number Diff line number Diff line Loading @@ -468,12 +468,14 @@ struct mdp_histogram { uint32_t *b; }; #define MISR_CRC_BATCH_SIZE 32 enum { DISPLAY_MISR_EDP, DISPLAY_MISR_DSI0, DISPLAY_MISR_DSI1, DISPLAY_MISR_HDMI, DISPLAY_MISR_LCDC, DISPLAY_MISR_MDP, DISPLAY_MISR_ATV, DISPLAY_MISR_DSI_CMD, DISPLAY_MISR_MAX Loading @@ -491,7 +493,7 @@ struct mdp_misr { uint32_t block_id; uint32_t frame_count; uint32_t crc_op_mode; uint32_t crc_value[32]; uint32_t crc_value[MISR_CRC_BATCH_SIZE]; }; /* Loading