int ux500_ab8500_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int fmt, fmt_if1; int channels, ret = 0, slots, driver_mode; unsigned int codec_slot_width, cpu_slot_width; bool streamIsPlayback; pr_debug("%s: Enter\n", __func__); pr_debug("%s: substream->pcm->name = %s\n" "substream->pcm->id = %s.\n" "substream->name = %s.\n" "substream->number = %d.\n", __func__, substream->pcm->name, substream->pcm->id, substream->name, substream->number); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S32_LE: cpu_slot_width = 32; break; default: case SNDRV_PCM_FORMAT_S16_LE: cpu_slot_width = 16; break; } /* Setup codec depending on driver-mode */ driver_mode = (channels == 8) ? DRIVERMODE_CODEC_ONLY : DRIVERMODE_NORMAL; pr_debug("%s: Driver-mode: %s.\n", __func__, (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); ab8500_audio_set_bit_delay(codec_dai, 1); ux500_msp_dai_set_data_delay(cpu_dai, MSP_DELAY_1); if (driver_mode == DRIVERMODE_NORMAL) { codec_slot_width = cpu_slot_width; ab8500_audio_set_word_length(codec_dai, codec_slot_width); fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CONT; } else { codec_slot_width = 20; ab8500_audio_set_word_length(codec_dai, codec_slot_width); fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_GATED; } ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { pr_err("%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", __func__, ret); return ret; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { pr_err("%s: ERROR: snd_soc_dai_set_fmt for cpu_dai (ret = %d)!\n", __func__, ret); return ret; } /* Setup TDM-slots */ streamIsPlayback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (channels) { case 1: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_MONO : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_MONO; break; case 2: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_STEREO : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_STEREO; break; case 8: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_8CH : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_8CH; break; default: return -EINVAL; } pr_debug("%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, cpu_slot_width); if (ret) return ret; pr_debug("%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, codec_slot_width); if (ret) return ret; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pr_debug("%s: Setup IF1 for FM-radio.\n", __func__); fmt_if1 = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_I2S; ret = ab8500_audio_setup_if1(codec_dai->codec, fmt_if1, 16, 1); if (ret) return ret; } return 0; }
int ux500_gen_msp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int channels = params_channels(params); int err = 0; pr_debug("%s: Enter.\n", __func__); pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name); pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id); pr_debug("%s: substream->name = %s.\n", __func__, substream->name); pr_debug("%s: substream->number = %d.\n", __func__, substream->number); pr_debug("%s: channels = %d.\n", __func__, channels); pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id); if (channels != 1) { pr_err("%s: Only 1 channel.\n", __func__); err = -EINVAL; goto out_err; } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; default: pr_err("%s: Only S16_LE.\n", __func__); err = -EINVAL; goto out_err; } err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF); if (err) { pr_err("%s: snd_soc_dai_set_fmt(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_sysclk(cpu_dai, UX500_MSP_MASTER_CLOCK, 19200000, 0); if (err) { pr_err("%s: snd_soc_dai_set_sysclk(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_tdm_slot(cpu_dai, 0x1, 0x1, 1, 16); if (err) { pr_err("%s: cg29xx_set_tdm_slot(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } ux500_msp_dai_set_data_delay(cpu_dai, MSP_DELAY_1); out_err: return err; }