Merge remote-tracking branches 'asoc/topic/sh', 'asoc/topic/sigmadsp', 'asoc/topic...
[pandora-kernel.git] / sound / soc / codecs / adau17x1.c
index 3e16c1c..fa2e690 100644 (file)
@@ -61,7 +61,8 @@ static const struct snd_kcontrol_new adau17x1_controls[] = {
 static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
-       struct adau *adau = snd_soc_codec_get_drvdata(w->codec);
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct adau *adau = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        if (SND_SOC_DAPM_EVENT_ON(event)) {
@@ -307,6 +308,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
        struct adau *adau = snd_soc_codec_get_drvdata(codec);
        unsigned int val, div, dsp_div;
        unsigned int freq;
+       int ret;
 
        if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
                freq = adau->pll_freq;
@@ -356,6 +358,12 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
                regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
        }
 
+       if (adau->sigmadsp) {
+               ret = adau17x1_setup_firmware(adau, params_rate(params));
+               if (ret < 0)
+                       return ret;
+       }
+
        if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
                return 0;
 
@@ -661,12 +669,24 @@ static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
        return 0;
 }
 
+static int adau17x1_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
+
+       if (adau->sigmadsp)
+               return sigmadsp_restrict_params(adau->sigmadsp, substream);
+
+       return 0;
+}
+
 const struct snd_soc_dai_ops adau17x1_dai_ops = {
        .hw_params      = adau17x1_hw_params,
        .set_sysclk     = adau17x1_set_dai_sysclk,
        .set_fmt        = adau17x1_set_dai_fmt,
        .set_pll        = adau17x1_set_dai_pll,
        .set_tdm_slot   = adau17x1_set_dai_tdm_slot,
+       .startup        = adau17x1_startup,
 };
 EXPORT_SYMBOL_GPL(adau17x1_dai_ops);
 
@@ -687,8 +707,22 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);
 
+bool adau17x1_precious_register(struct device *dev, unsigned int reg)
+{
+       /* SigmaDSP parameter memory */
+       if (reg < 0x400)
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(adau17x1_precious_register);
+
 bool adau17x1_readable_register(struct device *dev, unsigned int reg)
 {
+       /* SigmaDSP parameter memory */
+       if (reg < 0x400)
+               return true;
+
        switch (reg) {
        case ADAU17X1_CLOCK_CONTROL:
        case ADAU17X1_PLL_CONTROL:
@@ -745,8 +779,7 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
 }
 EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
 
-int adau17x1_load_firmware(struct adau *adau, struct device *dev,
-       const char *firmware)
+int adau17x1_setup_firmware(struct adau *adau, unsigned int rate)
 {
        int ret;
        int dspsr;
@@ -758,7 +791,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev,
        regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
 
-       ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware);
+       ret = sigmadsp_setup(adau->sigmadsp, rate);
        if (ret) {
                regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
                return ret;
@@ -767,7 +800,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(adau17x1_load_firmware);
+EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);
 
 int adau17x1_add_widgets(struct snd_soc_codec *codec)
 {
@@ -787,8 +820,21 @@ int adau17x1_add_widgets(struct snd_soc_codec *codec)
                ret = snd_soc_dapm_new_controls(&codec->dapm,
                        adau17x1_dsp_dapm_widgets,
                        ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
+               if (ret)
+                       return ret;
+
+               if (!adau->sigmadsp)
+                       return 0;
+
+               ret = sigmadsp_attach(adau->sigmadsp, &codec->component);
+               if (ret) {
+                       dev_err(codec->dev, "Failed to attach firmware: %d\n",
+                               ret);
+                       return ret;
+               }
        }
-       return ret;
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(adau17x1_add_widgets);
 
@@ -829,7 +875,8 @@ int adau17x1_resume(struct snd_soc_codec *codec)
 EXPORT_SYMBOL_GPL(adau17x1_resume);
 
 int adau17x1_probe(struct device *dev, struct regmap *regmap,
-       enum adau17x1_type type, void (*switch_mode)(struct device *dev))
+       enum adau17x1_type type, void (*switch_mode)(struct device *dev),
+       const char *firmware_name)
 {
        struct adau *adau;
 
@@ -846,6 +893,16 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,
 
        dev_set_drvdata(dev, adau);
 
+       if (firmware_name) {
+               adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL,
+                       firmware_name);
+               if (IS_ERR(adau->sigmadsp)) {
+                       dev_warn(dev, "Could not find firmware file: %ld\n",
+                               PTR_ERR(adau->sigmadsp));
+                       adau->sigmadsp = NULL;
+               }
+       }
+
        if (switch_mode)
                switch_mode(dev);