aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Jackson <Andrew.Jackson@arm.com>2014-12-30 05:55:45 -0500
committerMark Brown <broonie@kernel.org>2014-12-30 11:46:14 -0500
commitb226efe5818bf01cecc8a3e0fbd0def4ebbcedaa (patch)
tree1f6e7ce4b046733ee4a126aa6cce40119366d5a7
parenta56257c657eab392d579e6be70e2f8430eef1aa3 (diff)
ASoC: dwc: Read I2S block configuration from registers
The I2S block provides component parameter registers which describe how the block is instantiated. Use these registers to extract the block's configuration rather than relying on platform data. Signed-off-by: Andrew Jackson <Andrew.Jackson@arm.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/dwc/designware_i2s.c96
1 files changed, 86 insertions, 10 deletions
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 10219b5be436..d3bdc6890eb5 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -54,6 +54,31 @@
54#define I2S_COMP_VERSION 0x01F8 54#define I2S_COMP_VERSION 0x01F8
55#define I2S_COMP_TYPE 0x01FC 55#define I2S_COMP_TYPE 0x01FC
56 56
57/*
58 * Component parameter register fields - define the I2S block's
59 * configuration.
60 */
61#define COMP1_TX_WORDSIZE_3(r) (((r) & GENMASK(27, 25)) >> 25)
62#define COMP1_TX_WORDSIZE_2(r) (((r) & GENMASK(24, 22)) >> 22)
63#define COMP1_TX_WORDSIZE_1(r) (((r) & GENMASK(21, 19)) >> 19)
64#define COMP1_TX_WORDSIZE_0(r) (((r) & GENMASK(18, 16)) >> 16)
65#define COMP1_TX_CHANNELS(r) (((r) & GENMASK(10, 9)) >> 9)
66#define COMP1_RX_CHANNELS(r) (((r) & GENMASK(8, 7)) >> 7)
67#define COMP1_RX_ENABLED(r) (((r) & BIT(6)) >> 6)
68#define COMP1_TX_ENABLED(r) (((r) & BIT(5)) >> 5)
69#define COMP1_MODE_EN(r) (((r) & BIT(4)) >> 4)
70#define COMP1_FIFO_DEPTH_GLOBAL(r) (((r) & GENMASK(3, 2)) >> 2)
71#define COMP1_APB_DATA_WIDTH(r) (((r) & GENMASK(1, 0)) >> 0)
72
73#define COMP2_RX_WORDSIZE_3(r) (((r) & GENMASK(12, 10)) >> 10)
74#define COMP2_RX_WORDSIZE_2(r) (((r) & GENMASK(9, 7)) >> 7)
75#define COMP2_RX_WORDSIZE_1(r) (((r) & GENMASK(5, 3)) >> 3)
76#define COMP2_RX_WORDSIZE_0(r) (((r) & GENMASK(2, 0)) >> 0)
77
78/* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */
79#define COMP_MAX_WORDSIZE (1 << 3)
80#define COMP_MAX_DATA_WIDTH (1 << 2)
81
57#define MAX_CHANNEL_NUM 8 82#define MAX_CHANNEL_NUM 8
58#define MIN_CHANNEL_NUM 2 83#define MIN_CHANNEL_NUM 2
59 84
@@ -324,11 +349,50 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
324#define dw_i2s_resume NULL 349#define dw_i2s_resume NULL
325#endif 350#endif
326 351
327static void dw_configure_dai_by_pd(struct dw_i2s_dev *dev, 352/*
353 * The following tables allow a direct lookup of various parameters
354 * defined in the I2S block's configuration in terms of sound system
355 * parameters. Each table is sized to the number of entries possible
356 * according to the number of configuration bits describing an I2S
357 * block parameter.
358 */
359
360/* Width of (DMA) bus */
361static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = {
362 DMA_SLAVE_BUSWIDTH_1_BYTE,
363 DMA_SLAVE_BUSWIDTH_2_BYTES,
364 DMA_SLAVE_BUSWIDTH_4_BYTES,
365 DMA_SLAVE_BUSWIDTH_UNDEFINED
366};
367
368/* PCM format to support channel resolution */
369static const u32 formats[COMP_MAX_WORDSIZE] = {
370 SNDRV_PCM_FMTBIT_S16_LE,
371 SNDRV_PCM_FMTBIT_S16_LE,
372 SNDRV_PCM_FMTBIT_S24_LE,
373 SNDRV_PCM_FMTBIT_S24_LE,
374 SNDRV_PCM_FMTBIT_S32_LE,
375 0,
376 0,
377 0
378};
379
380static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
328 struct snd_soc_dai_driver *dw_i2s_dai, 381 struct snd_soc_dai_driver *dw_i2s_dai,
329 struct resource *res, 382 struct resource *res,
330 const struct i2s_platform_data *pdata) 383 const struct i2s_platform_data *pdata)
331{ 384{
385 /*
386 * Read component parameter registers to extract
387 * the I2S block's configuration.
388 */
389 u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
390 u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2);
391 u32 idx = COMP1_APB_DATA_WIDTH(comp1);
392
393 if (WARN_ON(idx >= ARRAY_SIZE(bus_widths)))
394 return -EINVAL;
395
332 /* Set DMA slaves info */ 396 /* Set DMA slaves info */
333 397
334 dev->play_dma_data.data = pdata->play_dma_data; 398 dev->play_dma_data.data = pdata->play_dma_data;
@@ -337,26 +401,36 @@ static void dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
337 dev->capture_dma_data.addr = res->start + I2S_RXDMA; 401 dev->capture_dma_data.addr = res->start + I2S_RXDMA;
338 dev->play_dma_data.max_burst = 16; 402 dev->play_dma_data.max_burst = 16;
339 dev->capture_dma_data.max_burst = 16; 403 dev->capture_dma_data.max_burst = 16;
340 dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 404 dev->play_dma_data.addr_width = bus_widths[idx];
341 dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 405 dev->capture_dma_data.addr_width = bus_widths[idx];
342 dev->play_dma_data.filter = pdata->filter; 406 dev->play_dma_data.filter = pdata->filter;
343 dev->capture_dma_data.filter = pdata->filter; 407 dev->capture_dma_data.filter = pdata->filter;
344 408
345 if (pdata->cap & DWC_I2S_PLAY) { 409 if (COMP1_TX_ENABLED(comp1)) {
346 dev_dbg(dev->dev, " designware: play supported\n"); 410 dev_dbg(dev->dev, " designware: play supported\n");
411 idx = COMP1_TX_WORDSIZE_0(comp1);
412 if (WARN_ON(idx >= ARRAY_SIZE(formats)))
413 return -EINVAL;
347 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; 414 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
348 dw_i2s_dai->playback.channels_max = pdata->channel; 415 dw_i2s_dai->playback.channels_max =
349 dw_i2s_dai->playback.formats = pdata->snd_fmts; 416 1 << (COMP1_TX_CHANNELS(comp1) + 1);
417 dw_i2s_dai->playback.formats = formats[idx];
350 dw_i2s_dai->playback.rates = pdata->snd_rates; 418 dw_i2s_dai->playback.rates = pdata->snd_rates;
351 } 419 }
352 420
353 if (pdata->cap & DWC_I2S_RECORD) { 421 if (COMP1_RX_ENABLED(comp1)) {
354 dev_dbg(dev->dev, "designware: record supported\n"); 422 dev_dbg(dev->dev, "designware: record supported\n");
423 idx = COMP2_RX_WORDSIZE_0(comp2);
424 if (WARN_ON(idx >= ARRAY_SIZE(formats)))
425 return -EINVAL;
355 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; 426 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
356 dw_i2s_dai->capture.channels_max = pdata->channel; 427 dw_i2s_dai->capture.channels_max =
357 dw_i2s_dai->capture.formats = pdata->snd_fmts; 428 1 << (COMP1_RX_CHANNELS(comp1) + 1);
429 dw_i2s_dai->capture.formats = formats[idx];
358 dw_i2s_dai->capture.rates = pdata->snd_rates; 430 dw_i2s_dai->capture.rates = pdata->snd_rates;
359 } 431 }
432
433 return 0;
360} 434}
361 435
362static int dw_i2s_probe(struct platform_device *pdev) 436static int dw_i2s_probe(struct platform_device *pdev)
@@ -392,7 +466,9 @@ static int dw_i2s_probe(struct platform_device *pdev)
392 return PTR_ERR(dev->i2s_base); 466 return PTR_ERR(dev->i2s_base);
393 467
394 dev->dev = &pdev->dev; 468 dev->dev = &pdev->dev;
395 dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); 469 ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
470 if (ret < 0)
471 return ret;
396 472
397 dev->capability = pdata->cap; 473 dev->capability = pdata->cap;
398 dev->i2s_clk_cfg = pdata->i2s_clk_cfg; 474 dev->i2s_clk_cfg = pdata->i2s_clk_cfg;