diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_debug.c | 234 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_debug.h | 29 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 10 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_util.c | 12 | ||||
| -rw-r--r-- | include/uapi/linux/msm_mdp.h | 4 |
5 files changed, 227 insertions, 62 deletions
diff --git a/drivers/video/fbdev/msm/mdss_debug.c b/drivers/video/fbdev/msm/mdss_debug.c index f933c8eaaf4a..0d0240fa9162 100644 --- a/drivers/video/fbdev/msm/mdss_debug.c +++ b/drivers/video/fbdev/msm/mdss_debug.c @@ -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; @@ -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, }, }; @@ -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; } @@ -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); @@ -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 { - 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); + 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); + 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); @@ -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]); + 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: - for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) - resp->crc_value[i] = map->crc_value[i]; - map->crc_index = 0; + if (map->is_ping_full) { + for (i = 0; i < MISR_CRC_BATCH_SIZE; i++) + 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; } @@ -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) - map->crc_index = 0; - config |= MDSS_MDP_LP_MISR_CTRL_STATUS_CLEAR; + 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; + 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); } diff --git a/drivers/video/fbdev/msm/mdss_debug.h b/drivers/video/fbdev/msm/mdss_debug.h index 29eb16c59d92..984caab3526b 100644 --- a/drivers/video/fbdev/msm/mdss_debug.h +++ b/drivers/video/fbdev/msm/mdss_debug.h @@ -16,30 +16,35 @@ #include "mdss.h" -#define MISR_POLL_SLEEP 2000 -#define MISR_POLL_TIMEOUT 32000 -#define MISR_CRC_BATCH_SIZE 32 -#define MISR_CRC_BATCH_CFG 0x101 +#define MISR_POLL_SLEEP 2000 +#define MISR_POLL_TIMEOUT 32000 +#define MISR_CRC_BATCH_CFG 0x101 #ifdef CONFIG_DEBUG_FS 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; } 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; } + 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) +{ 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) { } + int block_id) { } #endif #endif /* MDSS_DEBUG_H */ diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 8034db1dfd4b..46273c839841 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -1958,7 +1958,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) @@ -1970,7 +1973,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, @@ -2003,7 +2006,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 = @@ -2015,7 +2021,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); diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index 788511b3ef53..2c0d0aca2736 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -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); diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h index c7be5398b5a8..bce016d7a76a 100644 --- a/include/uapi/linux/msm_mdp.h +++ b/include/uapi/linux/msm_mdp.h @@ -472,12 +472,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 @@ -495,7 +497,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]; }; /* |
