]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge remote-tracking branches 'asoc/topic/rt5641', 'asoc/topic/rt5677' and 'asoc...
authorMark Brown <broonie@kernel.org>
Sun, 12 Apr 2015 18:49:17 +0000 (19:49 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 12 Apr 2015 18:49:17 +0000 (19:49 +0100)
arch/arm/mach-shmobile/board-armadillo800eva.c
include/sound/simple_card.h
sound/soc/codecs/rt5631.c
sound/soc/codecs/rt5677.c
sound/soc/codecs/rt5677.h
sound/soc/generic/simple-card.c

index 6d949f1c850bda8bdf25b0ec3cc56e3658e514be..36aaeb12e1a558af99c7aa383adfdf2d5bcaa665 100644 (file)
@@ -1015,7 +1015,6 @@ static struct asoc_simple_card_info fsi_wm8978_info = {
        .platform       = "sh_fsi2",
        .daifmt         = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
        .cpu_dai = {
-               .fmt    = SND_SOC_DAIFMT_IB_NF,
                .name   = "fsia-dai",
        },
        .codec_dai = {
@@ -1040,9 +1039,9 @@ static struct asoc_simple_card_info fsi2_hdmi_info = {
        .card           = "FSI2B-HDMI",
        .codec          = "sh-mobile-hdmi",
        .platform       = "sh_fsi2",
+       .daifmt         = SND_SOC_DAIFMT_CBS_CFS,
        .cpu_dai = {
                .name   = "fsib-dai",
-               .fmt    = SND_SOC_DAIFMT_CBS_CFS,
        },
        .codec_dai = {
                .name = "sh_mobile_hdmi-hifi",
index 1255ddb1d3e2c22d05b188a82bc589f62c307b9b..b9b4f289fe6b32130848cf4062ac94e4864f5bfb 100644 (file)
@@ -16,7 +16,6 @@
 
 struct asoc_simple_dai {
        const char *name;
-       unsigned int fmt;
        unsigned int sysclk;
        int slots;
        int slot_width;
index c61852742ee30889c3fa482135acd1960324602f..2c10d77727af5d0c848a64fae5202a183dcd3f69 100644 (file)
@@ -1675,7 +1675,7 @@ static const struct i2c_device_id rt5631_i2c_id[] = {
 MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
 
 #ifdef CONFIG_OF
-static struct of_device_id rt5631_i2c_dt_ids[] = {
+static const struct of_device_id rt5631_i2c_dt_ids[] = {
        { .compatible = "realtek,rt5631"},
        { .compatible = "realtek,alc5631"},
        { }
index c2a6e4091357704b5b0cd714304d8bf862462f5d..af182586712d42f9bbac6d5b03338e3e5219cf23 100644 (file)
@@ -1034,6 +1034,169 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
        return 0;
 }
 
+/**
+ * rt5677_sel_asrc_clk_src - select ASRC clock source for a set of filters
+ * @codec: SoC audio codec device.
+ * @filter_mask: mask of filters.
+ * @clk_src: clock source
+ *
+ * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5677 can
+ * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
+ * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
+ * ASRC function will track i2s clock and generate a corresponding system clock
+ * for codec. This function provides an API to select the clock source for a
+ * set of filters specified by the mask. And the codec driver will turn on ASRC
+ * for these filters if ASRC is selected as their clock source.
+ */
+int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
+               unsigned int filter_mask, unsigned int clk_src)
+{
+       struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+       unsigned int asrc3_mask = 0, asrc3_value = 0;
+       unsigned int asrc4_mask = 0, asrc4_value = 0;
+       unsigned int asrc5_mask = 0, asrc5_value = 0;
+       unsigned int asrc6_mask = 0, asrc6_value = 0;
+       unsigned int asrc7_mask = 0, asrc7_value = 0;
+
+       switch (clk_src) {
+       case RT5677_CLK_SEL_SYS:
+       case RT5677_CLK_SEL_I2S1_ASRC:
+       case RT5677_CLK_SEL_I2S2_ASRC:
+       case RT5677_CLK_SEL_I2S3_ASRC:
+       case RT5677_CLK_SEL_I2S4_ASRC:
+       case RT5677_CLK_SEL_I2S5_ASRC:
+       case RT5677_CLK_SEL_I2S6_ASRC:
+       case RT5677_CLK_SEL_SYS2:
+       case RT5677_CLK_SEL_SYS3:
+       case RT5677_CLK_SEL_SYS4:
+       case RT5677_CLK_SEL_SYS5:
+       case RT5677_CLK_SEL_SYS6:
+       case RT5677_CLK_SEL_SYS7:
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* ASRC 3 */
+       if (filter_mask & RT5677_DA_STEREO_FILTER) {
+               asrc3_mask |= RT5677_DA_STO_CLK_SEL_MASK;
+               asrc3_value = (asrc3_value & ~RT5677_DA_STO_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_STO_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DA_MONO2_L_FILTER) {
+               asrc3_mask |= RT5677_DA_MONO2L_CLK_SEL_MASK;
+               asrc3_value = (asrc3_value & ~RT5677_DA_MONO2L_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO2L_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DA_MONO2_R_FILTER) {
+               asrc3_mask |= RT5677_DA_MONO2R_CLK_SEL_MASK;
+               asrc3_value = (asrc3_value & ~RT5677_DA_MONO2R_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO2R_CLK_SEL_SFT);
+       }
+
+       if (asrc3_mask)
+               regmap_update_bits(rt5677->regmap, RT5677_ASRC_3, asrc3_mask,
+                       asrc3_value);
+
+       /* ASRC 4 */
+       if (filter_mask & RT5677_DA_MONO3_L_FILTER) {
+               asrc4_mask |= RT5677_DA_MONO3L_CLK_SEL_MASK;
+               asrc4_value = (asrc4_value & ~RT5677_DA_MONO3L_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO3L_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DA_MONO3_R_FILTER) {
+               asrc4_mask |= RT5677_DA_MONO3R_CLK_SEL_MASK;
+               asrc4_value = (asrc4_value & ~RT5677_DA_MONO3R_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO3R_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DA_MONO4_L_FILTER) {
+               asrc4_mask |= RT5677_DA_MONO4L_CLK_SEL_MASK;
+               asrc4_value = (asrc4_value & ~RT5677_DA_MONO4L_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO4L_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DA_MONO4_R_FILTER) {
+               asrc4_mask |= RT5677_DA_MONO4R_CLK_SEL_MASK;
+               asrc4_value = (asrc4_value & ~RT5677_DA_MONO4R_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DA_MONO4R_CLK_SEL_SFT);
+       }
+
+       if (asrc4_mask)
+               regmap_update_bits(rt5677->regmap, RT5677_ASRC_4, asrc4_mask,
+                       asrc4_value);
+
+       /* ASRC 5 */
+       if (filter_mask & RT5677_AD_STEREO1_FILTER) {
+               asrc5_mask |= RT5677_AD_STO1_CLK_SEL_MASK;
+               asrc5_value = (asrc5_value & ~RT5677_AD_STO1_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_STO1_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_AD_STEREO2_FILTER) {
+               asrc5_mask |= RT5677_AD_STO2_CLK_SEL_MASK;
+               asrc5_value = (asrc5_value & ~RT5677_AD_STO2_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_STO2_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_AD_STEREO3_FILTER) {
+               asrc5_mask |= RT5677_AD_STO3_CLK_SEL_MASK;
+               asrc5_value = (asrc5_value & ~RT5677_AD_STO3_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_STO3_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_AD_STEREO4_FILTER) {
+               asrc5_mask |= RT5677_AD_STO4_CLK_SEL_MASK;
+               asrc5_value = (asrc5_value & ~RT5677_AD_STO4_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_STO4_CLK_SEL_SFT);
+       }
+
+       if (asrc5_mask)
+               regmap_update_bits(rt5677->regmap, RT5677_ASRC_5, asrc5_mask,
+                       asrc5_value);
+
+       /* ASRC 6 */
+       if (filter_mask & RT5677_AD_MONO_L_FILTER) {
+               asrc6_mask |= RT5677_AD_MONOL_CLK_SEL_MASK;
+               asrc6_value = (asrc6_value & ~RT5677_AD_MONOL_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_MONOL_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_AD_MONO_R_FILTER) {
+               asrc6_mask |= RT5677_AD_MONOR_CLK_SEL_MASK;
+               asrc6_value = (asrc6_value & ~RT5677_AD_MONOR_CLK_SEL_MASK)
+                       | (clk_src << RT5677_AD_MONOR_CLK_SEL_SFT);
+       }
+
+       if (asrc6_mask)
+               regmap_update_bits(rt5677->regmap, RT5677_ASRC_6, asrc6_mask,
+                       asrc6_value);
+
+       /* ASRC 7 */
+       if (filter_mask & RT5677_DSP_OB_0_3_FILTER) {
+               asrc7_mask |= RT5677_DSP_OB_0_3_CLK_SEL_MASK;
+               asrc7_value = (asrc7_value & ~RT5677_DSP_OB_0_3_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DSP_OB_0_3_CLK_SEL_SFT);
+       }
+
+       if (filter_mask & RT5677_DSP_OB_4_7_FILTER) {
+               asrc7_mask |= RT5677_DSP_OB_4_7_CLK_SEL_MASK;
+               asrc7_value = (asrc7_value & ~RT5677_DSP_OB_4_7_CLK_SEL_MASK)
+                       | (clk_src << RT5677_DSP_OB_4_7_CLK_SEL_SFT);
+       }
+
+       if (asrc7_mask)
+               regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask,
+                       asrc7_value);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src);
+
 /* Digital Mixer */
 static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
        SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
index 07df96b43f5962fb67dca3bcd3bd014c268d6029..9dceb41d18ea910db762dd69b7aa4506632ae1a5 100644 (file)
 #define RT5677_DSP_CLK_SRC_PLL2                        (0x0 << 7)
 #define RT5677_DSP_CLK_SRC_BYPASS              (0x1 << 7)
 
+/* ASRC Control 3 (0x85) */
+#define RT5677_DA_STO_CLK_SEL_MASK             (0xf << 12)
+#define RT5677_DA_STO_CLK_SEL_SFT              12
+#define RT5677_DA_MONO2L_CLK_SEL_MASK          (0xf << 4)
+#define RT5677_DA_MONO2L_CLK_SEL_SFT           4
+#define RT5677_DA_MONO2R_CLK_SEL_MASK          (0xf << 0)
+#define RT5677_DA_MONO2R_CLK_SEL_SFT           0
+
+/* ASRC Control 4 (0x86) */
+#define RT5677_DA_MONO3L_CLK_SEL_MASK          (0xf << 12)
+#define RT5677_DA_MONO3L_CLK_SEL_SFT           12
+#define RT5677_DA_MONO3R_CLK_SEL_MASK          (0xf << 8)
+#define RT5677_DA_MONO3R_CLK_SEL_SFT           8
+#define RT5677_DA_MONO4L_CLK_SEL_MASK          (0xf << 4)
+#define RT5677_DA_MONO4L_CLK_SEL_SFT           4
+#define RT5677_DA_MONO4R_CLK_SEL_MASK          (0xf << 0)
+#define RT5677_DA_MONO4R_CLK_SEL_SFT           0
+
+/* ASRC Control 5 (0x87) */
+#define RT5677_AD_STO1_CLK_SEL_MASK            (0xf << 12)
+#define RT5677_AD_STO1_CLK_SEL_SFT             12
+#define RT5677_AD_STO2_CLK_SEL_MASK            (0xf << 8)
+#define RT5677_AD_STO2_CLK_SEL_SFT             8
+#define RT5677_AD_STO3_CLK_SEL_MASK            (0xf << 4)
+#define RT5677_AD_STO3_CLK_SEL_SFT             4
+#define RT5677_AD_STO4_CLK_SEL_MASK            (0xf << 0)
+#define RT5677_AD_STO4_CLK_SEL_SFT             0
+
+/* ASRC Control 6 (0x88) */
+#define RT5677_AD_MONOL_CLK_SEL_MASK           (0xf << 12)
+#define RT5677_AD_MONOL_CLK_SEL_SFT            12
+#define RT5677_AD_MONOR_CLK_SEL_MASK           (0xf << 8)
+#define RT5677_AD_MONOR_CLK_SEL_SFT            8
+
+/* ASRC Control 7 (0x89) */
+#define RT5677_DSP_OB_0_3_CLK_SEL_MASK         (0xf << 12)
+#define RT5677_DSP_OB_0_3_CLK_SEL_SFT          12
+#define RT5677_DSP_OB_4_7_CLK_SEL_MASK         (0xf << 8)
+#define RT5677_DSP_OB_4_7_CLK_SEL_SFT          8
+
 /* VAD Function Control 4 (0x9f) */
 #define RT5677_VAD_SRC_MASK                    (0x7 << 8)
 #define RT5677_VAD_SRC_SFT                     8
@@ -1670,6 +1710,42 @@ enum rt5677_type {
        RT5676,
 };
 
+/* ASRC clock source selection */
+enum {
+       RT5677_CLK_SEL_SYS,
+       RT5677_CLK_SEL_I2S1_ASRC,
+       RT5677_CLK_SEL_I2S2_ASRC,
+       RT5677_CLK_SEL_I2S3_ASRC,
+       RT5677_CLK_SEL_I2S4_ASRC,
+       RT5677_CLK_SEL_I2S5_ASRC,
+       RT5677_CLK_SEL_I2S6_ASRC,
+       RT5677_CLK_SEL_SYS2,
+       RT5677_CLK_SEL_SYS3,
+       RT5677_CLK_SEL_SYS4,
+       RT5677_CLK_SEL_SYS5,
+       RT5677_CLK_SEL_SYS6,
+       RT5677_CLK_SEL_SYS7,
+};
+
+/* filter mask */
+enum {
+       RT5677_DA_STEREO_FILTER = 0x1,
+       RT5677_DA_MONO2_L_FILTER = (0x1 << 1),
+       RT5677_DA_MONO2_R_FILTER = (0x1 << 2),
+       RT5677_DA_MONO3_L_FILTER = (0x1 << 3),
+       RT5677_DA_MONO3_R_FILTER = (0x1 << 4),
+       RT5677_DA_MONO4_L_FILTER = (0x1 << 5),
+       RT5677_DA_MONO4_R_FILTER = (0x1 << 6),
+       RT5677_AD_STEREO1_FILTER = (0x1 << 7),
+       RT5677_AD_STEREO2_FILTER = (0x1 << 8),
+       RT5677_AD_STEREO3_FILTER = (0x1 << 9),
+       RT5677_AD_STEREO4_FILTER = (0x1 << 10),
+       RT5677_AD_MONO_L_FILTER = (0x1 << 11),
+       RT5677_AD_MONO_R_FILTER = (0x1 << 12),
+       RT5677_DSP_OB_0_3_FILTER = (0x1 << 13),
+       RT5677_DSP_OB_4_7_FILTER = (0x1 << 14),
+};
+
 struct rt5677_priv {
        struct snd_soc_codec *codec;
        struct rt5677_platform_data pdata;
@@ -1696,4 +1772,7 @@ struct rt5677_priv {
        bool is_vref_slow;
 };
 
+int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
+               unsigned int filter_mask, unsigned int clk_src);
+
 #endif /* __RT5677_H__ */
index c49a408fc7a6a267e4a9d106d1019547b558c3ed..33feee9ca8c3a336f9f04ed0940f515dba4ddf64 100644 (file)
@@ -125,14 +125,6 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
 {
        int ret;
 
-       if (set->fmt) {
-               ret = snd_soc_dai_set_fmt(dai, set->fmt);
-               if (ret && ret != -ENOTSUPP) {
-                       dev_err(dai->dev, "simple-card: set_fmt error\n");
-                       goto err;
-               }
-       }
-
        if (set->sysclk) {
                ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
                if (ret && ret != -ENOTSUPP) {
@@ -269,12 +261,10 @@ static int asoc_simple_card_parse_daifmt(struct device_node *node,
                                         struct device_node *codec,
                                         char *prefix, int idx)
 {
+       struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
        struct device *dev = simple_priv_to_dev(priv);
        struct device_node *bitclkmaster = NULL;
        struct device_node *framemaster = NULL;
-       struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
-       struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
-       struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
        unsigned int daifmt;
 
        daifmt = snd_soc_of_parse_daifmt(node, prefix,
@@ -289,8 +279,7 @@ static int asoc_simple_card_parse_daifmt(struct device_node *node,
                 */
                dev_dbg(dev, "Revert to legacy daifmt parsing\n");
 
-               cpu_dai->fmt = codec_dai->fmt =
-                       snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
+               daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
                        (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
        } else {
                if (codec == bitclkmaster)
@@ -299,11 +288,10 @@ static int asoc_simple_card_parse_daifmt(struct device_node *node,
                else
                        daifmt |= (codec == framemaster) ?
                                SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
-
-               cpu_dai->fmt    = daifmt;
-               codec_dai->fmt  = daifmt;
        }
 
+       dai_link->dai_fmt = daifmt;
+
        of_node_put(bitclkmaster);
        of_node_put(framemaster);
 
@@ -384,13 +372,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
        dai_link->init = asoc_simple_card_dai_init;
 
        dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
-       dev_dbg(dev, "\tcpu : %s / %04x / %d\n",
+       dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
+       dev_dbg(dev, "\tcpu : %s / %d\n",
                dai_link->cpu_dai_name,
-               dai_props->cpu_dai.fmt,
                dai_props->cpu_dai.sysclk);
-       dev_dbg(dev, "\tcodec : %s / %04x / %d\n",
+       dev_dbg(dev, "\tcodec : %s / %d\n",
                dai_link->codec_dai_name,
-               dai_props->codec_dai.fmt,
                dai_props->codec_dai.sysclk);
 
        /*
@@ -577,14 +564,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
                dai_link->codec_name    = cinfo->codec;
                dai_link->cpu_dai_name  = cinfo->cpu_dai.name;
                dai_link->codec_dai_name = cinfo->codec_dai.name;
+               dai_link->dai_fmt       = cinfo->daifmt;
                dai_link->init          = asoc_simple_card_dai_init;
                memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
                                        sizeof(priv->dai_props->cpu_dai));
                memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
                                        sizeof(priv->dai_props->codec_dai));
 
-               priv->dai_props->cpu_dai.fmt    |= cinfo->daifmt;
-               priv->dai_props->codec_dai.fmt  |= cinfo->daifmt;
        }
 
        snd_soc_card_set_drvdata(&priv->snd_card, priv);