0001
0002
0003
0004
0005
0006
0007
0008 #include <sound/soc.h>
0009
0010 #include "uniperif.h"
0011
0012 #define UNIPERIF_READER_I2S_IN 0
0013
0014
0015
0016
0017 static const struct snd_pcm_hardware uni_reader_pcm_hw = {
0018 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
0019 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP |
0020 SNDRV_PCM_INFO_MMAP_VALID,
0021 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE,
0022
0023 .rates = SNDRV_PCM_RATE_CONTINUOUS,
0024 .rate_min = 8000,
0025 .rate_max = 96000,
0026
0027 .channels_min = 2,
0028 .channels_max = 8,
0029
0030 .periods_min = 2,
0031 .periods_max = 48,
0032
0033 .period_bytes_min = 128,
0034 .period_bytes_max = 64 * PAGE_SIZE,
0035 .buffer_bytes_max = 256 * PAGE_SIZE
0036 };
0037
0038
0039
0040
0041
0042
0043 static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
0044 {
0045 irqreturn_t ret = IRQ_NONE;
0046 struct uniperif *reader = dev_id;
0047 unsigned int status;
0048
0049 spin_lock(&reader->irq_lock);
0050 if (!reader->substream)
0051 goto irq_spin_unlock;
0052
0053 snd_pcm_stream_lock(reader->substream);
0054 if (reader->state == UNIPERIF_STATE_STOPPED) {
0055
0056 dev_warn(reader->dev, "unexpected IRQ\n");
0057 goto stream_unlock;
0058 }
0059
0060
0061 status = GET_UNIPERIF_ITS(reader);
0062 SET_UNIPERIF_ITS_BCLR(reader, status);
0063
0064
0065 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
0066 dev_err(reader->dev, "FIFO error detected\n");
0067
0068 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
0069
0070 ret = IRQ_HANDLED;
0071 }
0072
0073 stream_unlock:
0074 snd_pcm_stream_unlock(reader->substream);
0075 irq_spin_unlock:
0076 spin_unlock(&reader->irq_lock);
0077
0078 return ret;
0079 }
0080
0081 static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime,
0082 struct uniperif *reader)
0083 {
0084 int slot_width;
0085
0086
0087 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK)
0088 == SND_SOC_DAIFMT_I2S) {
0089 slot_width = 32;
0090 } else {
0091 switch (runtime->format) {
0092 case SNDRV_PCM_FORMAT_S16_LE:
0093 slot_width = 16;
0094 break;
0095 default:
0096 slot_width = 32;
0097 break;
0098 }
0099 }
0100
0101
0102 switch (slot_width) {
0103 case 32:
0104 SET_UNIPERIF_I2S_FMT_NBIT_32(reader);
0105 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);
0106 break;
0107 case 16:
0108 SET_UNIPERIF_I2S_FMT_NBIT_16(reader);
0109 SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(reader);
0110 break;
0111 default:
0112 dev_err(reader->dev, "subframe format not supported\n");
0113 return -EINVAL;
0114 }
0115
0116
0117 switch (runtime->format) {
0118 case SNDRV_PCM_FORMAT_S16_LE:
0119
0120 SET_UNIPERIF_CONFIG_MEM_FMT_16_16(reader);
0121 break;
0122
0123 case SNDRV_PCM_FORMAT_S32_LE:
0124
0125
0126
0127
0128 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
0129 break;
0130
0131 default:
0132 dev_err(reader->dev, "format not supported\n");
0133 return -EINVAL;
0134 }
0135
0136
0137 if ((runtime->channels % 2) || (runtime->channels < 2) ||
0138 (runtime->channels > 10)) {
0139 dev_err(reader->dev, "%s: invalid nb of channels\n", __func__);
0140 return -EINVAL;
0141 }
0142
0143 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
0144 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
0145
0146 return 0;
0147 }
0148
0149 static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime,
0150 struct uniperif *reader)
0151 {
0152 int frame_size;
0153
0154 unsigned int word_pos[4] = {
0155 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};
0156
0157 frame_size = sti_uniperiph_get_user_frame_size(runtime);
0158
0159
0160 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
0161 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);
0162
0163
0164 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2);
0165
0166 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
0167 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
0168 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader);
0169
0170
0171
0172
0173
0174
0175
0176
0177 sti_uniperiph_get_tdm_word_pos(reader, word_pos);
0178 SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]);
0179 SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]);
0180 SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]);
0181 SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]);
0182
0183 return 0;
0184 }
0185
0186 static int uni_reader_prepare(struct snd_pcm_substream *substream,
0187 struct snd_soc_dai *dai)
0188 {
0189 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0190 struct uniperif *reader = priv->dai_data.uni;
0191 struct snd_pcm_runtime *runtime = substream->runtime;
0192 int transfer_size, trigger_limit, ret;
0193
0194
0195 if (reader->state != UNIPERIF_STATE_STOPPED) {
0196 dev_err(reader->dev, "%s: invalid reader state %d\n", __func__,
0197 reader->state);
0198 return -EINVAL;
0199 }
0200
0201
0202 if (reader->type == SND_ST_UNIPERIF_TYPE_TDM) {
0203
0204 transfer_size =
0205 sti_uniperiph_get_user_frame_size(runtime) / 4;
0206 } else {
0207 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
0208 }
0209
0210
0211 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
0212 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size;
0213 else
0214
0215
0216
0217
0218
0219 trigger_limit = transfer_size;
0220
0221
0222 if ((!trigger_limit % 2) ||
0223 (trigger_limit != 1 && transfer_size % 2) ||
0224 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) {
0225 dev_err(reader->dev, "invalid trigger limit %d\n",
0226 trigger_limit);
0227 return -EINVAL;
0228 }
0229
0230 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit);
0231
0232 if (UNIPERIF_TYPE_IS_TDM(reader))
0233 ret = uni_reader_prepare_tdm(runtime, reader);
0234 else
0235 ret = uni_reader_prepare_pcm(runtime, reader);
0236 if (ret)
0237 return ret;
0238
0239 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0240 case SND_SOC_DAIFMT_I2S:
0241 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
0242 SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(reader);
0243 break;
0244 case SND_SOC_DAIFMT_LEFT_J:
0245 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
0246 SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader);
0247 break;
0248 case SND_SOC_DAIFMT_RIGHT_J:
0249 SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(reader);
0250 SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader);
0251 break;
0252 default:
0253 dev_err(reader->dev, "format not supported\n");
0254 return -EINVAL;
0255 }
0256
0257
0258 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) {
0259 case SND_SOC_DAIFMT_NB_NF:
0260 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
0261 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
0262 break;
0263 case SND_SOC_DAIFMT_NB_IF:
0264 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
0265 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
0266 break;
0267 case SND_SOC_DAIFMT_IB_NF:
0268 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
0269 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
0270 break;
0271 case SND_SOC_DAIFMT_IB_IF:
0272 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
0273 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
0274 break;
0275 }
0276
0277
0278 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader));
0279
0280 SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(reader, 0);
0281
0282
0283 SET_UNIPERIF_ITM_BSET_DMA_ERROR(reader);
0284 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader);
0285 SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader);
0286
0287
0288 if (reader->underflow_enabled) {
0289 SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader);
0290 SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader);
0291 }
0292
0293
0294 return sti_uniperiph_reset(reader);
0295 }
0296
0297 static int uni_reader_start(struct uniperif *reader)
0298 {
0299
0300 if (reader->state != UNIPERIF_STATE_STOPPED) {
0301 dev_err(reader->dev, "%s: invalid reader state\n", __func__);
0302 return -EINVAL;
0303 }
0304
0305
0306 SET_UNIPERIF_ITS_BCLR_FIFO_ERROR(reader);
0307 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader);
0308
0309
0310 SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(reader);
0311
0312
0313 reader->state = UNIPERIF_STATE_STARTED;
0314 return 0;
0315 }
0316
0317 static int uni_reader_stop(struct uniperif *reader)
0318 {
0319
0320 if (reader->state == UNIPERIF_STATE_STOPPED) {
0321 dev_err(reader->dev, "%s: invalid reader state\n", __func__);
0322 return -EINVAL;
0323 }
0324
0325
0326 SET_UNIPERIF_CTRL_OPERATION_OFF(reader);
0327
0328
0329 SET_UNIPERIF_ITM_BCLR(reader, GET_UNIPERIF_ITM(reader));
0330
0331
0332 reader->state = UNIPERIF_STATE_STOPPED;
0333
0334 return 0;
0335 }
0336
0337 static int uni_reader_trigger(struct snd_pcm_substream *substream,
0338 int cmd, struct snd_soc_dai *dai)
0339 {
0340 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0341 struct uniperif *reader = priv->dai_data.uni;
0342
0343 switch (cmd) {
0344 case SNDRV_PCM_TRIGGER_START:
0345 return uni_reader_start(reader);
0346 case SNDRV_PCM_TRIGGER_STOP:
0347 return uni_reader_stop(reader);
0348 default:
0349 return -EINVAL;
0350 }
0351 }
0352
0353 static int uni_reader_startup(struct snd_pcm_substream *substream,
0354 struct snd_soc_dai *dai)
0355 {
0356 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0357 struct uniperif *reader = priv->dai_data.uni;
0358 unsigned long flags;
0359 int ret;
0360
0361 spin_lock_irqsave(&reader->irq_lock, flags);
0362 reader->substream = substream;
0363 spin_unlock_irqrestore(&reader->irq_lock, flags);
0364
0365 if (!UNIPERIF_TYPE_IS_TDM(reader))
0366 return 0;
0367
0368
0369 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
0370 SNDRV_PCM_HW_PARAM_CHANNELS,
0371 sti_uniperiph_fix_tdm_chan,
0372 reader, SNDRV_PCM_HW_PARAM_CHANNELS,
0373 -1);
0374 if (ret < 0)
0375 return ret;
0376
0377 return snd_pcm_hw_rule_add(substream->runtime, 0,
0378 SNDRV_PCM_HW_PARAM_FORMAT,
0379 sti_uniperiph_fix_tdm_format,
0380 reader, SNDRV_PCM_HW_PARAM_FORMAT,
0381 -1);
0382 }
0383
0384 static void uni_reader_shutdown(struct snd_pcm_substream *substream,
0385 struct snd_soc_dai *dai)
0386 {
0387 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0388 struct uniperif *reader = priv->dai_data.uni;
0389 unsigned long flags;
0390
0391 spin_lock_irqsave(&reader->irq_lock, flags);
0392 if (reader->state != UNIPERIF_STATE_STOPPED) {
0393
0394 uni_reader_stop(reader);
0395 }
0396 reader->substream = NULL;
0397 spin_unlock_irqrestore(&reader->irq_lock, flags);
0398 }
0399
0400 static const struct snd_soc_dai_ops uni_reader_dai_ops = {
0401 .startup = uni_reader_startup,
0402 .shutdown = uni_reader_shutdown,
0403 .prepare = uni_reader_prepare,
0404 .trigger = uni_reader_trigger,
0405 .hw_params = sti_uniperiph_dai_hw_params,
0406 .set_fmt = sti_uniperiph_dai_set_fmt,
0407 .set_tdm_slot = sti_uniperiph_set_tdm_slot
0408 };
0409
0410 int uni_reader_init(struct platform_device *pdev,
0411 struct uniperif *reader)
0412 {
0413 int ret = 0;
0414
0415 reader->dev = &pdev->dev;
0416 reader->state = UNIPERIF_STATE_STOPPED;
0417 reader->dai_ops = &uni_reader_dai_ops;
0418
0419 if (UNIPERIF_TYPE_IS_TDM(reader))
0420 reader->hw = &uni_tdm_hw;
0421 else
0422 reader->hw = &uni_reader_pcm_hw;
0423
0424 ret = devm_request_irq(&pdev->dev, reader->irq,
0425 uni_reader_irq_handler, IRQF_SHARED,
0426 dev_name(&pdev->dev), reader);
0427 if (ret < 0) {
0428 dev_err(&pdev->dev, "Failed to request IRQ\n");
0429 return -EBUSY;
0430 }
0431
0432 spin_lock_init(&reader->irq_lock);
0433
0434 return 0;
0435 }
0436 EXPORT_SYMBOL_GPL(uni_reader_init);