1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) STMicroelectronics SA 2015 4 * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> 5 * for STMicroelectronics. 6 */ 7 8 #include <sound/soc.h> 9 10 #include "uniperif.h" 11 12 #define UNIPERIF_READER_I2S_IN 0 /* reader id connected to I2S/TDM TX bus */ 13 /* 14 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to 15 * integrate unireader capability in term of rate and supported channels 16 */ 17 static const struct snd_pcm_hardware uni_reader_pcm_hw = { 18 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 19 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP | 20 SNDRV_PCM_INFO_MMAP_VALID, 21 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE, 22 23 .rates = SNDRV_PCM_RATE_CONTINUOUS, 24 .rate_min = 8000, 25 .rate_max = 96000, 26 27 .channels_min = 2, 28 .channels_max = 8, 29 30 .periods_min = 2, 31 .periods_max = 48, 32 33 .period_bytes_min = 128, 34 .period_bytes_max = 64 * PAGE_SIZE, 35 .buffer_bytes_max = 256 * PAGE_SIZE 36 }; 37 38 /* 39 * uni_reader_irq_handler 40 * In case of error audio stream is stopped; stop action is protected via PCM 41 * stream lock to avoid race condition with trigger callback. 42 */ 43 static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) 44 { 45 irqreturn_t ret = IRQ_NONE; 46 struct uniperif *reader = dev_id; 47 unsigned int status; 48 49 spin_lock(&reader->irq_lock); 50 if (!reader->substream) 51 goto irq_spin_unlock; 52 53 snd_pcm_stream_lock(reader->substream); 54 if (reader->state == UNIPERIF_STATE_STOPPED) { 55 /* Unexpected IRQ: do nothing */ 56 dev_warn(reader->dev, "unexpected IRQ\n"); 57 goto stream_unlock; 58 } 59 60 /* Get interrupt status & clear them immediately */ 61 status = GET_UNIPERIF_ITS(reader); 62 SET_UNIPERIF_ITS_BCLR(reader, status); 63 64 /* Check for fifo overflow error */ 65 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { 66 dev_err(reader->dev, "FIFO error detected\n"); 67 68 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); 69 70 ret = IRQ_HANDLED; 71 } 72 73 stream_unlock: 74 snd_pcm_stream_unlock(reader->substream); 75 irq_spin_unlock: 76 spin_unlock(&reader->irq_lock); 77 78 return ret; 79 } 80 81 static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime, 82 struct uniperif *reader) 83 { 84 int slot_width; 85 86 /* Force slot width to 32 in I2S mode */ 87 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) 88 == SND_SOC_DAIFMT_I2S) { 89 slot_width = 32; 90 } else { 91 switch (runtime->format) { 92 case SNDRV_PCM_FORMAT_S16_LE: 93 slot_width = 16; 94 break; 95 default: 96 slot_width = 32; 97 break; 98 } 99 } 100 101 /* Number of bits per subframe (i.e one channel sample) on input. */ 102 switch (slot_width) { 103 case 32: 104 SET_UNIPERIF_I2S_FMT_NBIT_32(reader); 105 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); 106 break; 107 case 16: 108 SET_UNIPERIF_I2S_FMT_NBIT_16(reader); 109 SET_UNIPERIF_I2S_FMT_DATA_SIZE_16(reader); 110 break; 111 default: 112 dev_err(reader->dev, "subframe format not supported\n"); 113 return -EINVAL; 114 } 115 116 /* Configure data memory format */ 117 switch (runtime->format) { 118 case SNDRV_PCM_FORMAT_S16_LE: 119 /* One data word contains two samples */ 120 SET_UNIPERIF_CONFIG_MEM_FMT_16_16(reader); 121 break; 122 123 case SNDRV_PCM_FORMAT_S32_LE: 124 /* 125 * Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits 126 * on the MSB then zeros (if less than 32 bytes)"... 127 */ 128 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); 129 break; 130 131 default: 132 dev_err(reader->dev, "format not supported\n"); 133 return -EINVAL; 134 } 135 136 /* Number of channels must be even */ 137 if ((runtime->channels % 2) || (runtime->channels < 2) || 138 (runtime->channels > 10)) { 139 dev_err(reader->dev, "%s: invalid nb of channels\n", __func__); 140 return -EINVAL; 141 } 142 143 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2); 144 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 145 146 return 0; 147 } 148 149 static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime, 150 struct uniperif *reader) 151 { 152 int frame_size; /* user tdm frame size in bytes */ 153 /* default unip TDM_WORD_POS_X_Y */ 154 unsigned int word_pos[4] = { 155 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A}; 156 157 frame_size = sti_uniperiph_get_user_frame_size(runtime); 158 159 /* fix 16/0 format */ 160 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader); 161 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader); 162 163 /* number of words inserted on the TDM line */ 164 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2); 165 166 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 167 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 168 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader); 169 170 /* 171 * set the timeslots allocation for words in FIFO 172 * 173 * HW bug: (LSB word < MSB word) => this config is not possible 174 * So if we want (LSB word < MSB) word, then it shall be 175 * handled by user 176 */ 177 sti_uniperiph_get_tdm_word_pos(reader, word_pos); 178 SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]); 179 SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]); 180 SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]); 181 SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]); 182 183 return 0; 184 } 185 186 static int uni_reader_prepare(struct snd_pcm_substream *substream, 187 struct snd_soc_dai *dai) 188 { 189 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 190 struct uniperif *reader = priv->dai_data.uni; 191 struct snd_pcm_runtime *runtime = substream->runtime; 192 int transfer_size, trigger_limit, ret; 193 194 /* The reader should be stopped */ 195 if (reader->state != UNIPERIF_STATE_STOPPED) { 196 dev_err(reader->dev, "%s: invalid reader state %d\n", __func__, 197 reader->state); 198 return -EINVAL; 199 } 200 201 /* Calculate transfer size (in fifo cells and bytes) for frame count */ 202 if (reader->type == SND_ST_UNIPERIF_TYPE_TDM) { 203 /* transfer size = unip frame size (in 32 bits FIFO cell) */ 204 transfer_size = 205 sti_uniperiph_get_user_frame_size(runtime) / 4; 206 } else { 207 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 208 } 209 210 /* Calculate number of empty cells available before asserting DREQ */ 211 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 212 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size; 213 else 214 /* 215 * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0 216 * FDMA_TRIGGER_LIMIT also controls when the state switches 217 * from OFF or STANDBY to AUDIO DATA. 218 */ 219 trigger_limit = transfer_size; 220 221 /* Trigger limit must be an even number */ 222 if ((!trigger_limit % 2) || 223 (trigger_limit != 1 && transfer_size % 2) || 224 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) { 225 dev_err(reader->dev, "invalid trigger limit %d\n", 226 trigger_limit); 227 return -EINVAL; 228 } 229 230 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit); 231 232 if (UNIPERIF_TYPE_IS_TDM(reader)) 233 ret = uni_reader_prepare_tdm(runtime, reader); 234 else 235 ret = uni_reader_prepare_pcm(runtime, reader); 236 if (ret) 237 return ret; 238 239 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { 240 case SND_SOC_DAIFMT_I2S: 241 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 242 SET_UNIPERIF_I2S_FMT_PADDING_I2S_MODE(reader); 243 break; 244 case SND_SOC_DAIFMT_LEFT_J: 245 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 246 SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); 247 break; 248 case SND_SOC_DAIFMT_RIGHT_J: 249 SET_UNIPERIF_I2S_FMT_ALIGN_RIGHT(reader); 250 SET_UNIPERIF_I2S_FMT_PADDING_SONY_MODE(reader); 251 break; 252 default: 253 dev_err(reader->dev, "format not supported\n"); 254 return -EINVAL; 255 } 256 257 /* Data clocking (changing) on the rising/falling edge */ 258 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) { 259 case SND_SOC_DAIFMT_NB_NF: 260 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); 261 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 262 break; 263 case SND_SOC_DAIFMT_NB_IF: 264 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); 265 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 266 break; 267 case SND_SOC_DAIFMT_IB_NF: 268 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader); 269 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); 270 break; 271 case SND_SOC_DAIFMT_IB_IF: 272 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader); 273 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader); 274 break; 275 } 276 277 /* Clear any pending interrupts */ 278 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); 279 280 SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_READ(reader, 0); 281 282 /* Set the interrupt mask */ 283 SET_UNIPERIF_ITM_BSET_DMA_ERROR(reader); 284 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader); 285 SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader); 286 287 /* Enable underflow recovery interrupts */ 288 if (reader->underflow_enabled) { 289 SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader); 290 SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader); 291 } 292 293 /* Reset uniperipheral reader */ 294 return sti_uniperiph_reset(reader); 295 } 296 297 static int uni_reader_start(struct uniperif *reader) 298 { 299 /* The reader should be stopped */ 300 if (reader->state != UNIPERIF_STATE_STOPPED) { 301 dev_err(reader->dev, "%s: invalid reader state\n", __func__); 302 return -EINVAL; 303 } 304 305 /* Enable reader interrupts (and clear possible stalled ones) */ 306 SET_UNIPERIF_ITS_BCLR_FIFO_ERROR(reader); 307 SET_UNIPERIF_ITM_BSET_FIFO_ERROR(reader); 308 309 /* Launch the reader */ 310 SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(reader); 311 312 /* Update state to started */ 313 reader->state = UNIPERIF_STATE_STARTED; 314 return 0; 315 } 316 317 static int uni_reader_stop(struct uniperif *reader) 318 { 319 /* The reader should not be in stopped state */ 320 if (reader->state == UNIPERIF_STATE_STOPPED) { 321 dev_err(reader->dev, "%s: invalid reader state\n", __func__); 322 return -EINVAL; 323 } 324 325 /* Turn the reader off */ 326 SET_UNIPERIF_CTRL_OPERATION_OFF(reader); 327 328 /* Disable interrupts */ 329 SET_UNIPERIF_ITM_BCLR(reader, GET_UNIPERIF_ITM(reader)); 330 331 /* Update state to stopped and return */ 332 reader->state = UNIPERIF_STATE_STOPPED; 333 334 return 0; 335 } 336 337 static int uni_reader_trigger(struct snd_pcm_substream *substream, 338 int cmd, struct snd_soc_dai *dai) 339 { 340 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 341 struct uniperif *reader = priv->dai_data.uni; 342 343 switch (cmd) { 344 case SNDRV_PCM_TRIGGER_START: 345 return uni_reader_start(reader); 346 case SNDRV_PCM_TRIGGER_STOP: 347 return uni_reader_stop(reader); 348 default: 349 return -EINVAL; 350 } 351 } 352 353 static int uni_reader_startup(struct snd_pcm_substream *substream, 354 struct snd_soc_dai *dai) 355 { 356 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 357 struct uniperif *reader = priv->dai_data.uni; 358 unsigned long flags; 359 int ret; 360 361 spin_lock_irqsave(&reader->irq_lock, flags); 362 reader->substream = substream; 363 spin_unlock_irqrestore(&reader->irq_lock, flags); 364 365 if (!UNIPERIF_TYPE_IS_TDM(reader)) 366 return 0; 367 368 /* refine hw constraint in tdm mode */ 369 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 370 SNDRV_PCM_HW_PARAM_CHANNELS, 371 sti_uniperiph_fix_tdm_chan, 372 reader, SNDRV_PCM_HW_PARAM_CHANNELS, 373 -1); 374 if (ret < 0) 375 return ret; 376 377 return snd_pcm_hw_rule_add(substream->runtime, 0, 378 SNDRV_PCM_HW_PARAM_FORMAT, 379 sti_uniperiph_fix_tdm_format, 380 reader, SNDRV_PCM_HW_PARAM_FORMAT, 381 -1); 382 } 383 384 static void uni_reader_shutdown(struct snd_pcm_substream *substream, 385 struct snd_soc_dai *dai) 386 { 387 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 388 struct uniperif *reader = priv->dai_data.uni; 389 unsigned long flags; 390 391 spin_lock_irqsave(&reader->irq_lock, flags); 392 if (reader->state != UNIPERIF_STATE_STOPPED) { 393 /* Stop the reader */ 394 uni_reader_stop(reader); 395 } 396 reader->substream = NULL; 397 spin_unlock_irqrestore(&reader->irq_lock, flags); 398 } 399 400 static const struct snd_soc_dai_ops uni_reader_dai_ops = { 401 .startup = uni_reader_startup, 402 .shutdown = uni_reader_shutdown, 403 .prepare = uni_reader_prepare, 404 .probe = sti_uniperiph_dai_probe, 405 .trigger = uni_reader_trigger, 406 .hw_params = sti_uniperiph_dai_hw_params, 407 .set_fmt = sti_uniperiph_dai_set_fmt, 408 .set_tdm_slot = sti_uniperiph_set_tdm_slot 409 }; 410 411 int uni_reader_init(struct platform_device *pdev, 412 struct uniperif *reader) 413 { 414 int ret = 0; 415 416 reader->dev = &pdev->dev; 417 reader->state = UNIPERIF_STATE_STOPPED; 418 reader->dai_ops = &uni_reader_dai_ops; 419 420 if (UNIPERIF_TYPE_IS_TDM(reader)) 421 reader->hw = &uni_tdm_hw; 422 else 423 reader->hw = &uni_reader_pcm_hw; 424 425 ret = devm_request_irq(&pdev->dev, reader->irq, 426 uni_reader_irq_handler, IRQF_SHARED, 427 dev_name(&pdev->dev), reader); 428 if (ret < 0) { 429 dev_err(&pdev->dev, "Failed to request IRQ\n"); 430 return -EBUSY; 431 } 432 433 spin_lock_init(&reader->irq_lock); 434 435 return 0; 436 } 437 EXPORT_SYMBOL_GPL(uni_reader_init); 438
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.