Merge remote-tracking branches 'asoc/topic/rk3036', 'asoc/topic/rockchip', 'asoc/topic/rt274' and 'asoc/topic/rt5514' into asoc-next
This commit is contained in:
commit
e5fadb7281
|
@ -29,11 +29,14 @@ pdm: pdm@ff040000 {
|
|||
dma-names = "rx";
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&pdmm0_clk
|
||||
&pdmm0_fsync
|
||||
&pdmm0_sdi0
|
||||
&pdmm0_sdi1
|
||||
&pdmm0_sdi2
|
||||
&pdmm0_sdi3>;
|
||||
pinctrl-1 = <&pdmm0_sleep>;
|
||||
pinctrl-1 = <&pdmm0_clk_sleep
|
||||
&pdmm0_sdi0_sleep
|
||||
&pdmm0_sdi1_sleep
|
||||
&pdmm0_sdi2_sleep
|
||||
&pdmm0_sdi3_sleep>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ Required properties:
|
|||
- compatible: "rockchip,rk3399-gru-sound"
|
||||
- rockchip,cpu: The phandle of the Rockchip I2S controller that's
|
||||
connected to the codecs
|
||||
- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
|
||||
- rockchip,codec: The phandle of the audio codecs
|
||||
|
||||
Optional properties:
|
||||
- dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready.
|
||||
|
|
|
@ -7,8 +7,12 @@ Required properties:
|
|||
|
||||
- compatible: should be one of the following:
|
||||
- "rockchip,rk3066-i2s": for rk3066
|
||||
- "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
|
||||
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
|
||||
- "rockchip,rk3228-i2s", "rockchip,rk3066-i2s": for rk3228
|
||||
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
|
||||
- "rockchip,rk3328-i2s", "rockchip,rk3066-i2s": for rk3328
|
||||
- "rockchip,rk3366-i2s", "rockchip,rk3066-i2s": for rk3366
|
||||
- "rockchip,rk3368-i2s", "rockchip,rk3066-i2s": for rk3368
|
||||
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
|
|
|
@ -1102,6 +1102,7 @@ MODULE_DEVICE_TABLE(i2c, rt274_i2c_id);
|
|||
|
||||
static const struct acpi_device_id rt274_acpi_match[] = {
|
||||
{ "10EC0274", 0 },
|
||||
{ "INT34C2", 0 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, rt274_acpi_match);
|
||||
|
|
|
@ -43,9 +43,7 @@ struct rt5514_dsp {
|
|||
struct mutex dma_lock;
|
||||
struct snd_pcm_substream *substream;
|
||||
unsigned int buf_base, buf_limit, buf_rp;
|
||||
size_t buf_size;
|
||||
size_t dma_offset;
|
||||
size_t dsp_offset;
|
||||
size_t buf_size, get_size, dma_offset;
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware rt5514_spi_pcm_hardware = {
|
||||
|
@ -80,6 +78,8 @@ static void rt5514_spi_copy_work(struct work_struct *work)
|
|||
container_of(work, struct rt5514_dsp, copy_work.work);
|
||||
struct snd_pcm_runtime *runtime;
|
||||
size_t period_bytes, truncated_bytes = 0;
|
||||
unsigned int cur_wp, remain_data;
|
||||
u8 buf[8];
|
||||
|
||||
mutex_lock(&rt5514_dsp->dma_lock);
|
||||
if (!rt5514_dsp->substream) {
|
||||
|
@ -90,8 +90,24 @@ static void rt5514_spi_copy_work(struct work_struct *work)
|
|||
runtime = rt5514_dsp->substream->runtime;
|
||||
period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream);
|
||||
|
||||
if (rt5514_dsp->buf_size - rt5514_dsp->dsp_offset < period_bytes)
|
||||
period_bytes = rt5514_dsp->buf_size - rt5514_dsp->dsp_offset;
|
||||
if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) {
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
cur_wp = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
if (cur_wp >= rt5514_dsp->buf_rp)
|
||||
remain_data = (cur_wp - rt5514_dsp->buf_rp);
|
||||
else
|
||||
remain_data =
|
||||
(rt5514_dsp->buf_limit - rt5514_dsp->buf_rp) +
|
||||
(cur_wp - rt5514_dsp->buf_base);
|
||||
|
||||
if (remain_data < period_bytes) {
|
||||
schedule_delayed_work(&rt5514_dsp->copy_work, 5);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (rt5514_dsp->buf_rp + period_bytes <= rt5514_dsp->buf_limit) {
|
||||
rt5514_spi_burst_read(rt5514_dsp->buf_rp,
|
||||
|
@ -112,24 +128,62 @@ static void rt5514_spi_copy_work(struct work_struct *work)
|
|||
runtime->dma_area + rt5514_dsp->dma_offset +
|
||||
truncated_bytes, period_bytes - truncated_bytes);
|
||||
|
||||
rt5514_dsp->buf_rp = rt5514_dsp->buf_base +
|
||||
period_bytes - truncated_bytes;
|
||||
rt5514_dsp->buf_rp = rt5514_dsp->buf_base + period_bytes -
|
||||
truncated_bytes;
|
||||
}
|
||||
|
||||
rt5514_dsp->get_size += period_bytes;
|
||||
rt5514_dsp->dma_offset += period_bytes;
|
||||
if (rt5514_dsp->dma_offset >= runtime->dma_bytes)
|
||||
rt5514_dsp->dma_offset = 0;
|
||||
|
||||
rt5514_dsp->dsp_offset += period_bytes;
|
||||
|
||||
snd_pcm_period_elapsed(rt5514_dsp->substream);
|
||||
|
||||
if (rt5514_dsp->dsp_offset < rt5514_dsp->buf_size)
|
||||
schedule_delayed_work(&rt5514_dsp->copy_work, 5);
|
||||
schedule_delayed_work(&rt5514_dsp->copy_work, 5);
|
||||
|
||||
done:
|
||||
mutex_unlock(&rt5514_dsp->dma_lock);
|
||||
}
|
||||
|
||||
static irqreturn_t rt5514_spi_irq(int irq, void *data)
|
||||
{
|
||||
struct rt5514_dsp *rt5514_dsp = data;
|
||||
u8 buf[8];
|
||||
|
||||
rt5514_dsp->get_size = 0;
|
||||
|
||||
/**
|
||||
* The address area x1800XXXX is the register address, and it cannot
|
||||
* support spi burst read perfectly. So we use the spi burst read
|
||||
* individually to make sure the data correctly.
|
||||
*/
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_BASE, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_base = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_LIMIT, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_limit = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_rp = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
if (rt5514_dsp->buf_rp % 8)
|
||||
rt5514_dsp->buf_rp = (rt5514_dsp->buf_rp / 8) * 8;
|
||||
|
||||
rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base;
|
||||
|
||||
if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit &&
|
||||
rt5514_dsp->buf_rp && rt5514_dsp->buf_size)
|
||||
schedule_delayed_work(&rt5514_dsp->copy_work, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* PCM for streaming audio from the DSP buffer */
|
||||
static int rt5514_spi_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -150,6 +204,7 @@ static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
|
|||
ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
rt5514_dsp->substream = substream;
|
||||
rt5514_dsp->dma_offset = 0;
|
||||
mutex_unlock(&rt5514_dsp->dma_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -170,59 +225,6 @@ static int rt5514_spi_hw_free(struct snd_pcm_substream *substream)
|
|||
return snd_pcm_lib_free_vmalloc_buffer(substream);
|
||||
}
|
||||
|
||||
static int rt5514_spi_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct rt5514_dsp *rt5514_dsp =
|
||||
snd_soc_platform_get_drvdata(rtd->platform);
|
||||
u8 buf[8];
|
||||
|
||||
rt5514_dsp->dma_offset = 0;
|
||||
rt5514_dsp->dsp_offset = 0;
|
||||
|
||||
/**
|
||||
* The address area x1800XXXX is the register address, and it cannot
|
||||
* support spi burst read perfectly. So we use the spi burst read
|
||||
* individually to make sure the data correctly.
|
||||
*/
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_BASE, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_base = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_LIMIT, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_limit = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_RP, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_rp = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
rt5514_spi_burst_read(RT5514_BUFFER_VOICE_SIZE, (u8 *)&buf,
|
||||
sizeof(buf));
|
||||
rt5514_dsp->buf_size = buf[0] | buf[1] << 8 | buf[2] << 16 |
|
||||
buf[3] << 24;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5514_spi_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct rt5514_dsp *rt5514_dsp =
|
||||
snd_soc_platform_get_drvdata(rtd->platform);
|
||||
|
||||
if (cmd == SNDRV_PCM_TRIGGER_START) {
|
||||
if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit &&
|
||||
rt5514_dsp->buf_rp && rt5514_dsp->buf_size)
|
||||
schedule_delayed_work(&rt5514_dsp->copy_work, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t rt5514_spi_pcm_pointer(
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -238,8 +240,6 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = {
|
|||
.open = rt5514_spi_pcm_open,
|
||||
.hw_params = rt5514_spi_hw_params,
|
||||
.hw_free = rt5514_spi_hw_free,
|
||||
.trigger = rt5514_spi_trigger,
|
||||
.prepare = rt5514_spi_prepare,
|
||||
.pointer = rt5514_spi_pcm_pointer,
|
||||
.mmap = snd_pcm_lib_mmap_vmalloc,
|
||||
.page = snd_pcm_lib_get_vmalloc_page,
|
||||
|
@ -248,6 +248,7 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = {
|
|||
static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
|
||||
{
|
||||
struct rt5514_dsp *rt5514_dsp;
|
||||
int ret;
|
||||
|
||||
rt5514_dsp = devm_kzalloc(platform->dev, sizeof(*rt5514_dsp),
|
||||
GFP_KERNEL);
|
||||
|
@ -257,6 +258,17 @@ static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
|
|||
INIT_DELAYED_WORK(&rt5514_dsp->copy_work, rt5514_spi_copy_work);
|
||||
snd_soc_platform_set_drvdata(platform, rt5514_dsp);
|
||||
|
||||
if (rt5514_spi->irq) {
|
||||
ret = devm_request_threaded_irq(&rt5514_spi->dev,
|
||||
rt5514_spi->irq, NULL, rt5514_spi_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5514-spi",
|
||||
rt5514_dsp);
|
||||
if (ret)
|
||||
dev_err(&rt5514_spi->dev,
|
||||
"%s Failed to reguest IRQ: %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
*/
|
||||
#define RT5514_SPI_BUF_LEN 240
|
||||
|
||||
#define RT5514_BUFFER_VOICE_BASE 0x18001034
|
||||
#define RT5514_BUFFER_VOICE_LIMIT 0x18001038
|
||||
#define RT5514_BUFFER_VOICE_RP 0x1800103c
|
||||
#define RT5514_BUFFER_VOICE_SIZE 0x18001040
|
||||
#define RT5514_BUFFER_VOICE_BASE 0x18000200
|
||||
#define RT5514_BUFFER_VOICE_LIMIT 0x18000204
|
||||
#define RT5514_BUFFER_VOICE_WP 0x1800020c
|
||||
|
||||
/* SPI Command */
|
||||
enum {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "rl6231.h"
|
||||
#include "rt5514.h"
|
||||
#if defined(CONFIG_SND_SOC_RT5514_SPI)
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
|
||||
#include "rt5514-spi.h"
|
||||
#endif
|
||||
|
||||
|
@ -63,6 +63,9 @@ static const struct reg_sequence rt5514_patch[] = {
|
|||
{RT5514_SRC_CTRL, 0x44000eee},
|
||||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_ADCFED, 0x00000800},
|
||||
{RT5514_ASRC_IN_CTRL1, 0x00000003},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000362},
|
||||
};
|
||||
|
||||
static const struct reg_default rt5514_reg[] = {
|
||||
|
@ -88,10 +91,10 @@ static const struct reg_default rt5514_reg[] = {
|
|||
{RT5514_DELAY_BUF_CTRL3, 0x00000000},
|
||||
{RT5514_DOWNFILTER0_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x00000362},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000362},
|
||||
{RT5514_DOWNFILTER1_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x00000362},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000362},
|
||||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_LDO18_16, 0x02000345},
|
||||
{RT5514_ANA_CTRL_ADC12, 0x0000a2a8},
|
||||
|
@ -311,7 +314,7 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
|
|||
|
||||
request_firmware(&fw, RT5514_FIRMWARE1, codec->dev);
|
||||
if (fw) {
|
||||
#if defined(CONFIG_SND_SOC_RT5514_SPI)
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
|
||||
rt5514_spi_burst_write(0x4ff60000, fw->data,
|
||||
((fw->size/8)+1)*8);
|
||||
#else
|
||||
|
@ -324,7 +327,7 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
|
|||
|
||||
request_firmware(&fw, RT5514_FIRMWARE2, codec->dev);
|
||||
if (fw) {
|
||||
#if defined(CONFIG_SND_SOC_RT5514_SPI)
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
|
||||
rt5514_spi_burst_write(0x4ffc0000, fw->data,
|
||||
((fw->size/8)+1)*8);
|
||||
#else
|
||||
|
@ -335,6 +338,39 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
|
|||
fw = NULL;
|
||||
}
|
||||
|
||||
if (rt5514->model_buf && rt5514->model_len) {
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
|
||||
int ret;
|
||||
|
||||
ret = rt5514_spi_burst_write(0x4ff80000,
|
||||
rt5514->model_buf,
|
||||
((rt5514->model_len / 8) + 1) * 8);
|
||||
if (ret) {
|
||||
dev_err(codec->dev,
|
||||
"Model load failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
dev_err(codec->dev,
|
||||
"No SPI driver for loading firmware\n");
|
||||
#endif
|
||||
} else {
|
||||
request_firmware(&fw, RT5514_FIRMWARE3,
|
||||
codec->dev);
|
||||
if (fw) {
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
|
||||
rt5514_spi_burst_write(0x4ff80000,
|
||||
fw->data,
|
||||
((fw->size/8)+1)*8);
|
||||
#else
|
||||
dev_err(codec->dev,
|
||||
"No SPI driver to load fw\n");
|
||||
#endif
|
||||
release_firmware(fw);
|
||||
fw = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* DSP run */
|
||||
regmap_write(rt5514->i2c_regmap, 0x18002f00,
|
||||
0x00055148);
|
||||
|
@ -349,6 +385,34 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt5514_hotword_model_put(struct snd_kcontrol *kcontrol,
|
||||
const unsigned int __user *bytes, unsigned int size)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component);
|
||||
struct snd_soc_codec *codec = rt5514->codec;
|
||||
int ret = 0;
|
||||
|
||||
if (rt5514->model_buf || rt5514->model_len < size) {
|
||||
if (rt5514->model_buf)
|
||||
devm_kfree(codec->dev, rt5514->model_buf);
|
||||
rt5514->model_buf = devm_kmalloc(codec->dev, size, GFP_KERNEL);
|
||||
if (!rt5514->model_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skips the TLV header. */
|
||||
bytes += 2;
|
||||
|
||||
if (copy_from_user(rt5514->model_buf, bytes, size))
|
||||
ret = -EFAULT;
|
||||
done:
|
||||
rt5514->model_len = (ret ? 0 : size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new rt5514_snd_controls[] = {
|
||||
SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST,
|
||||
RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv),
|
||||
|
@ -360,6 +424,8 @@ static const struct snd_kcontrol_new rt5514_snd_controls[] = {
|
|||
adc_vol_tlv),
|
||||
SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0,
|
||||
rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put),
|
||||
SND_SOC_BYTES_TLV("Hotword Model", 0x8504,
|
||||
NULL, rt5514_hotword_model_put),
|
||||
};
|
||||
|
||||
/* ADC Mixer*/
|
||||
|
@ -471,33 +537,13 @@ static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt5514_pre_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
static int rt5514_i2s_use_asrc(struct snd_soc_dapm_widget *source,
|
||||
struct snd_soc_dapm_widget *sink)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
|
||||
struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec);
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
/**
|
||||
* If the DSP is enabled in start of recording, the DSP
|
||||
* should be disabled, and sync back to normal recording
|
||||
* settings to make sure recording properly.
|
||||
*/
|
||||
if (rt5514->dsp_enabled) {
|
||||
rt5514->dsp_enabled = 0;
|
||||
regmap_multi_reg_write(rt5514->i2c_regmap,
|
||||
rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch));
|
||||
regcache_mark_dirty(rt5514->regmap);
|
||||
regcache_sync(rt5514->regmap);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (rt5514->sysclk > rt5514->lrck * 384);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = {
|
||||
|
@ -570,6 +616,10 @@ static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = {
|
|||
RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0,
|
||||
NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("ASRC AD1", 1, RT5514_CLK_CTRL2,
|
||||
RT5514_CLK_AD0_ASRC_EN_BIT, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("ASRC AD2", 1, RT5514_CLK_CTRL2,
|
||||
RT5514_CLK_AD1_ASRC_EN_BIT, 0, NULL, 0),
|
||||
|
||||
/* ADC Mux */
|
||||
SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
|
||||
|
@ -607,8 +657,6 @@ static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = {
|
|||
|
||||
/* Audio Interface */
|
||||
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
SND_SOC_DAPM_PRE("DAPM Pre", rt5514_pre_event),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route rt5514_dapm_routes[] = {
|
||||
|
@ -669,6 +717,7 @@ static const struct snd_soc_dapm_route rt5514_dapm_routes[] = {
|
|||
{ "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" },
|
||||
{ "Stereo1 ADC MIX", NULL, "adc stereo1 filter" },
|
||||
{ "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll },
|
||||
{ "adc stereo1 filter", NULL, "ASRC AD1", rt5514_i2s_use_asrc },
|
||||
|
||||
{ "Stereo2 DMIC Mux", "DMIC1", "DMIC1" },
|
||||
{ "Stereo2 DMIC Mux", "DMIC2", "DMIC2" },
|
||||
|
@ -685,6 +734,7 @@ static const struct snd_soc_dapm_route rt5514_dapm_routes[] = {
|
|||
{ "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" },
|
||||
{ "Stereo2 ADC MIX", NULL, "adc stereo2 filter" },
|
||||
{ "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll },
|
||||
{ "adc stereo2 filter", NULL, "ASRC AD2", rt5514_i2s_use_asrc },
|
||||
|
||||
{ "AIF1TX", NULL, "Stereo1 ADC MIX"},
|
||||
{ "AIF1TX", NULL, "Stereo2 ADC MIX"},
|
||||
|
@ -737,6 +787,9 @@ static int rt5514_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK,
|
||||
val_len);
|
||||
regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1,
|
||||
RT5514_CLK_AD_ANA1_SEL_MASK,
|
||||
(pre_div + 1) << RT5514_CLK_AD_ANA1_SEL_SFT);
|
||||
regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2,
|
||||
RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK,
|
||||
pre_div << RT5514_CLK_SYS_DIV_OUT_SFT |
|
||||
|
@ -902,11 +955,38 @@ static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
|||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int val = 0;
|
||||
unsigned int val = 0, val2 = 0;
|
||||
|
||||
if (rx_mask || tx_mask)
|
||||
val |= RT5514_TDM_MODE;
|
||||
|
||||
switch (tx_mask) {
|
||||
case 0x3:
|
||||
val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 |
|
||||
RT5514_TDM_DOCKING_START_SLOT0;
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 |
|
||||
RT5514_TDM_DOCKING_START_SLOT4;
|
||||
break;
|
||||
|
||||
case 0xf:
|
||||
val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 |
|
||||
RT5514_TDM_DOCKING_START_SLOT0;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 |
|
||||
RT5514_TDM_DOCKING_START_SLOT4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (slots) {
|
||||
case 4:
|
||||
val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH;
|
||||
|
@ -952,6 +1032,10 @@ static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
|
|||
RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK |
|
||||
RT5514_TDM_MODE2, val);
|
||||
|
||||
regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL2,
|
||||
RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH_MASK |
|
||||
RT5514_TDM_DOCKING_START_MASK, val2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -975,6 +1059,24 @@ static int rt5514_set_bias_level(struct snd_soc_codec *codec,
|
|||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
|
||||
/*
|
||||
* If the DSP is enabled in start of recording, the DSP
|
||||
* should be disabled, and sync back to normal recording
|
||||
* settings to make sure recording properly.
|
||||
*/
|
||||
if (rt5514->dsp_enabled) {
|
||||
rt5514->dsp_enabled = 0;
|
||||
regmap_multi_reg_write(rt5514->i2c_regmap,
|
||||
rt5514_i2c_patch,
|
||||
ARRAY_SIZE(rt5514_i2c_patch));
|
||||
regcache_mark_dirty(rt5514->regmap);
|
||||
regcache_sync(rt5514->regmap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1019,7 +1121,7 @@ static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val)
|
|||
#define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
||||
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
|
||||
|
||||
struct snd_soc_dai_ops rt5514_aif_dai_ops = {
|
||||
static const struct snd_soc_dai_ops rt5514_aif_dai_ops = {
|
||||
.hw_params = rt5514_hw_params,
|
||||
.set_fmt = rt5514_set_dai_fmt,
|
||||
.set_sysclk = rt5514_set_dai_sysclk,
|
||||
|
@ -1027,7 +1129,7 @@ struct snd_soc_dai_ops rt5514_aif_dai_ops = {
|
|||
.set_tdm_slot = rt5514_set_tdm_slot,
|
||||
};
|
||||
|
||||
struct snd_soc_dai_driver rt5514_dai[] = {
|
||||
static struct snd_soc_dai_driver rt5514_dai[] = {
|
||||
{
|
||||
.name = "rt5514-aif1",
|
||||
.id = 0,
|
||||
|
@ -1097,7 +1199,7 @@ MODULE_DEVICE_TABLE(of, rt5514_of_match);
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static struct acpi_device_id rt5514_acpi_match[] = {
|
||||
static const struct acpi_device_id rt5514_acpi_match[] = {
|
||||
{ "10EC5514", 0},
|
||||
{},
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define RT5514_PLL3_CALIB_CTRL5 0x2124
|
||||
#define RT5514_DELAY_BUF_CTRL1 0x2140
|
||||
#define RT5514_DELAY_BUF_CTRL3 0x2148
|
||||
#define RT5514_ASRC_IN_CTRL1 0x2180
|
||||
#define RT5514_DOWNFILTER0_CTRL1 0x2190
|
||||
#define RT5514_DOWNFILTER0_CTRL2 0x2194
|
||||
#define RT5514_DOWNFILTER0_CTRL3 0x2198
|
||||
|
@ -164,6 +165,18 @@
|
|||
#define RT5514_I2S_DL_24 (0x2 << 0)
|
||||
#define RT5514_I2S_DL_8 (0x3 << 0)
|
||||
|
||||
/* RT5514_I2S_CTRL2 (0x2014) */
|
||||
#define RT5514_TDM_DOCKING_MODE (0x1 << 31)
|
||||
#define RT5514_TDM_DOCKING_MODE_SFT 31
|
||||
#define RT5514_TDM_DOCKING_VALID_CH_MASK (0x1 << 29)
|
||||
#define RT5514_TDM_DOCKING_VALID_CH_SFT 29
|
||||
#define RT5514_TDM_DOCKING_VALID_CH2 (0x0 << 29)
|
||||
#define RT5514_TDM_DOCKING_VALID_CH4 (0x1 << 29)
|
||||
#define RT5514_TDM_DOCKING_START_MASK (0x1 << 28)
|
||||
#define RT5514_TDM_DOCKING_START_SFT 28
|
||||
#define RT5514_TDM_DOCKING_START_SLOT0 (0x0 << 28)
|
||||
#define RT5514_TDM_DOCKING_START_SLOT4 (0x1 << 28)
|
||||
|
||||
/* RT5514_DIG_SOURCE_CTRL (0x20a4) */
|
||||
#define RT5514_AD1_DMIC_INPUT_SEL (0x1 << 1)
|
||||
#define RT5514_AD1_DMIC_INPUT_SEL_SFT 1
|
||||
|
@ -185,8 +198,14 @@
|
|||
#define RT5514_CLK_AD0_EN_BIT 23
|
||||
#define RT5514_CLK_DMIC_OUT_SEL_MASK (0x7 << 8)
|
||||
#define RT5514_CLK_DMIC_OUT_SEL_SFT 8
|
||||
#define RT5514_CLK_AD_ANA1_SEL_MASK (0xf << 0)
|
||||
#define RT5514_CLK_AD_ANA1_SEL_SFT 0
|
||||
|
||||
/* RT5514_CLK_CTRL2 (0x2108) */
|
||||
#define RT5514_CLK_AD1_ASRC_EN (0x1 << 17)
|
||||
#define RT5514_CLK_AD1_ASRC_EN_BIT 17
|
||||
#define RT5514_CLK_AD0_ASRC_EN (0x1 << 16)
|
||||
#define RT5514_CLK_AD0_ASRC_EN_BIT 16
|
||||
#define RT5514_CLK_SYS_DIV_OUT_MASK (0x7 << 8)
|
||||
#define RT5514_CLK_SYS_DIV_OUT_SFT 8
|
||||
#define RT5514_SEL_ADC_OSR_MASK (0x7 << 4)
|
||||
|
@ -236,6 +255,7 @@
|
|||
|
||||
#define RT5514_FIRMWARE1 "rt5514_dsp_fw1.bin"
|
||||
#define RT5514_FIRMWARE2 "rt5514_dsp_fw2.bin"
|
||||
#define RT5514_FIRMWARE3 "rt5514_dsp_fw3.bin"
|
||||
|
||||
/* System Clock Source */
|
||||
enum {
|
||||
|
@ -262,6 +282,8 @@ struct rt5514_priv {
|
|||
int pll_in;
|
||||
int pll_out;
|
||||
int dsp_enabled;
|
||||
u8 *model_buf;
|
||||
unsigned int model_len;
|
||||
};
|
||||
|
||||
#endif /* __RT5514_H__ */
|
||||
|
|
|
@ -68,6 +68,8 @@ config SND_SOC_RK3399_GRU_SOUND
|
|||
select SND_SOC_RT5514
|
||||
select SND_SOC_DA7219
|
||||
select SND_SOC_RT5514_SPI
|
||||
select SND_SOC_HDMI_CODEC
|
||||
select SND_SOC_DMIC
|
||||
help
|
||||
Say Y or M here if you want to add support multiple codecs for SoC
|
||||
audio on Rockchip RK3399 GRU boards.
|
||||
|
|
|
@ -147,7 +147,7 @@ static int rk_init(struct snd_soc_pcm_runtime *runtime)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops rk_ops = {
|
||||
static const struct snd_soc_ops rk_ops = {
|
||||
.hw_params = rk_hw_params,
|
||||
};
|
||||
|
||||
|
@ -272,8 +272,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#define SOUND_FS 256
|
||||
|
||||
static unsigned int rt5514_dmic_delay;
|
||||
static unsigned int dmic_wakeup_delay;
|
||||
|
||||
static struct snd_soc_jack rockchip_sound_jack;
|
||||
|
||||
|
@ -126,7 +126,7 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
/* Wait for DMIC stable */
|
||||
msleep(rt5514_dmic_delay);
|
||||
msleep(dmic_wakeup_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -228,6 +228,67 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int mclk, ret;
|
||||
|
||||
/* in bypass mode, the mclk has to be one of the frequencies below */
|
||||
switch (params_rate(params)) {
|
||||
case 8000:
|
||||
case 16000:
|
||||
case 24000:
|
||||
case 32000:
|
||||
case 48000:
|
||||
case 64000:
|
||||
case 96000:
|
||||
mclk = 12288000;
|
||||
break;
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 88200:
|
||||
mclk = 11289600;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
|
||||
SND_SOC_CLOCK_OUT);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
unsigned int mclk;
|
||||
int ret;
|
||||
|
||||
mclk = params_rate(params) * SOUND_FS;
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
|
||||
if (ret) {
|
||||
dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
|
||||
__func__, mclk, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait for DMIC stable */
|
||||
msleep(dmic_wakeup_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
|
||||
.hw_params = rockchip_sound_max98357a_hw_params,
|
||||
};
|
||||
|
@ -240,16 +301,70 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = {
|
|||
.hw_params = rockchip_sound_da7219_hw_params,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops rockchip_sound_cdndp_ops = {
|
||||
.hw_params = rockchip_sound_cdndp_hw_params,
|
||||
};
|
||||
|
||||
static const struct snd_soc_ops rockchip_sound_dmic_ops = {
|
||||
.hw_params = rockchip_sound_dmic_hw_params,
|
||||
};
|
||||
|
||||
static struct snd_soc_card rockchip_sound_card = {
|
||||
.name = "rk3399-gru-sound",
|
||||
.owner = THIS_MODULE,
|
||||
.dapm_widgets = rockchip_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
|
||||
.dapm_routes = rockchip_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
|
||||
.controls = rockchip_controls,
|
||||
.num_controls = ARRAY_SIZE(rockchip_controls),
|
||||
};
|
||||
|
||||
enum {
|
||||
DAILINK_CDNDP,
|
||||
DAILINK_DA7219,
|
||||
DAILINK_DMIC,
|
||||
DAILINK_MAX98357A,
|
||||
DAILINK_RT5514,
|
||||
DAILINK_DA7219,
|
||||
DAILINK_RT5514_DSP,
|
||||
};
|
||||
|
||||
#define DAILINK_ENTITIES (DAILINK_DA7219 + 1)
|
||||
static const char * const dailink_compat[] = {
|
||||
[DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp",
|
||||
[DAILINK_DA7219] = "dlg,da7219",
|
||||
[DAILINK_DMIC] = "dmic-codec",
|
||||
[DAILINK_MAX98357A] = "maxim,max98357a",
|
||||
[DAILINK_RT5514] = "realtek,rt5514-i2c",
|
||||
[DAILINK_RT5514_DSP] = "realtek,rt5514-spi",
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link rockchip_dailinks[] = {
|
||||
static const struct snd_soc_dai_link rockchip_dais[] = {
|
||||
[DAILINK_CDNDP] = {
|
||||
.name = "DP",
|
||||
.stream_name = "DP PCM",
|
||||
.codec_dai_name = "i2s-hifi",
|
||||
.ops = &rockchip_sound_cdndp_ops,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
},
|
||||
[DAILINK_DA7219] = {
|
||||
.name = "DA7219",
|
||||
.stream_name = "DA7219 PCM",
|
||||
.codec_dai_name = "da7219-hifi",
|
||||
.init = rockchip_sound_da7219_init,
|
||||
.ops = &rockchip_sound_da7219_ops,
|
||||
/* set da7219 as slave */
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
},
|
||||
[DAILINK_DMIC] = {
|
||||
.name = "DMIC",
|
||||
.stream_name = "DMIC PCM",
|
||||
.codec_dai_name = "dmic-hifi",
|
||||
.ops = &rockchip_sound_dmic_ops,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
},
|
||||
[DAILINK_MAX98357A] = {
|
||||
.name = "MAX98357A",
|
||||
.stream_name = "MAX98357A PCM",
|
||||
|
@ -268,108 +383,95 @@ static struct snd_soc_dai_link rockchip_dailinks[] = {
|
|||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
},
|
||||
[DAILINK_DA7219] = {
|
||||
.name = "DA7219",
|
||||
.stream_name = "DA7219 PCM",
|
||||
.codec_dai_name = "da7219-hifi",
|
||||
.init = rockchip_sound_da7219_init,
|
||||
.ops = &rockchip_sound_da7219_ops,
|
||||
/* set da7219 as slave */
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
},
|
||||
/* RT5514 DSP for voice wakeup via spi bus */
|
||||
[DAILINK_RT5514_DSP] = {
|
||||
.name = "RT5514 DSP",
|
||||
.stream_name = "Wake on Voice",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_dai_name = "rt5514-dsp-cpu-dai",
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_card rockchip_sound_card = {
|
||||
.name = "rk3399-gru-sound",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = rockchip_dailinks,
|
||||
.num_links = ARRAY_SIZE(rockchip_dailinks),
|
||||
.dapm_widgets = rockchip_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
|
||||
.dapm_routes = rockchip_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
|
||||
.controls = rockchip_controls,
|
||||
.num_controls = ARRAY_SIZE(rockchip_controls),
|
||||
};
|
||||
|
||||
static int rockchip_sound_match_stub(struct device *dev, void *data)
|
||||
static int rockchip_sound_codec_node_match(struct device_node *np_codec)
|
||||
{
|
||||
return 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dailink_compat); i++) {
|
||||
if (of_device_is_compatible(np_codec, dailink_compat[i]))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rockchip_sound_of_parse_dais(struct device *dev,
|
||||
struct snd_soc_card *card)
|
||||
{
|
||||
struct device_node *np_cpu, *np_cpu0, *np_cpu1;
|
||||
struct device_node *np_codec;
|
||||
struct snd_soc_dai_link *dai;
|
||||
int i, index;
|
||||
|
||||
card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
|
||||
GFP_KERNEL);
|
||||
if (!card->dai_link)
|
||||
return -ENOMEM;
|
||||
|
||||
np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
|
||||
np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
|
||||
|
||||
card->num_links = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
|
||||
np_codec = of_parse_phandle(dev->of_node,
|
||||
"rockchip,codec", i);
|
||||
if (!np_codec)
|
||||
break;
|
||||
|
||||
if (!of_device_is_available(np_codec))
|
||||
continue;
|
||||
|
||||
index = rockchip_sound_codec_node_match(np_codec);
|
||||
if (index < 0)
|
||||
continue;
|
||||
|
||||
np_cpu = (index == DAILINK_CDNDP) ? np_cpu1 : np_cpu0;
|
||||
if (!np_cpu) {
|
||||
dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
|
||||
rockchip_dais[index].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dai = &card->dai_link[card->num_links++];
|
||||
*dai = rockchip_dais[index];
|
||||
|
||||
dai->codec_of_node = np_codec;
|
||||
dai->platform_of_node = np_cpu;
|
||||
dai->cpu_of_node = np_cpu;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_sound_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &rockchip_sound_card;
|
||||
struct device_node *cpu_node;
|
||||
struct device *dev;
|
||||
struct device_driver *drv;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0);
|
||||
if (!cpu_node) {
|
||||
dev_err(&pdev->dev, "Property 'rockchip,cpu' missing or invalid\n");
|
||||
return -EINVAL;
|
||||
ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < DAILINK_ENTITIES; i++) {
|
||||
rockchip_dailinks[i].platform_of_node = cpu_node;
|
||||
rockchip_dailinks[i].cpu_of_node = cpu_node;
|
||||
|
||||
rockchip_dailinks[i].codec_of_node =
|
||||
of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
|
||||
if (!rockchip_dailinks[i].codec_of_node) {
|
||||
dev_err(&pdev->dev,
|
||||
"Property[%d] 'rockchip,codec' missing or invalid\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To acquire the spi driver of the rt5514 and set the dai-links names
|
||||
* for soc_bind_dai_link
|
||||
*/
|
||||
drv = driver_find("rt5514", &spi_bus_type);
|
||||
if (!drv) {
|
||||
dev_err(&pdev->dev, "Can not find the rt5514 driver at the spi bus\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = driver_find_device(drv, NULL, NULL, rockchip_sound_match_stub);
|
||||
if (!dev) {
|
||||
dev_err(&pdev->dev, "Can not find the rt5514 device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Set DMIC delay */
|
||||
ret = device_property_read_u32(&pdev->dev, "dmic-delay",
|
||||
&rt5514_dmic_delay);
|
||||
/* Set DMIC wakeup delay */
|
||||
ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
|
||||
&dmic_wakeup_delay);
|
||||
if (ret) {
|
||||
rt5514_dmic_delay = 0;
|
||||
dmic_wakeup_delay = 0;
|
||||
dev_dbg(&pdev->dev,
|
||||
"no optional property 'dmic-delay' found, default: no delay\n");
|
||||
"no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
|
||||
}
|
||||
|
||||
rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL);
|
||||
rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL);
|
||||
rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL);
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
||||
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
return devm_snd_soc_register_card(&pdev->dev, card);
|
||||
}
|
||||
|
||||
static const struct of_device_id rockchip_sound_of_match[] = {
|
||||
|
|
|
@ -579,10 +579,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
|
|||
int val;
|
||||
|
||||
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
|
||||
if (!i2s) {
|
||||
dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
|
||||
if (!i2s)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2s->dev = &pdev->dev;
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops rockchip_pdm_dai_ops = {
|
||||
static const struct snd_soc_dai_ops rockchip_pdm_dai_ops = {
|
||||
.set_fmt = rockchip_pdm_set_fmt,
|
||||
.trigger = rockchip_pdm_trigger,
|
||||
.hw_params = rockchip_pdm_hw_params,
|
||||
|
|
Loading…
Reference in New Issue