summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.c234
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.h29
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c10
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c12
-rw-r--r--include/uapi/linux/msm_mdp.h4
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];
};
/*