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 am not sure the tdm_slot function is correct -> (snd_soc_dai_set_tdm_slot(cpu_dai, 0xFFFFFF, 0xFFFFFF, 24, 32);
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, 24, 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.
*/
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;
}
- Error log
root@am335x-evm:~# arecord -f S24_LE -r44100 -c2 -D hw:0 -F0 --period-size=1024 -B0 --buffer-size=4096 test.wav [ 1593.396642] [kdj6724] soc_pcm_open(459) [ 1593.400984] [kdj6724] soc_pcm_open(472) [ 1593.404870] [kdj6724] davinci_mcasp_startup(1329) [ 1593.415125] [kdj6724] soc_pcm_open(474) [ 1593.425865] [kdj6724] soc_pcm_open(483) [ 1593.433381] [kdj6724] soc_pcm_open(485) [ 1593.443950] [kdj6724] soc_pcm_open(515) [ 1593.453006] [kdj6724] evm_startup(40) [ 1593.456750] [kdj6724] soc_pcm_open(517) [ 1593.468324] [kdj6724] soc_pcm_open(529) [ 1593.472254] [kdj6724] snd_soc_dai_stream_valid(46) [ 1593.489922] [kdj6724] soc_pcm_open(532) [ 1593.494655] [kdj6724] snd_pcm_mmap(3510)Recording WAVE 'test.wav' : Signed 24 bit Little Endian, Rate 44100 Hz, [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) Stereo [ 1593.533111] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.545722] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.558987] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.564374] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.584878] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.595159] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.607747] [kdj6724] snd_pcm_lib_ioctl_fifo_size(1819) [ 1593.613125] [kdj6724] pcm5102a_capture_hw_params(105) codec_dai:pcm5102a-hifi cup_dai:48038000.mcasp[kdj6724] snd_soc_dai_stream_valid(46) [ 1593.643995] [kdj6724] davinci_mcasp_hw_params(1131) cpu_dai->name:48038000.mcasp [ 1593.664293] [kdj6724] davinci_mcasp_set_dai_fmt(436) val:3 [ 1593.678043] [kdj6724] davinci_mcasp_hw_params(1156) mcasp->op_mode:0 [ 1593.684574] [kdj6724] mcasp_i2s_hw_param(933) stream:1 channels:2 total_slots:2 [ 1593.707050] [kdj6724] mcasp_i2s_hw_param(964) active_slots:2 active_serializers:1 [ 1593.714878] [kdj6724] mcasp_i2s_hw_param(980) 0x00000003 [ 1593.735435] [kdj6724] davinci_config_channel_size(792) [ 1593.927522] [kdj6724] snd_pcm_capture_ioctl1(2919) cmd:-2146680495 [ 1593.933892] [kdj6724] cmd:1 [ 1593.936704] [kdj6724] davinci_mcasp_start(271) stream:1 [ 1594.057939] [kdj6724] TXTDM_REG : 0x00000000 arecord: pcm_read:2032: read error: Input/output error[ 1604.208364] [kdj6724] cmd:0 [ 1604.215127] [kdj6724] mcasp_stop_rx(283) [kdj6724] davinci_mcasp_shutdown(1419) [ 1604.359540] [kdj6724] TXTDM_REG : 0x00000000 [ 1604.364288] [kdj6724] evm_shutdown(54) root@am335x-evm:~#




