Skip to content

Commit 1785524

Browse files
author
Fox Snowpatch
committed
1 parent 1ecdccb commit 1785524

File tree

9 files changed

+1260
-9
lines changed

9 files changed

+1260
-9
lines changed

include/uapi/sound/compress_params.h

+21-2
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,14 @@ union snd_codec_options {
334334
struct snd_dec_wma wma_d;
335335
struct snd_dec_alac alac_d;
336336
struct snd_dec_ape ape_d;
337+
struct {
338+
__u32 out_sample_rate;
339+
} src_d;
340+
} __attribute__((packed, aligned(4)));
341+
342+
struct snd_codec_desc_src {
343+
__u32 out_sample_rate_min;
344+
__u32 out_sample_rate_max;
337345
} __attribute__((packed, aligned(4)));
338346

339347
/** struct snd_codec_desc - description of codec capabilities
@@ -347,6 +355,9 @@ union snd_codec_options {
347355
* @modes: Supported modes. See SND_AUDIOMODE defines
348356
* @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
349357
* @min_buffer: Minimum buffer size handled by codec implementation
358+
* @pcm_formats: Output (for decoders) or input (for encoders)
359+
* PCM formats (required to accel mode, 0 for other modes)
360+
* @u_space: union space (for codec dependent data)
350361
* @reserved: reserved for future use
351362
*
352363
* This structure provides a scalar value for profiles, modes and stream
@@ -370,7 +381,12 @@ struct snd_codec_desc {
370381
__u32 modes;
371382
__u32 formats;
372383
__u32 min_buffer;
373-
__u32 reserved[15];
384+
__u32 pcm_formats;
385+
union {
386+
__u32 u_space[6];
387+
struct snd_codec_desc_src src;
388+
} __attribute__((packed, aligned(4)));
389+
__u32 reserved[8];
374390
} __attribute__((packed, aligned(4)));
375391

376392
/** struct snd_codec
@@ -395,6 +411,8 @@ struct snd_codec_desc {
395411
* @align: Block alignment in bytes of an audio sample.
396412
* Only required for PCM or IEC formats.
397413
* @options: encoder-specific settings
414+
* @pcm_format: Output (for decoders) or input (for encoders)
415+
* PCM formats (required to accel mode, 0 for other modes)
398416
* @reserved: reserved for future use
399417
*/
400418

@@ -411,7 +429,8 @@ struct snd_codec {
411429
__u32 format;
412430
__u32 align;
413431
union snd_codec_options options;
414-
__u32 reserved[3];
432+
__u32 pcm_format;
433+
__u32 reserved[2];
415434
} __attribute__((packed, aligned(4)));
416435

417436
#endif

sound/soc/fsl/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ config SND_SOC_FSL_ASRC
88
depends on HAS_DMA
99
select REGMAP_MMIO
1010
select SND_SOC_GENERIC_DMAENGINE_PCM
11+
select SND_COMPRESS_ACCEL
1112
help
1213
Say Y if you want to add Asynchronous Sample Rate Converter (ASRC)
1314
support for the Freescale CPUs.

sound/soc/fsl/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
1010
# Freescale SSI/DMA/SAI/SPDIF Support
1111
snd-soc-fsl-audmix-y := fsl_audmix.o
1212
snd-soc-fsl-asoc-card-y := fsl-asoc-card.o
13-
snd-soc-fsl-asrc-y := fsl_asrc.o fsl_asrc_dma.o
13+
snd-soc-fsl-asrc-y := fsl_asrc.o fsl_asrc_dma.o fsl_asrc_m2m.o
1414
snd-soc-fsl-lpc3xxx-y := lpc3xxx-pcm.o lpc3xxx-i2s.o
1515
snd-soc-fsl-sai-y := fsl_sai.o
1616
snd-soc-fsl-ssi-y := fsl_ssi.o

sound/soc/fsl/fsl_asrc.c

+175-4
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,139 @@ static int fsl_asrc_get_fifo_addr(u8 dir, enum asrc_pair_index index)
10631063
return REG_ASRDx(dir, index);
10641064
}
10651065

1066+
/* Get sample numbers in FIFO */
1067+
static unsigned int fsl_asrc_get_output_fifo_size(struct fsl_asrc_pair *pair)
1068+
{
1069+
struct fsl_asrc *asrc = pair->asrc;
1070+
enum asrc_pair_index index = pair->index;
1071+
u32 val;
1072+
1073+
regmap_read(asrc->regmap, REG_ASRFST(index), &val);
1074+
1075+
val &= ASRFSTi_OUTPUT_FIFO_MASK;
1076+
1077+
return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
1078+
}
1079+
1080+
static int fsl_asrc_m2m_prepare(struct fsl_asrc_pair *pair)
1081+
{
1082+
struct fsl_asrc_pair_priv *pair_priv = pair->private;
1083+
struct fsl_asrc *asrc = pair->asrc;
1084+
struct device *dev = &asrc->pdev->dev;
1085+
struct asrc_config config;
1086+
int ret;
1087+
1088+
/* fill config */
1089+
config.pair = pair->index;
1090+
config.channel_num = pair->channels;
1091+
config.input_sample_rate = pair->rate[IN];
1092+
config.output_sample_rate = pair->rate[OUT];
1093+
config.input_format = pair->sample_format[IN];
1094+
config.output_format = pair->sample_format[OUT];
1095+
config.inclk = INCLK_NONE;
1096+
config.outclk = OUTCLK_ASRCK1_CLK;
1097+
1098+
pair_priv->config = &config;
1099+
ret = fsl_asrc_config_pair(pair, true);
1100+
if (ret) {
1101+
dev_err(dev, "failed to config pair: %d\n", ret);
1102+
return ret;
1103+
}
1104+
1105+
pair->first_convert = 1;
1106+
1107+
return 0;
1108+
}
1109+
1110+
static int fsl_asrc_m2m_start(struct fsl_asrc_pair *pair)
1111+
{
1112+
if (pair->first_convert) {
1113+
fsl_asrc_start_pair(pair);
1114+
pair->first_convert = 0;
1115+
}
1116+
/*
1117+
* Clear DMA request during the stall state of ASRC:
1118+
* During STALL state, the remaining in input fifo would never be
1119+
* smaller than the input threshold while the output fifo would not
1120+
* be bigger than output one. Thus the DMA request would be cleared.
1121+
*/
1122+
fsl_asrc_set_watermarks(pair, ASRC_FIFO_THRESHOLD_MIN,
1123+
ASRC_FIFO_THRESHOLD_MAX);
1124+
1125+
/* Update the real input threshold to raise DMA request */
1126+
fsl_asrc_set_watermarks(pair, ASRC_M2M_INPUTFIFO_WML,
1127+
ASRC_M2M_OUTPUTFIFO_WML);
1128+
1129+
return 0;
1130+
}
1131+
1132+
static int fsl_asrc_m2m_stop(struct fsl_asrc_pair *pair)
1133+
{
1134+
if (!pair->first_convert) {
1135+
fsl_asrc_stop_pair(pair);
1136+
pair->first_convert = 1;
1137+
}
1138+
1139+
return 0;
1140+
}
1141+
1142+
/* calculate capture data length according to output data length and sample rate */
1143+
static int fsl_asrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length)
1144+
{
1145+
unsigned int in_width, out_width;
1146+
unsigned int channels = pair->channels;
1147+
unsigned int in_samples, out_samples;
1148+
unsigned int out_length;
1149+
1150+
in_width = snd_pcm_format_physical_width(pair->sample_format[IN]) / 8;
1151+
out_width = snd_pcm_format_physical_width(pair->sample_format[OUT]) / 8;
1152+
1153+
in_samples = input_buffer_length / in_width / channels;
1154+
out_samples = pair->rate[OUT] * in_samples / pair->rate[IN];
1155+
out_length = (out_samples - ASRC_OUTPUT_LAST_SAMPLE) * out_width * channels;
1156+
1157+
return out_length;
1158+
}
1159+
1160+
static int fsl_asrc_m2m_get_maxburst(u8 dir, struct fsl_asrc_pair *pair)
1161+
{
1162+
struct fsl_asrc *asrc = pair->asrc;
1163+
struct fsl_asrc_priv *asrc_priv = asrc->private;
1164+
int wml = (dir == IN) ? ASRC_M2M_INPUTFIFO_WML : ASRC_M2M_OUTPUTFIFO_WML;
1165+
1166+
if (!asrc_priv->soc->use_edma)
1167+
return wml * pair->channels;
1168+
else
1169+
return 1;
1170+
}
1171+
1172+
static int fsl_asrc_m2m_get_cap(struct fsl_asrc_m2m_cap *cap)
1173+
{
1174+
cap->fmt_in = FSL_ASRC_FORMATS;
1175+
cap->fmt_out = FSL_ASRC_FORMATS | SNDRV_PCM_FMTBIT_S8;
1176+
1177+
cap->rate_in = supported_asrc_rate;
1178+
cap->rate_in_count = ARRAY_SIZE(supported_asrc_rate);
1179+
cap->rate_out = supported_asrc_rate;
1180+
cap->rate_out_count = ARRAY_SIZE(supported_asrc_rate);
1181+
cap->chan_min = 1;
1182+
cap->chan_max = 10;
1183+
1184+
return 0;
1185+
}
1186+
1187+
static int fsl_asrc_m2m_pair_resume(struct fsl_asrc_pair *pair)
1188+
{
1189+
struct fsl_asrc *asrc = pair->asrc;
1190+
int i;
1191+
1192+
for (i = 0; i < pair->channels * 4; i++)
1193+
regmap_write(asrc->regmap, REG_ASRDI(pair->index), 0);
1194+
1195+
pair->first_convert = 1;
1196+
return 0;
1197+
}
1198+
10661199
static int fsl_asrc_runtime_resume(struct device *dev);
10671200
static int fsl_asrc_runtime_suspend(struct device *dev);
10681201

@@ -1147,6 +1280,15 @@ static int fsl_asrc_probe(struct platform_device *pdev)
11471280
asrc->get_fifo_addr = fsl_asrc_get_fifo_addr;
11481281
asrc->pair_priv_size = sizeof(struct fsl_asrc_pair_priv);
11491282

1283+
asrc->m2m_prepare = fsl_asrc_m2m_prepare;
1284+
asrc->m2m_start = fsl_asrc_m2m_start;
1285+
asrc->m2m_stop = fsl_asrc_m2m_stop;
1286+
asrc->get_output_fifo_size = fsl_asrc_get_output_fifo_size;
1287+
asrc->m2m_calc_out_len = fsl_asrc_m2m_calc_out_len;
1288+
asrc->m2m_get_maxburst = fsl_asrc_m2m_get_maxburst;
1289+
asrc->m2m_pair_resume = fsl_asrc_m2m_pair_resume;
1290+
asrc->m2m_get_cap = fsl_asrc_m2m_get_cap;
1291+
11501292
if (of_device_is_compatible(np, "fsl,imx35-asrc")) {
11511293
asrc_priv->clk_map[IN] = input_clk_map_imx35;
11521294
asrc_priv->clk_map[OUT] = output_clk_map_imx35;
@@ -1242,6 +1384,12 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12421384
goto err_pm_get_sync;
12431385
}
12441386

1387+
ret = fsl_asrc_m2m_init(asrc);
1388+
if (ret) {
1389+
dev_err(&pdev->dev, "failed to init m2m device %d\n", ret);
1390+
return ret;
1391+
}
1392+
12451393
return 0;
12461394

12471395
err_pm_get_sync:
@@ -1254,6 +1402,10 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12541402

12551403
static void fsl_asrc_remove(struct platform_device *pdev)
12561404
{
1405+
struct fsl_asrc *asrc = dev_get_drvdata(&pdev->dev);
1406+
1407+
fsl_asrc_m2m_exit(asrc);
1408+
12571409
pm_runtime_disable(&pdev->dev);
12581410
if (!pm_runtime_status_suspended(&pdev->dev))
12591411
fsl_asrc_runtime_suspend(&pdev->dev);
@@ -1355,10 +1507,29 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
13551507
return 0;
13561508
}
13571509

1510+
static int fsl_asrc_suspend(struct device *dev)
1511+
{
1512+
struct fsl_asrc *asrc = dev_get_drvdata(dev);
1513+
int ret;
1514+
1515+
fsl_asrc_m2m_suspend(asrc);
1516+
ret = pm_runtime_force_suspend(dev);
1517+
return ret;
1518+
}
1519+
1520+
static int fsl_asrc_resume(struct device *dev)
1521+
{
1522+
struct fsl_asrc *asrc = dev_get_drvdata(dev);
1523+
int ret;
1524+
1525+
ret = pm_runtime_force_resume(dev);
1526+
fsl_asrc_m2m_resume(asrc);
1527+
return ret;
1528+
}
1529+
13581530
static const struct dev_pm_ops fsl_asrc_pm = {
1359-
SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
1360-
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1361-
pm_runtime_force_resume)
1531+
RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL)
1532+
SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume)
13621533
};
13631534

13641535
static const struct fsl_asrc_soc_data fsl_asrc_imx35_data = {
@@ -1396,7 +1567,7 @@ static struct platform_driver fsl_asrc_driver = {
13961567
.driver = {
13971568
.name = "fsl-asrc",
13981569
.of_match_table = fsl_asrc_ids,
1399-
.pm = &fsl_asrc_pm,
1570+
.pm = pm_ptr(&fsl_asrc_pm),
14001571
},
14011572
};
14021573
module_platform_driver(fsl_asrc_driver);

sound/soc/fsl/fsl_asrc.h

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include "fsl_asrc_common.h"
1414

15+
#define ASRC_M2M_INPUTFIFO_WML 0x4
16+
#define ASRC_M2M_OUTPUTFIFO_WML 0x2
1517
#define ASRC_DMA_BUFFER_NUM 2
1618
#define ASRC_INPUTFIFO_THRESHOLD 32
1719
#define ASRC_OUTPUTFIFO_THRESHOLD 32

0 commit comments

Comments
 (0)