ASoC: stm32: sai: Add support of S/PDIF playback
Add support of S/PDIF iec60958 playback on STM32 SAI. Signed-off-by: olivier moysan <olivier.moysan@st.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
994f46610b
commit
6eb17d7093
|
@ -30,10 +30,12 @@
|
||||||
|
|
||||||
static const struct stm32_sai_conf stm32_sai_conf_f4 = {
|
static const struct stm32_sai_conf stm32_sai_conf_f4 = {
|
||||||
.version = SAI_STM32F4,
|
.version = SAI_STM32F4,
|
||||||
|
.has_spdif = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stm32_sai_conf stm32_sai_conf_h7 = {
|
static const struct stm32_sai_conf stm32_sai_conf_h7 = {
|
||||||
.version = SAI_STM32H7,
|
.version = SAI_STM32H7,
|
||||||
|
.has_spdif = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id stm32_sai_ids[] = {
|
static const struct of_device_id stm32_sai_ids[] = {
|
||||||
|
|
|
@ -248,9 +248,11 @@ enum stm32_sai_version {
|
||||||
/**
|
/**
|
||||||
* struct stm32_sai_conf - SAI configuration
|
* struct stm32_sai_conf - SAI configuration
|
||||||
* @version: SAI version
|
* @version: SAI version
|
||||||
|
* @has_spdif: SAI S/PDIF support flag
|
||||||
*/
|
*/
|
||||||
struct stm32_sai_conf {
|
struct stm32_sai_conf {
|
||||||
int version;
|
int version;
|
||||||
|
bool has_spdif;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
#include <sound/asoundef.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/dmaengine_pcm.h>
|
#include <sound/dmaengine_pcm.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
#include "stm32_sai.h"
|
#include "stm32_sai.h"
|
||||||
|
|
||||||
#define SAI_FREE_PROTOCOL 0x0
|
#define SAI_FREE_PROTOCOL 0x0
|
||||||
|
#define SAI_SPDIF_PROTOCOL 0x1
|
||||||
|
|
||||||
#define SAI_SLOT_SIZE_AUTO 0x0
|
#define SAI_SLOT_SIZE_AUTO 0x0
|
||||||
#define SAI_SLOT_SIZE_16 0x1
|
#define SAI_SLOT_SIZE_16 0x1
|
||||||
|
@ -59,8 +61,13 @@
|
||||||
#define SAI_SYNC_INTERNAL 0x1
|
#define SAI_SYNC_INTERNAL 0x1
|
||||||
#define SAI_SYNC_EXTERNAL 0x2
|
#define SAI_SYNC_EXTERNAL 0x2
|
||||||
|
|
||||||
|
#define STM_SAI_PROTOCOL_IS_SPDIF(ip) ((ip)->spdif)
|
||||||
|
#define STM_SAI_HAS_SPDIF(x) ((x)->pdata->conf->has_spdif)
|
||||||
#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
|
#define STM_SAI_HAS_EXT_SYNC(x) (!STM_SAI_IS_F4(sai->pdata))
|
||||||
|
|
||||||
|
#define SAI_IEC60958_BLOCK_FRAMES 192
|
||||||
|
#define SAI_IEC60958_STATUS_BYTES 24
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
|
* struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
|
||||||
* @pdev: device data pointer
|
* @pdev: device data pointer
|
||||||
|
@ -78,6 +85,7 @@
|
||||||
* @id: SAI sub block id corresponding to sub-block A or B
|
* @id: SAI sub block id corresponding to sub-block A or B
|
||||||
* @dir: SAI block direction (playback or capture). set at init
|
* @dir: SAI block direction (playback or capture). set at init
|
||||||
* @master: SAI block mode flag. (true=master, false=slave) set at init
|
* @master: SAI block mode flag. (true=master, false=slave) set at init
|
||||||
|
* @spdif: SAI S/PDIF iec60958 mode flag. set at init
|
||||||
* @fmt: SAI block format. relevant only for custom protocols. set at init
|
* @fmt: SAI block format. relevant only for custom protocols. set at init
|
||||||
* @sync: SAI block synchronization mode. (none, internal or external)
|
* @sync: SAI block synchronization mode. (none, internal or external)
|
||||||
* @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
|
* @synco: SAI block ext sync source (provider setting). (none, sub-block A/B)
|
||||||
|
@ -87,6 +95,8 @@
|
||||||
* @slot_width: rx or tx slot width in bits
|
* @slot_width: rx or tx slot width in bits
|
||||||
* @slot_mask: rx or tx active slots mask. set at init or at runtime
|
* @slot_mask: rx or tx active slots mask. set at init or at runtime
|
||||||
* @data_size: PCM data width. corresponds to PCM substream width.
|
* @data_size: PCM data width. corresponds to PCM substream width.
|
||||||
|
* @spdif_frm_cnt: S/PDIF playback frame counter
|
||||||
|
* @spdif_status_bits: S/PDIF status bits
|
||||||
*/
|
*/
|
||||||
struct stm32_sai_sub_data {
|
struct stm32_sai_sub_data {
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
@ -104,6 +114,7 @@ struct stm32_sai_sub_data {
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
int dir;
|
int dir;
|
||||||
bool master;
|
bool master;
|
||||||
|
bool spdif;
|
||||||
int fmt;
|
int fmt;
|
||||||
int sync;
|
int sync;
|
||||||
int synco;
|
int synco;
|
||||||
|
@ -113,6 +124,8 @@ struct stm32_sai_sub_data {
|
||||||
int slot_width;
|
int slot_width;
|
||||||
int slot_mask;
|
int slot_mask;
|
||||||
int data_size;
|
int data_size;
|
||||||
|
unsigned int spdif_frm_cnt;
|
||||||
|
unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum stm32_sai_fifo_th {
|
enum stm32_sai_fifo_th {
|
||||||
|
@ -171,6 +184,10 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const unsigned char default_status_bits[SAI_IEC60958_STATUS_BYTES] = {
|
||||||
|
0, 0, 0, IEC958_AES3_CON_FS_48000,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config stm32_sai_sub_regmap_config_f4 = {
|
static const struct regmap_config stm32_sai_sub_regmap_config_f4 = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
|
@ -277,6 +294,11 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
|
||||||
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||||
int slotr, slotr_mask, slot_size;
|
int slotr, slotr_mask, slot_size;
|
||||||
|
|
||||||
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
|
dev_warn(cpu_dai->dev, "Slot setting relevant only for TDM\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
|
dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n",
|
||||||
tx_mask, rx_mask, slots, slot_width);
|
tx_mask, rx_mask, slots, slot_width);
|
||||||
|
|
||||||
|
@ -326,8 +348,17 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||||
|
|
||||||
dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
|
dev_dbg(cpu_dai->dev, "fmt %x\n", fmt);
|
||||||
|
|
||||||
cr1_mask = SAI_XCR1_PRTCFG_MASK;
|
/* Do not generate master by default */
|
||||||
cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
|
cr1 = SAI_XCR1_NODIV;
|
||||||
|
cr1_mask = SAI_XCR1_NODIV;
|
||||||
|
|
||||||
|
cr1_mask |= SAI_XCR1_PRTCFG_MASK;
|
||||||
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
|
cr1 |= SAI_XCR1_PRTCFG_SET(SAI_SPDIF_PROTOCOL);
|
||||||
|
goto conf_update;
|
||||||
|
}
|
||||||
|
|
||||||
|
cr1 |= SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||||
/* SCK active high for all protocols */
|
/* SCK active high for all protocols */
|
||||||
|
@ -409,10 +440,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||||
|
|
||||||
cr1_mask |= SAI_XCR1_SLAVE;
|
cr1_mask |= SAI_XCR1_SLAVE;
|
||||||
|
|
||||||
/* do not generate master by default */
|
conf_update:
|
||||||
cr1 |= SAI_XCR1_NODIV;
|
|
||||||
cr1_mask |= SAI_XCR1_NODIV;
|
|
||||||
|
|
||||||
ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
|
ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
|
dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
|
||||||
|
@ -478,6 +506,12 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
|
||||||
SAI_XCR2_FFLUSH |
|
SAI_XCR2_FFLUSH |
|
||||||
SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
|
SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
|
||||||
|
|
||||||
|
/* DS bits in CR1 not set for SPDIF (size forced to 24 bits).*/
|
||||||
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
|
sai->spdif_frm_cnt = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mode, data format and channel config */
|
/* Mode, data format and channel config */
|
||||||
cr1_mask = SAI_XCR1_DS_MASK;
|
cr1_mask = SAI_XCR1_DS_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
|
@ -592,13 +626,14 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
|
||||||
int cr1, mask, div = 0;
|
int cr1, mask, div = 0;
|
||||||
int sai_clk_rate, mclk_ratio, den, ret;
|
int sai_clk_rate, mclk_ratio, den, ret;
|
||||||
int version = sai->pdata->conf->version;
|
int version = sai->pdata->conf->version;
|
||||||
|
unsigned int rate = params_rate(params);
|
||||||
|
|
||||||
if (!sai->mclk_rate) {
|
if (!sai->mclk_rate) {
|
||||||
dev_err(cpu_dai->dev, "Mclk rate is null\n");
|
dev_err(cpu_dai->dev, "Mclk rate is null\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(params_rate(params) % 11025))
|
if (!(rate % 11025))
|
||||||
clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
|
clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
|
||||||
else
|
else
|
||||||
clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
|
clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
|
||||||
|
@ -623,24 +658,28 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
|
||||||
* MCKDIV = sai_ck / (frl x ws) (NOMCK=1)
|
* MCKDIV = sai_ck / (frl x ws) (NOMCK=1)
|
||||||
* Note: NOMCK/NODIV correspond to same bit.
|
* Note: NOMCK/NODIV correspond to same bit.
|
||||||
*/
|
*/
|
||||||
if (sai->mclk_rate) {
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
mclk_ratio = sai->mclk_rate / params_rate(params);
|
div = DIV_ROUND_CLOSEST(sai_clk_rate,
|
||||||
if (mclk_ratio != 256) {
|
(params_rate(params) * 128));
|
||||||
|
} else {
|
||||||
|
if (sai->mclk_rate) {
|
||||||
|
mclk_ratio = sai->mclk_rate / rate;
|
||||||
if (mclk_ratio == 512) {
|
if (mclk_ratio == 512) {
|
||||||
mask = SAI_XCR1_OSR;
|
mask = SAI_XCR1_OSR;
|
||||||
cr1 = SAI_XCR1_OSR;
|
cr1 = SAI_XCR1_OSR;
|
||||||
} else {
|
} else if (mclk_ratio != 256) {
|
||||||
dev_err(cpu_dai->dev,
|
dev_err(cpu_dai->dev,
|
||||||
"Wrong mclk ratio %d\n",
|
"Wrong mclk ratio %d\n",
|
||||||
mclk_ratio);
|
mclk_ratio);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
div = DIV_ROUND_CLOSEST(sai_clk_rate,
|
||||||
|
sai->mclk_rate);
|
||||||
|
} else {
|
||||||
|
/* mclk-fs not set, master clock not active */
|
||||||
|
den = sai->fs_length * params_rate(params);
|
||||||
|
div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
|
||||||
}
|
}
|
||||||
div = DIV_ROUND_CLOSEST(sai_clk_rate, sai->mclk_rate);
|
|
||||||
} else {
|
|
||||||
/* mclk-fs not set, master clock not active. NOMCK=1 */
|
|
||||||
den = sai->fs_length * params_rate(params);
|
|
||||||
div = DIV_ROUND_CLOSEST(sai_clk_rate, den);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,10 +709,12 @@ static int stm32_sai_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
sai->data_size = params_width(params);
|
sai->data_size = params_width(params);
|
||||||
|
|
||||||
ret = stm32_sai_set_slots(cpu_dai);
|
if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
|
||||||
if (ret < 0)
|
ret = stm32_sai_set_slots(cpu_dai);
|
||||||
return ret;
|
if (ret < 0)
|
||||||
stm32_sai_set_frame(cpu_dai);
|
return ret;
|
||||||
|
stm32_sai_set_frame(cpu_dai);
|
||||||
|
}
|
||||||
|
|
||||||
ret = stm32_sai_set_config(cpu_dai, substream, params);
|
ret = stm32_sai_set_config(cpu_dai, substream, params);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -723,6 +764,9 @@ static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
(unsigned int)~SAI_XCR1_DMAEN);
|
(unsigned int)~SAI_XCR1_DMAEN);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
|
dev_err(cpu_dai->dev, "Failed to update CR1 register\n");
|
||||||
|
|
||||||
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
|
||||||
|
sai->spdif_frm_cnt = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -776,6 +820,10 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
|
||||||
sai->synco, sai->synci);
|
sai->synco, sai->synci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
|
||||||
|
memcpy(sai->spdif_status_bits, default_status_bits,
|
||||||
|
sizeof(default_status_bits));
|
||||||
|
|
||||||
cr1_mask |= SAI_XCR1_SYNCEN_MASK;
|
cr1_mask |= SAI_XCR1_SYNCEN_MASK;
|
||||||
cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
|
cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
|
||||||
|
|
||||||
|
@ -792,6 +840,42 @@ static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = {
|
||||||
.shutdown = stm32_sai_shutdown,
|
.shutdown = stm32_sai_shutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream,
|
||||||
|
int channel, unsigned long hwoff,
|
||||||
|
void *buf, unsigned long bytes)
|
||||||
|
{
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
|
struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
|
||||||
|
int *ptr = (int *)(runtime->dma_area + hwoff +
|
||||||
|
channel * (runtime->dma_bytes / runtime->channels));
|
||||||
|
ssize_t cnt = bytes_to_samples(runtime, bytes);
|
||||||
|
unsigned int frm_cnt = sai->spdif_frm_cnt;
|
||||||
|
unsigned int byte;
|
||||||
|
unsigned int mask;
|
||||||
|
|
||||||
|
do {
|
||||||
|
*ptr = ((*ptr >> 8) & 0x00ffffff);
|
||||||
|
|
||||||
|
/* Set channel status bit */
|
||||||
|
byte = frm_cnt >> 3;
|
||||||
|
mask = 1 << (frm_cnt - (byte << 3));
|
||||||
|
if (sai->spdif_status_bits[byte] & mask)
|
||||||
|
*ptr |= 0x04000000;
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if (!(cnt % 2))
|
||||||
|
frm_cnt++;
|
||||||
|
|
||||||
|
if (frm_cnt == SAI_IEC60958_BLOCK_FRAMES)
|
||||||
|
frm_cnt = 0;
|
||||||
|
} while (--cnt);
|
||||||
|
sai->spdif_frm_cnt = frm_cnt;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
|
static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
|
||||||
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
|
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
|
||||||
.buffer_bytes_max = 8 * PAGE_SIZE,
|
.buffer_bytes_max = 8 * PAGE_SIZE,
|
||||||
|
@ -842,8 +926,14 @@ static struct snd_soc_dai_driver stm32_sai_capture_dai[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
|
static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
|
||||||
.pcm_hardware = &stm32_sai_pcm_hw,
|
.pcm_hardware = &stm32_sai_pcm_hw,
|
||||||
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
|
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config_spdif = {
|
||||||
|
.pcm_hardware = &stm32_sai_pcm_hw,
|
||||||
|
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
|
||||||
|
.process = stm32_sai_pcm_process_spdif,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_soc_component_driver stm32_component = {
|
static const struct snd_soc_component_driver stm32_component = {
|
||||||
|
@ -900,6 +990,18 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get spdif iec60958 property */
|
||||||
|
sai->spdif = false;
|
||||||
|
if (of_get_property(np, "st,iec60958", NULL)) {
|
||||||
|
if (!STM_SAI_HAS_SPDIF(sai) ||
|
||||||
|
sai->dir == SNDRV_PCM_STREAM_CAPTURE) {
|
||||||
|
dev_err(&pdev->dev, "S/PDIF IEC60958 not supported\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
sai->spdif = true;
|
||||||
|
sai->master = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get synchronization property */
|
/* Get synchronization property */
|
||||||
args.np = NULL;
|
args.np = NULL;
|
||||||
ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args);
|
ret = of_parse_phandle_with_fixed_args(np, "st,sync", 1, 0, &args);
|
||||||
|
@ -999,6 +1101,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct stm32_sai_sub_data *sai;
|
struct stm32_sai_sub_data *sai;
|
||||||
const struct of_device_id *of_id;
|
const struct of_device_id *of_id;
|
||||||
|
const struct snd_dmaengine_pcm_config *conf = &stm32_sai_pcm_config;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
|
sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
|
||||||
|
@ -1039,8 +1142,10 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
|
if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
|
||||||
&stm32_sai_pcm_config, 0);
|
conf = &stm32_sai_pcm_config_spdif;
|
||||||
|
|
||||||
|
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Could not register pcm dma\n");
|
dev_err(&pdev->dev, "Could not register pcm dma\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue