drm/exynos/hdmi: use mappings for registers with IP dependent address
authorAndrzej Hajda <a.hajda@samsung.com>
Mon, 24 Oct 2016 07:57:34 +0000 (09:57 +0200)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:54:05 +0000 (13:54 +0900)
Some registers resides at different offsets depending on device version.
This patch adds infrastructure for mapping such registers to proper address
based on hdmi_type. It adds also mappings to some registers.

Change-Id: Ic345e1a4cb398aebea62b50fd86a44f30b5fd1e5
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/regs-hdmi.h

index a0566151f2a06c6b199817251f2e974d8dba1c0c..74c08deddfe890b92462961d484d5c089350ceeb 100644 (file)
 enum hdmi_type {
        HDMI_TYPE13,
        HDMI_TYPE14,
+       HDMI_TYPE_COUNT
+};
+
+#define HDMI_MAPPED_BASE 0xffff0000
+
+enum hdmi_mapped_regs {
+       HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
+       HDMI_PHY_RSTOUT,
+       HDMI_ACR_CON,
+};
+
+static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
+       { HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
+       { HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
+       { HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
 };
 
 struct string_array_spec {
@@ -96,7 +111,6 @@ struct hdmi_driver_data {
        unsigned int has_sysreg:1;
        unsigned int has_phy_power:1;
        u8 phy_mode_set_done;
-       u32 phy_status;
        u32 sysreg_clksel;
        struct string_array_spec clk_gates;
        struct string_array_spec clk_muxes;
@@ -654,7 +668,6 @@ static struct hdmi_driver_data exynos5430_hdmi_driver_data = {
        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates5430),
        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes5430),
        .phy_mode_set_done = HDMIPHY5433_MODE_SET_DONE,
-       .phy_status     = HDMI_V14_PHY_STATUS_0,
 };
 
 static struct hdmi_driver_data exynos5420_hdmi_driver_data = {
@@ -665,7 +678,6 @@ static struct hdmi_driver_data exynos5420_hdmi_driver_data = {
        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
        .phy_mode_set_done = HDMIPHY_MODE_SET_DONE,
-       .phy_status     = HDMI_V14_PHY_STATUS_0,
 };
 
 static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
@@ -676,7 +688,6 @@ static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
        .phy_mode_set_done = HDMIPHY_MODE_SET_DONE,
-       .phy_status     = HDMI_V14_PHY_STATUS_0,
 };
 
 static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
@@ -687,7 +698,6 @@ static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
        .phy_mode_set_done = HDMIPHY_MODE_SET_DONE,
-       .phy_status     = HDMI_V13_PHY_STATUS,
 };
 
 static struct hdmi_driver_data exynos5_hdmi_driver_data = {
@@ -698,23 +708,31 @@ static struct hdmi_driver_data exynos5_hdmi_driver_data = {
        .clk_gates      = INIT_ARRAY_SPEC(hdmi_clk_gates4),
        .clk_muxes      = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
        .phy_mode_set_done = HDMIPHY_MODE_SET_DONE,
-       .phy_status     = HDMI_V14_PHY_STATUS_0,
 };
 
+static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
+{
+       if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
+               return hdmi_reg_map[reg_id & 0xffff][hdata->drv_data->type];
+       return reg_id;
+}
+
 static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
 {
-       return readl(hdata->regs + reg_id);
+       return readl(hdata->regs + hdmi_map_reg(hdata, reg_id));
 }
 
 static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
                                 u32 reg_id, u8 value)
 {
-       writel(value, hdata->regs + reg_id);
+       writel(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
 }
 
 static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
                                   int bytes, u32 val)
 {
+       reg_id = hdmi_map_reg(hdata, reg_id);
+
        while (--bytes >= 0) {
                writel(val & 0xff, hdata->regs + reg_id);
                val >>= 8;
@@ -725,7 +743,10 @@ static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
 static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
                                 u32 reg_id, u32 value, u32 mask)
 {
-       u32 old = readl(hdata->regs + reg_id);
+       u32 old;
+
+       reg_id = hdmi_map_reg(hdata, reg_id);
+       old = readl(hdata->regs + reg_id);
        value = (value & mask) | (old & ~mask);
        writel(value, hdata->regs + reg_id);
 }
@@ -876,7 +897,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
        DUMPREG(HDMI_PHY_STATUS_0);
        DUMPREG(HDMI_PHY_STATUS_PLL);
        DUMPREG(HDMI_PHY_CON_0);
-       DUMPREG(HDMI_PHY_RSTOUT);
+       DUMPREG(HDMI_V14_PHY_RSTOUT);
        DUMPREG(HDMI_PHY_VPLL);
        DUMPREG(HDMI_PHY_CMU);
        DUMPREG(HDMI_CORE_RSTOUT);
@@ -1356,11 +1377,7 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
        hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
        hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
        hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
-
-       if (hdata->drv_data->type == HDMI_TYPE13)
-               hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
-       else
-               hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
+       hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
 }
 
 static void hdmi_audio_init(struct hdmi_context *hdata)
@@ -1769,23 +1786,16 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)
 
 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 {
-       u32 reg;
-
        hdmi_clk_set_parents(hdata, false);
 
        /* operation mode */
        hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
                                HDMI_PHY_ENABLE_MODE_SET);
 
-       if (hdata->drv_data->type == HDMI_TYPE13)
-               reg = HDMI_V13_PHY_RSTOUT;
-       else
-               reg = HDMI_PHY_RSTOUT;
-
        /* reset hdmiphy */
-       hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
+       hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
        usleep_range(10000, 12000);
-       hdmi_reg_writemask(hdata, reg,  0, HDMI_PHY_SW_RSTOUT);
+       hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
        usleep_range(10000, 12000);
 }
 
@@ -1821,7 +1831,7 @@ static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
        int tries;
 
        for (tries = 0; tries < 100; ++tries) {
-               u32 val = hdmi_reg_read(hdata, hdata->drv_data->phy_status);
+               u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
 
                if (val & HDMI_PHY_STATUS_READY) {
                        DRM_DEBUG_KMS("PLL stabilized after %d tries", tries);
index 4e7bcac734ef912f6eb2dcc3277a15429b1aadb2..e7adc25254664208c5ba6c025d7f3334c2f0c68f 100644 (file)
 #define HDMI_HPD_ST                    HDMI_CTRL_BASE(0x0044)
 #define HDMI_HPD_TH_X                  HDMI_CTRL_BASE(0x0050)
 #define HDMI_AUDIO_CLKSEL              HDMI_CTRL_BASE(0x0070)
-#define HDMI_PHY_RSTOUT                        HDMI_CTRL_BASE(0x0074)
+#define HDMI_V14_PHY_RSTOUT            HDMI_CTRL_BASE(0x0074)
 #define HDMI_PHY_VPLL                  HDMI_CTRL_BASE(0x0078)
 #define HDMI_PHY_CMU                   HDMI_CTRL_BASE(0x007C)
 #define HDMI_CORE_RSTOUT               HDMI_CTRL_BASE(0x0080)
 #define HDMI_ASP_CHCFG2                        HDMI_CORE_BASE(0x0318)
 #define HDMI_ASP_CHCFG3                        HDMI_CORE_BASE(0x031C)
 
-#define HDMI_ACR_CON                   HDMI_CORE_BASE(0x0400)
+#define HDMI_V14_ACR_CON               HDMI_CORE_BASE(0x0400)
 #define HDMI_ACR_MCTS0                 HDMI_CORE_BASE(0x0410)
 #define HDMI_ACR_MCTS1                 HDMI_CORE_BASE(0x0414)
 #define HDMI_ACR_MCTS2                 HDMI_CORE_BASE(0x0418)