Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: fsl: add memory to memory function for ASRC

Merge series from Shengjiu Wang <shengjiu.wang@nxp.com>:

This function is base on the accelerator implementation
for compress API:
04177158cf98 ("ALSA: compress_offload: introduce accel operation mode")

Audio signal processing also has the requirement for memory to
memory similar as Video.

This asrc memory to memory (memory ->asrc->memory) case is a non
real time use case.

User fills the input buffer to the asrc module, after conversion, then asrc
sends back the output buffer to user. So it is not a traditional ALSA playback
and capture case.

Because we had implemented the "memory -> asrc ->i2s device-> codec"
use case in ALSA. Now the "memory->asrc->memory" needs
to reuse the code in asrc driver, so the patch 1 and patch 2 is for refining
the code to make it can be shared by the "memory->asrc->memory"
driver.

Other change is to add memory to memory support for two kinds of i.MX ASRC
modules.

+1261 -9
+21 -2
include/uapi/sound/compress_params.h
··· 334 334 struct snd_dec_wma wma_d; 335 335 struct snd_dec_alac alac_d; 336 336 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; 337 345 } __attribute__((packed, aligned(4))); 338 346 339 347 /** struct snd_codec_desc - description of codec capabilities ··· 355 347 * @modes: Supported modes. See SND_AUDIOMODE defines 356 348 * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines 357 349 * @min_buffer: Minimum buffer size handled by codec implementation 350 + * @pcm_formats: Output (for decoders) or input (for encoders) 351 + * PCM formats (required to accel mode, 0 for other modes) 352 + * @u_space: union space (for codec dependent data) 358 353 * @reserved: reserved for future use 359 354 * 360 355 * This structure provides a scalar value for profiles, modes and stream ··· 381 370 __u32 modes; 382 371 __u32 formats; 383 372 __u32 min_buffer; 384 - __u32 reserved[15]; 373 + __u32 pcm_formats; 374 + union { 375 + __u32 u_space[6]; 376 + struct snd_codec_desc_src src; 377 + } __attribute__((packed, aligned(4))); 378 + __u32 reserved[8]; 385 379 } __attribute__((packed, aligned(4))); 386 380 387 381 /** struct snd_codec ··· 411 395 * @align: Block alignment in bytes of an audio sample. 412 396 * Only required for PCM or IEC formats. 413 397 * @options: encoder-specific settings 398 + * @pcm_format: Output (for decoders) or input (for encoders) 399 + * PCM formats (required to accel mode, 0 for other modes) 414 400 * @reserved: reserved for future use 415 401 */ 416 402 ··· 429 411 __u32 format; 430 412 __u32 align; 431 413 union snd_codec_options options; 432 - __u32 reserved[3]; 414 + __u32 pcm_format; 415 + __u32 reserved[2]; 433 416 } __attribute__((packed, aligned(4))); 434 417 435 418 #endif
+2
sound/soc/fsl/Kconfig
··· 8 8 depends on HAS_DMA 9 9 select REGMAP_MMIO 10 10 select SND_SOC_GENERIC_DMAENGINE_PCM 11 + select SND_COMPRESS_ACCEL 12 + select SND_COMPRESS_OFFLOAD 11 13 help 12 14 Say Y if you want to add Asynchronous Sample Rate Converter (ASRC) 13 15 support for the Freescale CPUs.
+1 -1
sound/soc/fsl/Makefile
··· 10 10 # Freescale SSI/DMA/SAI/SPDIF Support 11 11 snd-soc-fsl-audmix-y := fsl_audmix.o 12 12 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 14 14 snd-soc-fsl-lpc3xxx-y := lpc3xxx-pcm.o lpc3xxx-i2s.o 15 15 snd-soc-fsl-sai-y := fsl_sai.o 16 16 snd-soc-fsl-ssi-y := fsl_ssi.o
+175 -4
sound/soc/fsl/fsl_asrc.c
··· 1063 1063 return REG_ASRDx(dir, index); 1064 1064 } 1065 1065 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 + 1066 1199 static int fsl_asrc_runtime_resume(struct device *dev); 1067 1200 static int fsl_asrc_runtime_suspend(struct device *dev); 1068 1201 ··· 1279 1146 asrc->release_pair = fsl_asrc_release_pair; 1280 1147 asrc->get_fifo_addr = fsl_asrc_get_fifo_addr; 1281 1148 asrc->pair_priv_size = sizeof(struct fsl_asrc_pair_priv); 1149 + 1150 + asrc->m2m_prepare = fsl_asrc_m2m_prepare; 1151 + asrc->m2m_start = fsl_asrc_m2m_start; 1152 + asrc->m2m_stop = fsl_asrc_m2m_stop; 1153 + asrc->get_output_fifo_size = fsl_asrc_get_output_fifo_size; 1154 + asrc->m2m_calc_out_len = fsl_asrc_m2m_calc_out_len; 1155 + asrc->m2m_get_maxburst = fsl_asrc_m2m_get_maxburst; 1156 + asrc->m2m_pair_resume = fsl_asrc_m2m_pair_resume; 1157 + asrc->m2m_get_cap = fsl_asrc_m2m_get_cap; 1282 1158 1283 1159 if (of_device_is_compatible(np, "fsl,imx35-asrc")) { 1284 1160 asrc_priv->clk_map[IN] = input_clk_map_imx35; ··· 1384 1242 goto err_pm_get_sync; 1385 1243 } 1386 1244 1245 + ret = fsl_asrc_m2m_init(asrc); 1246 + if (ret) { 1247 + dev_err(&pdev->dev, "failed to init m2m device %d\n", ret); 1248 + return ret; 1249 + } 1250 + 1387 1251 return 0; 1388 1252 1389 1253 err_pm_get_sync: ··· 1402 1254 1403 1255 static void fsl_asrc_remove(struct platform_device *pdev) 1404 1256 { 1257 + struct fsl_asrc *asrc = dev_get_drvdata(&pdev->dev); 1258 + 1259 + fsl_asrc_m2m_exit(asrc); 1260 + 1405 1261 pm_runtime_disable(&pdev->dev); 1406 1262 if (!pm_runtime_status_suspended(&pdev->dev)) 1407 1263 fsl_asrc_runtime_suspend(&pdev->dev); ··· 1507 1355 return 0; 1508 1356 } 1509 1357 1358 + static int fsl_asrc_suspend(struct device *dev) 1359 + { 1360 + struct fsl_asrc *asrc = dev_get_drvdata(dev); 1361 + int ret; 1362 + 1363 + fsl_asrc_m2m_suspend(asrc); 1364 + ret = pm_runtime_force_suspend(dev); 1365 + return ret; 1366 + } 1367 + 1368 + static int fsl_asrc_resume(struct device *dev) 1369 + { 1370 + struct fsl_asrc *asrc = dev_get_drvdata(dev); 1371 + int ret; 1372 + 1373 + ret = pm_runtime_force_resume(dev); 1374 + fsl_asrc_m2m_resume(asrc); 1375 + return ret; 1376 + } 1377 + 1510 1378 static const struct dev_pm_ops fsl_asrc_pm = { 1511 - SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) 1512 - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1513 - pm_runtime_force_resume) 1379 + RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) 1380 + SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume) 1514 1381 }; 1515 1382 1516 1383 static const struct fsl_asrc_soc_data fsl_asrc_imx35_data = { ··· 1567 1396 .driver = { 1568 1397 .name = "fsl-asrc", 1569 1398 .of_match_table = fsl_asrc_ids, 1570 - .pm = &fsl_asrc_pm, 1399 + .pm = pm_ptr(&fsl_asrc_pm), 1571 1400 }, 1572 1401 }; 1573 1402 module_platform_driver(fsl_asrc_driver);
+2
sound/soc/fsl/fsl_asrc.h
··· 12 12 13 13 #include "fsl_asrc_common.h" 14 14 15 + #define ASRC_M2M_INPUTFIFO_WML 0x4 16 + #define ASRC_M2M_OUTPUTFIFO_WML 0x2 15 17 #define ASRC_DMA_BUFFER_NUM 2 16 18 #define ASRC_INPUTFIFO_THRESHOLD 32 17 19 #define ASRC_OUTPUTFIFO_THRESHOLD 32
+70
sound/soc/fsl/fsl_asrc_common.h
··· 22 22 #define PAIR_CTX_NUM 0x4 23 23 24 24 /** 25 + * struct fsl_asrc_m2m_cap - capability data 26 + * @fmt_in: input sample format 27 + * @fmt_out: output sample format 28 + * @chan_min: minimum channel number 29 + * @chan_max: maximum channel number 30 + * @rate_in: minimum rate 31 + * @rate_out: maximum rete 32 + */ 33 + struct fsl_asrc_m2m_cap { 34 + u64 fmt_in; 35 + u64 fmt_out; 36 + int chan_min; 37 + int chan_max; 38 + const unsigned int *rate_in; 39 + int rate_in_count; 40 + const unsigned int *rate_out; 41 + int rate_out_count; 42 + }; 43 + 44 + /** 25 45 * fsl_asrc_pair: ASRC Pair common data 26 46 * 27 47 * @asrc: pointer to its parent module ··· 54 34 * @pos: hardware pointer position 55 35 * @req_dma_chan: flag to release dev_to_dev chan 56 36 * @private: pair private area 37 + * @complete: dma task complete 38 + * @sample_format: format of m2m 39 + * @rate: rate of m2m 40 + * @buf_len: buffer length of m2m 41 + * @dma_buffer: buffer pointers 42 + * @first_convert: start of conversion 43 + * @ratio_mod_flag: flag for new ratio modifier 44 + * @ratio_mod: ratio modification 57 45 */ 58 46 struct fsl_asrc_pair { 59 47 struct fsl_asrc *asrc; ··· 77 49 bool req_dma_chan; 78 50 79 51 void *private; 52 + 53 + /* used for m2m */ 54 + struct completion complete[2]; 55 + snd_pcm_format_t sample_format[2]; 56 + unsigned int rate[2]; 57 + unsigned int buf_len[2]; 58 + struct snd_dma_buffer dma_buffer[2]; 59 + unsigned int first_convert; 60 + bool ratio_mod_flag; 61 + unsigned int ratio_mod; 80 62 }; 81 63 82 64 /** ··· 100 62 * @mem_clk: clock source to access register 101 63 * @ipg_clk: clock source to drive peripheral 102 64 * @spba_clk: SPBA clock (optional, depending on SoC design) 65 + * @card: compress sound card 103 66 * @lock: spin lock for resource protection 104 67 * @pair: pair pointers 105 68 * @channel_avail: non-occupied channel numbers ··· 111 72 * @request_pair: function pointer 112 73 * @release_pair: function pointer 113 74 * @get_fifo_addr: function pointer 75 + * @m2m_get_cap: function pointer 76 + * @m2m_prepare: function pointer 77 + * @m2m_start: function pointer 78 + * @m2m_unprepare: function pointer 79 + * @m2m_stop: function pointer 80 + * @m2m_calc_out_len: function pointer 81 + * @m2m_get_maxburst: function pointer 82 + * @m2m_pair_suspend: function pointer 83 + * @m2m_pair_resume: function pointer 84 + * @m2m_set_ratio_mod: function pointer 85 + * @get_output_fifo_size: function pointer 114 86 * @pair_priv_size: size of pair private struct. 115 87 * @private: private data structure 116 88 */ ··· 134 84 struct clk *mem_clk; 135 85 struct clk *ipg_clk; 136 86 struct clk *spba_clk; 87 + struct snd_card *card; 137 88 spinlock_t lock; /* spin lock for resource protection */ 138 89 139 90 struct fsl_asrc_pair *pair[PAIR_CTX_NUM]; ··· 148 97 int (*request_pair)(int channels, struct fsl_asrc_pair *pair); 149 98 void (*release_pair)(struct fsl_asrc_pair *pair); 150 99 int (*get_fifo_addr)(u8 dir, enum asrc_pair_index index); 100 + int (*m2m_get_cap)(struct fsl_asrc_m2m_cap *cap); 101 + 102 + int (*m2m_prepare)(struct fsl_asrc_pair *pair); 103 + int (*m2m_start)(struct fsl_asrc_pair *pair); 104 + int (*m2m_unprepare)(struct fsl_asrc_pair *pair); 105 + int (*m2m_stop)(struct fsl_asrc_pair *pair); 106 + 107 + int (*m2m_calc_out_len)(struct fsl_asrc_pair *pair, int input_buffer_length); 108 + int (*m2m_get_maxburst)(u8 dir, struct fsl_asrc_pair *pair); 109 + int (*m2m_pair_suspend)(struct fsl_asrc_pair *pair); 110 + int (*m2m_pair_resume)(struct fsl_asrc_pair *pair); 111 + int (*m2m_set_ratio_mod)(struct fsl_asrc_pair *pair, int val); 112 + 113 + unsigned int (*get_output_fifo_size)(struct fsl_asrc_pair *pair); 151 114 size_t pair_priv_size; 152 115 153 116 void *private; ··· 169 104 170 105 #define DRV_NAME "fsl-asrc-dai" 171 106 extern struct snd_soc_component_driver fsl_asrc_component; 107 + 108 + int fsl_asrc_m2m_init(struct fsl_asrc *asrc); 109 + void fsl_asrc_m2m_exit(struct fsl_asrc *asrc); 110 + int fsl_asrc_m2m_resume(struct fsl_asrc *asrc); 111 + int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc); 172 112 173 113 #endif /* _FSL_ASRC_COMMON_H */
+727
sound/soc/fsl/fsl_asrc_m2m.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Copyright (C) 2014-2016 Freescale Semiconductor, Inc. 4 + // Copyright (C) 2019-2024 NXP 5 + // 6 + // Freescale ASRC Memory to Memory (M2M) driver 7 + 8 + #include <linux/dma/imx-dma.h> 9 + #include <linux/dma-buf.h> 10 + #include <linux/dma-mapping.h> 11 + #include <linux/pm_runtime.h> 12 + #include <sound/asound.h> 13 + #include <sound/dmaengine_pcm.h> 14 + #include <sound/initval.h> 15 + 16 + #include "fsl_asrc_common.h" 17 + 18 + #define DIR_STR(dir) (dir) == IN ? "in" : "out" 19 + 20 + #define ASRC_xPUT_DMA_CALLBACK(dir) \ 21 + (((dir) == IN) ? asrc_input_dma_callback \ 22 + : asrc_output_dma_callback) 23 + 24 + /* Maximum output and capture buffer size */ 25 + #define ASRC_M2M_BUFFER_SIZE (512 * 1024) 26 + 27 + /* Maximum output and capture period size */ 28 + #define ASRC_M2M_PERIOD_SIZE (48 * 1024) 29 + 30 + /* dma complete callback */ 31 + static void asrc_input_dma_callback(void *data) 32 + { 33 + struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data; 34 + 35 + complete(&pair->complete[IN]); 36 + } 37 + 38 + /* dma complete callback */ 39 + static void asrc_output_dma_callback(void *data) 40 + { 41 + struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data; 42 + 43 + complete(&pair->complete[OUT]); 44 + } 45 + 46 + /** 47 + *asrc_read_last_fifo: read all the remaining data from FIFO 48 + *@pair: Structure pointer of fsl_asrc_pair 49 + *@dma_vaddr: virtual address of capture buffer 50 + *@length: payload length of capture buffer 51 + */ 52 + static void asrc_read_last_fifo(struct fsl_asrc_pair *pair, void *dma_vaddr, u32 *length) 53 + { 54 + struct fsl_asrc *asrc = pair->asrc; 55 + enum asrc_pair_index index = pair->index; 56 + u32 i, reg, size, t_size = 0, width; 57 + u32 *reg32 = NULL; 58 + u16 *reg16 = NULL; 59 + u8 *reg24 = NULL; 60 + 61 + width = snd_pcm_format_physical_width(pair->sample_format[OUT]); 62 + if (width == 32) 63 + reg32 = dma_vaddr + *length; 64 + else if (width == 16) 65 + reg16 = dma_vaddr + *length; 66 + else 67 + reg24 = dma_vaddr + *length; 68 + retry: 69 + size = asrc->get_output_fifo_size(pair); 70 + if (size + *length > ASRC_M2M_BUFFER_SIZE) 71 + goto end; 72 + 73 + for (i = 0; i < size * pair->channels; i++) { 74 + regmap_read(asrc->regmap, asrc->get_fifo_addr(OUT, index), &reg); 75 + if (reg32) { 76 + *reg32++ = reg; 77 + } else if (reg16) { 78 + *reg16++ = (u16)reg; 79 + } else { 80 + *reg24++ = (u8)reg; 81 + *reg24++ = (u8)(reg >> 8); 82 + *reg24++ = (u8)(reg >> 16); 83 + } 84 + } 85 + t_size += size; 86 + 87 + /* In case there is data left in FIFO */ 88 + if (size) 89 + goto retry; 90 + end: 91 + /* Update payload length */ 92 + if (reg32) 93 + *length += t_size * pair->channels * 4; 94 + else if (reg16) 95 + *length += t_size * pair->channels * 2; 96 + else 97 + *length += t_size * pair->channels * 3; 98 + } 99 + 100 + /* config dma channel */ 101 + static int asrc_dmaconfig(struct fsl_asrc_pair *pair, 102 + struct dma_chan *chan, 103 + u32 dma_addr, dma_addr_t buf_addr, u32 buf_len, 104 + int dir, int width) 105 + { 106 + struct fsl_asrc *asrc = pair->asrc; 107 + struct device *dev = &asrc->pdev->dev; 108 + struct dma_slave_config slave_config; 109 + enum dma_slave_buswidth buswidth; 110 + unsigned int sg_len, max_period_size; 111 + struct scatterlist *sg; 112 + int ret, i; 113 + 114 + switch (width) { 115 + case 8: 116 + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; 117 + break; 118 + case 16: 119 + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 120 + break; 121 + case 24: 122 + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; 123 + break; 124 + case 32: 125 + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; 126 + break; 127 + default: 128 + dev_err(dev, "invalid word width\n"); 129 + return -EINVAL; 130 + } 131 + 132 + memset(&slave_config, 0, sizeof(slave_config)); 133 + if (dir == IN) { 134 + slave_config.direction = DMA_MEM_TO_DEV; 135 + slave_config.dst_addr = dma_addr; 136 + slave_config.dst_addr_width = buswidth; 137 + slave_config.dst_maxburst = asrc->m2m_get_maxburst(IN, pair); 138 + } else { 139 + slave_config.direction = DMA_DEV_TO_MEM; 140 + slave_config.src_addr = dma_addr; 141 + slave_config.src_addr_width = buswidth; 142 + slave_config.src_maxburst = asrc->m2m_get_maxburst(OUT, pair); 143 + } 144 + 145 + ret = dmaengine_slave_config(chan, &slave_config); 146 + if (ret) { 147 + dev_err(dev, "failed to config dmaengine for %s task: %d\n", 148 + DIR_STR(dir), ret); 149 + return -EINVAL; 150 + } 151 + 152 + max_period_size = rounddown(ASRC_M2M_PERIOD_SIZE, width * pair->channels / 8); 153 + /* scatter gather mode */ 154 + sg_len = buf_len / max_period_size; 155 + if (buf_len % max_period_size) 156 + sg_len += 1; 157 + 158 + sg = kmalloc_array(sg_len, sizeof(*sg), GFP_KERNEL); 159 + if (!sg) 160 + return -ENOMEM; 161 + 162 + sg_init_table(sg, sg_len); 163 + for (i = 0; i < (sg_len - 1); i++) { 164 + sg_dma_address(&sg[i]) = buf_addr + i * max_period_size; 165 + sg_dma_len(&sg[i]) = max_period_size; 166 + } 167 + sg_dma_address(&sg[i]) = buf_addr + i * max_period_size; 168 + sg_dma_len(&sg[i]) = buf_len - i * max_period_size; 169 + 170 + pair->desc[dir] = dmaengine_prep_slave_sg(chan, sg, sg_len, 171 + slave_config.direction, 172 + DMA_PREP_INTERRUPT); 173 + kfree(sg); 174 + if (!pair->desc[dir]) { 175 + dev_err(dev, "failed to prepare dmaengine for %s task\n", DIR_STR(dir)); 176 + return -EINVAL; 177 + } 178 + 179 + pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir); 180 + pair->desc[dir]->callback_param = pair; 181 + 182 + return 0; 183 + } 184 + 185 + /* main function of converter */ 186 + static void asrc_m2m_device_run(struct fsl_asrc_pair *pair, struct snd_compr_task_runtime *task) 187 + { 188 + struct fsl_asrc *asrc = pair->asrc; 189 + struct device *dev = &asrc->pdev->dev; 190 + enum asrc_pair_index index = pair->index; 191 + struct snd_dma_buffer *src_buf, *dst_buf; 192 + unsigned int in_buf_len; 193 + unsigned int out_dma_len; 194 + unsigned int width; 195 + u32 fifo_addr; 196 + int ret; 197 + 198 + /* set ratio mod */ 199 + if (asrc->m2m_set_ratio_mod) { 200 + if (pair->ratio_mod_flag) { 201 + asrc->m2m_set_ratio_mod(pair, pair->ratio_mod); 202 + pair->ratio_mod_flag = false; 203 + } 204 + } 205 + 206 + src_buf = &pair->dma_buffer[IN]; 207 + dst_buf = &pair->dma_buffer[OUT]; 208 + 209 + width = snd_pcm_format_physical_width(pair->sample_format[IN]); 210 + fifo_addr = asrc->paddr + asrc->get_fifo_addr(IN, index); 211 + 212 + in_buf_len = task->input_size; 213 + 214 + if (in_buf_len < width * pair->channels / 8 || 215 + in_buf_len > ASRC_M2M_BUFFER_SIZE || 216 + in_buf_len % (width * pair->channels / 8)) { 217 + dev_err(dev, "out buffer size is error: [%d]\n", in_buf_len); 218 + goto end; 219 + } 220 + 221 + /* dma config for output dma channel */ 222 + ret = asrc_dmaconfig(pair, 223 + pair->dma_chan[IN], 224 + fifo_addr, 225 + src_buf->addr, 226 + in_buf_len, IN, width); 227 + if (ret) { 228 + dev_err(dev, "out dma config error\n"); 229 + goto end; 230 + } 231 + 232 + width = snd_pcm_format_physical_width(pair->sample_format[OUT]); 233 + fifo_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index); 234 + out_dma_len = asrc->m2m_calc_out_len(pair, in_buf_len); 235 + if (out_dma_len > 0 && out_dma_len <= ASRC_M2M_BUFFER_SIZE) { 236 + /* dma config for capture dma channel */ 237 + ret = asrc_dmaconfig(pair, 238 + pair->dma_chan[OUT], 239 + fifo_addr, 240 + dst_buf->addr, 241 + out_dma_len, OUT, width); 242 + if (ret) { 243 + dev_err(dev, "cap dma config error\n"); 244 + goto end; 245 + } 246 + } else if (out_dma_len > ASRC_M2M_BUFFER_SIZE) { 247 + dev_err(dev, "cap buffer size error\n"); 248 + goto end; 249 + } 250 + 251 + reinit_completion(&pair->complete[IN]); 252 + reinit_completion(&pair->complete[OUT]); 253 + 254 + /* Submit DMA request */ 255 + dmaengine_submit(pair->desc[IN]); 256 + dma_async_issue_pending(pair->desc[IN]->chan); 257 + if (out_dma_len > 0) { 258 + dmaengine_submit(pair->desc[OUT]); 259 + dma_async_issue_pending(pair->desc[OUT]->chan); 260 + } 261 + 262 + asrc->m2m_start(pair); 263 + 264 + if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) { 265 + dev_err(dev, "out DMA task timeout\n"); 266 + goto end; 267 + } 268 + 269 + if (out_dma_len > 0) { 270 + if (!wait_for_completion_interruptible_timeout(&pair->complete[OUT], 10 * HZ)) { 271 + dev_err(dev, "cap DMA task timeout\n"); 272 + goto end; 273 + } 274 + } 275 + 276 + /* read the last words from FIFO */ 277 + asrc_read_last_fifo(pair, dst_buf->area, &out_dma_len); 278 + /* update payload length for capture */ 279 + task->output_size = out_dma_len; 280 + end: 281 + return; 282 + } 283 + 284 + static int fsl_asrc_m2m_comp_open(struct snd_compr_stream *stream) 285 + { 286 + struct fsl_asrc *asrc = stream->private_data; 287 + struct snd_compr_runtime *runtime = stream->runtime; 288 + struct device *dev = &asrc->pdev->dev; 289 + struct fsl_asrc_pair *pair; 290 + int size, ret; 291 + 292 + pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL); 293 + if (!pair) 294 + return -ENOMEM; 295 + 296 + pair->private = (void *)pair + sizeof(struct fsl_asrc_pair); 297 + pair->asrc = asrc; 298 + 299 + init_completion(&pair->complete[IN]); 300 + init_completion(&pair->complete[OUT]); 301 + 302 + runtime->private_data = pair; 303 + 304 + size = ASRC_M2M_BUFFER_SIZE; 305 + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[IN]); 306 + if (ret) 307 + goto error_alloc_in_buf; 308 + 309 + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[OUT]); 310 + if (ret) 311 + goto error_alloc_out_buf; 312 + 313 + ret = pm_runtime_get_sync(dev); 314 + if (ret < 0) { 315 + dev_err(dev, "Failed to power up asrc\n"); 316 + goto err_pm_runtime; 317 + } 318 + 319 + return 0; 320 + 321 + err_pm_runtime: 322 + snd_dma_free_pages(&pair->dma_buffer[OUT]); 323 + error_alloc_out_buf: 324 + snd_dma_free_pages(&pair->dma_buffer[IN]); 325 + error_alloc_in_buf: 326 + kfree(pair); 327 + return ret; 328 + } 329 + 330 + static int fsl_asrc_m2m_comp_release(struct snd_compr_stream *stream) 331 + { 332 + struct fsl_asrc *asrc = stream->private_data; 333 + struct snd_compr_runtime *runtime = stream->runtime; 334 + struct fsl_asrc_pair *pair = runtime->private_data; 335 + struct device *dev = &asrc->pdev->dev; 336 + 337 + pm_runtime_put_sync(dev); 338 + 339 + snd_dma_free_pages(&pair->dma_buffer[IN]); 340 + snd_dma_free_pages(&pair->dma_buffer[OUT]); 341 + 342 + kfree(runtime->private_data); 343 + 344 + return 0; 345 + } 346 + 347 + static int fsl_asrc_m2m_comp_set_params(struct snd_compr_stream *stream, 348 + struct snd_compr_params *params) 349 + { 350 + struct fsl_asrc *asrc = stream->private_data; 351 + struct snd_compr_runtime *runtime = stream->runtime; 352 + struct fsl_asrc_pair *pair = runtime->private_data; 353 + struct fsl_asrc_m2m_cap cap; 354 + int ret, i; 355 + 356 + ret = asrc->m2m_get_cap(&cap); 357 + if (ret) 358 + return -EINVAL; 359 + 360 + if (pcm_format_to_bits(params->codec.format) & cap.fmt_in) 361 + pair->sample_format[IN] = params->codec.format; 362 + else 363 + return -EINVAL; 364 + 365 + if (pcm_format_to_bits(params->codec.pcm_format) & cap.fmt_out) 366 + pair->sample_format[OUT] = params->codec.pcm_format; 367 + else 368 + return -EINVAL; 369 + 370 + /* check input rate is in scope */ 371 + for (i = 0; i < cap.rate_in_count; i++) 372 + if (params->codec.sample_rate == cap.rate_in[i]) { 373 + pair->rate[IN] = params->codec.sample_rate; 374 + break; 375 + } 376 + if (i == cap.rate_in_count) 377 + return -EINVAL; 378 + 379 + /* check output rate is in scope */ 380 + for (i = 0; i < cap.rate_out_count; i++) 381 + if (params->codec.options.src_d.out_sample_rate == cap.rate_out[i]) { 382 + pair->rate[OUT] = params->codec.options.src_d.out_sample_rate; 383 + break; 384 + } 385 + if (i == cap.rate_out_count) 386 + return -EINVAL; 387 + 388 + if (params->codec.ch_in != params->codec.ch_out || 389 + params->codec.ch_in < cap.chan_min || 390 + params->codec.ch_in > cap.chan_max) 391 + return -EINVAL; 392 + 393 + pair->channels = params->codec.ch_in; 394 + pair->buf_len[IN] = params->buffer.fragment_size; 395 + pair->buf_len[OUT] = params->buffer.fragment_size; 396 + 397 + return 0; 398 + } 399 + 400 + static int fsl_asrc_m2m_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) 401 + { 402 + struct snd_dma_buffer *dmab = dmabuf->priv; 403 + 404 + return snd_dma_buffer_mmap(dmab, vma); 405 + } 406 + 407 + static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *attachment, 408 + enum dma_data_direction direction) 409 + { 410 + struct snd_dma_buffer *dmab = attachment->dmabuf->priv; 411 + struct sg_table *sgt; 412 + 413 + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); 414 + if (!sgt) 415 + return NULL; 416 + 417 + if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0) 418 + goto free; 419 + 420 + if (dma_map_sgtable(attachment->dev, sgt, direction, 0)) 421 + goto free; 422 + 423 + return sgt; 424 + 425 + free: 426 + sg_free_table(sgt); 427 + kfree(sgt); 428 + return NULL; 429 + } 430 + 431 + static void fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment *attachment, 432 + struct sg_table *table, 433 + enum dma_data_direction direction) 434 + { 435 + dma_unmap_sgtable(attachment->dev, table, direction, 0); 436 + } 437 + 438 + static void fsl_asrc_m2m_release(struct dma_buf *dmabuf) 439 + { 440 + /* buffer is released by fsl_asrc_m2m_comp_release() */ 441 + } 442 + 443 + static const struct dma_buf_ops fsl_asrc_m2m_dma_buf_ops = { 444 + .mmap = fsl_asrc_m2m_mmap, 445 + .map_dma_buf = fsl_asrc_m2m_map_dma_buf, 446 + .unmap_dma_buf = fsl_asrc_m2m_unmap_dma_buf, 447 + .release = fsl_asrc_m2m_release, 448 + }; 449 + 450 + static int fsl_asrc_m2m_comp_task_create(struct snd_compr_stream *stream, 451 + struct snd_compr_task_runtime *task) 452 + { 453 + DEFINE_DMA_BUF_EXPORT_INFO(exp_info_in); 454 + DEFINE_DMA_BUF_EXPORT_INFO(exp_info_out); 455 + struct fsl_asrc *asrc = stream->private_data; 456 + struct snd_compr_runtime *runtime = stream->runtime; 457 + struct fsl_asrc_pair *pair = runtime->private_data; 458 + struct device *dev = &asrc->pdev->dev; 459 + int ret; 460 + 461 + exp_info_in.ops = &fsl_asrc_m2m_dma_buf_ops; 462 + exp_info_in.size = ASRC_M2M_BUFFER_SIZE; 463 + exp_info_in.flags = O_RDWR; 464 + exp_info_in.priv = &pair->dma_buffer[IN]; 465 + task->input = dma_buf_export(&exp_info_in); 466 + if (IS_ERR(task->input)) { 467 + ret = PTR_ERR(task->input); 468 + return ret; 469 + } 470 + 471 + exp_info_out.ops = &fsl_asrc_m2m_dma_buf_ops; 472 + exp_info_out.size = ASRC_M2M_BUFFER_SIZE; 473 + exp_info_out.flags = O_RDWR; 474 + exp_info_out.priv = &pair->dma_buffer[OUT]; 475 + task->output = dma_buf_export(&exp_info_out); 476 + if (IS_ERR(task->output)) { 477 + ret = PTR_ERR(task->output); 478 + return ret; 479 + } 480 + 481 + /* Request asrc pair/context */ 482 + ret = asrc->request_pair(pair->channels, pair); 483 + if (ret) { 484 + dev_err(dev, "failed to request pair: %d\n", ret); 485 + goto err_request_pair; 486 + } 487 + 488 + ret = asrc->m2m_prepare(pair); 489 + if (ret) { 490 + dev_err(dev, "failed to start pair part one: %d\n", ret); 491 + goto err_start_part_one; 492 + } 493 + 494 + /* Request dma channels */ 495 + pair->dma_chan[IN] = asrc->get_dma_channel(pair, IN); 496 + if (!pair->dma_chan[IN]) { 497 + dev_err(dev, "[ctx%d] failed to get input DMA channel\n", pair->index); 498 + ret = -EBUSY; 499 + goto err_dma_channel_in; 500 + } 501 + 502 + pair->dma_chan[OUT] = asrc->get_dma_channel(pair, OUT); 503 + if (!pair->dma_chan[OUT]) { 504 + dev_err(dev, "[ctx%d] failed to get output DMA channel\n", pair->index); 505 + ret = -EBUSY; 506 + goto err_dma_channel_out; 507 + } 508 + 509 + return 0; 510 + 511 + err_dma_channel_out: 512 + dma_release_channel(pair->dma_chan[IN]); 513 + err_dma_channel_in: 514 + if (asrc->m2m_unprepare) 515 + asrc->m2m_unprepare(pair); 516 + err_start_part_one: 517 + asrc->release_pair(pair); 518 + err_request_pair: 519 + return ret; 520 + } 521 + 522 + static int fsl_asrc_m2m_comp_task_start(struct snd_compr_stream *stream, 523 + struct snd_compr_task_runtime *task) 524 + { 525 + struct snd_compr_runtime *runtime = stream->runtime; 526 + struct fsl_asrc_pair *pair = runtime->private_data; 527 + 528 + asrc_m2m_device_run(pair, task); 529 + 530 + return 0; 531 + } 532 + 533 + static int fsl_asrc_m2m_comp_task_stop(struct snd_compr_stream *stream, 534 + struct snd_compr_task_runtime *task) 535 + { 536 + return 0; 537 + } 538 + 539 + static int fsl_asrc_m2m_comp_task_free(struct snd_compr_stream *stream, 540 + struct snd_compr_task_runtime *task) 541 + { 542 + struct fsl_asrc *asrc = stream->private_data; 543 + struct snd_compr_runtime *runtime = stream->runtime; 544 + struct fsl_asrc_pair *pair = runtime->private_data; 545 + 546 + /* Stop & release pair/context */ 547 + if (asrc->m2m_stop) 548 + asrc->m2m_stop(pair); 549 + 550 + if (asrc->m2m_unprepare) 551 + asrc->m2m_unprepare(pair); 552 + asrc->release_pair(pair); 553 + 554 + /* Release dma channel */ 555 + if (pair->dma_chan[IN]) 556 + dma_release_channel(pair->dma_chan[IN]); 557 + if (pair->dma_chan[OUT]) 558 + dma_release_channel(pair->dma_chan[OUT]); 559 + 560 + return 0; 561 + } 562 + 563 + static int fsl_asrc_m2m_get_caps(struct snd_compr_stream *cstream, 564 + struct snd_compr_caps *caps) 565 + { 566 + caps->num_codecs = 1; 567 + caps->min_fragment_size = 4096; 568 + caps->max_fragment_size = 4096; 569 + caps->min_fragments = 1; 570 + caps->max_fragments = 1; 571 + caps->codecs[0] = SND_AUDIOCODEC_PCM; 572 + 573 + return 0; 574 + } 575 + 576 + static int fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc *asrc, 577 + struct snd_compr_codec_caps *codec) 578 + { 579 + struct fsl_asrc_m2m_cap cap; 580 + snd_pcm_format_t k; 581 + int j = 0; 582 + int ret; 583 + 584 + ret = asrc->m2m_get_cap(&cap); 585 + if (ret) 586 + return -EINVAL; 587 + 588 + pcm_for_each_format(k) { 589 + if (pcm_format_to_bits(k) & cap.fmt_in) { 590 + codec->descriptor[j].max_ch = cap.chan_max; 591 + memcpy(codec->descriptor[j].sample_rates, 592 + cap.rate_in, 593 + cap.rate_in_count * sizeof(__u32)); 594 + codec->descriptor[j].num_sample_rates = cap.rate_in_count; 595 + codec->descriptor[j].formats = k; 596 + codec->descriptor[j].pcm_formats = cap.fmt_out; 597 + codec->descriptor[j].src.out_sample_rate_min = cap.rate_out[0]; 598 + codec->descriptor[j].src.out_sample_rate_max = 599 + cap.rate_out[cap.rate_out_count - 1]; 600 + j++; 601 + } 602 + } 603 + 604 + codec->codec = SND_AUDIOCODEC_PCM; 605 + codec->num_descriptors = j; 606 + return 0; 607 + } 608 + 609 + static int fsl_asrc_m2m_get_codec_caps(struct snd_compr_stream *stream, 610 + struct snd_compr_codec_caps *codec) 611 + { 612 + struct fsl_asrc *asrc = stream->private_data; 613 + 614 + return fsl_asrc_m2m_fill_codec_caps(asrc, codec); 615 + } 616 + 617 + static struct snd_compr_ops fsl_asrc_m2m_compr_ops = { 618 + .open = fsl_asrc_m2m_comp_open, 619 + .free = fsl_asrc_m2m_comp_release, 620 + .set_params = fsl_asrc_m2m_comp_set_params, 621 + .get_caps = fsl_asrc_m2m_get_caps, 622 + .get_codec_caps = fsl_asrc_m2m_get_codec_caps, 623 + .task_create = fsl_asrc_m2m_comp_task_create, 624 + .task_start = fsl_asrc_m2m_comp_task_start, 625 + .task_stop = fsl_asrc_m2m_comp_task_stop, 626 + .task_free = fsl_asrc_m2m_comp_task_free, 627 + }; 628 + 629 + int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc) 630 + { 631 + struct fsl_asrc_pair *pair; 632 + int i; 633 + 634 + for (i = 0; i < PAIR_CTX_NUM; i++) { 635 + pair = asrc->pair[i]; 636 + if (!pair) 637 + continue; 638 + if (!completion_done(&pair->complete[IN])) { 639 + if (pair->dma_chan[IN]) 640 + dmaengine_terminate_all(pair->dma_chan[IN]); 641 + asrc_input_dma_callback((void *)pair); 642 + } 643 + if (!completion_done(&pair->complete[OUT])) { 644 + if (pair->dma_chan[OUT]) 645 + dmaengine_terminate_all(pair->dma_chan[OUT]); 646 + asrc_output_dma_callback((void *)pair); 647 + } 648 + 649 + if (asrc->m2m_pair_suspend) 650 + asrc->m2m_pair_suspend(pair); 651 + } 652 + 653 + return 0; 654 + } 655 + EXPORT_SYMBOL_GPL(fsl_asrc_m2m_suspend); 656 + 657 + int fsl_asrc_m2m_resume(struct fsl_asrc *asrc) 658 + { 659 + struct fsl_asrc_pair *pair; 660 + int i; 661 + 662 + for (i = 0; i < PAIR_CTX_NUM; i++) { 663 + pair = asrc->pair[i]; 664 + if (!pair) 665 + continue; 666 + if (asrc->m2m_pair_resume) 667 + asrc->m2m_pair_resume(pair); 668 + } 669 + 670 + return 0; 671 + } 672 + EXPORT_SYMBOL_GPL(fsl_asrc_m2m_resume); 673 + 674 + int fsl_asrc_m2m_init(struct fsl_asrc *asrc) 675 + { 676 + struct device *dev = &asrc->pdev->dev; 677 + struct snd_card *card; 678 + struct snd_compr *compr; 679 + int ret; 680 + 681 + ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 682 + THIS_MODULE, 0, &card); 683 + if (ret < 0) 684 + return ret; 685 + 686 + strscpy(card->driver, "fsl-asrc-m2m", sizeof(card->driver)); 687 + strscpy(card->shortname, "ASRC-M2M", sizeof(card->shortname)); 688 + strscpy(card->longname, "ASRC-M2M", sizeof(card->shortname)); 689 + 690 + asrc->card = card; 691 + 692 + compr = devm_kzalloc(dev, sizeof(*compr), GFP_KERNEL); 693 + if (!compr) { 694 + ret = -ENOMEM; 695 + goto err; 696 + } 697 + 698 + compr->ops = &fsl_asrc_m2m_compr_ops; 699 + compr->private_data = asrc; 700 + 701 + ret = snd_compress_new(card, 0, SND_COMPRESS_ACCEL, "ASRC M2M", compr); 702 + if (ret < 0) 703 + goto err; 704 + 705 + ret = snd_card_register(card); 706 + if (ret < 0) 707 + goto err; 708 + 709 + return 0; 710 + err: 711 + snd_card_free(card); 712 + return ret; 713 + } 714 + EXPORT_SYMBOL_GPL(fsl_asrc_m2m_init); 715 + 716 + void fsl_asrc_m2m_exit(struct fsl_asrc *asrc) 717 + { 718 + struct snd_card *card = asrc->card; 719 + 720 + snd_card_free(card); 721 + } 722 + EXPORT_SYMBOL_GPL(fsl_asrc_m2m_exit); 723 + 724 + MODULE_IMPORT_NS("DMA_BUF"); 725 + MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>"); 726 + MODULE_DESCRIPTION("Freescale ASRC M2M driver"); 727 + MODULE_LICENSE("GPL");
+259 -2
sound/soc/fsl/fsl_easrc.c
··· 1861 1861 return REG_EASRC_FIFO(dir, index); 1862 1862 } 1863 1863 1864 + /* Get sample numbers in FIFO */ 1865 + static unsigned int fsl_easrc_get_output_fifo_size(struct fsl_asrc_pair *pair) 1866 + { 1867 + struct fsl_asrc *asrc = pair->asrc; 1868 + enum asrc_pair_index index = pair->index; 1869 + u32 val; 1870 + 1871 + regmap_read(asrc->regmap, REG_EASRC_SFS(index), &val); 1872 + val &= EASRC_SFS_NSGO_MASK; 1873 + 1874 + return val >> EASRC_SFS_NSGO_SHIFT; 1875 + } 1876 + 1877 + static int fsl_easrc_m2m_prepare(struct fsl_asrc_pair *pair) 1878 + { 1879 + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; 1880 + struct fsl_asrc *asrc = pair->asrc; 1881 + struct device *dev = &asrc->pdev->dev; 1882 + int ret; 1883 + 1884 + ctx_priv->in_params.sample_rate = pair->rate[IN]; 1885 + ctx_priv->in_params.sample_format = pair->sample_format[IN]; 1886 + ctx_priv->out_params.sample_rate = pair->rate[OUT]; 1887 + ctx_priv->out_params.sample_format = pair->sample_format[OUT]; 1888 + 1889 + ctx_priv->in_params.fifo_wtmk = FSL_EASRC_INPUTFIFO_WML; 1890 + ctx_priv->out_params.fifo_wtmk = FSL_EASRC_OUTPUTFIFO_WML; 1891 + /* Fill the right half of the re-sampler with zeros */ 1892 + ctx_priv->rs_init_mode = 0x2; 1893 + /* Zero fill the right half of the prefilter */ 1894 + ctx_priv->pf_init_mode = 0x2; 1895 + 1896 + ret = fsl_easrc_set_ctx_format(pair, 1897 + &ctx_priv->in_params.sample_format, 1898 + &ctx_priv->out_params.sample_format); 1899 + if (ret) { 1900 + dev_err(dev, "failed to set context format: %d\n", ret); 1901 + return ret; 1902 + } 1903 + 1904 + ret = fsl_easrc_config_context(asrc, pair->index); 1905 + if (ret) { 1906 + dev_err(dev, "failed to config context %d\n", ret); 1907 + return ret; 1908 + } 1909 + 1910 + ctx_priv->in_params.iterations = 1; 1911 + ctx_priv->in_params.group_len = pair->channels; 1912 + ctx_priv->in_params.access_len = pair->channels; 1913 + ctx_priv->out_params.iterations = 1; 1914 + ctx_priv->out_params.group_len = pair->channels; 1915 + ctx_priv->out_params.access_len = pair->channels; 1916 + 1917 + ret = fsl_easrc_set_ctx_organziation(pair); 1918 + if (ret) { 1919 + dev_err(dev, "failed to set fifo organization\n"); 1920 + return ret; 1921 + } 1922 + 1923 + /* The context start flag */ 1924 + pair->first_convert = 1; 1925 + return 0; 1926 + } 1927 + 1928 + static int fsl_easrc_m2m_start(struct fsl_asrc_pair *pair) 1929 + { 1930 + /* start context once */ 1931 + if (pair->first_convert) { 1932 + fsl_easrc_start_context(pair); 1933 + pair->first_convert = 0; 1934 + } 1935 + 1936 + return 0; 1937 + } 1938 + 1939 + static int fsl_easrc_m2m_stop(struct fsl_asrc_pair *pair) 1940 + { 1941 + /* Stop pair/context */ 1942 + if (!pair->first_convert) { 1943 + fsl_easrc_stop_context(pair); 1944 + pair->first_convert = 1; 1945 + } 1946 + 1947 + return 0; 1948 + } 1949 + 1950 + /* calculate capture data length according to output data length and sample rate */ 1951 + static int fsl_easrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length) 1952 + { 1953 + struct fsl_asrc *easrc = pair->asrc; 1954 + struct fsl_easrc_priv *easrc_priv = easrc->private; 1955 + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; 1956 + unsigned int in_rate = ctx_priv->in_params.norm_rate; 1957 + unsigned int out_rate = ctx_priv->out_params.norm_rate; 1958 + unsigned int channels = pair->channels; 1959 + unsigned int in_samples, out_samples; 1960 + unsigned int in_width, out_width; 1961 + unsigned int out_length; 1962 + unsigned int frac_bits; 1963 + u64 val1, val2; 1964 + 1965 + switch (easrc_priv->rs_num_taps) { 1966 + case EASRC_RS_32_TAPS: 1967 + /* integer bits = 5; */ 1968 + frac_bits = 39; 1969 + break; 1970 + case EASRC_RS_64_TAPS: 1971 + /* integer bits = 6; */ 1972 + frac_bits = 38; 1973 + break; 1974 + case EASRC_RS_128_TAPS: 1975 + /* integer bits = 7; */ 1976 + frac_bits = 37; 1977 + break; 1978 + default: 1979 + return -EINVAL; 1980 + } 1981 + 1982 + val1 = (u64)in_rate << frac_bits; 1983 + do_div(val1, out_rate); 1984 + val1 += (s64)ctx_priv->ratio_mod << (frac_bits - 31); 1985 + 1986 + in_width = snd_pcm_format_physical_width(ctx_priv->in_params.sample_format) / 8; 1987 + out_width = snd_pcm_format_physical_width(ctx_priv->out_params.sample_format) / 8; 1988 + 1989 + ctx_priv->in_filled_len += input_buffer_length; 1990 + if (ctx_priv->in_filled_len <= ctx_priv->in_filled_sample * in_width * channels) { 1991 + out_length = 0; 1992 + } else { 1993 + in_samples = ctx_priv->in_filled_len / (in_width * channels) - 1994 + ctx_priv->in_filled_sample; 1995 + 1996 + /* right shift 12 bit to make ratio in 32bit space */ 1997 + val2 = (u64)in_samples << (frac_bits - 12); 1998 + val1 = val1 >> 12; 1999 + do_div(val2, val1); 2000 + out_samples = val2; 2001 + 2002 + out_length = out_samples * out_width * channels; 2003 + ctx_priv->in_filled_len = ctx_priv->in_filled_sample * in_width * channels; 2004 + } 2005 + 2006 + return out_length; 2007 + } 2008 + 2009 + static int fsl_easrc_m2m_get_maxburst(u8 dir, struct fsl_asrc_pair *pair) 2010 + { 2011 + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; 2012 + 2013 + if (dir == IN) 2014 + return ctx_priv->in_params.fifo_wtmk * pair->channels; 2015 + else 2016 + return ctx_priv->out_params.fifo_wtmk * pair->channels; 2017 + } 2018 + 2019 + static int fsl_easrc_m2m_pair_suspend(struct fsl_asrc_pair *pair) 2020 + { 2021 + fsl_easrc_stop_context(pair); 2022 + 2023 + return 0; 2024 + } 2025 + 2026 + static int fsl_easrc_m2m_pair_resume(struct fsl_asrc_pair *pair) 2027 + { 2028 + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; 2029 + 2030 + pair->first_convert = 1; 2031 + ctx_priv->in_filled_len = 0; 2032 + 2033 + return 0; 2034 + } 2035 + 2036 + /* val is Q31 */ 2037 + static int fsl_easrc_m2m_set_ratio_mod(struct fsl_asrc_pair *pair, int val) 2038 + { 2039 + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; 2040 + struct fsl_asrc *easrc = pair->asrc; 2041 + struct fsl_easrc_priv *easrc_priv = easrc->private; 2042 + unsigned int frac_bits; 2043 + 2044 + ctx_priv->ratio_mod += val; 2045 + 2046 + switch (easrc_priv->rs_num_taps) { 2047 + case EASRC_RS_32_TAPS: 2048 + /* integer bits = 5; */ 2049 + frac_bits = 39; 2050 + break; 2051 + case EASRC_RS_64_TAPS: 2052 + /* integer bits = 6; */ 2053 + frac_bits = 38; 2054 + break; 2055 + case EASRC_RS_128_TAPS: 2056 + /* integer bits = 7; */ 2057 + frac_bits = 37; 2058 + break; 2059 + default: 2060 + return -EINVAL; 2061 + } 2062 + 2063 + val <<= (frac_bits - 31); 2064 + regmap_write(easrc->regmap, REG_EASRC_RUC(pair->index), EASRC_RSUC_RS_RM(val)); 2065 + 2066 + return 0; 2067 + } 2068 + 2069 + static int fsl_easrc_m2m_get_cap(struct fsl_asrc_m2m_cap *cap) 2070 + { 2071 + cap->fmt_in = FSL_EASRC_FORMATS; 2072 + cap->fmt_out = FSL_EASRC_FORMATS | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; 2073 + cap->rate_in = easrc_rates; 2074 + cap->rate_in_count = ARRAY_SIZE(easrc_rates); 2075 + cap->rate_out = easrc_rates; 2076 + cap->rate_out_count = ARRAY_SIZE(easrc_rates); 2077 + cap->chan_min = 1; 2078 + cap->chan_max = 32; 2079 + return 0; 2080 + } 2081 + 1864 2082 static const struct of_device_id fsl_easrc_dt_ids[] = { 1865 2083 { .compatible = "fsl,imx8mn-easrc",}, 1866 2084 {} ··· 2144 1926 easrc->release_pair = fsl_easrc_release_context; 2145 1927 easrc->get_fifo_addr = fsl_easrc_get_fifo_addr; 2146 1928 easrc->pair_priv_size = sizeof(struct fsl_easrc_ctx_priv); 1929 + easrc->m2m_prepare = fsl_easrc_m2m_prepare; 1930 + easrc->m2m_start = fsl_easrc_m2m_start; 1931 + easrc->m2m_stop = fsl_easrc_m2m_stop; 1932 + easrc->get_output_fifo_size = fsl_easrc_get_output_fifo_size; 1933 + easrc->m2m_calc_out_len = fsl_easrc_m2m_calc_out_len; 1934 + easrc->m2m_get_maxburst = fsl_easrc_m2m_get_maxburst; 1935 + easrc->m2m_pair_suspend = fsl_easrc_m2m_pair_suspend; 1936 + easrc->m2m_pair_resume = fsl_easrc_m2m_pair_resume; 1937 + easrc->m2m_set_ratio_mod = fsl_easrc_m2m_set_ratio_mod; 1938 + easrc->m2m_get_cap = fsl_easrc_m2m_get_cap; 2147 1939 2148 1940 easrc_priv->rs_num_taps = EASRC_RS_32_TAPS; 2149 1941 easrc_priv->const_coeff = 0x3FF0000000000000; ··· 2204 1976 goto err_pm_disable; 2205 1977 } 2206 1978 1979 + ret = fsl_asrc_m2m_init(easrc); 1980 + if (ret) { 1981 + dev_err(&pdev->dev, "failed to init m2m device %d\n", ret); 1982 + return ret; 1983 + } 1984 + 2207 1985 return 0; 2208 1986 2209 1987 err_pm_disable: ··· 2219 1985 2220 1986 static void fsl_easrc_remove(struct platform_device *pdev) 2221 1987 { 1988 + struct fsl_asrc *easrc = dev_get_drvdata(&pdev->dev); 1989 + 1990 + fsl_asrc_m2m_exit(easrc); 1991 + 2222 1992 pm_runtime_disable(&pdev->dev); 2223 1993 } 2224 1994 ··· 2323 2085 return ret; 2324 2086 } 2325 2087 2088 + static int fsl_easrc_suspend(struct device *dev) 2089 + { 2090 + struct fsl_asrc *easrc = dev_get_drvdata(dev); 2091 + int ret; 2092 + 2093 + fsl_asrc_m2m_suspend(easrc); 2094 + ret = pm_runtime_force_suspend(dev); 2095 + return ret; 2096 + } 2097 + 2098 + static int fsl_easrc_resume(struct device *dev) 2099 + { 2100 + struct fsl_asrc *easrc = dev_get_drvdata(dev); 2101 + int ret; 2102 + 2103 + ret = pm_runtime_force_resume(dev); 2104 + fsl_asrc_m2m_resume(easrc); 2105 + return ret; 2106 + } 2107 + 2326 2108 static const struct dev_pm_ops fsl_easrc_pm_ops = { 2327 2109 RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, fsl_easrc_runtime_resume, NULL) 2328 - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 2329 - pm_runtime_force_resume) 2110 + SYSTEM_SLEEP_PM_OPS(fsl_easrc_suspend, fsl_easrc_resume) 2330 2111 }; 2331 2112 2332 2113 static struct platform_driver fsl_easrc_driver = {
+4
sound/soc/fsl/fsl_easrc.h
··· 601 601 * @out_missed_sample: sample missed in output 602 602 * @st1_addexp: exponent added for stage1 603 603 * @st2_addexp: exponent added for stage2 604 + * @ratio_mod: update ratio 605 + * @in_filled_len: input filled length 604 606 */ 605 607 struct fsl_easrc_ctx_priv { 606 608 struct fsl_easrc_io_params in_params; ··· 620 618 int out_missed_sample; 621 619 int st1_addexp; 622 620 int st2_addexp; 621 + int ratio_mod; 622 + unsigned int in_filled_len; 623 623 }; 624 624 625 625 /**