#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
 
 #include "acp5x.h"
 
 struct acp5x_dev_data {
        void __iomem *acp5x_base;
+       bool acp5x_audio_mode;
+       struct resource *res;
+       struct platform_device *pdev[ACP5x_DEVS];
 };
 
 static int acp5x_power_on(void __iomem *acp5x_base)
                           const struct pci_device_id *pci_id)
 {
        struct acp5x_dev_data *adata;
-       int ret;
-       u32 addr;
+       struct platform_device_info pdevinfo[ACP5x_DEVS];
+       unsigned int irqflags;
+       int ret, i;
+       u32 addr, val;
 
+       irqflags = IRQF_SHARED;
        if (pci->revision != 0x50)
                return -ENODEV;
 
        if (ret)
                goto release_regions;
 
+       val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG);
+       switch (val) {
+       case I2S_MODE:
+               adata->res = devm_kzalloc(&pci->dev,
+                                         sizeof(struct resource) * ACP5x_RES,
+                                         GFP_KERNEL);
+               if (!adata->res) {
+                       ret = -ENOMEM;
+                       goto de_init;
+               }
+
+               adata->res[0].name = "acp5x_i2s_iomem";
+               adata->res[0].flags = IORESOURCE_MEM;
+               adata->res[0].start = addr;
+               adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START);
+
+               adata->res[1].name = "acp5x_i2s_sp";
+               adata->res[1].flags = IORESOURCE_MEM;
+               adata->res[1].start = addr + ACP5x_I2STDM_REG_START;
+               adata->res[1].end = addr + ACP5x_I2STDM_REG_END;
+
+               adata->res[2].name = "acp5x_i2s_hs";
+               adata->res[2].flags = IORESOURCE_MEM;
+               adata->res[2].start = addr + ACP5x_HS_TDM_REG_START;
+               adata->res[2].end = addr + ACP5x_HS_TDM_REG_END;
+
+               adata->res[3].name = "acp5x_i2s_irq";
+               adata->res[3].flags = IORESOURCE_IRQ;
+               adata->res[3].start = pci->irq;
+               adata->res[3].end = adata->res[3].start;
+
+               adata->acp5x_audio_mode = ACP5x_I2S_MODE;
+
+               memset(&pdevinfo, 0, sizeof(pdevinfo));
+               pdevinfo[0].name = "acp5x_i2s_dma";
+               pdevinfo[0].id = 0;
+               pdevinfo[0].parent = &pci->dev;
+               pdevinfo[0].num_res = 4;
+               pdevinfo[0].res = &adata->res[0];
+               pdevinfo[0].data = &irqflags;
+               pdevinfo[0].size_data = sizeof(irqflags);
+
+               pdevinfo[1].name = "acp5x_i2s_playcap";
+               pdevinfo[1].id = 0;
+               pdevinfo[1].parent = &pci->dev;
+               pdevinfo[1].num_res = 1;
+               pdevinfo[1].res = &adata->res[1];
+
+               pdevinfo[2].name = "acp5x_i2s_playcap";
+               pdevinfo[2].id = 1;
+               pdevinfo[2].parent = &pci->dev;
+               pdevinfo[2].num_res = 1;
+               pdevinfo[2].res = &adata->res[2];
+
+               for (i = 0; i < ACP5x_DEVS; i++) {
+                       adata->pdev[i] =
+                               platform_device_register_full(&pdevinfo[i]);
+                       if (IS_ERR(adata->pdev[i])) {
+                               dev_err(&pci->dev, "cannot register %s device\n",
+                                       pdevinfo[i].name);
+                               ret = PTR_ERR(adata->pdev[i]);
+                               goto unregister_devs;
+                       }
+               }
+               break;
+       default:
+               dev_info(&pci->dev, "ACP audio mode : %d\n", val);
+       }
+       return 0;
+
+unregister_devs:
+       for (--i; i >= 0; i--)
+               platform_device_unregister(adata->pdev[i]);
+de_init:
+       if (acp5x_deinit(adata->acp5x_base))
+               dev_err(&pci->dev, "ACP de-init failed\n");
 release_regions:
        pci_release_regions(pci);
 disable_pci:
 static void snd_acp5x_remove(struct pci_dev *pci)
 {
        struct acp5x_dev_data *adata;
-       int ret;
+       int i, ret;
 
        adata = pci_get_drvdata(pci);
+       if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) {
+               for (i = 0; i < ACP5x_DEVS; i++)
+                       platform_device_unregister(adata->pdev[i]);
+       }
        ret = acp5x_deinit(adata->acp5x_base);
        if (ret)
                dev_err(&pci->dev, "ACP de-init failed\n");