sound: fix pcm186x driver playback/capture
authorRenjun Xu <renjun.xu@amlogic.com>
Fri, 16 Mar 2018 07:25:36 +0000 (15:25 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Sun, 18 Mar 2018 11:54:25 +0000 (03:54 -0800)
PD#161075: fix pcm186x driver playback/capture

Change-Id: I04d66ca1987efcaaff2ed897593748cf101db921
Signed-off-by: Renjun Xu <renjun.xu@amlogic.com>
Documentation/devicetree/bindings/sound/pcm186x.txt [new file with mode: 0644]
MAINTAINERS
sound/soc/codecs/amlogic/pcm186x.c

diff --git a/Documentation/devicetree/bindings/sound/pcm186x.txt b/Documentation/devicetree/bindings/sound/pcm186x.txt
new file mode 100644 (file)
index 0000000..b00ce3d
--- /dev/null
@@ -0,0 +1,83 @@
+Texas Instruments pcm186x DT bindings
+
+This driver supports the I2C.
+
+Required properties on I2C:
+ - compatible: "ti, pcm1864"
+ - reg: the I2C address
+
+
+Examples:
+
+&i2c_c {
+       status = "okay";
+       pinctrl-names="default";
+       pinctrl-0=<&c_i2c_master_pin1>;
+
+       pcm1864_4a: pcm1864_4a@4a {
+           compatible = "ti, pcm1864";
+               #sound-dai-cells = <0>;
+               slots_mask = <0x0f>;
+               reg = <0x4a>;
+               status = "okay";
+       };
+};
+
+Note:
+   Because pcm1864 need to use a fixed frequency,
+   So we also need to modify pcm config.
+Reference is as follows:
+
+diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c
+index d235a8d..a294e1b 100644
+--- a/sound/soc/amlogic/auge/tdm.c
++++ b/sound/soc/amlogic/auge/tdm.c
+@@ -451,11 +451,12 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
+ }
+
+ static int pcm_setting_init(struct pcm_setting *setting, unsigned int rate,
+-                      unsigned int channels)
++                      unsigned int channels, unsigned int fixbclk)
+ {
+       unsigned int ratio = 0;
+       setting->lrclk = rate;
+-      setting->bclk_lrclk_ratio = setting->slots * setting->slot_width;
++
++      setting->bclk_lrclk_ratio = setting->slots * setting->slot_width * fixbclk;
+       setting->bclk = setting->lrclk * setting->bclk_lrclk_ratio;
+
+       /* calculate mclk */
+@@ -534,8 +535,13 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream,
+       unsigned int rate = params_rate(params);
+       unsigned int channels = params_channels(params);
+       int ret;
+-
+-      ret = pcm_setting_init(setting, rate, channels);
++
++      // FOR PCM1864 TDM BCLK NEED 12.288MHz
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              ret = pcm_setting_init(setting, rate, channels, 1);
++      } else {
++              ret = pcm_setting_init(setting, rate, channels, 2);
++      }
+       if (ret)
+               return ret;
+
+diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c
+index a294e1b..a756035 100644
+--- a/sound/soc/amlogic/auge/tdm.c
++++ b/sound/soc/amlogic/auge/tdm.c
+@@ -455,8 +455,11 @@ static int pcm_setting_init(struct pcm_setting *setting, unsigned int rate,
+ {
+       unsigned int ratio = 0;
+       setting->lrclk = rate;
+-
+-      setting->bclk_lrclk_ratio = setting->slots * setting->slot_width * fixbclk;
++
++      if (fixbclk == 2)
++              setting->bclk_lrclk_ratio = setting->slots * 32 * fixbclk;
++      else
++              setting->bclk_lrclk_ratio = setting->slots * setting->slot_width * fixbclk;
+       setting->bclk = setting->lrclk * setting->bclk_lrclk_ratio;
+
+       /* calculate mclk */
index 6301330..2aa9add 100644 (file)
@@ -14389,3 +14389,7 @@ AMLOGIC G12A CVBS DRIVER
 M:     Nian Jing <nian.jing@amlogic.com>
 F:     drivers/amlogic/media/vout/cvbs/
 F:     arch/arm64/boot/dts/amlogic/g12a*.dts
+
+AMLOGIC FIX PCM186X DRIVER
+M:    Renjun Xu <renjun.xu@amlogic.com>
+F:    sound/soc/codecs/amlogic/pcm186x.c
index 2c436c6..98ecd1b 100644 (file)
@@ -302,7 +302,7 @@ static int pcm186x_dsp_coefficients_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static const DECLARE_TLV_DB_SCALE(pcm186x_pga_tlv, -1200, 4000, 50);
+static const DECLARE_TLV_DB_SCALE(pcm186x_pga_tlv, -1200, 50, 0);
 
 static const struct snd_kcontrol_new pcm1863_snd_controls[] = {
        SOC_DOUBLE_R_S_TLV("Analog Gain", PCM186X_PGA_VAL_CH1_L,
@@ -719,8 +719,8 @@ static int pcm186x_set_fmt(struct snd_soc_dai *dai, unsigned int format)
         * We only support the non-inverted clocks. Note that clock polarity
         * depends on the actual FORMAT.
         */
-       if ((format & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
-               return -EINVAL;
+       //if ((format & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
+       //      return -EINVAL;
 
        priv->dai_format = format;
 
@@ -739,10 +739,10 @@ static int pcm186x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
                "%s() tx_mask=0x%x rx_mask=0x%x slots=%d slot_width=%d\n",
                __func__, tx_mask, rx_mask, slots, slot_width);
 
-       if (!tx_mask) {
-               dev_err(codec->dev, "tdm tx mask must not be 0\n");
-               return -EINVAL;
-       }
+       //if (!tx_mask) {
+       //      dev_err(codec->dev, "tdm tx mask must not be 0\n");
+       //      return -EINVAL;
+       //}
        tx_mask = priv->slots_mask;
        first_slot = __ffs(tx_mask);
        last_slot = __fls(tx_mask);
@@ -762,7 +762,7 @@ static int pcm186x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
        }
 
        priv->tdm_offset = tdm_offset;
-       tdm_offset += 1;
+       //tdm_offset += 1;
        ret = regmap_write(priv->regmap, PCM186X_TDM_TX_OFFSET, tdm_offset);
        if (ret < 0)
                dev_err(codec->dev, "failed to write register: %d\n", ret);
@@ -1164,25 +1164,36 @@ int pcm186x_probe(struct device *dev, enum pcm186x_type type, int irq,
                goto err_disable_reg;
        }
 
+       ret = regmap_write(regmap, PCM186X_PGA_VAL_CH2_L, 0x0C);
+       if (ret != 0) {
+               dev_err(dev, "failed to write device: %d\n", ret);
+               goto err_disable_reg;
+       }
+       ret = regmap_write(regmap, PCM186X_PGA_VAL_CH2_R, 0x0C);
+       if (ret != 0) {
+               dev_err(dev, "failed to write device: %d\n", ret);
+               goto err_disable_reg;
+       }
+
        /*default ADC1 Input Channel Select*/
-       ret = regmap_write(regmap, PCM186X_ADC1_INPUT_SEL_L, 0x50);
+       ret = regmap_write(regmap, PCM186X_ADC1_INPUT_SEL_L, 0x02);
        if (ret != 0) {
                dev_err(dev, "failed to write device: %d\n", ret);
                goto err_disable_reg;
        }
-       ret = regmap_write(regmap, PCM186X_ADC1_INPUT_SEL_R, 0x50);
+       ret = regmap_write(regmap, PCM186X_ADC1_INPUT_SEL_R, 0x02);
        if (ret != 0) {
                dev_err(dev, "failed to write device: %d\n", ret);
                goto err_disable_reg;
        }
 
        /*default ADC2 Input Channel Select*/
-       ret = regmap_write(regmap, PCM186X_ADC2_INPUT_SEL_L, 0x40);
+       ret = regmap_write(regmap, PCM186X_ADC2_INPUT_SEL_L, 0x60);
        if (ret != 0) {
                dev_err(dev, "failed to write device: %d\n", ret);
                goto err_disable_reg;
        }
-       ret = regmap_write(regmap, PCM186X_ADC2_INPUT_SEL_R, 0x40);
+       ret = regmap_write(regmap, PCM186X_ADC2_INPUT_SEL_R, 0x60);
        if (ret != 0) {
                dev_err(dev, "failed to write device: %d\n", ret);
                goto err_disable_reg;