drm/msm/sde: add driver for sde support
Initial DRM/KMS driver to support snapdragon display engine.
Change-Id: I2f93d7cd24acf77359682f90b6b9647017ed62ba
Signed-off-by: Abhijit Kulkarni <kabhijit@codeaurora.org>
Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c
new file mode 100644
index 0000000..e678003
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_pingpong.c
@@ -0,0 +1,159 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sde_hw_mdss.h"
+#include "sde_hwio.h"
+#include "sde_hw_catalog.h"
+#include "sde_hw_pingpong.h"
+
+#define PP_TEAR_CHECK_EN 0x000
+#define PP_SYNC_CONFIG_VSYNC 0x004
+#define PP_SYNC_CONFIG_HEIGHT 0x008
+#define PP_SYNC_WRCOUNT 0x00C
+#define PP_VSYNC_INIT_VAL 0x010
+#define PP_INT_COUNT_VAL 0x014
+#define PP_SYNC_THRESH 0x018
+#define PP_START_POS 0x01C
+#define PP_RD_PTR_IRQ 0x020
+#define PP_WR_PTR_IRQ 0x024
+#define PP_OUT_LINE_COUNT 0x028
+#define PP_LINE_COUNT 0x02C
+#define PP_AUTOREFRESH_CONFIG 0x030
+
+#define PP_FBC_MODE 0x034
+#define PP_FBC_BUDGET_CTL 0x038
+#define PP_FBC_LOSSY_MODE 0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP 0x0c8
+
+static struct sde_pingpong_cfg *_pingpong_offset(enum sde_pingpong pp,
+ struct sde_mdss_cfg *m,
+ void __iomem *addr,
+ struct sde_hw_blk_reg_map *b)
+{
+ int i;
+
+ for (i = 0; i < m->pingpong_count; i++) {
+ if (pp == m->pingpong[i].id) {
+ b->base_off = addr;
+ b->blk_off = m->pingpong[i].base;
+ b->hwversion = m->hwversion;
+ return &m->pingpong[i];
+ }
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int sde_hw_pp_setup_te_config(struct sde_hw_pingpong *pp,
+ struct sde_hw_tear_check *te)
+{
+ struct sde_hw_blk_reg_map *c = &pp->hw;
+ int cfg;
+
+ cfg = BIT(19); /*VSYNC_COUNTER_EN */
+ if (te->hw_vsync_mode)
+ cfg |= BIT(20);
+
+ cfg |= te->vsync_count;
+
+ SDE_REG_WRITE(c, PP_SYNC_CONFIG_VSYNC, cfg);
+ SDE_REG_WRITE(c, PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
+ SDE_REG_WRITE(c, PP_VSYNC_INIT_VAL, te->vsync_init_val);
+ SDE_REG_WRITE(c, PP_RD_PTR_IRQ, te->rd_ptr_irq);
+ SDE_REG_WRITE(c, PP_START_POS, te->start_pos);
+ SDE_REG_WRITE(c, PP_SYNC_THRESH,
+ ((te->sync_threshold_continue << 16) |
+ te->sync_threshold_start));
+ SDE_REG_WRITE(c, PP_SYNC_WRCOUNT,
+ (te->start_pos + te->sync_threshold_start + 1));
+
+ return 0;
+}
+
+int sde_hw_pp_setup_autorefresh_config(struct sde_hw_pingpong *pp,
+ struct sde_hw_autorefresh *cfg)
+{
+ struct sde_hw_blk_reg_map *c = &pp->hw;
+ u32 refresh_cfg;
+
+ if (cfg->enable)
+ refresh_cfg = BIT(31) | cfg->frame_count;
+ else
+ refresh_cfg = 0;
+
+ SDE_REG_WRITE(c, PP_AUTOREFRESH_CONFIG,
+ refresh_cfg);
+
+ return 0;
+}
+
+int sde_hw_pp_setup_dsc_compression(struct sde_hw_pingpong *pp,
+ struct sde_hw_dsc_cfg *cfg)
+{
+ return 0;
+}
+int sde_hw_pp_enable_te(struct sde_hw_pingpong *pp, bool enable)
+{
+ struct sde_hw_blk_reg_map *c = &pp->hw;
+
+ SDE_REG_WRITE(c, PP_TEAR_CHECK_EN, enable);
+ return 0;
+}
+
+int sde_hw_pp_get_vsync_info(struct sde_hw_pingpong *pp,
+ struct sde_hw_pp_vsync_info *info)
+{
+ struct sde_hw_blk_reg_map *c = &pp->hw;
+
+ info->init_val = SDE_REG_READ(c, PP_VSYNC_INIT_VAL) & 0xffff;
+ info->vsync_count = SDE_REG_READ(c, PP_SYNC_CONFIG_HEIGHT) & 0xffff;
+ info->line_count = SDE_REG_READ(c, PP_INT_COUNT_VAL) & 0xffff;
+
+ return 0;
+}
+
+static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops,
+ unsigned long cap)
+{
+ ops->setup_tearcheck = sde_hw_pp_setup_te_config;
+ ops->enable_tearcheck = sde_hw_pp_enable_te;
+ ops->get_vsync_info = sde_hw_pp_get_vsync_info;
+ ops->setup_autorefresh = sde_hw_pp_setup_autorefresh_config;
+ ops->setup_dsc = sde_hw_pp_setup_dsc_compression;
+};
+
+struct sde_hw_pingpong *sde_hw_pingpong_init(enum sde_pingpong idx,
+ void __iomem *addr,
+ struct sde_mdss_cfg *m)
+{
+ struct sde_hw_pingpong *c;
+ struct sde_pingpong_cfg *cfg;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return ERR_PTR(-ENOMEM);
+
+ cfg = _pingpong_offset(idx, m, addr, &c->hw);
+ if (IS_ERR_OR_NULL(cfg)) {
+ kfree(c);
+ return ERR_PTR(-EINVAL);
+ }
+
+ c->idx = idx;
+ c->pingpong_hw_cap = cfg;
+ _setup_pingpong_ops(&c->ops, c->pingpong_hw_cap->features);
+
+ return c;
+}
+