#include <linux/delay.h>
 #include <linux/iopoll.h>
+#include <linux/platform_device.h>
 #include <linux/rational.h>
 #include <drm/display/drm_dp_helper.h>
 #include <drm/drm_print.h>
        (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
        PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
 
+#define DP_DEFAULT_AHB_OFFSET  0x0000
+#define DP_DEFAULT_AHB_SIZE    0x0200
+#define DP_DEFAULT_AUX_OFFSET  0x0200
+#define DP_DEFAULT_AUX_SIZE    0x0200
+#define DP_DEFAULT_LINK_OFFSET 0x0400
+#define DP_DEFAULT_LINK_SIZE   0x0C00
+#define DP_DEFAULT_P0_OFFSET   0x1000
+#define DP_DEFAULT_P0_SIZE     0x0400
+
+struct dss_io_region {
+       size_t len;
+       void __iomem *base;
+};
+
+struct dss_io_data {
+       struct dss_io_region ahb;
+       struct dss_io_region aux;
+       struct dss_io_region link;
+       struct dss_io_region p0;
+};
+
 struct dp_catalog_private {
        struct device *dev;
        struct drm_device *drm_dev;
-       struct dp_io *io;
+       struct dss_io_data io;
        u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX];
        struct dp_catalog dp_catalog;
        u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX];
 {
        struct dp_catalog_private *catalog = container_of(dp_catalog,
                        struct dp_catalog_private, dp_catalog);
-       struct dss_io_data *dss = &catalog->io->dp_controller;
+       struct dss_io_data *dss = &catalog->io;
 
        msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb");
        msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux");
 
 static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset)
 {
-       return readl_relaxed(catalog->io->dp_controller.aux.base + offset);
+       return readl_relaxed(catalog->io.aux.base + offset);
 }
 
 static inline void dp_write_aux(struct dp_catalog_private *catalog,
         * To make sure aux reg writes happens before any other operation,
         * this function uses writel() instread of writel_relaxed()
         */
-       writel(data, catalog->io->dp_controller.aux.base + offset);
+       writel(data, catalog->io.aux.base + offset);
 }
 
 static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset)
 {
-       return readl_relaxed(catalog->io->dp_controller.ahb.base + offset);
+       return readl_relaxed(catalog->io.ahb.base + offset);
 }
 
 static inline void dp_write_ahb(struct dp_catalog_private *catalog,
         * To make sure phy reg writes happens before any other operation,
         * this function uses writel() instread of writel_relaxed()
         */
-       writel(data, catalog->io->dp_controller.ahb.base + offset);
+       writel(data, catalog->io.ahb.base + offset);
 }
 
 static inline void dp_write_p0(struct dp_catalog_private *catalog,
         * To make sure interface reg writes happens before any other operation,
         * this function uses writel() instread of writel_relaxed()
         */
-       writel(data, catalog->io->dp_controller.p0.base + offset);
+       writel(data, catalog->io.p0.base + offset);
 }
 
 static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
         * To make sure interface reg writes happens before any other operation,
         * this function uses writel() instread of writel_relaxed()
         */
-       return readl_relaxed(catalog->io->dp_controller.p0.base + offset);
+       return readl_relaxed(catalog->io.p0.base + offset);
 }
 
 static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset)
 {
-       return readl_relaxed(catalog->io->dp_controller.link.base + offset);
+       return readl_relaxed(catalog->io.link.base + offset);
 }
 
 static inline void dp_write_link(struct dp_catalog_private *catalog,
         * To make sure link reg writes happens before any other operation,
         * this function uses writel() instread of writel_relaxed()
         */
-       writel(data, catalog->io->dp_controller.link.base + offset);
+       writel(data, catalog->io.link.base + offset);
 }
 
 /* aux related catalog functions */
                                struct dp_catalog_private, dp_catalog);
 
        /* poll for hpd connected status every 2ms and timeout after 500ms */
-       return readl_poll_timeout(catalog->io->dp_controller.aux.base +
+       return readl_poll_timeout(catalog->io.aux.base +
                                REG_DP_DP_HPD_INT_STATUS,
                                state, state & DP_DP_HPD_STATE_STATUS_CONNECTED,
                                2000, 500000);
 {
        struct dp_catalog_private *catalog = container_of(dp_catalog,
                struct dp_catalog_private, dp_catalog);
-       struct dss_io_data *io = &catalog->io->dp_controller;
+       struct dss_io_data *io = &catalog->io;
 
        pr_info("AHB regs\n");
        dump_regs(io->ahb.base, io->ahb.len);
        bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
 
        /* Poll for mainlink ready status */
-       ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base +
+       ret = readx_poll_timeout(readl, catalog->io.link.base +
                                        REG_DP_MAINLINK_READY,
                                        data, data & bit,
                                        POLLING_SLEEP_US, POLLING_TIMEOUT_US);
                                struct dp_catalog_private, dp_catalog);
 
        /* Poll for mainlink ready status */
-       ret = readl_poll_timeout(catalog->io->dp_controller.link.base +
+       ret = readl_poll_timeout(catalog->io.link.base +
                                REG_DP_MAINLINK_READY,
                                data, data & DP_MAINLINK_READY_FOR_VIDEO,
                                POLLING_SLEEP_US, POLLING_TIMEOUT_US);
        dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0);
 }
 
-struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io)
+static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
 {
-       struct dp_catalog_private *catalog;
+       struct resource *res;
+       void __iomem *base;
+
+       base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
+       if (!IS_ERR(base))
+               *len = resource_size(res);
+
+       return base;
+}
+
+static int dp_catalog_get_io(struct dp_catalog_private *catalog)
+{
+       struct platform_device *pdev = to_platform_device(catalog->dev);
+       struct dss_io_data *dss = &catalog->io;
+
+       dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
+       if (IS_ERR(dss->ahb.base))
+               return PTR_ERR(dss->ahb.base);
 
-       if (!io) {
-               DRM_ERROR("invalid input\n");
-               return ERR_PTR(-EINVAL);
+       dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
+       if (IS_ERR(dss->aux.base)) {
+               /*
+                * The initial binding had a single reg, but in order to
+                * support variation in the sub-region sizes this was split.
+                * dp_ioremap() will fail with -EINVAL here if only a single
+                * reg is specified, so fill in the sub-region offsets and
+                * lengths based on this single region.
+                */
+               if (PTR_ERR(dss->aux.base) == -EINVAL) {
+                       if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
+                               DRM_ERROR("legacy memory region not large enough\n");
+                               return -EINVAL;
+                       }
+
+                       dss->ahb.len = DP_DEFAULT_AHB_SIZE;
+                       dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
+                       dss->aux.len = DP_DEFAULT_AUX_SIZE;
+                       dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
+                       dss->link.len = DP_DEFAULT_LINK_SIZE;
+                       dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
+                       dss->p0.len = DP_DEFAULT_P0_SIZE;
+               } else {
+                       DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
+                       return PTR_ERR(dss->aux.base);
+               }
+       } else {
+               dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
+               if (IS_ERR(dss->link.base)) {
+                       DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
+                       return PTR_ERR(dss->link.base);
+               }
+
+               dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
+               if (IS_ERR(dss->p0.base)) {
+                       DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
+                       return PTR_ERR(dss->p0.base);
+               }
        }
 
+       return 0;
+}
+
+struct dp_catalog *dp_catalog_get(struct device *dev)
+{
+       struct dp_catalog_private *catalog;
+       int ret;
+
        catalog  = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL);
        if (!catalog)
                return ERR_PTR(-ENOMEM);
 
        catalog->dev = dev;
-       catalog->io = io;
+
+       ret = dp_catalog_get_io(catalog);
+       if (ret)
+               return ERR_PTR(ret);
 
        return &catalog->dp_catalog;
 }
 
 #include "dp_parser.h"
 #include "dp_reg.h"
 
-#define DP_DEFAULT_AHB_OFFSET  0x0000
-#define DP_DEFAULT_AHB_SIZE    0x0200
-#define DP_DEFAULT_AUX_OFFSET  0x0200
-#define DP_DEFAULT_AUX_SIZE    0x0200
-#define DP_DEFAULT_LINK_OFFSET 0x0400
-#define DP_DEFAULT_LINK_SIZE   0x0C00
-#define DP_DEFAULT_P0_OFFSET   0x1000
-#define DP_DEFAULT_P0_SIZE     0x0400
-
-static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
-{
-       struct resource *res;
-       void __iomem *base;
-
-       base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
-       if (!IS_ERR(base))
-               *len = resource_size(res);
-
-       return base;
-}
-
 static int dp_parser_ctrl_res(struct dp_parser *parser)
 {
        struct platform_device *pdev = parser->pdev;
-       struct dp_io *io = &parser->io;
-       struct dss_io_data *dss = &io->dp_controller;
-
-       dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
-       if (IS_ERR(dss->ahb.base))
-               return PTR_ERR(dss->ahb.base);
-
-       dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
-       if (IS_ERR(dss->aux.base)) {
-               /*
-                * The initial binding had a single reg, but in order to
-                * support variation in the sub-region sizes this was split.
-                * dp_ioremap() will fail with -EINVAL here if only a single
-                * reg is specified, so fill in the sub-region offsets and
-                * lengths based on this single region.
-                */
-               if (PTR_ERR(dss->aux.base) == -EINVAL) {
-                       if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
-                               DRM_ERROR("legacy memory region not large enough\n");
-                               return -EINVAL;
-                       }
-
-                       dss->ahb.len = DP_DEFAULT_AHB_SIZE;
-                       dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
-                       dss->aux.len = DP_DEFAULT_AUX_SIZE;
-                       dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
-                       dss->link.len = DP_DEFAULT_LINK_SIZE;
-                       dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
-                       dss->p0.len = DP_DEFAULT_P0_SIZE;
-               } else {
-                       DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
-                       return PTR_ERR(dss->aux.base);
-               }
-       } else {
-               dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
-               if (IS_ERR(dss->link.base)) {
-                       DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
-                       return PTR_ERR(dss->link.base);
-               }
-
-               dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
-               if (IS_ERR(dss->p0.base)) {
-                       DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
-                       return PTR_ERR(dss->p0.base);
-               }
-       }
 
-       io->phy = devm_phy_get(&pdev->dev, "dp");
-       if (IS_ERR(io->phy))
-               return PTR_ERR(io->phy);
+       parser->phy = devm_phy_get(&pdev->dev, "dp");
+       if (IS_ERR(parser->phy))
+               return PTR_ERR(parser->phy);
 
        return 0;
 }