static int uni_player_prepare_tdm(struct uniperif *player, struct snd_pcm_runtime *runtime) { int tdm_frame_size; /* unip tdm frame size in bytes */ int user_frame_size; /* user tdm frame size in bytes */ /* default unip TDM_WORD_POS_X_Y */ unsigned int word_pos[4] = { 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; int freq, ret; tdm_frame_size = sti_uniperiph_get_unip_tdm_frame_size(player); user_frame_size = sti_uniperiph_get_user_frame_size(runtime); /* fix 16/0 format */ SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player); /* number of words inserted on the TDM line */ SET_UNIPERIF_I2S_FMT_NUM_CH(player, user_frame_size / 4 / 2); SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player); /* Enable the tdm functionality */ SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(player); /* number of 8 bits timeslots avail in unip tdm frame */ SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(player, tdm_frame_size); /* set the timeslot allocation for words in FIFO */ sti_uniperiph_get_tdm_word_pos(player, word_pos); SET_UNIPERIF_TDM_WORD_POS(player, 1_2, word_pos[WORD_1_2]); SET_UNIPERIF_TDM_WORD_POS(player, 3_4, word_pos[WORD_3_4]); SET_UNIPERIF_TDM_WORD_POS(player, 5_6, word_pos[WORD_5_6]); SET_UNIPERIF_TDM_WORD_POS(player, 7_8, word_pos[WORD_7_8]); /* set unip clk rate (not done vai set_sysclk ops) */ freq = runtime->rate * tdm_frame_size * 8; mutex_lock(&player->ctrl_lock); ret = uni_player_clk_set_rate(player, freq); if (!ret) player->mclk = freq; mutex_unlock(&player->ctrl_lock); return 0; }
static int uni_reader_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *reader = priv->dai_data.uni; struct snd_pcm_runtime *runtime = substream->runtime; int transfer_size, trigger_limit; int slot_width; int count = 10; /* The reader should be stopped */ if (reader->state != UNIPERIF_STATE_STOPPED) { dev_err(reader->dev, "%s: invalid reader state %d", __func__, reader->state); return -EINVAL; } /* Calculate transfer size (in fifo cells and bytes) for frame count */ transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; /* Calculate number of empty cells available before asserting DREQ */ if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; else /* * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 * FDMA_TRIGGER_LIMIT also controls when the state switches * from OFF or STANDBY to AUDIO DATA. */ trigger_limit = transfer_size; /* Trigger limit must be an even number */ if ((!trigger_limit % 2) || (trigger_limit != 1 && transfer_size % 2) || (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { dev_err(reader->dev, "invalid trigger limit %d", trigger_limit); return -EINVAL; } SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: case SND_SOC_DAIFMT_NB_IF: SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); break; default: SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); } /* Force slot width to 32 in I2S mode */ if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) { slot_width = 32; } else { switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: slot_width = 16; break; default: slot_width = 32; break; } } /* Number of bits per subframe (i.e one channel sample) on input. */ switch (slot_width) { case 32: SET_UNIPERIF_I2S_FMT_NBIT_32(reader); SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); break; case 16: SET_UNIPERIF_I2S_FMT_NBIT_16(reader); SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(reader); break; default: dev_err(reader->dev, "subframe format not supported"); return -EINVAL; } /* Configure data memory format */ switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: /* One data word contains two samples */ SET_UNIPERIF_CONFIG_MEM_FMT_16_16(reader); break; case SNDRV_PCM_FORMAT_S32_LE: /* * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits * on the MSB then zeros (if less than 32 bytes)"... */ SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); break; default: dev_err(reader->dev, "format not supported"); return -EINVAL; } switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(reader); break; case SND_SOC_DAIFMT_LEFT_J: SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); break; case SND_SOC_DAIFMT_RIGHT_J: SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(reader); SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); break; default: dev_err(reader->dev, "format not supported"); return -EINVAL; } SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); /* Data clocking (changing) on the rising edge */ SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); /* Number of channels must be even */ if ((runtime->channels % 2) || (runtime->channels < 2) || (runtime->channels > 10)) { dev_err(reader->dev, "%s: invalid nb of channels", __func__); return -EINVAL; } SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); /* Clear any pending interrupts */ SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(reader, 0); /* Set the interrupt mask */ SET_UNIPERIF_ITM_BSET_DMA_ERROR(reader); SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader); SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader); /* Enable underflow recovery interrupts */ if (reader->info->underflow_enabled) { SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader); SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader); } /* Reset uniperipheral reader */ SET_UNIPERIF_SOFT_RST_SOFT_RST(reader); while (GET_UNIPERIF_SOFT_RST_SOFT_RST(reader)) { udelay(5); count--; } if (!count) { dev_err(reader->dev, "Failed to reset uniperif"); return -EIO; } return 0; }
static int uni_player_prepare_pcm(struct uniperif *player, struct snd_pcm_runtime *runtime) { int output_frame_size, slot_width, clk_div; /* Force slot width to 32 in I2S mode (HW constraint) */ if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) slot_width = 32; else slot_width = snd_pcm_format_width(runtime->format); output_frame_size = slot_width * runtime->channels; clk_div = player->mclk / runtime->rate; /* * For 32 bits subframe clk_div must be a multiple of 128, * for 16 bits must be a multiple of 64 */ if ((slot_width == 32) && (clk_div % 128)) { dev_err(player->dev, "%s: invalid clk_div\n", __func__); return -EINVAL; } if ((slot_width == 16) && (clk_div % 64)) { dev_err(player->dev, "%s: invalid clk_div\n", __func__); return -EINVAL; } /* * Number of bits per subframe (which is one channel sample) * on output - Transfer 16 or 32 bits from FIFO */ switch (slot_width) { case 32: SET_UNIPERIF_I2S_FMT_NBIT_32(player); SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player); break; case 16: SET_UNIPERIF_I2S_FMT_NBIT_16(player); SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(player); break; default: dev_err(player->dev, "subframe format not supported\n"); return -EINVAL; } /* Configure data memory format */ switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: /* One data word contains two samples */ SET_UNIPERIF_CONFIG_MEM_FMT_16_16(player); break; case SNDRV_PCM_FORMAT_S32_LE: /* * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits * on the left than zeros (if less than 32 bytes)"... ;-) */ SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); break; default: dev_err(player->dev, "format not supported\n"); return -EINVAL; } /* Set rounding to off */ SET_UNIPERIF_CTRL_ROUNDING_OFF(player); /* Set clock divisor */ SET_UNIPERIF_CTRL_DIVIDER(player, clk_div / (2 * output_frame_size)); /* Number of channelsmust be even*/ if ((runtime->channels % 2) || (runtime->channels < 2) || (runtime->channels > 10)) { dev_err(player->dev, "%s: invalid nb of channels\n", __func__); return -EINVAL; } SET_UNIPERIF_I2S_FMT_NUM_CH(player, runtime->channels / 2); /* Set 1-bit audio format to disabled */ SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); /* No iec958 formatting as outputting to DAC */ SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); return 0; }
static int uni_player_prepare_iec958(struct uniperif *player, struct snd_pcm_runtime *runtime) { int clk_div; clk_div = player->mclk / runtime->rate; /* Oversampling must be multiple of 128 as iec958 frame is 32-bits */ if ((clk_div % 128) || (clk_div <= 0)) { dev_err(player->dev, "%s: invalid clk_div %d\n", __func__, clk_div); return -EINVAL; } switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: /* 16/16 memory format */ SET_UNIPERIF_CONFIG_MEM_FMT_16_16(player); /* 16-bits per sub-frame */ SET_UNIPERIF_I2S_FMT_NBIT_32(player); /* Set 16-bit sample precision */ SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(player); break; case SNDRV_PCM_FORMAT_S32_LE: /* 16/0 memory format */ SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player); /* 32-bits per sub-frame */ SET_UNIPERIF_I2S_FMT_NBIT_32(player); /* Set 24-bit sample precision */ SET_UNIPERIF_I2S_FMT_DATA_SIZE_24(player); break; default: dev_err(player->dev, "format not supported\n"); return -EINVAL; } /* Set parity to be calculated by the hardware */ SET_UNIPERIF_CONFIG_PARITY_CNTR_BY_HW(player); /* Set channel status bits to be inserted by the hardware */ SET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR_BY_HW(player); /* Set user data bits to be inserted by the hardware */ SET_UNIPERIF_CONFIG_USER_DAT_CNTR_BY_HW(player); /* Set validity bits to be inserted by the hardware */ SET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_BY_HW(player); /* Set full software control to disabled */ SET_UNIPERIF_CONFIG_SPDIF_SW_CTRL_DISABLE(player); SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player); /* Update the channel status */ uni_player_set_channel_status(player, runtime); /* Clear the user validity user bits */ SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0); /* Disable one-bit audio mode */ SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); /* Enable consecutive frames repetition of Z preamble (not for HBRA) */ SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENABLE(player); /* Change to SUF0_SUBF1 and left/right channels swap! */ SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF1_SUBF0(player); /* Set data output as MSB first */ SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); if (player->stream_settings.encoding_mode == UNIPERIF_IEC958_ENCODING_MODE_ENCODED) SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_ON(player); else SET_UNIPERIF_CTRL_EXIT_STBY_ON_EOBLOCK_OFF(player); SET_UNIPERIF_I2S_FMT_NUM_CH(player, runtime->channels / 2); /* Set rounding to off */ SET_UNIPERIF_CTRL_ROUNDING_OFF(player); /* Set clock divisor */ SET_UNIPERIF_CTRL_DIVIDER(player, clk_div / 128); /* Set the spdif latency to not wait before starting player */ SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); /* * Ensure iec958 formatting is off. It will be enabled in function * uni_player_start() at the same time as the operation * mode is set to work around a silicon issue. */ if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); else SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); return 0; }