Part Number:AM3352
Tool/software: Linux
Hi.
I am trying to read MCASP using ALSA library.
I found read error message. "arecord: pcm_read:2032: read error: Input/output error"
please check my system.
- I2S format
AM3352 receive I2S data and clock from Bluetooth module.
I2S bit format is 32bit slot size, 24bit word and Left justified.
- Kernel device driver (4.4.32 version)
I can not understand to config slot size as 32bit. So I attached "mcasp->slot_width = 32;" in davinci-mcasp.c. Is this OK?
Also I am not sure MCASP slave configuration. Please check my clock configuration in davinci-evm.c
davinci-evm.c static int pcm5102a_capture_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; struct snd_soc_card *soc_card = rtd->card; unsigned int bclk_freq = evm_get_bclk(params); int ret = 0; unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) snd_soc_card_get_drvdata(soc_card))->sysclk; printk("[kdj6724] %s(%d) codec_dai:%s cup_dai:%s", __FUNCTION__, __LINE__, codec_dai->name, cpu_dai->name); /* set the codec system clock */ ret = snd_soc_dai_set_clkdiv(cpu_dai, 1, sysclk/bclk_freq); if (ret < 0) return ret; /* set the CPU system clock */ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT); if (ret < 0) return ret; //ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFFFFFF, 0xFFFFFF, 2, 32); //if (ret < 0) // return ret; return 0; } // kdj6724 static struct snd_soc_ops pcm5102a_capture_ops = { .startup = evm_startup, .shutdown = evm_shutdown, .hw_params = pcm5102a_capture_hw_params, //.hw_params = pcm5102a_playback_hw_params, }; static struct snd_soc_dai_link evm_dai_pcm5102a_in = { .name = "PCM5102A", //This is chosen arbitrarily. Can be anything. .stream_name = "Capture", //This comes from the PCM5102a driver create previously. .codec_dai_name = "pcm5102a-hifi", //This comes from the PCM5102a driver create previously .ops = &pcm5102a_capture_ops, //This is a structure that we will create later. //.ops = &pcm5102a_playback_ops, //This is a structure that we will create later. .dai_fmt = (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_IB_NF), };
davinci-mcasp.c static int davinci_config_channel_size(struct davinci_mcasp *mcasp, int sample_width) { u32 fmt; u32 tx_rotate = (sample_width / 4) & 0x7; u32 mask = (1ULL << sample_width) - 1; u32 slot_width = sample_width; /* * For captured data we should not rotate, inversion and masking is * enoguh to get the data to the right position: * Format data from bus after reverse (XRBUF) * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| */ u32 rx_rotate = 0; /* * Setting the tdm slot width either with set_clkdiv() or * set_tdm_slot() allows us to for example send 32 bits per * channel to the codec, while only 16 of them carry audio * payload. */ // kdj6724 add mcasp->slot_width = 32; if (mcasp->slot_width) { /* * When we have more bclk then it is needed for the * data, we need to use the rotation to move the * received samples to have correct alignment. */ slot_width = mcasp->slot_width; rx_rotate = (slot_width - sample_width) / 4; } /* mapping of the XSSZ bit-field as described in the datasheet */ fmt = (slot_width >> 1) - 1; if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { printk("[kdj6724] %s(%d)", __FUNCTION__, __LINE__); mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), RXSSZ(0x0F)); mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), TXSSZ(0x0F)); mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), TXROT(7)); mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), RXROT(7)); mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); } mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); mcasp_reg_dump(mcasp); return 0; }