drm/msm/sde: add debugfs for crtc
Enable basic debugfs support for CRTC driver.
Change-Id: I9d1498515d28d1702850b6ac9fa13aa95abee0bb
Signed-off-by: Clarence Ip <cip@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 2f7485b..30b2da1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -11,6 +11,7 @@
*/
#include <linux/sort.h>
+#include <linux/debugfs.h>
#include <uapi/drm/sde_drm.h>
#include <drm/drm_mode.h>
#include <drm/drm_crtc.h>
@@ -46,7 +47,7 @@
const struct sde_hw_res_map *plat_hw_res_map;
enum sde_lm unused_lm_id[CRTC_DUAL_MIXERS] = {0};
enum sde_lm lm_idx;
- int i, count = 0;
+ int i, unused_lm_count = 0;
if (!sde_kms) {
DBG("[%s] invalid kms", __func__);
@@ -57,10 +58,10 @@
return -EINVAL;
/* Get unused LMs */
- for (i = 0; i < sde_kms->catalog->mixer_count; i++) {
+ for (i = sde_kms->catalog->mixer_count - 1; i >= 0; --i) {
if (!sde_rm_get_mixer(sde_kms, LM(i))) {
- unused_lm_id[count++] = LM(i);
- if (count == CRTC_DUAL_MIXERS)
+ unused_lm_id[unused_lm_count++] = LM(i);
+ if (unused_lm_count == CRTC_DUAL_MIXERS)
break;
}
}
@@ -98,13 +99,13 @@
plat_hw_res_map = sde_rm_get_res_map(sde_kms, i);
lm_idx = plat_hw_res_map->lm;
- if (!lm_idx)
- lm_idx = unused_lm_id[sde_crtc->num_mixers];
+ if (!lm_idx && unused_lm_count)
+ lm_idx = unused_lm_id[--unused_lm_count];
DBG("Acquiring LM %d", lm_idx);
mixer->hw_lm = sde_rm_acquire_mixer(sde_kms, lm_idx);
if (IS_ERR_OR_NULL(mixer->hw_lm)) {
- DBG("[%s], Invalid mixer", __func__);
+ DRM_ERROR("Invalid mixer\n");
return -EACCES;
}
/* interface info */
@@ -118,7 +119,7 @@
sde_crtc->num_ctls, sde_crtc->num_mixers,
sde_crtc->mixer[0].hw_lm->idx,
sde_crtc->mixer[0].hw_ctl->idx);
- if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
+ if (sde_crtc->num_mixers > 1)
DBG("lm[1] %d, ctl[1], %d",
sde_crtc->mixer[1].hw_lm->idx,
sde_crtc->mixer[1].hw_ctl->idx);
@@ -130,6 +131,7 @@
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
DBG("");
+ debugfs_remove_recursive(sde_crtc->debugfs_root);
drm_crtc_cleanup(crtc);
kfree(sde_crtc);
}
@@ -224,6 +226,7 @@
}
} else {
cfg->bg.inv_alpha_sel = 1;
+ /* force 100% alpha */
cfg->fg.const_alpha = 0xFF;
cfg->bg.const_alpha = 0x00;
}
@@ -245,7 +248,6 @@
struct sde_crtc_mixer *mixer = sde_crtc->mixer;
struct drm_plane *plane;
struct sde_plane_state *pstate;
- struct sde_hw_stage_cfg stage_cfg;
struct sde_hw_blend_cfg blend;
struct sde_hw_ctl *ctl;
struct sde_hw_mixer *lm;
@@ -262,7 +264,7 @@
goto out;
/* initialize stage cfg */
- memset(&stage_cfg, 0, sizeof(stage_cfg));
+ memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg));
for (i = 0; i < sde_crtc->num_mixers; i++) {
if ((!mixer[i].hw_lm) || (!mixer[i].hw_ctl))
@@ -274,9 +276,9 @@
drm_atomic_crtc_for_each_plane(plane, crtc) {
pstate = to_sde_plane_state(plane->state);
- stage_cfg.stage[pstate->stage][i] =
+ sde_crtc->stage_cfg.stage[pstate->stage][i] =
sde_plane_pipe(plane);
- DBG("crtc_id %d, layer %d, at stage %d",
+ DBG("crtc_id %d - pipe %d at stage %d",
sde_crtc->id,
sde_plane_pipe(plane),
pstate->stage);
@@ -308,8 +310,9 @@
* If there is no base layer, enable border color.
* currently border color is always black
*/
- if ((stage_cfg.stage[SDE_STAGE_BASE][0] == SSPP_NONE) && plane_cnt) {
- stage_cfg.border_enable = 1;
+ if ((sde_crtc->stage_cfg.stage[SDE_STAGE_BASE][0] == SSPP_NONE) &&
+ plane_cnt) {
+ sde_crtc->stage_cfg.border_enable = 1;
DBG("Border Color is enabled");
}
@@ -321,9 +324,9 @@
ctl = mixer[i].hw_ctl;
lm = mixer[i].hw_lm;
- /* stage config */
+ /* same stage config to all mixers */
ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
- &stage_cfg);
+ &sde_crtc->stage_cfg);
}
out:
spin_unlock_irqrestore(&sde_crtc->lm_lock, flags);
@@ -706,6 +709,70 @@
{
}
+static int _sde_debugfs_mixer_read(struct seq_file *s, void *data)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_mixer *m;
+ int i, j;
+
+ if (!s || !s->private)
+ return -EINVAL;
+
+ sde_crtc = s->private;
+ for (i = 0; i < sde_crtc->num_mixers; ++i) {
+ m = &sde_crtc->mixer[i];
+ if (!m->hw_lm) {
+ seq_printf(s, "Mixer[%d] has no LM\n", i);
+ } else if (!m->hw_ctl) {
+ seq_printf(s, "Mixer[%d] has no CTL\n", i);
+ } else {
+ seq_printf(s, "LM_%d/CTL_%d -> INTF_%d\n",
+ m->hw_lm->idx - LM_0,
+ m->hw_ctl->idx - CTL_0,
+ m->intf_idx - INTF_0);
+ }
+ }
+ seq_printf(s, "Border: %d\n", sde_crtc->stage_cfg.border_enable);
+ for (i = 0; i < SDE_STAGE_MAX; ++i) {
+ if (i == SDE_STAGE_BASE)
+ seq_puts(s, "Base Stage:");
+ else
+ seq_printf(s, "Stage %d:", i - SDE_STAGE_0);
+ for (j = 0; j < PIPES_PER_STAGE; ++j)
+ seq_printf(s, " % 2d", sde_crtc->stage_cfg.stage[i][j]);
+ seq_puts(s, "\n");
+ }
+ return 0;
+}
+
+static int _sde_debugfs_mixer_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, _sde_debugfs_mixer_read, inode->i_private);
+}
+
+static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc,
+ struct sde_kms *sde_kms)
+{
+ static const struct file_operations debugfs_mixer_fops = {
+ .open = _sde_debugfs_mixer_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ };
+ if (sde_crtc && sde_kms) {
+ sde_crtc->debugfs_root = debugfs_create_dir(sde_crtc->name,
+ sde_debugfs_get_root(sde_kms));
+ if (sde_crtc->debugfs_root) {
+ /* don't error check these */
+ debugfs_create_u32("vsync_count", 0444,
+ sde_crtc->debugfs_root,
+ &sde_crtc->vsync_count);
+ debugfs_create_file("mixers", 0444,
+ sde_crtc->debugfs_root,
+ sde_crtc, &debugfs_mixer_fops);
+ }
+ }
+}
/* initialize crtc */
struct drm_crtc *sde_crtc_init(struct drm_device *dev,
@@ -713,9 +780,14 @@
struct drm_plane *plane, int id)
{
struct drm_crtc *crtc = NULL;
- struct sde_crtc *sde_crtc;
+ struct sde_crtc *sde_crtc = NULL;
+ struct msm_drm_private *priv = NULL;
+ struct sde_kms *kms = NULL;
int rc;
+ priv = dev->dev_private;
+ kms = to_sde_kms(priv->kms);
+
sde_crtc = kzalloc(sizeof(*sde_crtc), GFP_KERNEL);
if (!sde_crtc)
return ERR_PTR(-ENOMEM);
@@ -738,6 +810,11 @@
return ERR_PTR(-EINVAL);
}
- DBG("%s: Successfully initialized crtc", __func__);
+ /* save user friendly CRTC name for later */
+ snprintf(sde_crtc->name, SDE_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
+
+ _sde_crtc_init_debugfs(sde_crtc, kms);
+
+ DBG("%s: Successfully initialized crtc", sde_crtc->name);
return crtc;
}