From 92c6a5fcfb41f98e68681cdd1c2beb3d7ed281ad Mon Sep 17 00:00:00 2001 From: Dieter Luecking Date: Fri, 28 Sep 2018 15:05:43 +0200 Subject: [PATCH] dai: Add support for 16ch MI2S AFE MI2S interfaces now support up to 8 data lines (16 channels). Add DAI support for the same. Change-Id: I7c507c0161733094c1260731c7a046561fb63200 Signed-off-by: Dieter Luecking Signed-off-by: Mangesh Kunchamwar --- asoc/msm-dai-fe.c | 6 +- asoc/msm-dai-q6-v2.c | 183 ++++++++++++++++++++++++++++++++++++++++--- asoc/msm-dai-q6-v2.h | 5 ++ 3 files changed, 181 insertions(+), 13 deletions(-) diff --git a/asoc/msm-dai-fe.c b/asoc/msm-dai-fe.c index 3dc4509fc565..7654e561f00d 100644 --- a/asoc/msm-dai-fe.c +++ b/asoc/msm-dai-fe.c @@ -99,7 +99,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 16, .rate_min = 8000, .rate_max = 384000, }, @@ -113,7 +113,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 16, .rate_min = 8000, .rate_max = 48000, }, @@ -311,7 +311,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 16, .rate_min = 8000, .rate_max = 384000, }, diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index c24bb65f59ac..0c9d0b013eb7 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -2095,7 +2095,7 @@ static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params, return 0; } -static u8 num_of_bits_set(u8 sd_line_mask) +static u16 num_of_bits_set(u16 sd_line_mask) { u8 num_bits_set = 0; @@ -4644,11 +4644,68 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream, dai_data->channels = params_channels(params); switch (dai_data->channels) { + case 15: + case 16: + switch (mi2s_dai_config->pdata_mi2s_lines) { + case AFE_PORT_I2S_16CHS: + dai_data->port_config.i2s.channel_mode + = AFE_PORT_I2S_16CHS; + break; + default: + goto error_invalid_data; + }; + break; + case 13: + case 14: + switch (mi2s_dai_config->pdata_mi2s_lines) { + case AFE_PORT_I2S_14CHS: + case AFE_PORT_I2S_16CHS: + dai_data->port_config.i2s.channel_mode + = AFE_PORT_I2S_14CHS; + break; + default: + goto error_invalid_data; + }; + break; + case 11: + case 12: + switch (mi2s_dai_config->pdata_mi2s_lines) { + case AFE_PORT_I2S_12CHS: + case AFE_PORT_I2S_14CHS: + case AFE_PORT_I2S_16CHS: + dai_data->port_config.i2s.channel_mode + = AFE_PORT_I2S_12CHS; + break; + default: + goto error_invalid_data; + }; + break; + case 9: + case 10: + switch (mi2s_dai_config->pdata_mi2s_lines) { + case AFE_PORT_I2S_10CHS: + case AFE_PORT_I2S_12CHS: + case AFE_PORT_I2S_14CHS: + case AFE_PORT_I2S_16CHS: + dai_data->port_config.i2s.channel_mode + = AFE_PORT_I2S_10CHS; + break; + default: + goto error_invalid_data; + }; + break; case 8: case 7: if (mi2s_dai_config->pdata_mi2s_lines < AFE_PORT_I2S_8CHS) goto error_invalid_data; - dai_data->port_config.i2s.channel_mode = AFE_PORT_I2S_8CHS; + else + if (mi2s_dai_config->pdata_mi2s_lines + == AFE_PORT_I2S_8CHS_2) + dai_data->port_config.i2s.channel_mode = + AFE_PORT_I2S_8CHS_2; + else + dai_data->port_config.i2s.channel_mode = + AFE_PORT_I2S_8CHS; break; case 6: case 5: @@ -4658,14 +4715,33 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream, break; case 4: case 3: - if (mi2s_dai_config->pdata_mi2s_lines < AFE_PORT_I2S_QUAD01) + switch (mi2s_dai_config->pdata_mi2s_lines) { + case AFE_PORT_I2S_SD0: + case AFE_PORT_I2S_SD1: + case AFE_PORT_I2S_SD2: + case AFE_PORT_I2S_SD3: + case AFE_PORT_I2S_SD4: + case AFE_PORT_I2S_SD5: + case AFE_PORT_I2S_SD6: + case AFE_PORT_I2S_SD7: goto error_invalid_data; - if (mi2s_dai_config->pdata_mi2s_lines == AFE_PORT_I2S_QUAD23) + break; + case AFE_PORT_I2S_QUAD01: + case AFE_PORT_I2S_QUAD23: + case AFE_PORT_I2S_QUAD45: + case AFE_PORT_I2S_QUAD67: dai_data->port_config.i2s.channel_mode = mi2s_dai_config->pdata_mi2s_lines; - else + break; + case AFE_PORT_I2S_8CHS_2: + dai_data->port_config.i2s.channel_mode = + AFE_PORT_I2S_QUAD45; + break; + default: dai_data->port_config.i2s.channel_mode = AFE_PORT_I2S_QUAD01; + break; + }; break; case 2: case 1: @@ -4676,12 +4752,20 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream, case AFE_PORT_I2S_SD1: case AFE_PORT_I2S_SD2: case AFE_PORT_I2S_SD3: + case AFE_PORT_I2S_SD4: + case AFE_PORT_I2S_SD5: + case AFE_PORT_I2S_SD6: + case AFE_PORT_I2S_SD7: dai_data->port_config.i2s.channel_mode = mi2s_dai_config->pdata_mi2s_lines; break; case AFE_PORT_I2S_QUAD01: case AFE_PORT_I2S_6CHS: case AFE_PORT_I2S_8CHS: + case AFE_PORT_I2S_10CHS: + case AFE_PORT_I2S_12CHS: + case AFE_PORT_I2S_14CHS: + case AFE_PORT_I2S_16CHS: if (dai_data->vi_feed_mono == SPKR_1) dai_data->port_config.i2s.channel_mode = AFE_PORT_I2S_SD0; @@ -4693,6 +4777,14 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream, dai_data->port_config.i2s.channel_mode = AFE_PORT_I2S_SD2; break; + case AFE_PORT_I2S_QUAD45: + dai_data->port_config.i2s.channel_mode = + AFE_PORT_I2S_SD4; + break; + case AFE_PORT_I2S_QUAD67: + dai_data->port_config.i2s.channel_mode = + AFE_PORT_I2S_SD6; + break; } if (dai_data->channels == 2) dai_data->port_config.i2s.mono_stereo = @@ -4864,15 +4956,17 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Primary MI2S Playback", .aif_name = "PRI_MI2S_RX", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_352800 | + SNDRV_PCM_RATE_384000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, }, .capture = { .stream_name = "Primary MI2S Capture", @@ -5257,6 +5351,18 @@ static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr, case MSM_MI2S_SD3: *config_ptr = AFE_PORT_I2S_SD3; break; + case MSM_MI2S_SD4: + *config_ptr = AFE_PORT_I2S_SD4; + break; + case MSM_MI2S_SD5: + *config_ptr = AFE_PORT_I2S_SD5; + break; + case MSM_MI2S_SD6: + *config_ptr = AFE_PORT_I2S_SD6; + break; + case MSM_MI2S_SD7: + *config_ptr = AFE_PORT_I2S_SD7; + break; default: pr_err("%s: invalid SD lines %d\n", __func__, sd_lines); @@ -5271,6 +5377,12 @@ static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr, case MSM_MI2S_SD2 | MSM_MI2S_SD3: *config_ptr = AFE_PORT_I2S_QUAD23; break; + case MSM_MI2S_SD4 | MSM_MI2S_SD5: + *config_ptr = AFE_PORT_I2S_QUAD45; + break; + case MSM_MI2S_SD6 | MSM_MI2S_SD7: + *config_ptr = AFE_PORT_I2S_QUAD67; + break; default: pr_err("%s: invalid SD lines %d\n", __func__, sd_lines); @@ -5293,6 +5405,57 @@ static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr, case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3: *config_ptr = AFE_PORT_I2S_8CHS; break; + case MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6 | MSM_MI2S_SD7: + *config_ptr = AFE_PORT_I2S_8CHS_2; + break; + default: + pr_err("%s: invalid SD lines %d\n", + __func__, sd_lines); + goto error_invalid_data; + } + break; + case 5: + switch (sd_lines) { + case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 + | MSM_MI2S_SD3 | MSM_MI2S_SD4: + *config_ptr = AFE_PORT_I2S_10CHS; + break; + default: + pr_err("%s: invalid SD lines %d\n", + __func__, sd_lines); + goto error_invalid_data; + } + break; + case 6: + switch (sd_lines) { + case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 + | MSM_MI2S_SD3 | MSM_MI2S_SD4 | MSM_MI2S_SD5: + *config_ptr = AFE_PORT_I2S_12CHS; + break; + default: + pr_err("%s: invalid SD lines %d\n", + __func__, sd_lines); + goto error_invalid_data; + } + break; + case 7: + switch (sd_lines) { + case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3 + | MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6: + *config_ptr = AFE_PORT_I2S_14CHS; + break; + default: + pr_err("%s: invalid SD lines %d\n", + __func__, sd_lines); + goto error_invalid_data; + } + break; + case 8: + switch (sd_lines) { + case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3 + | MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6 | MSM_MI2S_SD7: + *config_ptr = AFE_PORT_I2S_16CHS; + break; default: pr_err("%s: invalid SD lines %d\n", __func__, sd_lines); diff --git a/asoc/msm-dai-q6-v2.h b/asoc/msm-dai-q6-v2.h index b3f457e9e544..2327cfd72eca 100644 --- a/asoc/msm-dai-q6-v2.h +++ b/asoc/msm-dai-q6-v2.h @@ -18,6 +18,11 @@ #define MSM_MI2S_SD1 (1 << 1) #define MSM_MI2S_SD2 (1 << 2) #define MSM_MI2S_SD3 (1 << 3) +#define MSM_MI2S_SD4 (1 << 4) +#define MSM_MI2S_SD5 (1 << 5) +#define MSM_MI2S_SD6 (1 << 6) +#define MSM_MI2S_SD7 (1 << 7) + #define MSM_MI2S_CAP_RX 0 #define MSM_MI2S_CAP_TX 1