Commit e5fadb72 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/rk3036', 'asoc/topic/rockchip',...

Merge remote-tracking branches 'asoc/topic/rk3036', 'asoc/topic/rockchip', 'asoc/topic/rt274' and 'asoc/topic/rt5514' into asoc-next
...@@ -29,11 +29,14 @@ pdm: pdm@ff040000 { ...@@ -29,11 +29,14 @@ pdm: pdm@ff040000 {
dma-names = "rx"; dma-names = "rx";
pinctrl-names = "default", "sleep"; pinctrl-names = "default", "sleep";
pinctrl-0 = <&pdmm0_clk pinctrl-0 = <&pdmm0_clk
&pdmm0_fsync
&pdmm0_sdi0 &pdmm0_sdi0
&pdmm0_sdi1 &pdmm0_sdi1
&pdmm0_sdi2 &pdmm0_sdi2
&pdmm0_sdi3>; &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"; status = "disabled";
}; };
...@@ -4,7 +4,7 @@ Required properties: ...@@ -4,7 +4,7 @@ Required properties:
- compatible: "rockchip,rk3399-gru-sound" - compatible: "rockchip,rk3399-gru-sound"
- rockchip,cpu: The phandle of the Rockchip I2S controller that's - rockchip,cpu: The phandle of the Rockchip I2S controller that's
connected to the codecs connected to the codecs
- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs - rockchip,codec: The phandle of the audio codecs
Optional properties: Optional properties:
- dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready. - dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready.
......
...@@ -7,8 +7,12 @@ Required properties: ...@@ -7,8 +7,12 @@ Required properties:
- compatible: should be one of the following: - compatible: should be one of the following:
- "rockchip,rk3066-i2s": for rk3066 - "rockchip,rk3066-i2s": for rk3066
- "rockchip,rk3036-i2s", "rockchip,rk3066-i2s": for rk3036
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188 - "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,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,rk3368-i2s", "rockchip,rk3066-i2s": for rk3368
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399 - "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
......
...@@ -1102,6 +1102,7 @@ MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); ...@@ -1102,6 +1102,7 @@ MODULE_DEVICE_TABLE(i2c, rt274_i2c_id);
static const struct acpi_device_id rt274_acpi_match[] = { static const struct acpi_device_id rt274_acpi_match[] = {
{ "10EC0274", 0 }, { "10EC0274", 0 },
{ "INT34C2", 0 },
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, rt274_acpi_match); MODULE_DEVICE_TABLE(acpi, rt274_acpi_match);
......
...@@ -43,9 +43,7 @@ struct rt5514_dsp { ...@@ -43,9 +43,7 @@ struct rt5514_dsp {
struct mutex dma_lock; struct mutex dma_lock;
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
unsigned int buf_base, buf_limit, buf_rp; unsigned int buf_base, buf_limit, buf_rp;
size_t buf_size; size_t buf_size, get_size, dma_offset;
size_t dma_offset;
size_t dsp_offset;
}; };
static const struct snd_pcm_hardware rt5514_spi_pcm_hardware = { static const struct snd_pcm_hardware rt5514_spi_pcm_hardware = {
...@@ -80,6 +78,8 @@ static void rt5514_spi_copy_work(struct work_struct *work) ...@@ -80,6 +78,8 @@ static void rt5514_spi_copy_work(struct work_struct *work)
container_of(work, struct rt5514_dsp, copy_work.work); container_of(work, struct rt5514_dsp, copy_work.work);
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
size_t period_bytes, truncated_bytes = 0; size_t period_bytes, truncated_bytes = 0;
unsigned int cur_wp, remain_data;
u8 buf[8];
mutex_lock(&rt5514_dsp->dma_lock); mutex_lock(&rt5514_dsp->dma_lock);
if (!rt5514_dsp->substream) { if (!rt5514_dsp->substream) {
...@@ -90,8 +90,24 @@ static void rt5514_spi_copy_work(struct work_struct *work) ...@@ -90,8 +90,24 @@ static void rt5514_spi_copy_work(struct work_struct *work)
runtime = rt5514_dsp->substream->runtime; runtime = rt5514_dsp->substream->runtime;
period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream);
if (rt5514_dsp->buf_size - rt5514_dsp->dsp_offset < period_bytes) if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) {
period_bytes = rt5514_dsp->buf_size - rt5514_dsp->dsp_offset; 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) { if (rt5514_dsp->buf_rp + period_bytes <= rt5514_dsp->buf_limit) {
rt5514_spi_burst_read(rt5514_dsp->buf_rp, rt5514_spi_burst_read(rt5514_dsp->buf_rp,
...@@ -112,24 +128,62 @@ static void rt5514_spi_copy_work(struct work_struct *work) ...@@ -112,24 +128,62 @@ static void rt5514_spi_copy_work(struct work_struct *work)
runtime->dma_area + rt5514_dsp->dma_offset + runtime->dma_area + rt5514_dsp->dma_offset +
truncated_bytes, period_bytes - truncated_bytes); truncated_bytes, period_bytes - truncated_bytes);
rt5514_dsp->buf_rp = rt5514_dsp->buf_base + rt5514_dsp->buf_rp = rt5514_dsp->buf_base + period_bytes -
period_bytes - truncated_bytes; truncated_bytes;
} }
rt5514_dsp->get_size += period_bytes;
rt5514_dsp->dma_offset += period_bytes; rt5514_dsp->dma_offset += period_bytes;
if (rt5514_dsp->dma_offset >= runtime->dma_bytes) if (rt5514_dsp->dma_offset >= runtime->dma_bytes)
rt5514_dsp->dma_offset = 0; rt5514_dsp->dma_offset = 0;
rt5514_dsp->dsp_offset += period_bytes;
snd_pcm_period_elapsed(rt5514_dsp->substream); 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: done:
mutex_unlock(&rt5514_dsp->dma_lock); 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 */ /* PCM for streaming audio from the DSP buffer */
static int rt5514_spi_pcm_open(struct snd_pcm_substream *substream) 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, ...@@ -150,6 +204,7 @@ static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
params_buffer_bytes(hw_params)); params_buffer_bytes(hw_params));
rt5514_dsp->substream = substream; rt5514_dsp->substream = substream;
rt5514_dsp->dma_offset = 0;
mutex_unlock(&rt5514_dsp->dma_lock); mutex_unlock(&rt5514_dsp->dma_lock);
return ret; return ret;
...@@ -170,59 +225,6 @@ static int rt5514_spi_hw_free(struct snd_pcm_substream *substream) ...@@ -170,59 +225,6 @@ static int rt5514_spi_hw_free(struct snd_pcm_substream *substream)
return snd_pcm_lib_free_vmalloc_buffer(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( static snd_pcm_uframes_t rt5514_spi_pcm_pointer(
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
...@@ -238,8 +240,6 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = { ...@@ -238,8 +240,6 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = {
.open = rt5514_spi_pcm_open, .open = rt5514_spi_pcm_open,
.hw_params = rt5514_spi_hw_params, .hw_params = rt5514_spi_hw_params,
.hw_free = rt5514_spi_hw_free, .hw_free = rt5514_spi_hw_free,
.trigger = rt5514_spi_trigger,
.prepare = rt5514_spi_prepare,
.pointer = rt5514_spi_pcm_pointer, .pointer = rt5514_spi_pcm_pointer,
.mmap = snd_pcm_lib_mmap_vmalloc, .mmap = snd_pcm_lib_mmap_vmalloc,
.page = snd_pcm_lib_get_vmalloc_page, .page = snd_pcm_lib_get_vmalloc_page,
...@@ -248,6 +248,7 @@ static const struct snd_pcm_ops rt5514_spi_pcm_ops = { ...@@ -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) static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
{ {
struct rt5514_dsp *rt5514_dsp; struct rt5514_dsp *rt5514_dsp;
int ret;
rt5514_dsp = devm_kzalloc(platform->dev, sizeof(*rt5514_dsp), rt5514_dsp = devm_kzalloc(platform->dev, sizeof(*rt5514_dsp),
GFP_KERNEL); GFP_KERNEL);
...@@ -257,6 +258,17 @@ static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform) ...@@ -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); INIT_DELAYED_WORK(&rt5514_dsp->copy_work, rt5514_spi_copy_work);
snd_soc_platform_set_drvdata(platform, rt5514_dsp); 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; return 0;
} }
......
...@@ -17,10 +17,9 @@ ...@@ -17,10 +17,9 @@
*/ */
#define RT5514_SPI_BUF_LEN 240 #define RT5514_SPI_BUF_LEN 240
#define RT5514_BUFFER_VOICE_BASE 0x18001034 #define RT5514_BUFFER_VOICE_BASE 0x18000200
#define RT5514_BUFFER_VOICE_LIMIT 0x18001038 #define RT5514_BUFFER_VOICE_LIMIT 0x18000204
#define RT5514_BUFFER_VOICE_RP 0x1800103c #define RT5514_BUFFER_VOICE_WP 0x1800020c
#define RT5514_BUFFER_VOICE_SIZE 0x18001040
/* SPI Command */ /* SPI Command */
enum { enum {
......
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define RT5514_PLL3_CALIB_CTRL5 0x2124 #define RT5514_PLL3_CALIB_CTRL5 0x2124
#define RT5514_DELAY_BUF_CTRL1 0x2140 #define RT5514_DELAY_BUF_CTRL1 0x2140
#define RT5514_DELAY_BUF_CTRL3 0x2148 #define RT5514_DELAY_BUF_CTRL3 0x2148
#define RT5514_ASRC_IN_CTRL1 0x2180
#define RT5514_DOWNFILTER0_CTRL1 0x2190 #define RT5514_DOWNFILTER0_CTRL1 0x2190
#define RT5514_DOWNFILTER0_CTRL2 0x2194 #define RT5514_DOWNFILTER0_CTRL2 0x2194
#define RT5514_DOWNFILTER0_CTRL3 0x2198 #define RT5514_DOWNFILTER0_CTRL3 0x2198
...@@ -164,6 +165,18 @@ ...@@ -164,6 +165,18 @@
#define RT5514_I2S_DL_24 (0x2 << 0) #define RT5514_I2S_DL_24 (0x2 << 0)
#define RT5514_I2S_DL_8 (0x3 << 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) */ /* RT5514_DIG_SOURCE_CTRL (0x20a4) */
#define RT5514_AD1_DMIC_INPUT_SEL (0x1 << 1) #define RT5514_AD1_DMIC_INPUT_SEL (0x1 << 1)
#define RT5514_AD1_DMIC_INPUT_SEL_SFT 1 #define RT5514_AD1_DMIC_INPUT_SEL_SFT 1
...@@ -185,8 +198,14 @@ ...@@ -185,8 +198,14 @@
#define RT5514_CLK_AD0_EN_BIT 23 #define RT5514_CLK_AD0_EN_BIT 23
#define RT5514_CLK_DMIC_OUT_SEL_MASK (0x7 << 8) #define RT5514_CLK_DMIC_OUT_SEL_MASK (0x7 << 8)
#define RT5514_CLK_DMIC_OUT_SEL_SFT 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) */ /* 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_MASK (0x7 << 8)
#define RT5514_CLK_SYS_DIV_OUT_SFT 8 #define RT5514_CLK_SYS_DIV_OUT_SFT 8
#define RT5514_SEL_ADC_OSR_MASK (0x7 << 4) #define RT5514_SEL_ADC_OSR_MASK (0x7 << 4)
...@@ -236,6 +255,7 @@ ...@@ -236,6 +255,7 @@
#define RT5514_FIRMWARE1 "rt5514_dsp_fw1.bin" #define RT5514_FIRMWARE1 "rt5514_dsp_fw1.bin"
#define RT5514_FIRMWARE2 "rt5514_dsp_fw2.bin" #define RT5514_FIRMWARE2 "rt5514_dsp_fw2.bin"
#define RT5514_FIRMWARE3 "rt5514_dsp_fw3.bin"
/* System Clock Source */ /* System Clock Source */
enum { enum {
...@@ -262,6 +282,8 @@ struct rt5514_priv { ...@@ -262,6 +282,8 @@ struct rt5514_priv {
int pll_in; int pll_in;
int pll_out; int pll_out;
int dsp_enabled; int dsp_enabled;
u8 *model_buf;
unsigned int model_len;
}; };
#endif /* __RT5514_H__ */ #endif /* __RT5514_H__ */
...@@ -68,6 +68,8 @@ config SND_SOC_RK3399_GRU_SOUND ...@@ -68,6 +68,8 @@ config SND_SOC_RK3399_GRU_SOUND
select SND_SOC_RT5514 select SND_SOC_RT5514
select SND_SOC_DA7219 select SND_SOC_DA7219
select SND_SOC_RT5514_SPI select SND_SOC_RT5514_SPI
select SND_SOC_HDMI_CODEC
select SND_SOC_DMIC
help help
Say Y or M here if you want to add support multiple codecs for SoC Say Y or M here if you want to add support multiple codecs for SoC
audio on Rockchip RK3399 GRU boards. audio on Rockchip RK3399 GRU boards.
...@@ -147,7 +147,7 @@ static int rk_init(struct snd_soc_pcm_runtime *runtime) ...@@ -147,7 +147,7 @@ static int rk_init(struct snd_soc_pcm_runtime *runtime)
return 0; return 0;
} }
static struct snd_soc_ops rk_ops = { static const struct snd_soc_ops rk_ops = {
.hw_params = rk_hw_params, .hw_params = rk_hw_params,
}; };
...@@ -272,8 +272,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev) ...@@ -272,8 +272,6 @@ static int snd_rk_mc_probe(struct platform_device *pdev)
return ret; return ret;
} }
platform_set_drvdata(pdev, card);
return ret; return ret;
} }
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define SOUND_FS 256 #define SOUND_FS 256
static unsigned int rt5514_dmic_delay; static unsigned int dmic_wakeup_delay;
static struct snd_soc_jack rockchip_sound_jack; static struct snd_soc_jack rockchip_sound_jack;
...@@ -126,7 +126,7 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, ...@@ -126,7 +126,7 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
} }
/* Wait for DMIC stable */ /* Wait for DMIC stable */
msleep(rt5514_dmic_delay); msleep(dmic_wakeup_delay);
return 0; return 0;
} }
...@@ -228,6 +228,67 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) ...@@ -228,6 +228,67 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
return 0; 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 = { static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
.hw_params = rockchip_sound_max98357a_hw_params, .hw_params = rockchip_sound_max98357a_hw_params,
}; };
...@@ -240,16 +301,70 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = { ...@@ -240,16 +301,70 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = {
.hw_params = rockchip_sound_da7219_hw_params, .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 { enum {
DAILINK_CDNDP,
DAILINK_DA7219,
DAILINK_DMIC,
DAILINK_MAX98357A, DAILINK_MAX98357A,
DAILINK_RT5514, DAILINK_RT5514,
DAILINK_DA7219,
DAILINK_RT5514_DSP, 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] = { [DAILINK_MAX98357A] = {
.name = "MAX98357A", .name = "MAX98357A",
.stream_name = "MAX98357A PCM", .stream_name = "MAX98357A PCM",
...@@ -268,108 +383,95 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { ...@@ -268,108 +383,95 @@ static struct snd_soc_dai_link rockchip_dailinks[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS, 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 */ /* RT5514 DSP for voice wakeup via spi bus */
[DAILINK_RT5514_DSP] = { [DAILINK_RT5514_DSP] = {
.name = "RT5514 DSP", .name = "RT5514 DSP",
.stream_name = "Wake on Voice", .stream_name = "Wake on Voice",
.codec_name = "snd-soc-dummy", .codec_dai_name = "rt5514-dsp-cpu-dai",
.codec_dai_name = "snd-soc-dummy-dai",
}, },
}; };
static struct snd_soc_card rockchip_sound_card = { static int rockchip_sound_codec_node_match(struct device_node *np_codec)
.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)
{ {
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_probe(struct platform_device *pdev) static int rockchip_sound_of_parse_dais(struct device *dev,
struct snd_soc_card *card)
{ {
struct snd_soc_card *card = &rockchip_sound_card; struct device_node *np_cpu, *np_cpu0, *np_cpu1;
struct device_node *cpu_node; struct device_node *np_codec;
struct device *dev; struct snd_soc_dai_link *dai;
struct device_driver *drv; int i, index;
int i, ret;
card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); GFP_KERNEL);
if (!cpu_node) { if (!card->dai_link)
dev_err(&pdev->dev, "Property 'rockchip,cpu' missing or invalid\n"); return -ENOMEM;
return -EINVAL;
} 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;
for (i = 0; i < DAILINK_ENTITIES; i++) { if (!of_device_is_available(np_codec))
rockchip_dailinks[i].platform_of_node = cpu_node; continue;
rockchip_dailinks[i].cpu_of_node = cpu_node;
rockchip_dailinks[i].codec_of_node = index = rockchip_sound_codec_node_match(np_codec);
of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i); if (index < 0)
if (!rockchip_dailinks[i].codec_of_node) { continue;
dev_err(&pdev->dev,
"Property[%d] 'rockchip,codec' missing or invalid\n", i); 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; return -EINVAL;
} }
}
/** dai = &card->dai_link[card->num_links++];
* To acquire the spi driver of the rt5514 and set the dai-links names *dai = rockchip_dais[index];
* for soc_bind_dai_link
*/ dai->codec_of_node = np_codec;
drv = driver_find("rt5514", &spi_bus_type); dai->platform_of_node = np_cpu;
if (!drv) { dai->cpu_of_node = np_cpu;
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); return 0;
if (!dev) { }
dev_err(&pdev->dev, "Can not find the rt5514 device\n");
return -ENODEV; static int rockchip_sound_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &rockchip_sound_card;
int ret;
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;
} }
/* Set DMIC delay */ /* Set DMIC wakeup delay */
ret = device_property_read_u32(&pdev->dev, "dmic-delay", ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
&rt5514_dmic_delay); &dmic_wakeup_delay);
if (ret) { if (ret) {
rt5514_dmic_delay = 0; dmic_wakeup_delay = 0;
dev_dbg(&pdev->dev, 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; card->dev = &pdev->dev;
platform_set_drvdata(pdev, card); return devm_snd_soc_register_card(&pdev->dev, 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;
} }
static const struct of_device_id rockchip_sound_of_match[] = { static const struct of_device_id rockchip_sound_of_match[] = {
......
...@@ -579,10 +579,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev) ...@@ -579,10 +579,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
int val; int val;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
if (!i2s) { if (!i2s)
dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
return -ENOMEM; return -ENOMEM;
}
i2s->dev = &pdev->dev; i2s->dev = &pdev->dev;
......
...@@ -249,7 +249,7 @@ static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai) ...@@ -249,7 +249,7 @@ static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
return 0; 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, .set_fmt = rockchip_pdm_set_fmt,
.trigger = rockchip_pdm_trigger, .trigger = rockchip_pdm_trigger,
.hw_params = rockchip_pdm_hw_params, .hw_params = rockchip_pdm_hw_params,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment