0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/pinctrl/consumer.h>
0010 #include <linux/delay.h>
0011
0012 #include "uniperif.h"
0013
0014
0015
0016
0017
0018
0019
0020 #define UNIPERIF_MAX_FRAME_SZ 0x20
0021 #define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ)
0022
0023 struct sti_uniperiph_dev_data {
0024 unsigned int id;
0025 unsigned int version;
0026 unsigned int stream;
0027 const char *dai_names;
0028 enum uniperif_type type;
0029 };
0030
0031 static const struct sti_uniperiph_dev_data sti_uniplayer_hdmi = {
0032 .id = 0,
0033 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0,
0034 .stream = SNDRV_PCM_STREAM_PLAYBACK,
0035 .dai_names = "Uni Player #0 (HDMI)",
0036 .type = SND_ST_UNIPERIF_TYPE_HDMI
0037 };
0038
0039 static const struct sti_uniperiph_dev_data sti_uniplayer_pcm_out = {
0040 .id = 1,
0041 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0,
0042 .stream = SNDRV_PCM_STREAM_PLAYBACK,
0043 .dai_names = "Uni Player #1 (PCM OUT)",
0044 .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM,
0045 };
0046
0047 static const struct sti_uniperiph_dev_data sti_uniplayer_dac = {
0048 .id = 2,
0049 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0,
0050 .stream = SNDRV_PCM_STREAM_PLAYBACK,
0051 .dai_names = "Uni Player #2 (DAC)",
0052 .type = SND_ST_UNIPERIF_TYPE_PCM,
0053 };
0054
0055 static const struct sti_uniperiph_dev_data sti_uniplayer_spdif = {
0056 .id = 3,
0057 .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0,
0058 .stream = SNDRV_PCM_STREAM_PLAYBACK,
0059 .dai_names = "Uni Player #3 (SPDIF)",
0060 .type = SND_ST_UNIPERIF_TYPE_SPDIF
0061 };
0062
0063 static const struct sti_uniperiph_dev_data sti_unireader_pcm_in = {
0064 .id = 0,
0065 .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0,
0066 .stream = SNDRV_PCM_STREAM_CAPTURE,
0067 .dai_names = "Uni Reader #0 (PCM IN)",
0068 .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM,
0069 };
0070
0071 static const struct sti_uniperiph_dev_data sti_unireader_hdmi_in = {
0072 .id = 1,
0073 .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0,
0074 .stream = SNDRV_PCM_STREAM_CAPTURE,
0075 .dai_names = "Uni Reader #1 (HDMI IN)",
0076 .type = SND_ST_UNIPERIF_TYPE_PCM,
0077 };
0078
0079 static const struct of_device_id snd_soc_sti_match[] = {
0080 { .compatible = "st,stih407-uni-player-hdmi",
0081 .data = &sti_uniplayer_hdmi
0082 },
0083 { .compatible = "st,stih407-uni-player-pcm-out",
0084 .data = &sti_uniplayer_pcm_out
0085 },
0086 { .compatible = "st,stih407-uni-player-dac",
0087 .data = &sti_uniplayer_dac
0088 },
0089 { .compatible = "st,stih407-uni-player-spdif",
0090 .data = &sti_uniplayer_spdif
0091 },
0092 { .compatible = "st,stih407-uni-reader-pcm_in",
0093 .data = &sti_unireader_pcm_in
0094 },
0095 { .compatible = "st,stih407-uni-reader-hdmi",
0096 .data = &sti_unireader_hdmi_in
0097 },
0098 {},
0099 };
0100 MODULE_DEVICE_TABLE(of, snd_soc_sti_match);
0101
0102 int sti_uniperiph_reset(struct uniperif *uni)
0103 {
0104 int count = 10;
0105
0106
0107 SET_UNIPERIF_SOFT_RST_SOFT_RST(uni);
0108
0109 if (uni->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) {
0110 while (GET_UNIPERIF_SOFT_RST_SOFT_RST(uni) && count) {
0111 udelay(5);
0112 count--;
0113 }
0114 }
0115
0116 if (!count) {
0117 dev_err(uni->dev, "Failed to reset uniperif\n");
0118 return -EIO;
0119 }
0120
0121 return 0;
0122 }
0123
0124 int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
0125 unsigned int rx_mask, int slots,
0126 int slot_width)
0127 {
0128 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0129 struct uniperif *uni = priv->dai_data.uni;
0130 int i, frame_size, avail_slots;
0131
0132 if (!UNIPERIF_TYPE_IS_TDM(uni)) {
0133 dev_err(uni->dev, "cpu dai not in tdm mode\n");
0134 return -EINVAL;
0135 }
0136
0137
0138 uni->tdm_slot.slots = slots;
0139 uni->tdm_slot.slot_width = slot_width;
0140
0141 uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask;
0142
0143
0144 for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) {
0145 if ((uni->tdm_slot.mask >> i) & 0x01)
0146 avail_slots++;
0147 }
0148 uni->tdm_slot.avail_slots = avail_slots;
0149
0150
0151 frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8;
0152
0153
0154 if ((frame_size > UNIPERIF_MAX_FRAME_SZ) ||
0155 (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) {
0156 dev_err(uni->dev, "frame size not allowed: %d bytes\n",
0157 frame_size);
0158 return -EINVAL;
0159 }
0160
0161 return 0;
0162 }
0163
0164 int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params,
0165 struct snd_pcm_hw_rule *rule)
0166 {
0167 struct uniperif *uni = rule->private;
0168 struct snd_interval t;
0169
0170 t.min = uni->tdm_slot.avail_slots;
0171 t.max = uni->tdm_slot.avail_slots;
0172 t.openmin = 0;
0173 t.openmax = 0;
0174 t.integer = 0;
0175
0176 return snd_interval_refine(hw_param_interval(params, rule->var), &t);
0177 }
0178
0179 int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params,
0180 struct snd_pcm_hw_rule *rule)
0181 {
0182 struct uniperif *uni = rule->private;
0183 struct snd_mask *maskp = hw_param_mask(params, rule->var);
0184 u64 format;
0185
0186 switch (uni->tdm_slot.slot_width) {
0187 case 16:
0188 format = SNDRV_PCM_FMTBIT_S16_LE;
0189 break;
0190 case 32:
0191 format = SNDRV_PCM_FMTBIT_S32_LE;
0192 break;
0193 default:
0194 dev_err(uni->dev, "format not supported: %d bits\n",
0195 uni->tdm_slot.slot_width);
0196 return -EINVAL;
0197 }
0198
0199 maskp->bits[0] &= (u_int32_t)format;
0200 maskp->bits[1] &= (u_int32_t)(format >> 32);
0201
0202 memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8);
0203
0204 if (!maskp->bits[0] && !maskp->bits[1])
0205 return -EINVAL;
0206
0207 return 0;
0208 }
0209
0210 int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
0211 unsigned int *word_pos)
0212 {
0213 int slot_width = uni->tdm_slot.slot_width / 8;
0214 int slots_num = uni->tdm_slot.slots;
0215 unsigned int slots_mask = uni->tdm_slot.mask;
0216 int i, j, k;
0217 unsigned int word16_pos[4];
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) {
0228 if ((slots_mask >> i) & 0x01) {
0229 word16_pos[j] = i * slot_width;
0230
0231 if (slot_width == 4) {
0232 word16_pos[j + 1] = word16_pos[j] + 2;
0233 j++;
0234 }
0235 j++;
0236
0237 if (j > 3) {
0238 word_pos[k] = word16_pos[1] |
0239 (word16_pos[0] << 8) |
0240 (word16_pos[3] << 16) |
0241 (word16_pos[2] << 24);
0242 j = 0;
0243 k++;
0244 }
0245 }
0246 }
0247
0248 return 0;
0249 }
0250
0251
0252
0253
0254
0255
0256 static int sti_uniperiph_dai_create_ctrl(struct snd_soc_dai *dai)
0257 {
0258 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0259 struct uniperif *uni = priv->dai_data.uni;
0260 struct snd_kcontrol_new *ctrl;
0261 int i;
0262
0263 if (!uni->num_ctrls)
0264 return 0;
0265
0266 for (i = 0; i < uni->num_ctrls; i++) {
0267
0268
0269
0270
0271 ctrl = &uni->snd_ctrls[i];
0272 ctrl->index = uni->id;
0273 ctrl->device = uni->id;
0274 }
0275
0276 return snd_soc_add_dai_controls(dai, uni->snd_ctrls, uni->num_ctrls);
0277 }
0278
0279
0280
0281
0282 int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
0283 struct snd_pcm_hw_params *params,
0284 struct snd_soc_dai *dai)
0285 {
0286 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0287 struct uniperif *uni = priv->dai_data.uni;
0288 struct snd_dmaengine_dai_dma_data *dma_data;
0289 int transfer_size;
0290
0291 if (uni->type == SND_ST_UNIPERIF_TYPE_TDM)
0292
0293 transfer_size = snd_soc_params_to_frame_size(params) / 32;
0294 else
0295 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES;
0296
0297 dma_data = snd_soc_dai_get_dma_data(dai, substream);
0298 dma_data->maxburst = transfer_size;
0299
0300 return 0;
0301 }
0302
0303 int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0304 {
0305 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0306
0307 priv->dai_data.uni->daifmt = fmt;
0308
0309 return 0;
0310 }
0311
0312 static int sti_uniperiph_suspend(struct snd_soc_component *component)
0313 {
0314 struct sti_uniperiph_data *priv = snd_soc_component_get_drvdata(component);
0315 struct uniperif *uni = priv->dai_data.uni;
0316 int ret;
0317
0318
0319 if (uni->state != UNIPERIF_STATE_STOPPED) {
0320 dev_err(uni->dev, "%s: invalid uni state( %d)\n",
0321 __func__, (int)uni->state);
0322 return -EBUSY;
0323 }
0324
0325
0326 ret = pinctrl_pm_select_sleep_state(uni->dev);
0327 if (ret)
0328 dev_err(uni->dev, "%s: failed to select pinctrl state\n",
0329 __func__);
0330
0331 return ret;
0332 }
0333
0334 static int sti_uniperiph_resume(struct snd_soc_component *component)
0335 {
0336 struct sti_uniperiph_data *priv = snd_soc_component_get_drvdata(component);
0337 struct uniperif *uni = priv->dai_data.uni;
0338 int ret;
0339
0340 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) {
0341 ret = uni_player_resume(uni);
0342 if (ret)
0343 return ret;
0344 }
0345
0346
0347 ret = pinctrl_pm_select_default_state(uni->dev);
0348 if (ret)
0349 dev_err(uni->dev, "%s: failed to select pinctrl state\n",
0350 __func__);
0351
0352 return ret;
0353 }
0354
0355 static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai)
0356 {
0357 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
0358 struct sti_uniperiph_dai *dai_data = &priv->dai_data;
0359
0360
0361 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK)
0362 snd_soc_dai_init_dma_data(dai, &dai_data->dma_data, NULL);
0363 else
0364 snd_soc_dai_init_dma_data(dai, NULL, &dai_data->dma_data);
0365
0366 dai_data->dma_data.addr = dai_data->uni->fifo_phys_address;
0367 dai_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0368
0369 return sti_uniperiph_dai_create_ctrl(dai);
0370 }
0371
0372 static const struct snd_soc_dai_driver sti_uniperiph_dai_template = {
0373 .probe = sti_uniperiph_dai_probe,
0374 };
0375
0376 static const struct snd_soc_component_driver sti_uniperiph_dai_component = {
0377 .name = "sti_cpu_dai",
0378 .suspend = sti_uniperiph_suspend,
0379 .resume = sti_uniperiph_resume,
0380 .legacy_dai_naming = 1,
0381 };
0382
0383 static int sti_uniperiph_cpu_dai_of(struct device_node *node,
0384 struct sti_uniperiph_data *priv)
0385 {
0386 struct device *dev = &priv->pdev->dev;
0387 struct sti_uniperiph_dai *dai_data = &priv->dai_data;
0388 struct snd_soc_dai_driver *dai = priv->dai;
0389 struct snd_soc_pcm_stream *stream;
0390 struct uniperif *uni;
0391 const struct of_device_id *of_id;
0392 const struct sti_uniperiph_dev_data *dev_data;
0393 const char *mode;
0394 int ret;
0395
0396
0397 of_id = of_match_node(snd_soc_sti_match, node);
0398 if (!of_id->data) {
0399 dev_err(dev, "data associated to device is missing\n");
0400 return -EINVAL;
0401 }
0402 dev_data = (struct sti_uniperiph_dev_data *)of_id->data;
0403
0404 uni = devm_kzalloc(dev, sizeof(*uni), GFP_KERNEL);
0405 if (!uni)
0406 return -ENOMEM;
0407
0408 uni->id = dev_data->id;
0409 uni->ver = dev_data->version;
0410
0411 *dai = sti_uniperiph_dai_template;
0412 dai->name = dev_data->dai_names;
0413
0414
0415 uni->base = devm_platform_get_and_ioremap_resource(priv->pdev, 0, &uni->mem_region);
0416 if (IS_ERR(uni->base))
0417 return PTR_ERR(uni->base);
0418
0419 uni->fifo_phys_address = uni->mem_region->start +
0420 UNIPERIF_FIFO_DATA_OFFSET(uni);
0421
0422 uni->irq = platform_get_irq(priv->pdev, 0);
0423 if (uni->irq < 0)
0424 return -ENXIO;
0425
0426 uni->type = dev_data->type;
0427
0428
0429 if (dev_data->type & SND_ST_UNIPERIF_TYPE_TDM) {
0430 if (!of_property_read_string(node, "st,tdm-mode", &mode))
0431 uni->type = SND_ST_UNIPERIF_TYPE_TDM;
0432 else
0433 uni->type = SND_ST_UNIPERIF_TYPE_PCM;
0434 }
0435
0436 dai_data->uni = uni;
0437 dai_data->stream = dev_data->stream;
0438
0439 if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) {
0440 ret = uni_player_init(priv->pdev, uni);
0441 stream = &dai->playback;
0442 } else {
0443 ret = uni_reader_init(priv->pdev, uni);
0444 stream = &dai->capture;
0445 }
0446 if (ret < 0)
0447 return ret;
0448
0449 dai->ops = uni->dai_ops;
0450
0451 stream->stream_name = dai->name;
0452 stream->channels_min = uni->hw->channels_min;
0453 stream->channels_max = uni->hw->channels_max;
0454 stream->rates = uni->hw->rates;
0455 stream->formats = uni->hw->formats;
0456
0457 return 0;
0458 }
0459
0460 static const struct snd_dmaengine_pcm_config dmaengine_pcm_config = {
0461 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
0462 };
0463
0464 static int sti_uniperiph_probe(struct platform_device *pdev)
0465 {
0466 struct sti_uniperiph_data *priv;
0467 struct device_node *node = pdev->dev.of_node;
0468 int ret;
0469
0470
0471 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0472 if (!priv)
0473 return -ENOMEM;
0474 priv->dai = devm_kzalloc(&pdev->dev, sizeof(*priv->dai), GFP_KERNEL);
0475 if (!priv->dai)
0476 return -ENOMEM;
0477
0478 priv->pdev = pdev;
0479
0480 ret = sti_uniperiph_cpu_dai_of(node, priv);
0481 if (ret < 0)
0482 return ret;
0483
0484 dev_set_drvdata(&pdev->dev, priv);
0485
0486 ret = devm_snd_soc_register_component(&pdev->dev,
0487 &sti_uniperiph_dai_component,
0488 priv->dai, 1);
0489 if (ret < 0)
0490 return ret;
0491
0492 return devm_snd_dmaengine_pcm_register(&pdev->dev,
0493 &dmaengine_pcm_config, 0);
0494 }
0495
0496 static struct platform_driver sti_uniperiph_driver = {
0497 .driver = {
0498 .name = "sti-uniperiph-dai",
0499 .of_match_table = snd_soc_sti_match,
0500 },
0501 .probe = sti_uniperiph_probe,
0502 };
0503 module_platform_driver(sti_uniperiph_driver);
0504
0505 MODULE_DESCRIPTION("uniperipheral DAI driver");
0506 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
0507 MODULE_LICENSE("GPL v2");