Merge remote-tracking branches 'asoc/topic/adsp' and 'asoc/topic/amd' into asoc-next
authorMark Brown <broonie@kernel.org>
Mon, 11 Jan 2016 13:54:32 +0000 (13:54 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 11 Jan 2016 13:54:32 +0000 (13:54 +0000)
1  2  3 
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/codecs/wm5110.c

diff --combined sound/soc/Kconfig
@@@@ -38,6 -38,6 -38,7 +38,7 @@@@ config SND_SOC_TOPOLOG
   
   # All the supported SoCs
   source "sound/soc/adi/Kconfig"
++ source "sound/soc/amd/Kconfig"
   source "sound/soc/atmel/Kconfig"
   source "sound/soc/au1x/Kconfig"
   source "sound/soc/bcm/Kconfig"
@@@@ -50,7 -50,6 -51,6 +51,7 @@@@ source "sound/soc/jz4740/Kconfig
   source "sound/soc/nuc900/Kconfig"
   source "sound/soc/omap/Kconfig"
   source "sound/soc/kirkwood/Kconfig"
 ++source "sound/soc/img/Kconfig"
   source "sound/soc/intel/Kconfig"
   source "sound/soc/mediatek/Kconfig"
   source "sound/soc/mxs/Kconfig"
diff --combined sound/soc/Makefile
@@@@ -18,6 -18,6 -18,7 +18,7 @@@@ obj-$(CONFIG_SND_SOC) += snd-soc-core.
   obj-$(CONFIG_SND_SOC)        += codecs/
   obj-$(CONFIG_SND_SOC)        += generic/
   obj-$(CONFIG_SND_SOC)        += adi/
++ obj-$(CONFIG_SND_SOC)        += amd/
   obj-$(CONFIG_SND_SOC)        += atmel/
   obj-$(CONFIG_SND_SOC)        += au1x/
   obj-$(CONFIG_SND_SOC)        += bcm/
@@@@ -27,7 -27,6 -28,6 +28,7 @@@@ obj-$(CONFIG_SND_SOC) += davinci
   obj-$(CONFIG_SND_SOC)        += dwc/
   obj-$(CONFIG_SND_SOC)        += fsl/
   obj-$(CONFIG_SND_SOC)        += jz4740/
 ++obj-$(CONFIG_SND_SOC)        += img/
   obj-$(CONFIG_SND_SOC)        += intel/
   obj-$(CONFIG_SND_SOC)        += mediatek/
   obj-$(CONFIG_SND_SOC)        += mxs/
@@@@ -360,13 -360,15 -360,15 +360,13 @@@@ static int wm5110_hp_ev(struct snd_soc_
   
   static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
   {
 --     struct reg_sequence clear_pga = {
 --             ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
 --     };
 ++     unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4;
        int ret;
   
 --     ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
 ++     ret = regmap_write(arizona->regmap, reg, 0x80);
        if (ret)
                dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
 --                     clear_pga.reg, ret);
 ++                     reg, ret);
   
        return ret;
   }
@@@@ -437,17 -439,18 -439,18 +437,17 @@@@ static int wm5110_in_pga_get(struct snd
   {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 --     struct snd_soc_card *card = dapm->card;
        int ret;
   
        /*
         * PGA Volume is also used as part of the enable sequence, so
         * usage of it should be avoided whilst that is running.
         */
 --     mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 ++     snd_soc_dapm_mutex_lock(dapm);
   
        ret = snd_soc_get_volsw_range(kcontrol, ucontrol);
   
 --     mutex_unlock(&card->dapm_mutex);
 ++     snd_soc_dapm_mutex_unlock(dapm);
   
        return ret;
   }
@@@@ -457,17 -460,18 -460,18 +457,17 @@@@ static int wm5110_in_pga_put(struct snd
   {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 --     struct snd_soc_card *card = dapm->card;
        int ret;
   
        /*
         * PGA Volume is also used as part of the enable sequence, so
         * usage of it should be avoided whilst that is running.
         */
 --     mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 ++     snd_soc_dapm_mutex_lock(dapm);
   
        ret = snd_soc_put_volsw_range(kcontrol, ucontrol);
   
 --     mutex_unlock(&card->dapm_mutex);
 ++     snd_soc_dapm_mutex_unlock(dapm);
   
        return ret;
   }
@@@@ -571,33 -575,33 -575,6 +571,33 @@@@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10
        SOC_SINGLE(name " NG SPKDAT2L Switch", base, 10, 1, 0), \
        SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0)
   
  +#define WM5110_RXANC_INPUT_ROUTES(widget, name) \
  +     { widget, NULL, name " NG Mux" }, \
  +     { name " NG Internal", NULL, "RXANC NG Clock" }, \
  +     { name " NG Internal", NULL, name " Channel" }, \
  +     { name " NG External", NULL, "RXANC NG External Clock" }, \
  +     { name " NG External", NULL, name " Channel" }, \
  +     { name " NG Mux", "None", name " Channel" }, \
  +     { name " NG Mux", "Internal", name " NG Internal" }, \
  +     { name " NG Mux", "External", name " NG External" }, \
  +     { name " Channel", "Left", name " Left Input" }, \
  +     { name " Channel", "Combine", name " Left Input" }, \
  +     { name " Channel", "Right", name " Right Input" }, \
  +     { name " Channel", "Combine", name " Right Input" }, \
  +     { name " Left Input", "IN1", "IN1L PGA" }, \
  +     { name " Right Input", "IN1", "IN1R PGA" }, \
  +     { name " Left Input", "IN2", "IN2L PGA" }, \
  +     { name " Right Input", "IN2", "IN2R PGA" }, \
  +     { name " Left Input", "IN3", "IN3L PGA" }, \
  +     { name " Right Input", "IN3", "IN3R PGA" }, \
  +     { name " Left Input", "IN4", "IN4L PGA" }, \
  +     { name " Right Input", "IN4", "IN4R PGA" }
  +
  +#define WM5110_RXANC_OUTPUT_ROUTES(widget, name) \
  +     { widget, NULL, name " ANC Source" }, \
  +     { name " ANC Source", "RXANCL", "RXANCL" }, \
  +     { name " ANC Source", "RXANCR", "RXANCR" }
  +
   static const struct snd_kcontrol_new wm5110_snd_controls[] = {
   SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]),
   SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),
@@@@ -662,15 -666,15 -639,6 +662,15 @@@@ SOC_SINGLE_TLV("IN4R Digital Volume", A
   SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
   SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
   
  +SND_SOC_BYTES("RXANC Coefficients", ARIZONA_ANC_COEFF_START,
  +           ARIZONA_ANC_COEFF_END - ARIZONA_ANC_COEFF_START + 1),
  +SND_SOC_BYTES("RXANCL Config", ARIZONA_FCL_FILTER_CONTROL, 1),
  +SND_SOC_BYTES("RXANCL Coefficients", ARIZONA_FCL_COEFF_START,
  +           ARIZONA_FCL_COEFF_END - ARIZONA_FCL_COEFF_START + 1),
  +SND_SOC_BYTES("RXANCR Config", ARIZONA_FCR_FILTER_CONTROL, 1),
  +SND_SOC_BYTES("RXANCR Coefficients", ARIZONA_FCR_COEFF_START,
  +           ARIZONA_FCR_COEFF_END - ARIZONA_FCR_COEFF_START + 1),
  +
   ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
   ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
   ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
@@@@ -1027,31 -1031,31 -995,6 +1027,31 @@@@ static const struct soc_enum wm5110_aec
   static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
        SOC_DAPM_ENUM("AEC Loopback", wm5110_aec_loopback);
   
  +static const struct snd_kcontrol_new wm5110_anc_input_mux[] = {
  +     SOC_DAPM_ENUM("RXANCL Input", arizona_anc_input_src[0]),
  +     SOC_DAPM_ENUM("RXANCL Channel", arizona_anc_input_src[1]),
  +     SOC_DAPM_ENUM("RXANCR Input", arizona_anc_input_src[2]),
  +     SOC_DAPM_ENUM("RXANCR Channel", arizona_anc_input_src[3]),
  +};
  +
  +static const struct snd_kcontrol_new wm5110_anc_ng_mux =
  +     SOC_DAPM_ENUM("RXANC NG Source", arizona_anc_ng_enum);
  +
  +static const struct snd_kcontrol_new wm5110_output_anc_src[] = {
  +     SOC_DAPM_ENUM("HPOUT1L ANC Source", arizona_output_anc_src[0]),
  +     SOC_DAPM_ENUM("HPOUT1R ANC Source", arizona_output_anc_src[1]),
  +     SOC_DAPM_ENUM("HPOUT2L ANC Source", arizona_output_anc_src[2]),
  +     SOC_DAPM_ENUM("HPOUT2R ANC Source", arizona_output_anc_src[3]),
  +     SOC_DAPM_ENUM("HPOUT3L ANC Source", arizona_output_anc_src[4]),
  +     SOC_DAPM_ENUM("HPOUT3R ANC Source", arizona_output_anc_src[5]),
  +     SOC_DAPM_ENUM("SPKOUTL ANC Source", arizona_output_anc_src[6]),
  +     SOC_DAPM_ENUM("SPKOUTR ANC Source", arizona_output_anc_src[7]),
  +     SOC_DAPM_ENUM("SPKDAT1L ANC Source", arizona_output_anc_src[8]),
  +     SOC_DAPM_ENUM("SPKDAT1R ANC Source", arizona_output_anc_src[9]),
  +     SOC_DAPM_ENUM("SPKDAT2L ANC Source", arizona_output_anc_src[10]),
  +     SOC_DAPM_ENUM("SPKDAT2R ANC Source", arizona_output_anc_src[11]),
  +};
  +
   static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
   SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
                    0, wm5110_sysclk_ev, SND_SOC_DAPM_POST_PMU),
@@@@ -1242,65 -1246,65 -1185,6 +1242,65 @@@@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZON
                       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
                       &wm5110_aec_loopback_mux),
   
  +SND_SOC_DAPM_SUPPLY("RXANC NG External Clock", SND_SOC_NOPM,
  +                ARIZONA_EXT_NG_SEL_SET_SHIFT, 0, arizona_anc_ev,
  +                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  +SND_SOC_DAPM_PGA("RXANCL NG External", SND_SOC_NOPM, 0, 0, NULL, 0),
  +SND_SOC_DAPM_PGA("RXANCR NG External", SND_SOC_NOPM, 0, 0, NULL, 0),
  +
  +SND_SOC_DAPM_SUPPLY("RXANC NG Clock", SND_SOC_NOPM,
  +                ARIZONA_CLK_NG_ENA_SET_SHIFT, 0, arizona_anc_ev,
  +                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  +SND_SOC_DAPM_PGA("RXANCL NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0),
  +SND_SOC_DAPM_PGA("RXANCR NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0),
  +
  +SND_SOC_DAPM_MUX("RXANCL Left Input", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[0]),
  +SND_SOC_DAPM_MUX("RXANCL Right Input", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[0]),
  +SND_SOC_DAPM_MUX("RXANCL Channel", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[1]),
  +SND_SOC_DAPM_MUX("RXANCL NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux),
  +SND_SOC_DAPM_MUX("RXANCR Left Input", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[2]),
  +SND_SOC_DAPM_MUX("RXANCR Right Input", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[2]),
  +SND_SOC_DAPM_MUX("RXANCR Channel", SND_SOC_NOPM, 0, 0,
  +              &wm5110_anc_input_mux[3]),
  +SND_SOC_DAPM_MUX("RXANCR NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux),
  +
  +SND_SOC_DAPM_PGA_E("RXANCL", SND_SOC_NOPM, ARIZONA_CLK_L_ENA_SET_SHIFT,
  +                0, NULL, 0, arizona_anc_ev,
  +                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  +SND_SOC_DAPM_PGA_E("RXANCR", SND_SOC_NOPM, ARIZONA_CLK_R_ENA_SET_SHIFT,
  +                0, NULL, 0, arizona_anc_ev,
  +                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  +
  +SND_SOC_DAPM_MUX("HPOUT1L ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[0]),
  +SND_SOC_DAPM_MUX("HPOUT1R ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[1]),
  +SND_SOC_DAPM_MUX("HPOUT2L ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[2]),
  +SND_SOC_DAPM_MUX("HPOUT2R ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[3]),
  +SND_SOC_DAPM_MUX("HPOUT3L ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[4]),
  +SND_SOC_DAPM_MUX("HPOUT3R ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[5]),
  +SND_SOC_DAPM_MUX("SPKOUTL ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[6]),
  +SND_SOC_DAPM_MUX("SPKOUTR ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[7]),
  +SND_SOC_DAPM_MUX("SPKDAT1L ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[8]),
  +SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[9]),
  +SND_SOC_DAPM_MUX("SPKDAT2L ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[10]),
  +SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0,
  +              &wm5110_output_anc_src[11]),
  +
   SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
                     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
   SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
@@@@ -1806,9 -1810,9 -1690,6 +1806,9 @@@@ static const struct snd_soc_dapm_route 
        { "Slim2 Capture", NULL, "SYSCLK" },
        { "Slim3 Capture", NULL, "SYSCLK" },
   
  +     { "Voice Control DSP", NULL, "DSP3" },
  +     { "Voice Control DSP", NULL, "SYSCLK" },
  +
        { "IN1L PGA", NULL, "IN1L" },
        { "IN1R PGA", NULL, "IN1R" },
   
        { "SPKDAT2L", NULL, "OUT6L" },
        { "SPKDAT2R", NULL, "OUT6R" },
   
  +     WM5110_RXANC_INPUT_ROUTES("RXANCL", "RXANCL"),
  +     WM5110_RXANC_INPUT_ROUTES("RXANCR", "RXANCR"),
  +
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT1L", "HPOUT1L"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT1R", "HPOUT1R"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT2L", "HPOUT2L"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT2R", "HPOUT2R"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT3L", "HPOUT3L"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT3R", "HPOUT3R"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT4L", "SPKOUTL"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT4R", "SPKOUTR"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT5L", "SPKDAT1L"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT5R", "SPKDAT1R"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT6L", "SPKDAT2L"),
  +     WM5110_RXANC_OUTPUT_ROUTES("OUT6R", "SPKDAT2R"),
  +
        { "MICSUPP", NULL, "SYSCLK" },
   
        { "DRC1 Signal Activity", NULL, "DRC1L" },
@@@@ -2131,52 -2135,65 -1996,12 +2131,65 @@@@ static struct snd_soc_dai_driver wm5110
                 },
                .ops = &arizona_simple_dai_ops,
        },
  +     {
  +             .name = "wm5110-cpu-voicectrl",
  +             .capture = {
  +                     .stream_name = "Voice Control CPU",
  +                     .channels_min = 1,
  +                     .channels_max = 1,
  +                     .rates = WM5110_RATES,
  +                     .formats = WM5110_FORMATS,
  +             },
  +             .compress_new = snd_soc_new_compress,
  +     },
  +     {
  +             .name = "wm5110-dsp-voicectrl",
  +             .capture = {
  +                     .stream_name = "Voice Control DSP",
  +                     .channels_min = 1,
  +                     .channels_max = 1,
  +                     .rates = WM5110_RATES,
  +                     .formats = WM5110_FORMATS,
  +             },
  +     },
   };
   
  +static int wm5110_open(struct snd_compr_stream *stream)
  +{
  +     struct snd_soc_pcm_runtime *rtd = stream->private_data;
  +     struct wm5110_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
  +     struct arizona *arizona = priv->core.arizona;
  +     int n_adsp;
  +
  +     if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) {
  +             n_adsp = 2;
  +     } else {
  +             dev_err(arizona->dev,
  +                     "No suitable compressed stream for DAI '%s'\n",
  +                     rtd->codec_dai->name);
  +             return -EINVAL;
  +     }
  +
  +     return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream);
  +}
  +
+ +static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
+ +{
+ +     struct wm5110_priv *florida = data;
+ +     int ret;
+ +
+ +     ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]);
+ +     if (ret == -ENODEV)
+ +             return IRQ_NONE;
+ +
+ +     return IRQ_HANDLED;
+ +}
+ +
   static int wm5110_codec_probe(struct snd_soc_codec *codec)
   {
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ +     struct arizona *arizona = priv->core.arizona;
        int i, ret;
   
        priv->core.arizona->dapm = dapm;
        arizona_init_gpio(codec);
        arizona_init_mono(codec);
   
+ +     ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+ +                               "ADSP2 Compressed IRQ", wm5110_adsp2_irq,
+ +                               priv);
+ +     if (ret != 0) {
+ +             dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+ +             return ret;
+ +     }
+ +
        for (i = 0; i < WM5110_NUM_ADSP; ++i) {
                ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
                if (ret)
@@@@ -2205,12 -2230,15 -2030,12 +2226,15 @@@@ err_adsp2_codec_probe
        for (--i; i >= 0; --i)
                wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
   
+ +     arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
+ +
        return ret;
   }
   
   static int wm5110_codec_remove(struct snd_soc_codec *codec)
   {
        struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ +     struct arizona *arizona = priv->core.arizona;
        int i;
   
        for (i = 0; i < WM5110_NUM_ADSP; ++i)
   
        priv->core.arizona->dapm = NULL;
   
+ +     arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
+ +
        return 0;
   }
   
@@@@ -2263,18 -2293,20 -2088,6 +2289,20 @@@@ static struct snd_soc_codec_driver soc_
        .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
   };
   
  +static struct snd_compr_ops wm5110_compr_ops = {
  +     .open = wm5110_open,
  +     .free = wm_adsp_compr_free,
  +     .set_params = wm_adsp_compr_set_params,
  +     .get_caps = wm_adsp_compr_get_caps,
  +     .trigger = wm_adsp_compr_trigger,
+ +     .pointer = wm_adsp_compr_pointer,
+ +     .copy = wm_adsp_compr_copy,
  +};
  +
  +static struct snd_soc_platform_driver wm5110_compr_platform = {
  +     .compr_ops = &wm5110_compr_ops,
  +};
  +
   static int wm5110_probe(struct platform_device *pdev)
   {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        pm_runtime_enable(&pdev->dev);
        pm_runtime_idle(&pdev->dev);
   
  -     return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
  +     ret = snd_soc_register_platform(&pdev->dev, &wm5110_compr_platform);
  +     if (ret < 0) {
  +             dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
  +             goto error;
  +     }
  +
  +     ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
                                      wm5110_dai, ARRAY_SIZE(wm5110_dai));
  +     if (ret < 0) {
  +             dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
  +             snd_soc_unregister_platform(&pdev->dev);
  +     }
  +
  +error:
  +     return ret;
   }
   
   static int wm5110_remove(struct platform_device *pdev)