Merge remote-tracking branches 'asoc/topic/ssm4567', 'asoc/topic/sta32x', 'asoc/topic...
authorMark Brown <broonie@kernel.org>
Mon, 8 Dec 2014 13:12:14 +0000 (13:12 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 8 Dec 2014 13:12:14 +0000 (13:12 +0000)
sound/soc/codecs/ssm4567.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/sta350.c
sound/soc/codecs/sta529.c
sound/soc/codecs/stac9766.c

index 4b5c17f..a984485 100644 (file)
 #define SSM4567_DAC_FS_64000_96000     0x3
 #define SSM4567_DAC_FS_128000_192000   0x4
 
+/* SAI_CTRL_1 */
+#define SSM4567_SAI_CTRL_1_BCLK                        BIT(6)
+#define SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK      (0x3 << 4)
+#define SSM4567_SAI_CTRL_1_TDM_BLCKS_32                (0x0 << 4)
+#define SSM4567_SAI_CTRL_1_TDM_BLCKS_48                (0x1 << 4)
+#define SSM4567_SAI_CTRL_1_TDM_BLCKS_64                (0x2 << 4)
+#define SSM4567_SAI_CTRL_1_FSYNC               BIT(3)
+#define SSM4567_SAI_CTRL_1_LJ                  BIT(2)
+#define SSM4567_SAI_CTRL_1_TDM                 BIT(1)
+#define SSM4567_SAI_CTRL_1_PDM                 BIT(0)
+
+/* SAI_CTRL_2 */
+#define SSM4567_SAI_CTRL_2_AUTO_SLOT           BIT(3)
+#define SSM4567_SAI_CTRL_2_TDM_SLOT_MASK       0x7
+#define SSM4567_SAI_CTRL_2_TDM_SLOT(x)         (x)
+
 struct ssm4567 {
        struct regmap *regmap;
 };
@@ -145,15 +161,24 @@ static const struct snd_kcontrol_new ssm4567_snd_controls[] = {
        SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0,
                0xff, 1, ssm4567_vol_tlv),
        SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0),
+       SOC_SINGLE("DAC High Pass Filter Switch", SSM4567_REG_DAC_CTRL,
+               5, 1, 0),
 };
 
+static const struct snd_kcontrol_new ssm4567_amplifier_boost_control =
+       SOC_DAPM_SINGLE("Switch", SSM4567_REG_POWER_CTRL, 1, 1, 1);
+
 static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1),
+       SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1,
+               &ssm4567_amplifier_boost_control),
 
        SND_SOC_DAPM_OUTPUT("OUT"),
 };
 
 static const struct snd_soc_dapm_route ssm4567_routes[] = {
+       { "OUT", NULL, "Amplifier Boost" },
+       { "Amplifier Boost", "Switch", "DAC" },
        { "OUT", NULL, "DAC" },
 };
 
@@ -192,6 +217,107 @@ static int ssm4567_mute(struct snd_soc_dai *dai, int mute)
                        SSM4567_DAC_MUTE, val);
 }
 
+static int ssm4567_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+       unsigned int rx_mask, int slots, int width)
+{
+       struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
+       unsigned int blcks;
+       int slot;
+       int ret;
+
+       if (tx_mask == 0)
+               return -EINVAL;
+
+       if (rx_mask && rx_mask != tx_mask)
+               return -EINVAL;
+
+       slot = __ffs(tx_mask);
+       if (tx_mask != BIT(slot))
+               return -EINVAL;
+
+       switch (width) {
+       case 32:
+               blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_32;
+               break;
+       case 48:
+               blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_48;
+               break;
+       case 64:
+               blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_64;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_2,
+               SSM4567_SAI_CTRL_2_AUTO_SLOT | SSM4567_SAI_CTRL_2_TDM_SLOT_MASK,
+               SSM4567_SAI_CTRL_2_TDM_SLOT(slot));
+       if (ret)
+               return ret;
+
+       return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1,
+               SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK, blcks);
+}
+
+static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
+       unsigned int ctrl1 = 0;
+       bool invert_fclk;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               invert_fclk = false;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
+               invert_fclk = false;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
+               invert_fclk = true;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
+               invert_fclk = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               ctrl1 |= SSM4567_SAI_CTRL_1_LJ;
+               invert_fclk = !invert_fclk;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               ctrl1 |= SSM4567_SAI_CTRL_1_TDM;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               ctrl1 |= SSM4567_SAI_CTRL_1_TDM | SSM4567_SAI_CTRL_1_LJ;
+               break;
+       case SND_SOC_DAIFMT_PDM:
+               ctrl1 |= SSM4567_SAI_CTRL_1_PDM;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (invert_fclk)
+               ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
+
+       return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1);
+}
+
 static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable)
 {
        int ret = 0;
@@ -246,6 +372,8 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec,
 static const struct snd_soc_dai_ops ssm4567_dai_ops = {
        .hw_params      = ssm4567_hw_params,
        .digital_mute   = ssm4567_mute,
+       .set_fmt        = ssm4567_set_dai_fmt,
+       .set_tdm_slot   = ssm4567_set_tdm_slot,
 };
 
 static struct snd_soc_dai_driver ssm4567_dai = {
index 4874085..7e18200 100644 (file)
@@ -833,23 +833,6 @@ static struct snd_soc_dai_driver sta32x_dai = {
        .ops = &sta32x_dai_ops,
 };
 
-#ifdef CONFIG_PM
-static int sta32x_suspend(struct snd_soc_codec *codec)
-{
-       sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
-static int sta32x_resume(struct snd_soc_codec *codec)
-{
-       sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       return 0;
-}
-#else
-#define sta32x_suspend NULL
-#define sta32x_resume NULL
-#endif
-
 static int sta32x_probe(struct snd_soc_codec *codec)
 {
        struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
@@ -936,7 +919,6 @@ static int sta32x_remove(struct snd_soc_codec *codec)
        struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 
        sta32x_watchdog_stop(sta32x);
-       sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
 
        return 0;
@@ -955,9 +937,8 @@ static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg)
 static const struct snd_soc_codec_driver sta32x_codec = {
        .probe =                sta32x_probe,
        .remove =               sta32x_remove,
-       .suspend =              sta32x_suspend,
-       .resume =               sta32x_resume,
        .set_bias_level =       sta32x_set_bias_level,
+       .suspend_bias_off =     true,
        .controls =             sta32x_snd_controls,
        .num_controls =         ARRAY_SIZE(sta32x_snd_controls),
        .dapm_widgets =         sta32x_dapm_widgets,
index cc97dd5..bda2ee1 100644 (file)
@@ -912,23 +912,6 @@ static struct snd_soc_dai_driver sta350_dai = {
        .ops = &sta350_dai_ops,
 };
 
-#ifdef CONFIG_PM
-static int sta350_suspend(struct snd_soc_codec *codec)
-{
-       sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
-static int sta350_resume(struct snd_soc_codec *codec)
-{
-       sta350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       return 0;
-}
-#else
-#define sta350_suspend NULL
-#define sta350_resume NULL
-#endif
-
 static int sta350_probe(struct snd_soc_codec *codec)
 {
        struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
@@ -1065,7 +1048,6 @@ static int sta350_remove(struct snd_soc_codec *codec)
 {
        struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec);
 
-       sta350_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies);
 
        return 0;
@@ -1074,9 +1056,8 @@ static int sta350_remove(struct snd_soc_codec *codec)
 static const struct snd_soc_codec_driver sta350_codec = {
        .probe =                sta350_probe,
        .remove =               sta350_remove,
-       .suspend =              sta350_suspend,
-       .resume =               sta350_resume,
        .set_bias_level =       sta350_set_bias_level,
+       .suspend_bias_off =     true,
        .controls =             sta350_snd_controls,
        .num_controls =         ARRAY_SIZE(sta350_snd_controls),
        .dapm_widgets =         sta350_dapm_widgets,
index 89c748d..b0f436d 100644 (file)
@@ -319,41 +319,10 @@ static struct snd_soc_dai_driver sta529_dai = {
        .ops    = &sta529_dai_ops,
 };
 
-static int sta529_probe(struct snd_soc_codec *codec)
-{
-       sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       return 0;
-}
-
-/* power down chip */
-static int sta529_remove(struct snd_soc_codec *codec)
-{
-       sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       return 0;
-}
-
-static int sta529_suspend(struct snd_soc_codec *codec)
-{
-       sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       return 0;
-}
-
-static int sta529_resume(struct snd_soc_codec *codec)
-{
-       sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       return 0;
-}
-
 static const struct snd_soc_codec_driver sta529_codec_driver = {
-       .probe = sta529_probe,
-       .remove = sta529_remove,
        .set_bias_level = sta529_set_bias_level,
-       .suspend = sta529_suspend,
-       .resume = sta529_resume,
+       .suspend_bias_off = true,
+
        .controls = sta529_snd_controls,
        .num_controls = ARRAY_SIZE(sta529_snd_controls),
 };
index f37a79e..dbff0c8 100644 (file)
@@ -258,12 +258,6 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
        return 0;
 }
 
-static int stac9766_codec_suspend(struct snd_soc_codec *codec)
-{
-       stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
 static int stac9766_codec_resume(struct snd_soc_codec *codec)
 {
        struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
@@ -273,7 +267,7 @@ static int stac9766_codec_resume(struct snd_soc_codec *codec)
        /* give the codec an AC97 warm reset to start the link */
 reset:
        if (reset > 5) {
-               printk(KERN_ERR "stac9766 failed to resume");
+               dev_err(codec->dev, "Failed to resume\n");
                return -EIO;
        }
        ac97->bus->ops->warm_reset(ac97);
@@ -283,7 +277,6 @@ reset:
                reset++;
                goto reset;
        }
-       stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
@@ -351,15 +344,10 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
        stac9766_reset(codec, 0);
        ret = stac9766_reset(codec, 1);
        if (ret < 0) {
-               printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
+               dev_err(codec->dev, "Failed to reset: AC97 link error\n");
                goto codec_err;
        }
 
-       stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
-                            ARRAY_SIZE(stac9766_snd_ac97_controls));
-
        return 0;
 
 codec_err:
@@ -376,12 +364,14 @@ static int stac9766_codec_remove(struct snd_soc_codec *codec)
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
+       .controls = stac9766_snd_ac97_controls,
+       .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls),
        .write = stac9766_ac97_write,
        .read = stac9766_ac97_read,
        .set_bias_level = stac9766_set_bias_level,
+       .suspend_bias_off = true,
        .probe = stac9766_codec_probe,
        .remove = stac9766_codec_remove,
-       .suspend = stac9766_codec_suspend,
        .resume = stac9766_codec_resume,
        .reg_cache_size = ARRAY_SIZE(stac9766_reg),
        .reg_word_size = sizeof(u16),