sound:i2s:wm8960:Support mono
authorXingyu Wu <xingyu.wu@starfivetech.com>
Mon, 29 Aug 2022 03:25:31 +0000 (11:25 +0800)
committerXingyu Wu <xingyu.wu@starfivetech.com>
Tue, 30 Aug 2022 12:49:06 +0000 (20:49 +0800)
16bit mono:support rate from 16k to 48k.
32bit mono:supoort rate from 22k to 48k.

Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
sound/soc/codecs/wm8960.c
sound/soc/dwc/dwc-i2s.c

index d32ffc8..4368873 100755 (executable)
@@ -940,15 +940,15 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
                        snd_soc_component_write(component, WM8960_BYPASS1, 0x00);
                        snd_soc_component_write(component, WM8960_BYPASS2, 0x00);
                        snd_soc_component_update_bits(component, WM8960_ADDCTL4, 0x73, 0);
-               } else {
+
                        if (params_channels(params) == 1)
-                               snd_soc_component_write(component, WM8960_LOUT1, 0x100);
-                       else {
-                               if (snd_soc_component_read(component, WM8960_LOUT1) & 0x7f)
-                                       snd_soc_component_update_bits(component, WM8960_LOUT1, 0x100, 0x100);
-                               else
-                                       snd_soc_component_write(component, WM8960_LOUT1, 0x170);
-                       }
+                               wm8960->lrclk /= 2;
+               } else {
+                       if (params_channels(params) == 1) {
+                               snd_soc_component_update_bits(component, WM8960_ADDCTL1, 0x10, 0x10);
+                               wm8960->lrclk /= 2;
+                       } else
+                               snd_soc_component_update_bits(component, WM8960_ADDCTL1, 0x10, 0);
                }
        }
 
index d21ffc6..c6aaeec 100755 (executable)
@@ -252,10 +252,11 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 
        dai_link->stop_dma_first = 1;
        config->chan_nr = params_channels(params);
+       config->sample_rate = params_rate(params);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               if (params_rate(params) == 8000) {
+               if (config->sample_rate == 8000) {
                        dev_err(dev->dev, "I2S: unsupported 8000 rate with S16_LE, Stereo.\n");
                        return -EINVAL;
                }
@@ -276,25 +277,18 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
                break;
 
        case SNDRV_PCM_FORMAT_S32_LE:
-               if (config->chan_nr == 1) {
-                       if (txrx == SNDRV_PCM_STREAM_PLAYBACK)
-                               dev->play_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-                       else
-                               dev->capture_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-
-                       config->data_width = 16;
-                       dev->ccr = 0x00;
-                       dev->xfer_resolution = 0x02;
-               } else if (config->chan_nr == 2) {
-                       if (txrx == SNDRV_PCM_STREAM_PLAYBACK)
-                               dev->play_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-                       else
-                               dev->capture_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-
-                       config->data_width = 32;
-                       dev->ccr = 0x10;
-                       dev->xfer_resolution = 0x05;
+               if ((config->sample_rate == 16000) && (config->chan_nr == 1)) {
+                       dev_err(dev->dev, "I2S: unsupported 16000 rate with S32_LE, Mono.\n");
+                       return -EINVAL;
                }
+               if (txrx == SNDRV_PCM_STREAM_PLAYBACK)
+                       dev->play_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               else
+                       dev->capture_dma_data.dt.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+               config->data_width = 32;
+               dev->ccr = 0x10;
+               dev->xfer_resolution = 0x05;
                break;
 
        default:
@@ -369,8 +363,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
 
        i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
 
-       config->sample_rate = params_rate(params);
-
        if (dev->capability & DW_I2S_MASTER) {
                if (dev->i2s_clk_cfg) {
                        ret = dev->i2s_clk_cfg(config);