1 /* 2 * Copyright (C) STMicroelectronics SA 2015 3 * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> 4 * for STMicroelectronics. 5 * License terms: GNU General Public License (GPL), version 2 6 */ 7 8 #include <linux/module.h> 9 #include <linux/pinctrl/consumer.h> 10 11 #include "uniperif.h" 12 13 /* 14 * User frame size shall be 2, 4, 6 or 8 32-bits words length 15 * (i.e. 8, 16, 24 or 32 bytes) 16 * This constraint comes from allowed values for 17 * UNIPERIF_I2S_FMT_NUM_CH register 18 */ 19 #define UNIPERIF_MAX_FRAME_SZ 0x20 20 #define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ) 21 22 struct sti_uniperiph_dev_data { 23 unsigned int id; /* Nb available player instances */ 24 unsigned int version; /* player IP version */ 25 unsigned int stream; 26 const char *dai_names; 27 enum uniperif_type type; 28 }; 29 30 static const struct sti_uniperiph_dev_data sti_uniplayer_hdmi = { 31 .id = 0, 32 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, 33 .stream = SNDRV_PCM_STREAM_PLAYBACK, 34 .dai_names = "Uni Player #0 (HDMI)", 35 .type = SND_ST_UNIPERIF_TYPE_HDMI 36 }; 37 38 static const struct sti_uniperiph_dev_data sti_uniplayer_pcm_out = { 39 .id = 1, 40 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, 41 .stream = SNDRV_PCM_STREAM_PLAYBACK, 42 .dai_names = "Uni Player #1 (PCM OUT)", 43 .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM, 44 }; 45 46 static const struct sti_uniperiph_dev_data sti_uniplayer_dac = { 47 .id = 2, 48 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, 49 .stream = SNDRV_PCM_STREAM_PLAYBACK, 50 .dai_names = "Uni Player #2 (DAC)", 51 .type = SND_ST_UNIPERIF_TYPE_PCM, 52 }; 53 54 static const struct sti_uniperiph_dev_data sti_uniplayer_spdif = { 55 .id = 3, 56 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, 57 .stream = SNDRV_PCM_STREAM_PLAYBACK, 58 .dai_names = "Uni Player #3 (SPDIF)", 59 .type = SND_ST_UNIPERIF_TYPE_SPDIF 60 }; 61 62 static const struct sti_uniperiph_dev_data sti_unireader_pcm_in = { 63 .id = 0, 64 .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0, 65 .stream = SNDRV_PCM_STREAM_CAPTURE, 66 .dai_names = "Uni Reader #0 (PCM IN)", 67 .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM, 68 }; 69 70 static const struct sti_uniperiph_dev_data sti_unireader_hdmi_in = { 71 .id = 1, 72 .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0, 73 .stream = SNDRV_PCM_STREAM_CAPTURE, 74 .dai_names = "Uni Reader #1 (HDMI IN)", 75 .type = SND_ST_UNIPERIF_TYPE_PCM, 76 }; 77 78 static const struct of_device_id snd_soc_sti_match[] = { 79 { .compatible = "st,stih407-uni-player-hdmi", 80 .data = &sti_uniplayer_hdmi 81 }, 82 { .compatible = "st,stih407-uni-player-pcm-out", 83 .data = &sti_uniplayer_pcm_out 84 }, 85 { .compatible = "st,stih407-uni-player-dac", 86 .data = &sti_uniplayer_dac 87 }, 88 { .compatible = "st,stih407-uni-player-spdif", 89 .data = &sti_uniplayer_spdif 90 }, 91 { .compatible = "st,stih407-uni-reader-pcm_in", 92 .data = &sti_unireader_pcm_in 93 }, 94 { .compatible = "st,stih407-uni-reader-hdmi", 95 .data = &sti_unireader_hdmi_in 96 }, 97 {}, 98 }; 99 100 int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 101 unsigned int rx_mask, int slots, 102 int slot_width) 103 { 104 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 105 struct uniperif *uni = priv->dai_data.uni; 106 int i, frame_size, avail_slots; 107 108 if (!UNIPERIF_TYPE_IS_TDM(uni)) { 109 dev_err(uni->dev, "cpu dai not in tdm mode\n"); 110 return -EINVAL; 111 } 112 113 /* store info in unip context */ 114 uni->tdm_slot.slots = slots; 115 uni->tdm_slot.slot_width = slot_width; 116 /* unip is unidirectionnal */ 117 uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask; 118 119 /* number of available timeslots */ 120 for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) { 121 if ((uni->tdm_slot.mask >> i) & 0x01) 122 avail_slots++; 123 } 124 uni->tdm_slot.avail_slots = avail_slots; 125 126 /* frame size in bytes */ 127 frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8; 128 129 /* check frame size is allowed */ 130 if ((frame_size > UNIPERIF_MAX_FRAME_SZ) || 131 (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) { 132 dev_err(uni->dev, "frame size not allowed: %d bytes\n", 133 frame_size); 134 return -EINVAL; 135 } 136 137 return 0; 138 } 139 140 int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params, 141 struct snd_pcm_hw_rule *rule) 142 { 143 struct uniperif *uni = rule->private; 144 struct snd_interval t; 145 146 t.min = uni->tdm_slot.avail_slots; 147 t.max = uni->tdm_slot.avail_slots; 148 t.openmin = 0; 149 t.openmax = 0; 150 t.integer = 0; 151 152 return snd_interval_refine(hw_param_interval(params, rule->var), &t); 153 } 154 155 int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params, 156 struct snd_pcm_hw_rule *rule) 157 { 158 struct uniperif *uni = rule->private; 159 struct snd_mask *maskp = hw_param_mask(params, rule->var); 160 u64 format; 161 162 switch (uni->tdm_slot.slot_width) { 163 case 16: 164 format = SNDRV_PCM_FMTBIT_S16_LE; 165 break; 166 case 32: 167 format = SNDRV_PCM_FMTBIT_S32_LE; 168 break; 169 default: 170 dev_err(uni->dev, "format not supported: %d bits\n", 171 uni->tdm_slot.slot_width); 172 return -EINVAL; 173 } 174 175 maskp->bits[0] &= (u_int32_t)format; 176 maskp->bits[1] &= (u_int32_t)(format >> 32); 177 /* clear remaining indexes */ 178 memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8); 179 180 if (!maskp->bits[0] && !maskp->bits[1]) 181 return -EINVAL; 182 183 return 0; 184 } 185 186 int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni, 187 unsigned int *word_pos) 188 { 189 int slot_width = uni->tdm_slot.slot_width / 8; 190 int slots_num = uni->tdm_slot.slots; 191 unsigned int slots_mask = uni->tdm_slot.mask; 192 int i, j, k; 193 unsigned int word16_pos[4]; 194 195 /* word16_pos: 196 * word16_pos[0] = WORDX_LSB 197 * word16_pos[1] = WORDX_MSB, 198 * word16_pos[2] = WORDX+1_LSB 199 * word16_pos[3] = WORDX+1_MSB 200 */ 201 202 /* set unip word position */ 203 for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) { 204 if ((slots_mask >> i) & 0x01) { 205 word16_pos[j] = i * slot_width; 206 207 if (slot_width == 4) { 208 word16_pos[j + 1] = word16_pos[j] + 2; 209 j++; 210 } 211 j++; 212 213 if (j > 3) { 214 word_pos[k] = word16_pos[1] | 215 (word16_pos[0] << 8) | 216 (word16_pos[3] << 16) | 217 (word16_pos[2] << 24); 218 j = 0; 219 k++; 220 } 221 } 222 } 223 224 return 0; 225 } 226 227 /* 228 * sti_uniperiph_dai_create_ctrl 229 * This function is used to create Ctrl associated to DAI but also pcm device. 230 * Request is done by front end to associate ctrl with pcm device id 231 */ 232 static int sti_uniperiph_dai_create_ctrl(struct snd_soc_dai *dai) 233 { 234 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 235 struct uniperif *uni = priv->dai_data.uni; 236 struct snd_kcontrol_new *ctrl; 237 int i; 238 239 if (!uni->num_ctrls) 240 return 0; 241 242 for (i = 0; i < uni->num_ctrls; i++) { 243 /* 244 * Several Control can have same name. Controls are indexed on 245 * Uniperipheral instance ID 246 */ 247 ctrl = &uni->snd_ctrls[i]; 248 ctrl->index = uni->id; 249 ctrl->device = uni->id; 250 } 251 252 return snd_soc_add_dai_controls(dai, uni->snd_ctrls, uni->num_ctrls); 253 } 254 255 /* 256 * DAI 257 */ 258 int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, 259 struct snd_pcm_hw_params *params, 260 struct snd_soc_dai *dai) 261 { 262 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 263 struct uniperif *uni = priv->dai_data.uni; 264 struct snd_dmaengine_dai_dma_data *dma_data; 265 int transfer_size; 266 267 if (uni->type == SND_ST_UNIPERIF_TYPE_TDM) 268 /* transfer size = user frame size (in 32-bits FIFO cell) */ 269 transfer_size = snd_soc_params_to_frame_size(params) / 32; 270 else 271 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; 272 273 dma_data = snd_soc_dai_get_dma_data(dai, substream); 274 dma_data->maxburst = transfer_size; 275 276 return 0; 277 } 278 279 int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 280 { 281 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 282 283 priv->dai_data.uni->daifmt = fmt; 284 285 return 0; 286 } 287 288 static int sti_uniperiph_dai_suspend(struct snd_soc_dai *dai) 289 { 290 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 291 struct uniperif *uni = priv->dai_data.uni; 292 int ret; 293 294 /* The uniperipheral should be in stopped state */ 295 if (uni->state != UNIPERIF_STATE_STOPPED) { 296 dev_err(uni->dev, "%s: invalid uni state( %d)", 297 __func__, (int)uni->state); 298 return -EBUSY; 299 } 300 301 /* Pinctrl: switch pinstate to sleep */ 302 ret = pinctrl_pm_select_sleep_state(uni->dev); 303 if (ret) 304 dev_err(uni->dev, "%s: failed to select pinctrl state", 305 __func__); 306 307 return ret; 308 } 309 310 static int sti_uniperiph_dai_resume(struct snd_soc_dai *dai) 311 { 312 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 313 struct uniperif *uni = priv->dai_data.uni; 314 int ret; 315 316 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) { 317 ret = uni_player_resume(uni); 318 if (ret) 319 return ret; 320 } 321 322 /* pinctrl: switch pinstate to default */ 323 ret = pinctrl_pm_select_default_state(uni->dev); 324 if (ret) 325 dev_err(uni->dev, "%s: failed to select pinctrl state", 326 __func__); 327 328 return ret; 329 } 330 331 static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai) 332 { 333 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 334 struct sti_uniperiph_dai *dai_data = &priv->dai_data; 335 336 /* DMA settings*/ 337 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) 338 snd_soc_dai_init_dma_data(dai, &dai_data->dma_data, NULL); 339 else 340 snd_soc_dai_init_dma_data(dai, NULL, &dai_data->dma_data); 341 342 dai_data->dma_data.addr = dai_data->uni->fifo_phys_address; 343 dai_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 344 345 return sti_uniperiph_dai_create_ctrl(dai); 346 } 347 348 static const struct snd_soc_dai_driver sti_uniperiph_dai_template = { 349 .probe = sti_uniperiph_dai_probe, 350 .suspend = sti_uniperiph_dai_suspend, 351 .resume = sti_uniperiph_dai_resume 352 }; 353 354 static const struct snd_soc_component_driver sti_uniperiph_dai_component = { 355 .name = "sti_cpu_dai", 356 }; 357 358 static int sti_uniperiph_cpu_dai_of(struct device_node *node, 359 struct sti_uniperiph_data *priv) 360 { 361 struct device *dev = &priv->pdev->dev; 362 struct sti_uniperiph_dai *dai_data = &priv->dai_data; 363 struct snd_soc_dai_driver *dai = priv->dai; 364 struct snd_soc_pcm_stream *stream; 365 struct uniperif *uni; 366 const struct of_device_id *of_id; 367 const struct sti_uniperiph_dev_data *dev_data; 368 const char *mode; 369 370 /* Populate data structure depending on compatibility */ 371 of_id = of_match_node(snd_soc_sti_match, node); 372 if (!of_id->data) { 373 dev_err(dev, "data associated to device is missing"); 374 return -EINVAL; 375 } 376 dev_data = (struct sti_uniperiph_dev_data *)of_id->data; 377 378 uni = devm_kzalloc(dev, sizeof(*uni), GFP_KERNEL); 379 if (!uni) 380 return -ENOMEM; 381 382 uni->id = dev_data->id; 383 uni->ver = dev_data->version; 384 385 *dai = sti_uniperiph_dai_template; 386 dai->name = dev_data->dai_names; 387 388 /* Get resources */ 389 uni->mem_region = platform_get_resource(priv->pdev, IORESOURCE_MEM, 0); 390 391 if (!uni->mem_region) { 392 dev_err(dev, "Failed to get memory resource"); 393 return -ENODEV; 394 } 395 396 uni->base = devm_ioremap_resource(dev, uni->mem_region); 397 398 if (IS_ERR(uni->base)) 399 return PTR_ERR(uni->base); 400 401 uni->fifo_phys_address = uni->mem_region->start + 402 UNIPERIF_FIFO_DATA_OFFSET(uni); 403 404 uni->irq = platform_get_irq(priv->pdev, 0); 405 if (uni->irq < 0) { 406 dev_err(dev, "Failed to get IRQ resource"); 407 return -ENXIO; 408 } 409 410 uni->type = dev_data->type; 411 412 /* check if player should be configured for tdm */ 413 if (dev_data->type & SND_ST_UNIPERIF_TYPE_TDM) { 414 if (!of_property_read_string(node, "st,tdm-mode", &mode)) 415 uni->type = SND_ST_UNIPERIF_TYPE_TDM; 416 else 417 uni->type = SND_ST_UNIPERIF_TYPE_PCM; 418 } 419 420 dai_data->uni = uni; 421 dai_data->stream = dev_data->stream; 422 423 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) { 424 uni_player_init(priv->pdev, uni); 425 stream = &dai->playback; 426 } else { 427 uni_reader_init(priv->pdev, uni); 428 stream = &dai->capture; 429 } 430 dai->ops = uni->dai_ops; 431 432 stream->stream_name = dai->name; 433 stream->channels_min = uni->hw->channels_min; 434 stream->channels_max = uni->hw->channels_max; 435 stream->rates = uni->hw->rates; 436 stream->formats = uni->hw->formats; 437 438 return 0; 439 } 440 441 static const struct snd_dmaengine_pcm_config dmaengine_pcm_config = { 442 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, 443 }; 444 445 static int sti_uniperiph_probe(struct platform_device *pdev) 446 { 447 struct sti_uniperiph_data *priv; 448 struct device_node *node = pdev->dev.of_node; 449 int ret; 450 451 /* Allocate the private data and the CPU_DAI array */ 452 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 453 if (!priv) 454 return -ENOMEM; 455 priv->dai = devm_kzalloc(&pdev->dev, sizeof(*priv->dai), GFP_KERNEL); 456 if (!priv->dai) 457 return -ENOMEM; 458 459 priv->pdev = pdev; 460 461 ret = sti_uniperiph_cpu_dai_of(node, priv); 462 463 dev_set_drvdata(&pdev->dev, priv); 464 465 ret = devm_snd_soc_register_component(&pdev->dev, 466 &sti_uniperiph_dai_component, 467 priv->dai, 1); 468 if (ret < 0) 469 return ret; 470 471 return devm_snd_dmaengine_pcm_register(&pdev->dev, 472 &dmaengine_pcm_config, 0); 473 } 474 475 static struct platform_driver sti_uniperiph_driver = { 476 .driver = { 477 .name = "sti-uniperiph-dai", 478 .of_match_table = snd_soc_sti_match, 479 }, 480 .probe = sti_uniperiph_probe, 481 }; 482 module_platform_driver(sti_uniperiph_driver); 483 484 MODULE_DESCRIPTION("uniperipheral DAI driver"); 485 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 486 MODULE_LICENSE("GPL v2"); 487