.tdm_mode = false,
 };
 
+static bool acp_asoc_init_ops(struct acp_card_drvdata *priv)
+{
+       return false;
+}
+
+static int acp_asoc_suspend_pre(struct snd_soc_card *card)
+{
+       int ret;
+
+       ret = acp_ops_suspend_pre(card);
+       if (ret == 1)
+               return 0;
+       else
+               return ret;
+}
+
+static int acp_asoc_resume_post(struct snd_soc_card *card)
+{
+       int ret;
+
+       ret = acp_ops_resume_post(card);
+       if (ret == 1)
+               return 0;
+       else
+               return ret;
+}
+
 static int acp_asoc_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = NULL;
        struct acp_card_drvdata *acp_card_drvdata;
        int ret;
 
-       if (!pdev->id_entry)
-               return -EINVAL;
+       if (!pdev->id_entry) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
-       if (!card)
-               return -ENOMEM;
+       if (!card) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
+       card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+       acp_card_drvdata = card->drvdata;
+       acp_card_drvdata->acpi_mach = (struct snd_soc_acpi_mach *)pdev->dev.platform_data;
        card->dev = dev;
        card->owner = THIS_MODULE;
        card->name = pdev->id_entry->name;
-       card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
-       /* Widgets and controls added per-codec in acp-mach-common.c */
 
-       acp_card_drvdata = card->drvdata;
+       acp_asoc_init_ops(card->drvdata);
+
+       /* If widgets and controls are not set in specific callback,
+        * they will be added per-codec in acp-mach-common.c
+        */
+       ret = acp_ops_configure_widgets(card);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Cannot configure widgets for card (%s): %d\n",
+                       card->name, ret);
+               goto out;
+       }
+       card->suspend_pre = acp_asoc_suspend_pre;
+       card->resume_post = acp_asoc_resume_post;
+
+       ret = acp_ops_probe(card);
+       if (ret < 0) {
+               dev_err(&pdev->dev,
+                       "Cannot probe card (%s): %d\n",
+                       card->name, ret);
+               goto out;
+       }
+
        dmi_id = dmi_first_match(acp_quirk_table);
        if (dmi_id && dmi_id->driver_data)
                acp_card_drvdata->tdm_mode = dmi_id->driver_data;
 
-       acp_legacy_dai_links_create(card);
+       ret = acp_legacy_dai_links_create(card);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "Cannot create dai links for card (%s): %d\n",
+                       card->name, ret);
+               goto out;
+       }
 
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
                dev_err(&pdev->dev,
                                "devm_snd_soc_register_card(%s) failed: %d\n",
                                card->name, ret);
-               return ret;
+               goto out;
        }
-
-       return 0;
+out:
+       return ret;
 }
 
 static const struct platform_device_id board_ids[] = {
 
 
 #define TDM_CHANNELS   8
 
+#define ACP_OPS(priv, cb)      ((priv)->ops.cb)
+
+#define acp_get_drvdata(card) ((struct acp_card_drvdata *)(card)->drvdata)
+
 enum be_id {
        HEADSET_BE_ID = 0,
        AMP_BE_ID,
        REMBRANDT,
 };
 
+struct acp_mach_ops {
+       int (*probe)(struct snd_soc_card *card);
+       int (*configure_link)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
+       int (*configure_widgets)(struct snd_soc_card *card);
+       int (*suspend_pre)(struct snd_soc_card *card);
+       int (*resume_post)(struct snd_soc_card *card);
+};
+
 struct acp_card_drvdata {
        unsigned int hs_cpu_id;
        unsigned int amp_cpu_id;
        unsigned int platform;
        struct clk *wclk;
        struct clk *bclk;
+       struct acp_mach_ops ops;
+       struct snd_soc_acpi_mach *acpi_mach;
+       void *mach_priv;
        bool soc_mclk;
        bool tdm_mode;
 };
 int acp_legacy_dai_links_create(struct snd_soc_card *card);
 extern const struct dmi_system_id acp_quirk_table[];
 
+static inline int acp_ops_probe(struct snd_soc_card *card)
+{
+       int ret = 1;
+       struct acp_card_drvdata *priv = acp_get_drvdata(card);
+
+       if (ACP_OPS(priv, probe))
+               ret = ACP_OPS(priv, probe)(card);
+       return ret;
+}
+
+static inline int acp_ops_configure_link(struct snd_soc_card *card,
+                                        struct snd_soc_dai_link *dai_link)
+{
+       int ret = 1;
+       struct acp_card_drvdata *priv = acp_get_drvdata(card);
+
+       if (ACP_OPS(priv, configure_link))
+               ret = ACP_OPS(priv, configure_link)(card, dai_link);
+       return ret;
+}
+
+static inline int acp_ops_configure_widgets(struct snd_soc_card *card)
+{
+       int ret = 1;
+       struct acp_card_drvdata *priv = acp_get_drvdata(card);
+
+       if (ACP_OPS(priv, configure_widgets))
+               ret = ACP_OPS(priv, configure_widgets)(card);
+       return ret;
+}
+
+static inline int acp_ops_suspend_pre(struct snd_soc_card *card)
+{
+       int ret = 1;
+       struct acp_card_drvdata *priv = acp_get_drvdata(card);
+
+       if (ACP_OPS(priv, suspend_pre))
+               ret = ACP_OPS(priv, suspend_pre)(card);
+       return ret;
+}
+
+static inline int acp_ops_resume_post(struct snd_soc_card *card)
+{
+       int ret = 1;
+       struct acp_card_drvdata *priv = acp_get_drvdata(card);
+
+       if (ACP_OPS(priv, resume_post))
+               ret = ACP_OPS(priv, resume_post)(card);
+       return ret;
+}
+
 #endif