Skip to content

Commit fd3bcdb

Browse files
author
Fox Snowpatch
committed
1 parent 960c1fd commit fd3bcdb

File tree

6 files changed

+121
-15
lines changed

6 files changed

+121
-15
lines changed

Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ properties:
2525
- fsl,imx53-asrc
2626
- fsl,imx8qm-asrc
2727
- fsl,imx8qxp-asrc
28+
- fsl,imx952-asrc
2829
- items:
2930
- enum:
3031
- fsl,imx6sx-asrc

sound/soc/fsl/fsl_asrc.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] = {
106106
},
107107
};
108108

109+
static unsigned char clk_map_imx952[ASRC_CLK_MAP_LEN] = {
110+
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x0,
111+
0x0, 0x1, 0x2, 0x3, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x4, 0x5, 0x6, 0x8, 0xf, 0xf,
112+
0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x7, 0x9, 0xa, 0xb, 0xc, 0xd, 0xf, 0xf, 0xf, 0xf,
113+
};
114+
109115
/*
110116
* According to RM, the divider range is 1 ~ 8,
111117
* prescaler is power of 2 from 1 ~ 128.
@@ -1078,6 +1084,27 @@ static unsigned int fsl_asrc_get_output_fifo_size(struct fsl_asrc_pair *pair)
10781084
return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
10791085
}
10801086

1087+
static bool fsl_asrc_m2m_output_ready(struct fsl_asrc_pair *pair)
1088+
{
1089+
struct fsl_asrc *asrc = pair->asrc;
1090+
enum asrc_pair_index index = pair->index;
1091+
int retry = 1000;
1092+
u32 val;
1093+
1094+
do {
1095+
regmap_read(asrc->regmap, REG_ASRFST(index), &val);
1096+
val &= ASRFSTi_OUTPUT_FIFO_MASK;
1097+
val = val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
1098+
} while (val < ASRC_M2M_OUTPUTFIFO_WML && --retry);
1099+
1100+
if (!retry) {
1101+
pair_warn("output is not ready\n");
1102+
return false;
1103+
}
1104+
1105+
return true;
1106+
}
1107+
10811108
static int fsl_asrc_m2m_prepare(struct fsl_asrc_pair *pair)
10821109
{
10831110
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -1275,6 +1302,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12751302

12761303
asrc_priv->soc = of_device_get_match_data(&pdev->dev);
12771304
asrc->use_edma = asrc_priv->soc->use_edma;
1305+
asrc->start_before_dma = asrc_priv->soc->start_before_dma;
12781306
asrc->get_dma_channel = fsl_asrc_get_dma_channel;
12791307
asrc->request_pair = fsl_asrc_request_pair;
12801308
asrc->release_pair = fsl_asrc_release_pair;
@@ -1289,6 +1317,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12891317
asrc->m2m_get_maxburst = fsl_asrc_m2m_get_maxburst;
12901318
asrc->m2m_pair_resume = fsl_asrc_m2m_pair_resume;
12911319
asrc->m2m_get_cap = fsl_asrc_m2m_get_cap;
1320+
asrc->m2m_output_ready = fsl_asrc_m2m_output_ready;
12921321

12931322
if (of_device_is_compatible(np, "fsl,imx35-asrc")) {
12941323
asrc_priv->clk_map[IN] = input_clk_map_imx35;
@@ -1315,6 +1344,9 @@ static int fsl_asrc_probe(struct platform_device *pdev)
13151344
asrc_priv->clk_map[IN] = clk_map_imx8qxp[map_idx];
13161345
asrc_priv->clk_map[OUT] = clk_map_imx8qxp[map_idx];
13171346
}
1347+
} else if (of_device_is_compatible(np, "fsl,imx952-asrc")) {
1348+
asrc_priv->clk_map[IN] = clk_map_imx952;
1349+
asrc_priv->clk_map[OUT] = clk_map_imx952;
13181350
}
13191351

13201352
asrc->channel_avail = 10;
@@ -1553,11 +1585,18 @@ static const struct fsl_asrc_soc_data fsl_asrc_imx8qxp_data = {
15531585
.channel_bits = 4,
15541586
};
15551587

1588+
static const struct fsl_asrc_soc_data fsl_asrc_imx952_data = {
1589+
.use_edma = true,
1590+
.channel_bits = 4,
1591+
.start_before_dma = true,
1592+
};
1593+
15561594
static const struct of_device_id fsl_asrc_ids[] = {
15571595
{ .compatible = "fsl,imx35-asrc", .data = &fsl_asrc_imx35_data },
15581596
{ .compatible = "fsl,imx53-asrc", .data = &fsl_asrc_imx53_data },
15591597
{ .compatible = "fsl,imx8qm-asrc", .data = &fsl_asrc_imx8qm_data },
15601598
{ .compatible = "fsl,imx8qxp-asrc", .data = &fsl_asrc_imx8qxp_data },
1599+
{ .compatible = "fsl,imx952-asrc", .data = &fsl_asrc_imx952_data },
15611600
{}
15621601
};
15631602
MODULE_DEVICE_TABLE(of, fsl_asrc_ids);

sound/soc/fsl/fsl_asrc.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,13 @@ enum asrc_inclk {
324324
INCLK_SAI6_TX_BCLK = 0x22,
325325
INCLK_HDMI_RX_SAI0_RX_BCLK = 0x24,
326326
INCLK_HDMI_TX_SAI0_TX_BCLK = 0x25,
327+
328+
INCLK_SAI2_TX_BCLK = 0x26,
329+
INCLK_SAI3_TX_BCLK = 0x27,
330+
INCLK_SAI4_RX_BCLK = 0x28,
331+
INCLK_SAI4_TX_BCLK = 0x29,
332+
INCLK_SAI5_RX_BCLK = 0x2a,
333+
INCLK_SAI5_TX_BCLK = 0x2b,
327334
};
328335

329336
enum asrc_outclk {
@@ -364,6 +371,13 @@ enum asrc_outclk {
364371
OUTCLK_SAI6_TX_BCLK = 0x22,
365372
OUTCLK_HDMI_RX_SAI0_RX_BCLK = 0x24,
366373
OUTCLK_HDMI_TX_SAI0_TX_BCLK = 0x25,
374+
375+
OUTCLK_SAI2_TX_BCLK = 0x26,
376+
OUTCLK_SAI3_TX_BCLK = 0x27,
377+
OUTCLK_SAI4_RX_BCLK = 0x28,
378+
OUTCLK_SAI4_TX_BCLK = 0x29,
379+
OUTCLK_SAI5_RX_BCLK = 0x2a,
380+
OUTCLK_SAI5_TX_BCLK = 0x2b,
367381
};
368382

369383
#define ASRC_CLK_MAX_NUM 16
@@ -432,10 +446,12 @@ struct dma_block {
432446
*
433447
* @use_edma: using edma as dma device or not
434448
* @channel_bits: width of ASRCNCR register for each pair
449+
* @start_before_dma: start asrc before dma
435450
*/
436451
struct fsl_asrc_soc_data {
437452
bool use_edma;
438453
unsigned int channel_bits;
454+
bool start_before_dma;
439455
};
440456

441457
/**

sound/soc/fsl/fsl_asrc_common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct fsl_asrc_pair {
107107
* @asrc_rate: default sample rate for ASoC Back-Ends
108108
* @asrc_format: default sample format for ASoC Back-Ends
109109
* @use_edma: edma is used
110+
* @start_before_dma: start asrc before dma
110111
* @get_dma_channel: function pointer
111112
* @request_pair: function pointer
112113
* @release_pair: function pointer
@@ -143,6 +144,7 @@ struct fsl_asrc {
143144
int asrc_rate;
144145
snd_pcm_format_t asrc_format;
145146
bool use_edma;
147+
bool start_before_dma;
146148

147149
struct dma_chan *(*get_dma_channel)(struct fsl_asrc_pair *pair, bool dir);
148150
int (*request_pair)(int channels, struct fsl_asrc_pair *pair);
@@ -154,6 +156,7 @@ struct fsl_asrc {
154156
int (*m2m_start)(struct fsl_asrc_pair *pair);
155157
int (*m2m_unprepare)(struct fsl_asrc_pair *pair);
156158
int (*m2m_stop)(struct fsl_asrc_pair *pair);
159+
bool (*m2m_output_ready)(struct fsl_asrc_pair *pair);
157160

158161
int (*m2m_calc_out_len)(struct fsl_asrc_pair *pair, int input_buffer_length);
159162
int (*m2m_get_maxburst)(u8 dir, struct fsl_asrc_pair *pair);

sound/soc/fsl/fsl_asrc_dma.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -449,18 +449,52 @@ fsl_asrc_dma_pcm_pointer(struct snd_soc_component *component,
449449
static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
450450
struct snd_soc_pcm_runtime *rtd)
451451
{
452-
struct snd_card *card = rtd->card->snd_card;
452+
struct device *dev = component->dev;
453+
struct fsl_asrc *asrc = dev_get_drvdata(dev);
454+
struct fsl_asrc_pair *pair;
453455
struct snd_pcm *pcm = rtd->pcm;
456+
struct dma_chan *chan;
454457
int ret;
455458

456-
ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
457-
if (ret) {
458-
dev_err(card->dev, "failed to set DMA mask\n");
459-
return ret;
459+
pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL);
460+
if (!pair)
461+
return -ENOMEM;
462+
463+
pair->asrc = asrc;
464+
pair->private = (void *)pair + sizeof(struct fsl_asrc_pair);
465+
466+
/* Request a dummy pair, which will be released later.
467+
* Request pair function needs channel num as input, for this
468+
* dummy pair, we just request "1" channel temporarily.
469+
*/
470+
ret = asrc->request_pair(1, pair);
471+
if (ret < 0) {
472+
dev_err(dev, "failed to request asrc pair\n");
473+
goto req_pair_err;
460474
}
461475

462-
return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
463-
card->dev, FSL_ASRC_DMABUF_SIZE);
476+
/* Request a dummy dma channel, which will be released later. */
477+
chan = asrc->get_dma_channel(pair, IN);
478+
if (!chan) {
479+
dev_err(dev, "failed to get dma channel\n");
480+
ret = -EINVAL;
481+
goto dma_chan_err;
482+
}
483+
484+
ret = snd_pcm_set_fixed_buffer_all(pcm,
485+
SNDRV_DMA_TYPE_DEV,
486+
chan->device->dev,
487+
FSL_ASRC_DMABUF_SIZE);
488+
489+
dma_release_channel(chan);
490+
491+
dma_chan_err:
492+
asrc->release_pair(pair);
493+
494+
req_pair_err:
495+
kfree(pair);
496+
497+
return ret;
464498
}
465499

466500
struct snd_soc_component_driver fsl_asrc_component = {

sound/soc/fsl/fsl_asrc_m2m.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,28 @@ static int asrc_m2m_device_run(struct fsl_asrc_pair *pair, struct snd_compr_task
253253
reinit_completion(&pair->complete[IN]);
254254
reinit_completion(&pair->complete[OUT]);
255255

256-
/* Submit DMA request */
257-
dmaengine_submit(pair->desc[IN]);
258-
dma_async_issue_pending(pair->desc[IN]->chan);
259-
if (out_dma_len > 0) {
260-
dmaengine_submit(pair->desc[OUT]);
261-
dma_async_issue_pending(pair->desc[OUT]->chan);
262-
}
256+
if (asrc->start_before_dma) {
257+
asrc->m2m_start(pair);
258+
/* Submit DMA request */
259+
dmaengine_submit(pair->desc[IN]);
260+
dma_async_issue_pending(pair->desc[IN]->chan);
261+
if (out_dma_len > 0) {
262+
if (asrc->m2m_output_ready)
263+
asrc->m2m_output_ready(pair);
264+
dmaengine_submit(pair->desc[OUT]);
265+
dma_async_issue_pending(pair->desc[OUT]->chan);
266+
}
267+
} else {
268+
/* Submit DMA request */
269+
dmaengine_submit(pair->desc[IN]);
270+
dma_async_issue_pending(pair->desc[IN]->chan);
271+
if (out_dma_len > 0) {
272+
dmaengine_submit(pair->desc[OUT]);
273+
dma_async_issue_pending(pair->desc[OUT]->chan);
274+
}
263275

264-
asrc->m2m_start(pair);
276+
asrc->m2m_start(pair);
277+
}
265278

266279
if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) {
267280
dev_err(dev, "out DMA task timeout\n");

0 commit comments

Comments
 (0)