mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
audio: auge: add sound card for sm1 [2/2]
PD#SWPL-6151 Problem: sound card for sm1 Solution: add sound card for sm1 Verify: ac200 Change-Id: I4f65472af7a8399fb6fe003db608158e11bed566 Signed-off-by: Xing Wang <xing.wang@amlogic.com> Signed-off-by: Luan Yuan <luan.yuan@amlogic.com>
This commit is contained in:
@@ -14679,7 +14679,7 @@ AMLOGIC TL1 NEW EQDRC
|
||||
AMLOGIC TL1 MIXER CONTROLS
|
||||
AMLOGIC TL1 VAD DRIVER
|
||||
AMLOGIC SM1 SOUND CARD
|
||||
M: Xing Wang <xing.wang@amlogic.com
|
||||
M: Xing Wang <xing.wang@amlogic.com>
|
||||
F: arch/arm/boot/dts/amlogic/tl1_pxp.dts
|
||||
F: include/dt-bindings/clock/amlogic,tl1-audio-clk.h
|
||||
F: include/dt-bindings/clock/amlogic,sm1-audio-clk.h
|
||||
|
||||
@@ -4,6 +4,7 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \
|
||||
axg,clocks.o \
|
||||
g12a,clocks.o \
|
||||
tl1,clocks.o \
|
||||
sm1,clocks.o \
|
||||
card.o \
|
||||
card_utils.o \
|
||||
tdm.o \
|
||||
@@ -32,4 +33,6 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \
|
||||
frhdmirx_hw.o \
|
||||
vad.o \
|
||||
vad_hw.o \
|
||||
vad_dev.o
|
||||
vad_dev.o \
|
||||
earc.o \
|
||||
earc_hw.o
|
||||
|
||||
@@ -36,6 +36,10 @@ static const struct of_device_id audio_clocks_of_match[] = {
|
||||
.compatible = "amlogic, tl1-audio-clocks",
|
||||
.data = &tl1_audio_clks_init,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-audio-clocks",
|
||||
.data = &sm1_audio_clks_init,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, audio_clocks_of_match);
|
||||
|
||||
@@ -93,6 +93,7 @@ struct audio_clk_init {
|
||||
extern struct audio_clk_init axg_audio_clks_init;
|
||||
extern struct audio_clk_init g12a_audio_clks_init;
|
||||
extern struct audio_clk_init tl1_audio_clks_init;
|
||||
extern struct audio_clk_init sm1_audio_clks_init;
|
||||
|
||||
struct clk_chipinfo {
|
||||
/* force clock source as oscin(24M) */
|
||||
|
||||
@@ -711,6 +711,9 @@ static int tdmout_c_binv_set_enum(
|
||||
SND_ENUM(xname, type, CTRL0, xenum, xshift, xmask)
|
||||
|
||||
#define SND_SWAP(xname, type, xenum, xshift, xmask) \
|
||||
SND_ENUM(xname, type, SWAP0, xenum, xshift, xmask)
|
||||
|
||||
#define SND_SPDIFOUT_SWAP(xname, type, xenum, xshift, xmask) \
|
||||
SND_ENUM(xname, type, SWAP, xenum, xshift, xmask)
|
||||
|
||||
#define TDM_MASK(xname, type, func) \
|
||||
@@ -992,9 +995,9 @@ static const struct snd_kcontrol_new snd_auge_controls[] = {
|
||||
spdif_channel_status_enum),
|
||||
|
||||
/*SPDIFOUT swap*/
|
||||
SND_SWAP("SPDIFOUT Lane0 Left Channel Swap",
|
||||
SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Left Channel Swap",
|
||||
SPDIFOUT, out_swap_channel_enum, 0, 0x7),
|
||||
SND_SWAP("SPDIFOUT Lane0 Right Channel Swap",
|
||||
SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Right Channel Swap",
|
||||
SPDIFOUT, out_swap_channel_enum, 4, 0x7),
|
||||
/*SPDIFOUT mixer*/
|
||||
SND_MIX("SPDIFOUT Mixer Channel",
|
||||
|
||||
@@ -1376,7 +1376,7 @@ static const char *const toddr_src_sel_texts[] = {
|
||||
"TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN",
|
||||
"PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A",
|
||||
"FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB",
|
||||
"RESERVED", "RESERVED", "RESERVED", "RESERVED",
|
||||
"EARCRX_DMAC", "RESERVED", "RESERVED", "RESERVED",
|
||||
"VAD"
|
||||
};
|
||||
|
||||
@@ -1500,6 +1500,15 @@ static struct ddr_chipinfo tl1_ddr_chipinfo = {
|
||||
.wakeup = 2,
|
||||
};
|
||||
|
||||
static struct ddr_chipinfo sm1_ddr_chipinfo = {
|
||||
.same_src_fn = true,
|
||||
.ugt = true,
|
||||
.src_sel_ctrl = true,
|
||||
.asrc_src_sel_ctrl = true,
|
||||
.fifo_num = 4,
|
||||
.wakeup = 2,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_ddr_mngr_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-audio-ddr-manager",
|
||||
@@ -1513,6 +1522,10 @@ static const struct of_device_id aml_ddr_mngr_device_id[] = {
|
||||
.compatible = "amlogic, tl1-audio-ddr-manager",
|
||||
.data = &tl1_ddr_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-audio-ddr-manager",
|
||||
.data = &sm1_ddr_chipinfo,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_ddr_mngr_device_id);
|
||||
@@ -1576,6 +1589,8 @@ static int aml_ddr_mngr_platform_probe(struct platform_device *pdev)
|
||||
&& (p_ddr_chipinfo->fifo_num == 4)) {
|
||||
toddrs[DDR_D].irq = platform_get_irq_byname(pdev, "toddr_d");
|
||||
frddrs[DDR_D].irq = platform_get_irq_byname(pdev, "frddr_d");
|
||||
if (toddrs[DDR_D].irq < 0 || frddrs[DDR_D].irq < 0)
|
||||
dev_err(&pdev->dev, "check irq for DDR_D\n");
|
||||
ddr_num = p_ddr_chipinfo->fifo_num;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ enum toddr_src {
|
||||
FRHDMIRX, /* from tl1 chipset*/
|
||||
LOOPBACK_B,
|
||||
SPDIFIN_LB,
|
||||
EARCRX_DMAC, /* from sm1 chipset */
|
||||
VAD,
|
||||
};
|
||||
|
||||
|
||||
792
sound/soc/amlogic/auge/earc.c
Normal file
792
sound/soc/amlogic/auge/earc.c
Normal file
@@ -0,0 +1,792 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/earc.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* Audio External Input/Out drirver
|
||||
* such as fratv, frhdmirx
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include "ddr_mngr.h"
|
||||
#include "earc_hw.h"
|
||||
|
||||
#define DRV_NAME "EARC"
|
||||
|
||||
struct earc {
|
||||
struct aml_audio_controller *actrl;
|
||||
struct device *dev;
|
||||
|
||||
struct clk *clk_rx_gate;
|
||||
struct clk *clk_rx_cmdc;
|
||||
struct clk *clk_rx_dmac;
|
||||
struct clk *clk_rx_cmdc_srcpll;
|
||||
struct clk *clk_rx_dmac_srcpll;
|
||||
struct clk *clk_tx_gate;
|
||||
struct clk *clk_tx_cmdc;
|
||||
struct clk *clk_tx_dmac;
|
||||
struct clk *clk_tx_cmdc_srcpll;
|
||||
struct clk *clk_tx_dmac_srcpll;
|
||||
|
||||
struct toddr *tddr;
|
||||
struct frddr *fddr;
|
||||
|
||||
int irq_rx_cmdc;
|
||||
int irq_rx_dmac;
|
||||
int irq_tx_cmdc;
|
||||
int irq_tx_dmac;
|
||||
|
||||
int sysclk_freq;
|
||||
};
|
||||
|
||||
#define PREALLOC_BUFFER_MAX (256 * 1024)
|
||||
|
||||
#define EARC_RATES (SNDRV_PCM_RATE_8000_192000)
|
||||
#define EARC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
|
||||
SNDRV_PCM_FMTBIT_S24_LE |\
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static const struct snd_pcm_hardware earc_hardware = {
|
||||
.info =
|
||||
SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_PAUSE,
|
||||
|
||||
.formats = EARC_FORMATS,
|
||||
|
||||
.period_bytes_min = 64,
|
||||
.period_bytes_max = 128 * 1024,
|
||||
.periods_min = 2,
|
||||
.periods_max = 1024,
|
||||
.buffer_bytes_max = 256 * 1024,
|
||||
|
||||
.rate_min = 8000,
|
||||
.rate_max = 192000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 32,
|
||||
};
|
||||
|
||||
static irqreturn_t earc_ddr_isr(int irq, void *devid)
|
||||
{
|
||||
struct snd_pcm_substream *substream =
|
||||
(struct snd_pcm_substream *)devid;
|
||||
|
||||
if (!snd_pcm_running(substream))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
snd_pcm_period_elapsed(substream);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t earc_rx_cmdc_isr(int irq, void *devid)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t earc_rx_dmac_isr(int irq, void *devid)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t earc_tx_cmdc_isr(int irq, void *devid)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t earc_tx_dmac_isr(int irq, void *devid)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int earc_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct device *dev = rtd->platform->dev;
|
||||
struct earc *p_earc;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
|
||||
p_earc = (struct earc *)dev_get_drvdata(dev);
|
||||
|
||||
snd_soc_set_runtime_hwparams(substream, &earc_hardware);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
p_earc->fddr = aml_audio_register_frddr(dev,
|
||||
p_earc->actrl,
|
||||
earc_ddr_isr, substream);
|
||||
if (p_earc->fddr == NULL) {
|
||||
dev_err(dev, "failed to claim from ddr\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
if (p_earc->irq_tx_cmdc > 0) {
|
||||
ret = request_irq(p_earc->irq_tx_cmdc,
|
||||
earc_tx_cmdc_isr, 0, "tx_cmdc",
|
||||
p_earc);
|
||||
if (ret) {
|
||||
dev_err(p_earc->dev, "failed to claim irq_tx_cmdc %u\n",
|
||||
p_earc->irq_tx_cmdc);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (p_earc->irq_tx_dmac > 0) {
|
||||
ret = request_irq(p_earc->irq_tx_dmac,
|
||||
earc_tx_dmac_isr, 0, "tx_dmac",
|
||||
p_earc);
|
||||
if (ret) {
|
||||
dev_err(p_earc->dev, "failed to claim irq_tx_dmac %u\n",
|
||||
p_earc->irq_tx_dmac);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_earc->tddr = aml_audio_register_toddr(dev,
|
||||
p_earc->actrl,
|
||||
earc_ddr_isr, substream);
|
||||
if (p_earc->tddr == NULL) {
|
||||
dev_err(dev, "failed to claim to ddr\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = request_irq(p_earc->irq_rx_cmdc,
|
||||
earc_rx_cmdc_isr, 0, "rx_cmdc",
|
||||
p_earc);
|
||||
if (ret) {
|
||||
dev_err(p_earc->dev, "failed to claim irq_rx_cmdc %u\n",
|
||||
p_earc->irq_rx_cmdc);
|
||||
return ret;
|
||||
}
|
||||
ret = request_irq(p_earc->irq_rx_dmac,
|
||||
earc_rx_dmac_isr, 0, "rx_dmac",
|
||||
p_earc);
|
||||
if (ret) {
|
||||
dev_err(p_earc->dev, "failed to claim rx_dmac %u\n",
|
||||
p_earc->irq_rx_dmac);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
runtime->private_data = p_earc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct earc *p_earc = runtime->private_data;
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
aml_audio_unregister_frddr(p_earc->dev, substream);
|
||||
|
||||
if (p_earc->irq_tx_cmdc > 0)
|
||||
free_irq(p_earc->irq_tx_cmdc, p_earc);
|
||||
|
||||
if (p_earc->irq_tx_dmac > 0)
|
||||
free_irq(p_earc->irq_tx_dmac, p_earc);
|
||||
} else {
|
||||
aml_audio_unregister_toddr(p_earc->dev, substream);
|
||||
free_irq(p_earc->irq_rx_cmdc, p_earc);
|
||||
free_irq(p_earc->irq_rx_dmac, p_earc);
|
||||
}
|
||||
runtime->private_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
return snd_pcm_lib_malloc_pages(substream,
|
||||
params_buffer_bytes(hw_params));
|
||||
}
|
||||
|
||||
static int earc_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct earc *p_earc = runtime->private_data;
|
||||
unsigned int start_addr, end_addr, int_addr;
|
||||
|
||||
start_addr = runtime->dma_addr;
|
||||
end_addr = start_addr + runtime->dma_bytes - 8;
|
||||
int_addr = frames_to_bytes(runtime, runtime->period_size) / 8;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
struct frddr *fr = p_earc->fddr;
|
||||
|
||||
aml_frddr_set_buf(fr, start_addr, end_addr);
|
||||
aml_frddr_set_intrpt(fr, int_addr);
|
||||
} else {
|
||||
struct toddr *to = p_earc->tddr;
|
||||
|
||||
aml_toddr_set_buf(to, start_addr, end_addr);
|
||||
aml_toddr_set_intrpt(to, int_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t earc_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct earc *p_earc = runtime->private_data;
|
||||
unsigned int addr, start_addr;
|
||||
snd_pcm_uframes_t frames;
|
||||
|
||||
start_addr = runtime->dma_addr;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
addr = aml_frddr_get_position(p_earc->fddr);
|
||||
else
|
||||
addr = aml_toddr_get_position(p_earc->tddr);
|
||||
|
||||
frames = bytes_to_frames(runtime, addr - start_addr);
|
||||
if (frames > runtime->buffer_size)
|
||||
frames = 0;
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
int earc_silence(struct snd_pcm_substream *substream, int channel,
|
||||
snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
char *ppos;
|
||||
int n;
|
||||
|
||||
n = frames_to_bytes(runtime, count);
|
||||
ppos = runtime->dma_area + frames_to_bytes(runtime, pos);
|
||||
memset(ppos, 0, n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_mmap(struct snd_pcm_substream *substream,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return snd_pcm_lib_default_mmap(substream, vma);
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops earc_ops = {
|
||||
.open = earc_open,
|
||||
.close = earc_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = earc_hw_params,
|
||||
.hw_free = earc_hw_free,
|
||||
.prepare = earc_prepare,
|
||||
.trigger = earc_trigger,
|
||||
.pointer = earc_pointer,
|
||||
.silence = earc_silence,
|
||||
.mmap = earc_mmap,
|
||||
};
|
||||
|
||||
static int earc_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
return snd_pcm_lib_preallocate_pages_for_all(
|
||||
rtd->pcm, SNDRV_DMA_TYPE_DEV,
|
||||
rtd->card->snd_card->dev,
|
||||
PREALLOC_BUFFER_MAX,
|
||||
PREALLOC_BUFFER_MAX);
|
||||
}
|
||||
|
||||
struct snd_soc_platform_driver earc_platform = {
|
||||
.ops = &earc_ops,
|
||||
.pcm_new = earc_new,
|
||||
};
|
||||
|
||||
static int earc_dai_probe(struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_remove(struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_prepare(
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
unsigned int bit_depth = snd_pcm_format_width(runtime->format);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
struct frddr *fr = p_earc->fddr;
|
||||
enum frddr_dest dst = frddr_src_get();
|
||||
|
||||
pr_info("%s Expected frddr dst:%s\n",
|
||||
__func__,
|
||||
frddr_src_get_str(dst));
|
||||
|
||||
aml_frddr_select_dst(fr, dst);
|
||||
aml_frddr_set_fifos(fr, 0x40, 0x20);
|
||||
} else {
|
||||
struct toddr *to = p_earc->tddr;
|
||||
unsigned int msb = 0, lsb = 0, toddr_type = 0;
|
||||
unsigned int src = EARCRX_DMAC;
|
||||
struct toddr_fmt fmt;
|
||||
|
||||
if (bit_depth == 24)
|
||||
toddr_type = 4;
|
||||
else
|
||||
toddr_type = 0;
|
||||
|
||||
pr_info("%s Expected toddr src:%s\n",
|
||||
__func__,
|
||||
toddr_src_get_str(src));
|
||||
|
||||
msb = bit_depth - 1;
|
||||
|
||||
pr_info("%s m:%d, n:%d\n", __func__, msb, lsb);
|
||||
|
||||
fmt.type = toddr_type;
|
||||
fmt.msb = msb;
|
||||
fmt.lsb = lsb;
|
||||
fmt.endian = 0;
|
||||
fmt.bit_depth = bit_depth;
|
||||
fmt.ch_num = runtime->channels;
|
||||
fmt.rate = runtime->rate;
|
||||
|
||||
aml_toddr_select_src(to, src);
|
||||
aml_toddr_set_format(to, &fmt);
|
||||
aml_toddr_set_fifos(to, 0x40);
|
||||
|
||||
earcrx_cmdc_init();
|
||||
earcrx_dmac_init();
|
||||
earc_arc_init();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
dev_info(substream->pcm->card->dev, "eARC/ARC TX enable\n");
|
||||
|
||||
aml_frddr_enable(p_earc->fddr, true);
|
||||
} else {
|
||||
dev_info(substream->pcm->card->dev, "eARC/ARC RX enable\n");
|
||||
|
||||
aml_toddr_enable(p_earc->tddr, true);
|
||||
}
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
dev_info(substream->pcm->card->dev, "eARC/ARC TX disable\n");
|
||||
|
||||
aml_frddr_enable(p_earc->fddr, false);
|
||||
} else {
|
||||
dev_info(substream->pcm->card->dev, "eARC/ARC RX disable\n");
|
||||
|
||||
aml_toddr_enable(p_earc->tddr, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_hw_params(
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
unsigned int rate = params_rate(params);
|
||||
int ret = 0;
|
||||
|
||||
pr_info("%s:rate:%d, sysclk:%d\n",
|
||||
__func__,
|
||||
rate,
|
||||
p_earc->sysclk_freq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int earc_dai_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
pr_info("asoc earc_dai_set_fmt, %#x, %p\n", fmt, p_earc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_set_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
p_earc->sysclk_freq = freq;
|
||||
pr_info("earc_dai_set_sysclk, %d, %d, %d\n",
|
||||
clk_id, freq, dir);
|
||||
|
||||
clk_set_rate(p_earc->clk_rx_cmdc, 2000000);
|
||||
clk_set_rate(p_earc->clk_rx_dmac, 24576000);
|
||||
|
||||
pr_info("earc rx cmdc clk:%lu rx dmac clk:%lu\n",
|
||||
clk_get_rate(p_earc->clk_rx_cmdc),
|
||||
clk_get_rate(p_earc->clk_rx_dmac));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int earc_dai_startup(
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret;
|
||||
|
||||
/* enable clock gate */
|
||||
if (!IS_ERR(p_earc->clk_rx_gate)) {
|
||||
ret = clk_prepare_enable(p_earc->clk_rx_gate);
|
||||
if (ret) {
|
||||
pr_err("Can't enable earc rx_gate: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x1 << 6);
|
||||
|
||||
/* enable clock */
|
||||
if (!IS_ERR(p_earc->clk_rx_cmdc)) {
|
||||
ret = clk_prepare_enable(p_earc->clk_rx_cmdc);
|
||||
if (ret) {
|
||||
pr_err("Can't enable earc clk_rx_cmdc: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!IS_ERR(p_earc->clk_rx_dmac)) {
|
||||
ret = clk_prepare_enable(p_earc->clk_rx_dmac);
|
||||
if (ret) {
|
||||
pr_err("Can't enable earc clk_rx_dmac: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!IS_ERR(p_earc->clk_tx_cmdc)) {
|
||||
ret = clk_prepare_enable(p_earc->clk_tx_cmdc);
|
||||
if (ret) {
|
||||
pr_err("Can't enable earc clk_tx_cmdc: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!IS_ERR(p_earc->clk_tx_dmac)) {
|
||||
ret = clk_prepare_enable(p_earc->clk_tx_dmac);
|
||||
if (ret) {
|
||||
pr_err("Can't enable earc clk_tx_dmac: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
pr_err("failed enable clock\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static void earc_dai_shutdown(
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
/* disable clock and gate */
|
||||
if (!IS_ERR(p_earc->clk_rx_cmdc))
|
||||
clk_disable_unprepare(p_earc->clk_rx_cmdc);
|
||||
if (!IS_ERR(p_earc->clk_rx_dmac))
|
||||
clk_disable_unprepare(p_earc->clk_rx_dmac);
|
||||
if (!IS_ERR(p_earc->clk_tx_cmdc))
|
||||
clk_disable_unprepare(p_earc->clk_tx_cmdc);
|
||||
if (!IS_ERR(p_earc->clk_tx_dmac))
|
||||
clk_disable_unprepare(p_earc->clk_tx_dmac);
|
||||
if (!IS_ERR(p_earc->clk_rx_gate))
|
||||
clk_disable_unprepare(p_earc->clk_rx_gate);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x0 << 6);
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops earc_dai_ops = {
|
||||
.prepare = earc_dai_prepare,
|
||||
.trigger = earc_dai_trigger,
|
||||
.hw_params = earc_dai_hw_params,
|
||||
.set_fmt = earc_dai_set_fmt,
|
||||
.set_sysclk = earc_dai_set_sysclk,
|
||||
.startup = earc_dai_startup,
|
||||
.shutdown = earc_dai_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver earc_dai[] = {
|
||||
{
|
||||
.name = "EARC/ARC",
|
||||
.id = 0,
|
||||
.probe = earc_dai_probe,
|
||||
.remove = earc_dai_remove,
|
||||
.playback = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 32,
|
||||
.rates = EARC_RATES,
|
||||
.formats = EARC_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 32,
|
||||
.rates = EARC_RATES,
|
||||
.formats = EARC_FORMATS,
|
||||
},
|
||||
.ops = &earc_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new earc_controls[] = {
|
||||
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver earc_component = {
|
||||
.controls = earc_controls,
|
||||
.num_controls = ARRAY_SIZE(earc_controls),
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
static const struct of_device_id earc_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-earc",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, earc_device_id);
|
||||
|
||||
static int earc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device_node *node_prt = NULL;
|
||||
struct platform_device *pdev_parent;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct aml_audio_controller *actrl = NULL;
|
||||
struct earc *p_earc = NULL;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
p_earc = devm_kzalloc(dev, sizeof(struct earc), GFP_KERNEL);
|
||||
if (!p_earc)
|
||||
return -ENOMEM;
|
||||
|
||||
p_earc->dev = dev;
|
||||
dev_set_drvdata(dev, p_earc);
|
||||
|
||||
/* get audio controller */
|
||||
node_prt = of_get_parent(node);
|
||||
if (node_prt == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
pdev_parent = of_find_device_by_node(node_prt);
|
||||
of_node_put(node_prt);
|
||||
actrl = (struct aml_audio_controller *)
|
||||
platform_get_drvdata(pdev_parent);
|
||||
p_earc->actrl = actrl;
|
||||
|
||||
/* clock gate */
|
||||
p_earc->clk_rx_gate = devm_clk_get(&pdev->dev, "rx_gate");
|
||||
if (IS_ERR(p_earc->clk_rx_gate)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't get earc gate\n");
|
||||
return PTR_ERR(p_earc->clk_rx_gate);
|
||||
}
|
||||
/* RX */
|
||||
p_earc->clk_rx_cmdc = devm_clk_get(&pdev->dev, "rx_cmdc");
|
||||
if (IS_ERR(p_earc->clk_rx_cmdc)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't get clk_rx_cmdc\n");
|
||||
return PTR_ERR(p_earc->clk_rx_cmdc);
|
||||
}
|
||||
p_earc->clk_rx_dmac = devm_clk_get(&pdev->dev, "rx_dmac");
|
||||
if (IS_ERR(p_earc->clk_rx_dmac)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't get clk_rx_dmac\n");
|
||||
return PTR_ERR(p_earc->clk_rx_dmac);
|
||||
}
|
||||
p_earc->clk_rx_cmdc_srcpll = devm_clk_get(&pdev->dev, "rx_cmdc_srcpll");
|
||||
if (IS_ERR(p_earc->clk_rx_cmdc_srcpll)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't get clk_rx_cmdc_srcpll\n");
|
||||
return PTR_ERR(p_earc->clk_rx_cmdc_srcpll);
|
||||
}
|
||||
p_earc->clk_rx_dmac_srcpll = devm_clk_get(&pdev->dev, "rx_dmac_srcpll");
|
||||
if (IS_ERR(p_earc->clk_rx_dmac_srcpll)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't get clk_rx_dmac_srcpll\n");
|
||||
return PTR_ERR(p_earc->clk_rx_dmac_srcpll);
|
||||
}
|
||||
ret = clk_set_parent(p_earc->clk_rx_cmdc, p_earc->clk_rx_cmdc_srcpll);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Can't set clk_rx_cmdc parent clock\n");
|
||||
ret = PTR_ERR(p_earc->clk_rx_cmdc);
|
||||
return ret;
|
||||
}
|
||||
ret = clk_set_parent(p_earc->clk_rx_dmac, p_earc->clk_rx_dmac_srcpll);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Can't set clk_rx_dmac parent clock\n");
|
||||
ret = PTR_ERR(p_earc->clk_rx_dmac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TX */
|
||||
p_earc->clk_tx_cmdc = devm_clk_get(&pdev->dev, "tx_cmdc");
|
||||
if (IS_ERR(p_earc->clk_tx_cmdc)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Check whether support eARC TX\n");
|
||||
}
|
||||
p_earc->clk_tx_dmac = devm_clk_get(&pdev->dev, "tx_dmac");
|
||||
if (IS_ERR(p_earc->clk_tx_dmac)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Check whether support eARC TX\n");
|
||||
}
|
||||
p_earc->clk_tx_cmdc_srcpll = devm_clk_get(&pdev->dev, "tx_cmdc_srcpll");
|
||||
if (IS_ERR(p_earc->clk_tx_cmdc_srcpll)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Check whether support eARC TX\n");
|
||||
}
|
||||
p_earc->clk_tx_dmac_srcpll = devm_clk_get(&pdev->dev, "tx_dmac_srcpll");
|
||||
if (IS_ERR(p_earc->clk_tx_dmac_srcpll)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Check whether support eARC TX\n");
|
||||
}
|
||||
if (!IS_ERR(p_earc->clk_tx_cmdc) &&
|
||||
!IS_ERR(p_earc->clk_tx_cmdc_srcpll)) {
|
||||
ret = clk_set_parent(p_earc->clk_tx_cmdc,
|
||||
p_earc->clk_tx_cmdc_srcpll);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Can't set clk_tx_cmdc parent clock\n");
|
||||
ret = PTR_ERR(p_earc->clk_tx_cmdc);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (!IS_ERR(p_earc->clk_tx_dmac) &&
|
||||
!IS_ERR(p_earc->clk_tx_dmac_srcpll)) {
|
||||
ret = clk_set_parent(p_earc->clk_tx_dmac,
|
||||
p_earc->clk_tx_dmac_srcpll);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Can't set clk_tx_dmac parent clock\n");
|
||||
ret = PTR_ERR(p_earc->clk_tx_dmac);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* irqs */
|
||||
p_earc->irq_rx_cmdc =
|
||||
platform_get_irq_byname(pdev, "rx_cmdc");
|
||||
if (p_earc->irq_rx_cmdc < 0) {
|
||||
dev_err(dev, "platform get irq rx_cmdc failed\n");
|
||||
return p_earc->irq_rx_cmdc;
|
||||
}
|
||||
p_earc->irq_rx_dmac =
|
||||
platform_get_irq_byname(pdev, "rx_dmac");
|
||||
if (p_earc->irq_rx_dmac < 0) {
|
||||
dev_err(dev, "platform get irq rx_dmac failed\n");
|
||||
return p_earc->irq_rx_dmac;
|
||||
}
|
||||
p_earc->irq_tx_cmdc =
|
||||
platform_get_irq_byname(pdev, "tx_cmdc");
|
||||
if (p_earc->irq_tx_cmdc < 0)
|
||||
dev_err(dev, "platform get irq tx_cmdc failed, Check whether support eARC TX\n");
|
||||
p_earc->irq_tx_dmac =
|
||||
platform_get_irq_byname(pdev, "tx_dmac");
|
||||
if (p_earc->irq_tx_dmac < 0)
|
||||
dev_err(dev, "platform get irq tx_dmac failed, Check whether support eARC TX\n");
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev,
|
||||
&earc_component,
|
||||
earc_dai,
|
||||
ARRAY_SIZE(earc_dai));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"snd_soc_register_component failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_info("%s, register soc platform\n", __func__);
|
||||
|
||||
return devm_snd_soc_register_platform(dev, &earc_platform);
|
||||
}
|
||||
|
||||
struct platform_driver earc_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = earc_device_id,
|
||||
},
|
||||
.probe = earc_platform_probe,
|
||||
};
|
||||
module_platform_driver(earc_driver);
|
||||
|
||||
MODULE_AUTHOR("Amlogic, Inc.");
|
||||
MODULE_DESCRIPTION("Amlogic eARC/ARC TX/RX ASoc driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("Platform:" DRV_NAME);
|
||||
MODULE_DEVICE_TABLE(of, earc_device_id);
|
||||
87
sound/soc/amlogic/auge/earc_hw.c
Normal file
87
sound/soc/amlogic/auge/earc_hw.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/earc_hw.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "earc_hw.h"
|
||||
|
||||
|
||||
void earcrx_cmdc_init(void)
|
||||
{
|
||||
/* set irq mask */
|
||||
earcrx_top_write(EARCRX_CMDC_INT_MASK,
|
||||
(0 << 15) | /* idle2_int */
|
||||
(0 << 14) | /* idle1_int */
|
||||
(0 << 13) | /* disc2_int */
|
||||
(0 << 12) | /* disc1_int */
|
||||
(0 << 11) | /* earc_int */
|
||||
(1 << 10) | /* hb_status_int */
|
||||
(0 << 9) | /* losthb_int */
|
||||
(0 << 8) | /* timeout_int */
|
||||
(0 << 7) | /* status_ch_int */
|
||||
(0 << 6) | /* int_rec_invalid_id */
|
||||
(0 << 5) | /* int_rec_invalid_offset */
|
||||
(0 << 4) | /* int_rec_unexp */
|
||||
(0 << 3) | /* int_rec_ecc_err */
|
||||
(0 << 2) | /* int_rec_parity_err */
|
||||
(0 << 1) | /* int_recv_packet */
|
||||
(0 << 0) /* int_rec_time_out */
|
||||
);
|
||||
}
|
||||
|
||||
void earcrx_dmac_init(void)
|
||||
{
|
||||
earcrx_dmac_write(EARCRX_DMAC_TOP_CTRL0, 1 << 31); /* reg_top_work_en */
|
||||
earcrx_dmac_write(EARCRX_DMAC_SYNC_CTRL0,
|
||||
(1 << 31) | /* reg_work_en */
|
||||
(1 << 30) | /* reg_rst_afifo_out_n */
|
||||
(1 << 29) | /* reg_rst_afifo_in_n */
|
||||
(1 << 16) | /* reg_ana_buf_data_sel_en */
|
||||
(3 << 12) | /* reg_ana_buf_data_sel */
|
||||
(7 << 8) | /* reg_ana_clr_cnt */
|
||||
(7 << 4) /* reg_ana_set_cnt */
|
||||
);
|
||||
earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0,
|
||||
(1 << 29) | /* reg_rst_afifo_out_n */
|
||||
(1 << 28) /* reg_rst_afifo_in_n */
|
||||
);
|
||||
earcrx_dmac_write(EARCRX_DMAC_UBIT_CTRL0,
|
||||
(1 << 31) | /* reg_work_enable */
|
||||
(47 << 16) | /* reg_fifo_thd */
|
||||
(1 << 12) | /* reg_user_lr */
|
||||
(29 << 0) /* reg_data_bit */
|
||||
);
|
||||
earcrx_dmac_write(EARCRX_ANA_RST_CTRL0, 1 << 31);
|
||||
earcrx_dmac_write(EARCRX_ERR_CORRECT_CTRL0, 1 << 31); /* reg_work_en */
|
||||
}
|
||||
|
||||
void earc_arc_init(void)
|
||||
{
|
||||
earcrx_dmac_write(EARCRX_SPDIFIN_CTRL0,
|
||||
(1 << 31) | /* reg_work_en */
|
||||
(1 << 30) | /* reg_chnum_sel */
|
||||
(1 << 25) | /* reg_findpapb_en */
|
||||
(0xFFF<<12) /* reg_nonpcm2pcm_th */
|
||||
);
|
||||
earcrx_dmac_write(EARCRX_SPDIFIN_CTRL2,
|
||||
(1 << 14) | /* reg_earc_auto */
|
||||
(1 << 13) /* reg_earcin_papb_lr */
|
||||
);
|
||||
earcrx_dmac_write(EARCRX_SPDIFIN_CTRL3,
|
||||
(0xEC37<<16) | /* reg_earc_pa_value */
|
||||
(0x5A5A<<0) /* reg_earc_pb_value */
|
||||
);
|
||||
}
|
||||
26
sound/soc/amlogic/auge/earc_hw.h
Normal file
26
sound/soc/amlogic/auge/earc_hw.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/earc_hw.h
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#ifndef __EARC_HW_H__
|
||||
#define __EARC_HW_H__
|
||||
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
extern void earcrx_cmdc_init(void);
|
||||
extern void earcrx_dmac_init(void);
|
||||
extern void earc_arc_init(void);
|
||||
#endif
|
||||
@@ -231,6 +231,87 @@ void vad_update_bits(unsigned int reg,
|
||||
}
|
||||
EXPORT_SYMBOL(vad_update_bits);
|
||||
|
||||
int earcrx_cmdc_read(unsigned int reg)
|
||||
{
|
||||
int ret, val = 0;
|
||||
|
||||
ret = aml_snd_read(IO_EARCRX_CMDC, reg, &val);
|
||||
|
||||
if (ret) {
|
||||
pr_err("read audio reg %x error %d\n", reg, ret);
|
||||
return -1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_cmdc_read);
|
||||
|
||||
void earcrx_cmdc_write(unsigned int reg, unsigned int val)
|
||||
{
|
||||
aml_snd_write(IO_EARCRX_CMDC, reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_cmdc_write);
|
||||
|
||||
void earcrx_cmdc_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
aml_snd_update_bits(IO_EARCRX_CMDC, reg, mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_cmdc_update_bits);
|
||||
|
||||
int earcrx_dmac_read(unsigned int reg)
|
||||
{
|
||||
int ret, val = 0;
|
||||
|
||||
ret = aml_snd_read(IO_EARCRX_DMAC, reg, &val);
|
||||
|
||||
if (ret) {
|
||||
pr_err("read audio reg %x error %d\n", reg, ret);
|
||||
return -1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_dmac_read);
|
||||
|
||||
void earcrx_dmac_write(unsigned int reg, unsigned int val)
|
||||
{
|
||||
aml_snd_write(IO_EARCRX_DMAC, reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_dmac_write);
|
||||
|
||||
void earcrx_dmac_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
aml_snd_update_bits(IO_EARCRX_DMAC, reg, mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_dmac_update_bits);
|
||||
|
||||
int earcrx_top_read(unsigned int reg)
|
||||
{
|
||||
int ret, val = 0;
|
||||
|
||||
ret = aml_snd_read(IO_EARCRX_TOP, reg, &val);
|
||||
|
||||
if (ret) {
|
||||
pr_err("read audio reg %x error %d\n", reg, ret);
|
||||
return -1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_top_read);
|
||||
|
||||
void earcrx_top_write(unsigned int reg, unsigned int val)
|
||||
{
|
||||
aml_snd_write(IO_EARCRX_TOP, reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_top_write);
|
||||
|
||||
void earcrx_top_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
aml_snd_update_bits(IO_EARCRX_TOP, reg, mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL(earcrx_top_update_bits);
|
||||
|
||||
static int snd_iomap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource res;
|
||||
|
||||
@@ -25,6 +25,9 @@ enum{
|
||||
IO_EQDRC_BUS,
|
||||
IO_RESET,
|
||||
IO_VAD,
|
||||
IO_EARCRX_CMDC,
|
||||
IO_EARCRX_DMAC,
|
||||
IO_EARCRX_TOP,
|
||||
|
||||
IO_MAX,
|
||||
};
|
||||
@@ -58,4 +61,17 @@ extern int vad_read(unsigned int reg);
|
||||
extern void vad_write(unsigned int reg, unsigned int val);
|
||||
extern void vad_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
|
||||
extern int earcrx_cmdc_read(unsigned int reg);
|
||||
extern void earcrx_cmdc_write(unsigned int reg, unsigned int val);
|
||||
extern void earcrx_cmdc_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
extern int earcrx_dmac_read(unsigned int reg);
|
||||
extern void earcrx_dmac_write(unsigned int reg, unsigned int val);
|
||||
extern void earcrx_dmac_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
extern int earcrx_top_read(unsigned int reg);
|
||||
extern void earcrx_top_write(unsigned int reg, unsigned int val);
|
||||
extern void earcrx_top_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
#endif
|
||||
|
||||
@@ -71,8 +71,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg)
|
||||
|
||||
if (id >= 0 && id <= 2) {
|
||||
/* tdmout_a, tdmout_b, tdmout_c */
|
||||
reg_base = EE_AUDIO_TDMOUT_A_SWAP;
|
||||
offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP;
|
||||
reg_base = EE_AUDIO_TDMOUT_A_SWAP0;
|
||||
offset = EE_AUDIO_TDMOUT_B_SWAP0 - EE_AUDIO_TDMOUT_A_SWAP0;
|
||||
} else if (id < 6) {
|
||||
/*lb_cfg->datalb_src for pad tdm in,
|
||||
*pad from tdmin_a, tdmin_b, tdmin_c
|
||||
@@ -115,8 +115,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg)
|
||||
audiobus_write(
|
||||
reg,
|
||||
lb_cfg->datalb_chmask);
|
||||
reg_base = EE_AUDIO_TDMIN_A_SWAP;
|
||||
offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP;
|
||||
reg_base = EE_AUDIO_TDMIN_A_SWAP0;
|
||||
offset = EE_AUDIO_TDMIN_B_SWAP0 - EE_AUDIO_TDMIN_A_SWAP0;
|
||||
} else {
|
||||
pr_err("unsupport datalb_src\n");
|
||||
return;
|
||||
@@ -124,7 +124,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg)
|
||||
|
||||
if (lb_cfg->datain_datalb_total > 8) {
|
||||
audiobus_write(
|
||||
EE_AUDIO_TDMIN_LB_SWAP,
|
||||
EE_AUDIO_TDMIN_LB_SWAP0,
|
||||
lb_cfg->datalb_chswap);
|
||||
|
||||
audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3);
|
||||
@@ -134,7 +134,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg)
|
||||
} else {
|
||||
/*swap same as tdmout */
|
||||
reg = reg_base + offset * id;
|
||||
audiobus_write(EE_AUDIO_TDMIN_LB_SWAP,
|
||||
audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0,
|
||||
audiobus_read(reg));
|
||||
|
||||
/*mask same as datalb*/
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "pdm.h"
|
||||
#include "pdm_hw.h"
|
||||
#include "pdm_match_table.c"
|
||||
#include "audio_io.h"
|
||||
#include "iomap.h"
|
||||
#include "regs.h"
|
||||
@@ -166,6 +167,46 @@ static int pdm_dclk_set_enum(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const pdm_train_texts[] = {
|
||||
"Disabled",
|
||||
"Enable",
|
||||
};
|
||||
|
||||
static const struct soc_enum pdm_train_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pdm_train_texts),
|
||||
pdm_train_texts);
|
||||
|
||||
static int pdm_train_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
|
||||
struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_pdm->train_en;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pdm_train_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
|
||||
struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
if (!p_pdm->chipinfo ||
|
||||
!p_pdm->chipinfo->train ||
|
||||
(p_pdm->train_en == ucontrol->value.enumerated.item[0]))
|
||||
return 0;
|
||||
|
||||
p_pdm->train_en = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (p_pdm->clk_on)
|
||||
pdm_train_en(p_pdm->train_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new snd_pdm_controls[] = {
|
||||
/* which set */
|
||||
@@ -184,7 +225,13 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = {
|
||||
pdm_dclk_enum,
|
||||
pdm_dclk_get_enum,
|
||||
pdm_dclk_set_enum),
|
||||
|
||||
SOC_ENUM_EXT("PDM Train",
|
||||
pdm_train_enum,
|
||||
pdm_train_get_enum,
|
||||
pdm_train_set_enum),
|
||||
};
|
||||
|
||||
#if 0
|
||||
static int pdm_mute_val_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
@@ -332,11 +379,19 @@ static irqreturn_t aml_pdm_isr_handler(int irq, void *data)
|
||||
{
|
||||
struct snd_pcm_substream *substream =
|
||||
(struct snd_pcm_substream *)data;
|
||||
int train_sts = pdm_train_sts();
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
snd_pcm_period_elapsed(substream);
|
||||
|
||||
if (train_sts) {
|
||||
pr_debug("%s train result:0x%x\n",
|
||||
__func__,
|
||||
train_sts);
|
||||
pdm_train_clr();
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -842,6 +897,9 @@ int aml_pdm_dai_startup(struct snd_pcm_substream *substream,
|
||||
pdm_running_create_controls(card, p_pdm);
|
||||
}
|
||||
#endif
|
||||
|
||||
p_pdm->clk_on = true;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
pr_err("failed enable clock\n");
|
||||
@@ -860,6 +918,8 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
}
|
||||
#endif
|
||||
|
||||
p_pdm->clk_on = false;
|
||||
|
||||
/* disable clock and gate */
|
||||
clk_disable_unprepare(p_pdm->clk_pdm_dclk);
|
||||
clk_disable_unprepare(p_pdm->clk_pdm_sysclk);
|
||||
@@ -897,32 +957,6 @@ static const struct snd_soc_component_driver aml_pdm_component = {
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
static struct pdm_chipinfo g12a_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = false,
|
||||
};
|
||||
|
||||
static struct pdm_chipinfo tl1_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_pdm_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-pdm",
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-pdm",
|
||||
.data = &g12a_pdm_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-pdm",
|
||||
.data = &tl1_pdm_chipinfo,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_pdm_device_id);
|
||||
|
||||
static int snd_soc_of_get_slot_mask(
|
||||
struct device_node *np,
|
||||
const char *prop_name,
|
||||
|
||||
@@ -54,6 +54,8 @@ struct pdm_chipinfo {
|
||||
bool mute_fn;
|
||||
/* truncate invalid data when filter init */
|
||||
bool truncate_data;
|
||||
/* train */
|
||||
bool train;
|
||||
};
|
||||
|
||||
struct aml_pdm {
|
||||
@@ -78,12 +80,16 @@ struct aml_pdm {
|
||||
int dclk_idx;
|
||||
/* PCM or Raw Data */
|
||||
int bypass;
|
||||
/* PDM clk on/off */
|
||||
bool clk_on;
|
||||
|
||||
/* lane mask in, each lane carries two channels */
|
||||
int lane_mask_in;
|
||||
|
||||
/* PDM clk on/off, only clk on, pdm registers can be accessed */
|
||||
bool clk_on;
|
||||
|
||||
/* train */
|
||||
bool train_en;
|
||||
|
||||
struct pdm_chipinfo *chipinfo;
|
||||
struct snd_kcontrol *controls[PDM_RUN_MAX];
|
||||
};
|
||||
|
||||
@@ -487,3 +487,24 @@ void pdm_init_truncate_data(int freq)
|
||||
|
||||
aml_pdm_write(PDM_MASK_NUM, mask_val);
|
||||
}
|
||||
|
||||
void pdm_train_en(bool en)
|
||||
{
|
||||
aml_pdm_update_bits(PDM_CTRL,
|
||||
0x1 << 19,
|
||||
en << 19);
|
||||
}
|
||||
|
||||
void pdm_train_clr(void)
|
||||
{
|
||||
aml_pdm_update_bits(PDM_CTRL,
|
||||
0x1 << 18,
|
||||
0x1 << 18);
|
||||
}
|
||||
|
||||
int pdm_train_sts(void)
|
||||
{
|
||||
int val = aml_pdm_read(PDM_STS);
|
||||
|
||||
return ((val >> 4) & 0xff);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ extern void pdm_set_mute_channel(int mute_chmask);
|
||||
|
||||
extern void pdm_init_truncate_data(int freq);
|
||||
|
||||
extern void pdm_train_en(bool en);
|
||||
extern void pdm_train_clr(void);
|
||||
extern int pdm_train_sts(void);
|
||||
|
||||
extern int pdm_hcic_shift_gain;
|
||||
extern int pdm_dclk;
|
||||
|
||||
|
||||
53
sound/soc/amlogic/auge/pdm_match_table.c
Normal file
53
sound/soc/amlogic/auge/pdm_match_table.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/pdm_match_table.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct pdm_chipinfo g12a_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = false,
|
||||
};
|
||||
|
||||
static struct pdm_chipinfo tl1_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = false,
|
||||
};
|
||||
|
||||
static struct pdm_chipinfo sm1_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = false,
|
||||
.train = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_pdm_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-pdm",
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-pdm",
|
||||
.data = &g12a_pdm_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-pdm",
|
||||
.data = &tl1_pdm_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-pdm",
|
||||
.data = &sm1_pdm_chipinfo,
|
||||
},
|
||||
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_pdm_device_id);
|
||||
@@ -108,6 +108,10 @@ enum clk_sel {
|
||||
#define EE_AUDIO_CLK_SPDIFIN_LB_CTRL 0x02f
|
||||
#define EE_AUDIO_CLK_EQDRC_CTRL0 0x030
|
||||
#define EE_AUDIO_VAD_CLK_CTRL 0x031
|
||||
#define EE_AUDIO_EARCTX_CMDC_CLK_CTRL 0x032
|
||||
#define EE_AUDIO_EARCTX_DMAC_CLK_CTRL 0x033
|
||||
#define EE_AUDIO_EARCRX_CMDC_CLK_CTRL 0x034
|
||||
#define EE_AUDIO_EARCRX_DMAC_CLK_CTRL 0x035
|
||||
|
||||
/*
|
||||
* AUDIO TODDR
|
||||
@@ -204,56 +208,93 @@ enum clk_sel {
|
||||
#define EE_AUDIO_LB_STS 0x0b6
|
||||
|
||||
#define EE_AUDIO_TDMIN_A_CTRL 0x0c0
|
||||
#define EE_AUDIO_TDMIN_A_SWAP 0x0c1
|
||||
#define EE_AUDIO_TDMIN_A_SWAP0 0x0c1
|
||||
#define EE_AUDIO_TDMIN_A_SWAP1 0x260
|
||||
#define EE_AUDIO_TDMIN_A_MASK0 0x0c2
|
||||
#define EE_AUDIO_TDMIN_A_MASK1 0x0c3
|
||||
#define EE_AUDIO_TDMIN_A_MASK2 0x0c4
|
||||
#define EE_AUDIO_TDMIN_A_MASK3 0x0c5
|
||||
#define EE_AUDIO_TDMIN_A_MASK4 0x261
|
||||
#define EE_AUDIO_TDMIN_A_MASK5 0x262
|
||||
#define EE_AUDIO_TDMIN_A_MASK6 0x263
|
||||
#define EE_AUDIO_TDMIN_A_MASK7 0x264
|
||||
#define EE_AUDIO_TDMIN_A_STAT 0x0c6
|
||||
#define EE_AUDIO_TDMIN_A_MUTE_VAL 0x0c7
|
||||
#define EE_AUDIO_TDMIN_A_MUTE0 0x0c8
|
||||
#define EE_AUDIO_TDMIN_A_MUTE1 0x0c9
|
||||
#define EE_AUDIO_TDMIN_A_MUTE2 0x0ca
|
||||
#define EE_AUDIO_TDMIN_A_MUTE3 0x0cb
|
||||
#define EE_AUDIO_TDMIN_A_MUTE4 0x265
|
||||
#define EE_AUDIO_TDMIN_A_MUTE5 0x266
|
||||
#define EE_AUDIO_TDMIN_A_MUTE6 0x267
|
||||
#define EE_AUDIO_TDMIN_A_MUTE7 0x268
|
||||
|
||||
#define EE_AUDIO_TDMIN_B_CTRL 0x0d0
|
||||
#define EE_AUDIO_TDMIN_B_SWAP 0x0d1
|
||||
#define EE_AUDIO_TDMIN_B_SWAP0 0x0d1
|
||||
#define EE_AUDIO_TDMIN_B_SWAP1 0x270
|
||||
#define EE_AUDIO_TDMIN_B_MASK0 0x0d2
|
||||
#define EE_AUDIO_TDMIN_B_MASK1 0x0d3
|
||||
#define EE_AUDIO_TDMIN_B_MASK2 0x0d4
|
||||
#define EE_AUDIO_TDMIN_B_MASK3 0x0d5
|
||||
#define EE_AUDIO_TDMIN_B_MASK4 0x271
|
||||
#define EE_AUDIO_TDMIN_B_MASK5 0x272
|
||||
#define EE_AUDIO_TDMIN_B_MASK6 0x273
|
||||
#define EE_AUDIO_TDMIN_B_MASK7 0x274
|
||||
#define EE_AUDIO_TDMIN_B_STAT 0x0d6
|
||||
#define EE_AUDIO_TDMIN_B_MUTE_VAL 0x0d7
|
||||
#define EE_AUDIO_TDMIN_B_MUTE0 0x0d8
|
||||
#define EE_AUDIO_TDMIN_B_MUTE1 0x0d9
|
||||
#define EE_AUDIO_TDMIN_B_MUTE2 0x0da
|
||||
#define EE_AUDIO_TDMIN_B_MUTE3 0x0db
|
||||
#define EE_AUDIO_TDMIN_B_MUTE4 0x275
|
||||
#define EE_AUDIO_TDMIN_B_MUTE5 0x276
|
||||
#define EE_AUDIO_TDMIN_B_MUTE6 0x277
|
||||
#define EE_AUDIO_TDMIN_B_MUTE7 0x278
|
||||
|
||||
#define EE_AUDIO_TDMIN_C_CTRL 0x0e0
|
||||
#define EE_AUDIO_TDMIN_C_SWAP0 0x0e1
|
||||
#define EE_AUDIO_TDMIN_C_SWAP1 0x280
|
||||
#define EE_AUDIO_TDMIN_C_SWAP 0x0e1
|
||||
#define EE_AUDIO_TDMIN_C_MASK0 0x0e2
|
||||
#define EE_AUDIO_TDMIN_C_MASK1 0x0e3
|
||||
#define EE_AUDIO_TDMIN_C_MASK2 0x0e4
|
||||
#define EE_AUDIO_TDMIN_C_MASK3 0x0e5
|
||||
#define EE_AUDIO_TDMIN_C_MASK4 0x281
|
||||
#define EE_AUDIO_TDMIN_C_MASK5 0x282
|
||||
#define EE_AUDIO_TDMIN_C_MASK6 0x283
|
||||
#define EE_AUDIO_TDMIN_C_MASK7 0x284
|
||||
#define EE_AUDIO_TDMIN_C_STAT 0x0e6
|
||||
#define EE_AUDIO_TDMIN_C_MUTE_VAL 0x0e7
|
||||
#define EE_AUDIO_TDMIN_C_MUTE0 0x0e8
|
||||
#define EE_AUDIO_TDMIN_C_MUTE1 0x0e9
|
||||
#define EE_AUDIO_TDMIN_C_MUTE2 0x0ea
|
||||
#define EE_AUDIO_TDMIN_C_MUTE3 0x0eb
|
||||
#define EE_AUDIO_TDMIN_C_MUTE4 0x285
|
||||
#define EE_AUDIO_TDMIN_C_MUTE5 0x286
|
||||
#define EE_AUDIO_TDMIN_C_MUTE6 0x287
|
||||
#define EE_AUDIO_TDMIN_C_MUTE7 0x288
|
||||
|
||||
#define EE_AUDIO_TDMIN_LB_CTRL 0x0f0
|
||||
#define EE_AUDIO_TDMIN_LB_SWAP 0x0f1
|
||||
#define EE_AUDIO_TDMIN_LB_SWAP0 0x0f1
|
||||
#define EE_AUDIO_TDMIN_LB_SWAP1 0x290
|
||||
#define EE_AUDIO_TDMIN_LB_MASK0 0x0f2
|
||||
#define EE_AUDIO_TDMIN_LB_MASK1 0x0f3
|
||||
#define EE_AUDIO_TDMIN_LB_MASK2 0x0f4
|
||||
#define EE_AUDIO_TDMIN_LB_MASK3 0x0f5
|
||||
#define EE_AUDIO_TDMIN_LB_MASK4 0x291
|
||||
#define EE_AUDIO_TDMIN_LB_MASK5 0x292
|
||||
#define EE_AUDIO_TDMIN_LB_MASK6 0x293
|
||||
#define EE_AUDIO_TDMIN_LB_MASK7 0x294
|
||||
#define EE_AUDIO_TDMIN_LB_STAT 0x0f6
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE_VAL 0x0f7
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE0 0x0f8
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE1 0x0f9
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE2 0x0fa
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE3 0x0fb
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE4 0x295
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE5 0x296
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE6 0x297
|
||||
#define EE_AUDIO_TDMIN_LB_MUTE7 0x298
|
||||
|
||||
/*
|
||||
* AUDIO OUTPUT
|
||||
@@ -315,53 +356,89 @@ enum clk_sel {
|
||||
|
||||
#define EE_AUDIO_TDMOUT_A_CTRL0 0x140
|
||||
#define EE_AUDIO_TDMOUT_A_CTRL1 0x141
|
||||
#define EE_AUDIO_TDMOUT_A_SWAP 0x142
|
||||
#define EE_AUDIO_TDMOUT_A_CTRL2 0x2a0
|
||||
#define EE_AUDIO_TDMOUT_A_SWAP0 0x142
|
||||
#define EE_AUDIO_TDMOUT_A_SWAP1 0x2a1
|
||||
#define EE_AUDIO_TDMOUT_A_MASK0 0x143
|
||||
#define EE_AUDIO_TDMOUT_A_MASK1 0x144
|
||||
#define EE_AUDIO_TDMOUT_A_MASK2 0x145
|
||||
#define EE_AUDIO_TDMOUT_A_MASK3 0x146
|
||||
#define EE_AUDIO_TDMOUT_A_MASK4 0x2a4
|
||||
#define EE_AUDIO_TDMOUT_A_MASK5 0x2a5
|
||||
#define EE_AUDIO_TDMOUT_A_MASK6 0x2a6
|
||||
#define EE_AUDIO_TDMOUT_A_MASK7 0x2a7
|
||||
#define EE_AUDIO_TDMOUT_A_STAT 0x147
|
||||
#define EE_AUDIO_TDMOUT_A_GAIN0 0x148
|
||||
#define EE_AUDIO_TDMOUT_A_GAIN1 0x149
|
||||
#define EE_AUDIO_TDMOUT_A_GAIN2 0x2a2
|
||||
#define EE_AUDIO_TDMOUT_A_GAIN3 0x2a3
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE_VAL 0x14a
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE0 0x14b
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE1 0x14c
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE2 0x14d
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE3 0x14e
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE4 0x2a8
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE5 0x2a9
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE6 0x2aa
|
||||
#define EE_AUDIO_TDMOUT_A_MUTE7 0x2ab
|
||||
#define EE_AUDIO_TDMOUT_A_MASK_VAL 0x14f
|
||||
|
||||
#define EE_AUDIO_TDMOUT_B_CTRL0 0x150
|
||||
#define EE_AUDIO_TDMOUT_B_CTRL1 0x151
|
||||
#define EE_AUDIO_TDMOUT_B_SWAP 0x152
|
||||
#define EE_AUDIO_TDMOUT_B_CTRL2 0x2b0
|
||||
#define EE_AUDIO_TDMOUT_B_SWAP0 0x152
|
||||
#define EE_AUDIO_TDMOUT_B_SWAP1 0x2b1
|
||||
#define EE_AUDIO_TDMOUT_B_MASK0 0x153
|
||||
#define EE_AUDIO_TDMOUT_B_MASK1 0x154
|
||||
#define EE_AUDIO_TDMOUT_B_MASK2 0x155
|
||||
#define EE_AUDIO_TDMOUT_B_MASK3 0x156
|
||||
#define EE_AUDIO_TDMOUT_B_MASK4 0x2b4
|
||||
#define EE_AUDIO_TDMOUT_B_MASK5 0x2b5
|
||||
#define EE_AUDIO_TDMOUT_B_MASK6 0x2b6
|
||||
#define EE_AUDIO_TDMOUT_B_MASK7 0x2b7
|
||||
#define EE_AUDIO_TDMOUT_B_STAT 0x157
|
||||
#define EE_AUDIO_TDMOUT_B_GAIN0 0x158
|
||||
#define EE_AUDIO_TDMOUT_B_GAIN1 0x159
|
||||
#define EE_AUDIO_TDMOUT_B_GAIN2 0x2b2
|
||||
#define EE_AUDIO_TDMOUT_B_GAIN3 0x2b3
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE_VAL 0x15a
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE0 0x15b
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE1 0x15c
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE2 0x15d
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE3 0x15e
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE4 0x2b8
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE5 0x2b9
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE6 0x2ba
|
||||
#define EE_AUDIO_TDMOUT_B_MUTE7 0x2bb
|
||||
#define EE_AUDIO_TDMOUT_B_MASK_VAL 0x15f
|
||||
|
||||
#define EE_AUDIO_TDMOUT_C_CTRL0 0x160
|
||||
#define EE_AUDIO_TDMOUT_C_CTRL1 0x161
|
||||
#define EE_AUDIO_TDMOUT_C_SWAP 0x162
|
||||
#define EE_AUDIO_TDMOUT_C_CTRL2 0x2c0
|
||||
#define EE_AUDIO_TDMOUT_C_SWAP0 0x162
|
||||
#define EE_AUDIO_TDMOUT_C_SWAP1 0x2c1
|
||||
#define EE_AUDIO_TDMOUT_C_MASK0 0x163
|
||||
#define EE_AUDIO_TDMOUT_C_MASK1 0x164
|
||||
#define EE_AUDIO_TDMOUT_C_MASK2 0x165
|
||||
#define EE_AUDIO_TDMOUT_C_MASK3 0x166
|
||||
#define EE_AUDIO_TDMOUT_C_MASK4 0x2c4
|
||||
#define EE_AUDIO_TDMOUT_C_MASK5 0x2c5
|
||||
#define EE_AUDIO_TDMOUT_C_MASK6 0x2c6
|
||||
#define EE_AUDIO_TDMOUT_C_MASK7 0x2c7
|
||||
#define EE_AUDIO_TDMOUT_C_STAT 0x167
|
||||
#define EE_AUDIO_TDMOUT_C_GAIN0 0x168
|
||||
#define EE_AUDIO_TDMOUT_C_GAIN1 0x169
|
||||
#define EE_AUDIO_TDMOUT_C_GAIN2 0x2c2
|
||||
#define EE_AUDIO_TDMOUT_C_GAIN3 0x2c3
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE_VAL 0x16a
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE0 0x16b
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE1 0x16c
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE2 0x16d
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE3 0x16e
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE4 0x2c8
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE5 0x2c9
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE6 0x2ca
|
||||
#define EE_AUDIO_TDMOUT_C_MUTE7 0x2cb
|
||||
#define EE_AUDIO_TDMOUT_C_MASK_VAL 0x16f
|
||||
|
||||
/*
|
||||
@@ -847,4 +924,184 @@ enum clk_sel {
|
||||
#define VAD_IN_SEL1 0x030
|
||||
#define VAD_TO_DDR 0x031
|
||||
|
||||
/*
|
||||
* eARC
|
||||
*/
|
||||
/* eARC RX CMDC */
|
||||
#define EARC_RX_CMDC_TOP_CTRL0 0x000
|
||||
#define EARC_RX_CMDC_TOP_CTRL1 0x001
|
||||
#define EARC_RX_CMDC_TOP_CTRL2 0x002
|
||||
#define EARC_RX_CMDC_TIMER_CTRL0 0x003
|
||||
#define EARC_RX_CMDC_TIMER_CTRL1 0x004
|
||||
#define EARC_RX_CMDC_TIMER_CTRL2 0x005
|
||||
#define EARC_RX_CMDC_TIMER_CTRL3 0x006
|
||||
#define EARC_RX_CMDC_VSM_CTRL0 0x007
|
||||
#define EARC_RX_CMDC_VSM_CTRL1 0x008
|
||||
#define EARC_RX_CMDC_VSM_CTRL2 0x009
|
||||
#define EARC_RX_CMDC_VSM_CTRL3 0x00a
|
||||
#define EARC_RX_CMDC_VSM_CTRL4 0x00b
|
||||
#define EARC_RX_CMDC_VSM_CTRL5 0x00c
|
||||
#define EARC_RX_CMDC_VSM_CTRL6 0x00d
|
||||
#define EARC_RX_CMDC_VSM_CTRL7 0x00e
|
||||
#define EARC_RX_CMDC_VSM_CTRL8 0x00f
|
||||
#define EARC_RX_CMDC_VSM_CTRL9 0x010
|
||||
#define EARC_RX_CMDC_SENDER_CTRL0 0x011
|
||||
#define EARC_RX_CMDC_PACKET_CTRL0 0x012
|
||||
#define EARC_RX_CMDC_PACKET_CTRL1 0x013
|
||||
#define EARC_RX_CMDC_PACKET_CTRL2 0x014
|
||||
#define EARC_RX_CMDC_PACKET_CTRL3 0x015
|
||||
#define EARC_RX_CMDC_PACKET_CTRL4 0x016
|
||||
#define EARC_RX_CMDC_PACKET_CTRL5 0x017
|
||||
#define EARC_RX_CMDC_PACKET_CTRL6 0x018
|
||||
#define EARC_RX_CMDC_BIPHASE_CTRL0 0x019
|
||||
#define EARC_RX_CMDC_BIPHASE_CTRL1 0x01a
|
||||
#define EARC_RX_CMDC_BIPHASE_CTRL2 0x01b
|
||||
#define EARC_RX_CMDC_BIPHASE_CTRL3 0x01c
|
||||
#define EARC_RX_CMDC_DEVICE_ID_CTRL 0x01d
|
||||
#define EARC_RX_CMDC_DEVICE_WDATA 0x01e
|
||||
#define EARC_RX_CMDC_DEVICE_RDATA 0x01f
|
||||
#define EARC_RX_ANA_CTRL0 0x020
|
||||
#define EARC_RX_ANA_CTRL1 0x021
|
||||
#define EARC_RX_ANA_CTRL2 0x022
|
||||
#define EARC_RX_ANA_CTRL3 0x023
|
||||
#define EARC_RX_ANA_CTRL4 0x024
|
||||
#define EARC_RX_ANA_CTRL5 0x025
|
||||
#define EARC_RX_ANA_STAT0 0x026
|
||||
#define EARC_RX_CMDC_STATUS0 0x027
|
||||
#define EARC_RX_CMDC_STATUS1 0x028
|
||||
#define EARC_RX_CMDC_STATUS2 0x029
|
||||
#define EARC_RX_CMDC_STATUS3 0x02a
|
||||
#define EARC_RX_CMDC_STATUS4 0x02b
|
||||
#define EARC_RX_CMDC_STATUS5 0x02c
|
||||
#define EARC_RX_CMDC_STATUS6 0x02d
|
||||
/* eARC TX CMDC */
|
||||
#define EARC_TX_CMDC_TOP_CTRL0 0x030
|
||||
#define EARC_TX_CMDC_TOP_CTRL1 0x031
|
||||
#define EARC_TX_CMDC_TOP_CTRL2 0x032
|
||||
#define EARC_TX_CMDC_TIMER_CTRL0 0x033
|
||||
#define EARC_TX_CMDC_TIMER_CTRL1 0x034
|
||||
#define EARC_TX_CMDC_TIMER_CTRL2 0x035
|
||||
#define EARC_TX_CMDC_TIMER_CTRL3 0x036
|
||||
#define EARC_TX_CMDC_VSM_CTRL0 0x037
|
||||
#define EARC_TX_CMDC_VSM_CTRL1 0x038
|
||||
#define EARC_TX_CMDC_VSM_CTRL2 0x039
|
||||
#define EARC_TX_CMDC_VSM_CTRL3 0x03a
|
||||
#define EARC_TX_CMDC_VSM_CTRL4 0x03b
|
||||
#define EARC_TX_CMDC_VSM_CTRL5 0x03c
|
||||
#define EARC_TX_CMDC_VSM_CTRL6 0x03d
|
||||
#define EARC_TX_CMDC_VSM_CTRL7 0x03e
|
||||
#define EARC_TX_CMDC_VSM_CTRL8 0x03f
|
||||
#define EARC_TX_CMDC_VSM_CTRL9 0x041
|
||||
#define EARC_TX_CMDC_SENDER_CTRL0 0x042
|
||||
#define EARC_TX_CMDC_PACKET_CTRL0 0x043
|
||||
#define EARC_TX_CMDC_PACKET_CTRL1 0x044
|
||||
#define EARC_TX_CMDC_PACKET_CTRL2 0x045
|
||||
#define EARC_TX_CMDC_PACKET_CTRL3 0x046
|
||||
#define EARC_TX_CMDC_PACKET_CTRL4 0x047
|
||||
#define EARC_TX_CMDC_PACKET_CTRL5 0x048
|
||||
#define EARC_TX_CMDC_PACKET_CTRL6 0x049
|
||||
#define EARC_TX_CMDC_BIPHASE_CTRL0 0x04a
|
||||
#define EARC_TX_CMDC_BIPHASE_CTRL1 0x04b
|
||||
#define EARC_TX_CMDC_BIPHASE_CTRL2 0x04c
|
||||
#define EARC_TX_CMDC_BIPHASE_CTRL3 0x04d
|
||||
#define EARC_TX_CMDC_DEVICE_ID_CTRL 0x04e
|
||||
#define EARC_TX_CMDC_DEVICE_WDATA 0x04f
|
||||
#define EARC_TX_CMDC_DEVICE_RDATA 0x050
|
||||
#define EARC_TX_CMDC_MASTER_CTRL 0x051
|
||||
#define EARC_TX_ANA_CTRL0 0x052
|
||||
#define EARC_TX_ANA_CTRL1 0x053
|
||||
#define EARC_TX_ANA_CTRL2 0x054
|
||||
#define EARC_TX_ANA_CTRL3 0x055
|
||||
#define EARC_TX_ANA_CTRL4 0x056
|
||||
#define EARC_TX_ANA_CTRL5 0x057
|
||||
#define EARC_TX_ANA_STAT0 0x058
|
||||
#define EARC_TX_CMDC_STATUS0 0x059
|
||||
#define EARC_TX_CMDC_STATUS1 0x05a
|
||||
#define EARC_TX_CMDC_STATUS2 0x05b
|
||||
#define EARC_TX_CMDC_STATUS3 0x05c
|
||||
#define EARC_TX_CMDC_STATUS4 0x05d
|
||||
#define EARC_TX_CMDC_STATUS5 0x05e
|
||||
#define EARC_TX_CMDC_STATUS6 0x05f
|
||||
/* eARC RX DMAC */
|
||||
#define EARCRX_DMAC_TOP_CTRL0 0x000
|
||||
#define EARCRX_DMAC_SYNC_CTRL0 0x001
|
||||
#define EARCRX_DMAC_SYNC_STAT0 0x002
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL0 0x003
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL1 0x004
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL2 0x005
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL3 0x006
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL4 0x007
|
||||
#define EARCRX_SPDIFIN_SAMPLE_CTRL5 0x008
|
||||
#define EARCRX_SPDIFIN_SAMPLE_STAT0 0x009
|
||||
#define EARCRX_SPDIFIN_SAMPLE_STAT1 0x00a
|
||||
#define EARCRX_SPDIFIN_MUTE_VAL 0x00b
|
||||
#define EARCRX_SPDIFIN_CTRL0 0x00c
|
||||
#define EARCRX_SPDIFIN_CTRL1 0x00d
|
||||
#define EARCRX_SPDIFIN_CTRL2 0x00e
|
||||
#define EARCRX_SPDIFIN_CTRL3 0x00f
|
||||
#define EARCRX_SPDIFIN_STAT0 0x010
|
||||
#define EARCRX_SPDIFIN_STAT1 0x011
|
||||
#define EARCRX_SPDIFIN_STAT2 0x012
|
||||
#define EARCRX_DMAC_UBIT_CTRL0 0x013
|
||||
#define EARCRX_IU_RDATA 0x014
|
||||
#define EARCRX_DMAC_UBIT_STAT0 0x015
|
||||
#define EARCRX_ERR_CORRECT_CTRL0 0x016
|
||||
#define EARCRX_ERR_CORRECT_STAT0 0x017
|
||||
#define EARCRX_ANA_RST_CTRL0 0x018
|
||||
#define EARCRX_ANA_RST_CTRL1 0x019
|
||||
/* eARC TX DMAC */
|
||||
#define EARCTX_DMAC_TOP_CTRL0 0x000
|
||||
#define EARCTX_MUTE_VAL 0x001
|
||||
#define EARCTX_SPDIFOUT_GAIN0 0x002
|
||||
#define EARCTX_SPDIFOUT_GAIN1 0x003
|
||||
#define EARCTX_SPDIFOUT_CTRL0 0x004
|
||||
#define EARCTX_SPDIFOUT_CTRL1 0x005
|
||||
#define EARCTX_SPDIFOUT_PREAMB 0x006
|
||||
#define EARCTX_SPDIFOUT_SWAP 0x007
|
||||
#define EARCTX_ERR_CORRT_CTRL0 0x008
|
||||
#define EARCTX_ERR_CORRT_CTRL1 0x009
|
||||
#define EARCTX_ERR_CORRT_CTRL2 0x00a
|
||||
#define EARCTX_ERR_CORRT_CTRL3 0x00b
|
||||
#define EARCTX_ERR_CORRT_CTRL4 0x00c
|
||||
#define EARCTX_ERR_CORRT_STAT0 0x00d
|
||||
#define EARCTX_SPDIFOUT_CHSTS0 0x00e
|
||||
#define EARCTX_SPDIFOUT_CHSTS1 0x00f
|
||||
#define EARCTX_SPDIFOUT_CHSTS2 0x010
|
||||
#define EARCTX_SPDIFOUT_CHSTS3 0x011
|
||||
#define EARCTX_SPDIFOUT_CHSTS4 0x012
|
||||
#define EARCTX_SPDIFOUT_CHSTS5 0x013
|
||||
#define EARCTX_SPDIFOUT_CHSTS6 0x014
|
||||
#define EARCTX_SPDIFOUT_CHSTS7 0x015
|
||||
#define EARCTX_SPDIFOUT_CHSTS8 0x016
|
||||
#define EARCTX_SPDIFOUT_CHSTS9 0x017
|
||||
#define EARCTX_SPDIFOUT_CHSTSA 0x018
|
||||
#define EARCTX_SPDIFOUT_CHSTSB 0x019
|
||||
#define EARCTX_FE_CTRL0 0x01a
|
||||
#define EARCTX_FE_STAT0 0x01b
|
||||
#define EARCTX_SPDIFOUT_STAT 0x01c
|
||||
/* eARC RX */
|
||||
#define EARCRX_TOP_CTRL0 0x000
|
||||
#define EARCRX_DMAC_INT_MASK 0x001
|
||||
#define EARCRX_DMAC_INT_PENDING 0x002
|
||||
#define EARCRX_CMDC_INT_MASK 0x003
|
||||
#define EARCRX_CMDC_INT_PENDING 0x004
|
||||
#define EARCRX_ANA_CTRL0 0x005
|
||||
#define EARCRX_ANA_CTRL1 0x006
|
||||
#define EARCRX_ANA_STAT0 0x007
|
||||
#define EARCRX_PLL_CTRL0 0x008
|
||||
#define EARCRX_PLL_CTRL1 0x009
|
||||
#define EARCRX_PLL_CTRL2 0x00a
|
||||
#define EARCRX_PLL_CTRL3 0x00b
|
||||
#define EARCRX_PLL_STAT0 0x00c
|
||||
/* eARC TX */
|
||||
#define EARCTX_TOP_CTRL0 0x000
|
||||
#define EARCTX_DMAC_INT_MASK 0x001
|
||||
#define EARCTX_DMAC_INT_PENDING 0x002
|
||||
#define EARCTX_CMDC_INT_MASK 0x003
|
||||
#define EARCTX_CMDC_INT_PENDING 0x004
|
||||
#define EARCTX_ANA_CTRL0 0x005
|
||||
#define EARCTX_ANA_CTRL1 0x006
|
||||
#define EARCTX_ANA_CTRL2 0x007
|
||||
#define EARCTX_ANA_STAT0 0x008
|
||||
|
||||
#endif
|
||||
|
||||
376
sound/soc/amlogic/auge/sm1,clocks.c
Normal file
376
sound/soc/amlogic/auge/sm1,clocks.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/sm1,clocks.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "sm1_audio_clocks: " fmt
|
||||
|
||||
#include <dt-bindings/clock/amlogic,sm1-audio-clk.h>
|
||||
|
||||
#include "audio_clks.h"
|
||||
#include "regs.h"
|
||||
|
||||
static spinlock_t aclk_lock;
|
||||
|
||||
static const char *const mclk_parent_names[] = {
|
||||
"mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll",
|
||||
"fclk_div3", "fclk_div4", "fclk_div5"};
|
||||
|
||||
static const char *const audioclk_parent_names[] = {
|
||||
"mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e",
|
||||
"mclk_f", "i_slv_sclk_a", "i_slv_sclk_b", "i_slv_sclk_c",
|
||||
"i_slv_sclk_d", "i_slv_sclk_e", "i_slv_sclk_f", "i_slv_sclk_g",
|
||||
"i_slv_sclk_h", "i_slv_sclk_i", "i_slv_sclk_j"};
|
||||
|
||||
CLOCK_GATE(audio_ddr_arb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 0);
|
||||
CLOCK_GATE(audio_pdm, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 1);
|
||||
CLOCK_GATE(audio_tdmina, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 2);
|
||||
CLOCK_GATE(audio_tdminb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 3);
|
||||
CLOCK_GATE(audio_tdminc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 4);
|
||||
CLOCK_GATE(audio_tdminlb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 5);
|
||||
CLOCK_GATE(audio_tdmouta, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 6);
|
||||
CLOCK_GATE(audio_tdmoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 7);
|
||||
CLOCK_GATE(audio_tdmoutc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 8);
|
||||
CLOCK_GATE(audio_frddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 9);
|
||||
CLOCK_GATE(audio_frddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 10);
|
||||
CLOCK_GATE(audio_frddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 11);
|
||||
CLOCK_GATE(audio_toddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 12);
|
||||
CLOCK_GATE(audio_toddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 13);
|
||||
CLOCK_GATE(audio_toddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 14);
|
||||
CLOCK_GATE(audio_loopbacka, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 15);
|
||||
CLOCK_GATE(audio_spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 16);
|
||||
CLOCK_GATE(audio_spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 17);
|
||||
CLOCK_GATE(audio_resamplea, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 18);
|
||||
CLOCK_GATE(audio_reserved0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 19);
|
||||
CLOCK_GATE(audio_toram, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 20);
|
||||
CLOCK_GATE(audio_spdifoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 21);
|
||||
CLOCK_GATE(audio_eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 22);
|
||||
CLOCK_GATE(audio_reserved1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 23);
|
||||
CLOCK_GATE(audio_reserved2, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 24);
|
||||
CLOCK_GATE(audio_reserved3, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 25);
|
||||
CLOCK_GATE(audio_resampleb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 26);
|
||||
CLOCK_GATE(audio_tovad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 27);
|
||||
CLOCK_GATE(audio_audiolocker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 28);
|
||||
CLOCK_GATE(audio_spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 29);
|
||||
CLOCK_GATE(audio_reserved4, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 30);
|
||||
CLOCK_GATE(audio_reserved5, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31);
|
||||
|
||||
CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0);
|
||||
CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1);
|
||||
CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2);
|
||||
CLOCK_GATE(audio_earc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6);
|
||||
|
||||
static struct clk_gate *sm1_audio_clk_gates[] = {
|
||||
&audio_ddr_arb,
|
||||
&audio_pdm,
|
||||
&audio_tdmina,
|
||||
&audio_tdminb,
|
||||
&audio_tdminc,
|
||||
&audio_tdminlb,
|
||||
&audio_tdmouta,
|
||||
&audio_tdmoutb,
|
||||
&audio_tdmoutc,
|
||||
&audio_frddra,
|
||||
&audio_frddrb,
|
||||
&audio_frddrc,
|
||||
&audio_toddra,
|
||||
&audio_toddrb,
|
||||
&audio_toddrc,
|
||||
&audio_loopbacka,
|
||||
&audio_spdifin,
|
||||
&audio_spdifout,
|
||||
&audio_resamplea,
|
||||
&audio_reserved0,
|
||||
&audio_toram,
|
||||
&audio_spdifoutb,
|
||||
&audio_eqdrc,
|
||||
&audio_reserved1,
|
||||
&audio_reserved2,
|
||||
&audio_reserved3,
|
||||
&audio_resampleb,
|
||||
&audio_tovad,
|
||||
&audio_audiolocker,
|
||||
&audio_spdifin_lb,
|
||||
&audio_reserved4,
|
||||
&audio_reserved5,
|
||||
|
||||
&audio_frddrd,
|
||||
&audio_toddrd,
|
||||
&audio_loopbackb,
|
||||
&audio_earc,
|
||||
};
|
||||
|
||||
/* Array of all clocks provided by this provider */
|
||||
static struct clk_hw *sm1_audio_clk_hws[] = {
|
||||
[CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw,
|
||||
[CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw,
|
||||
[CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw,
|
||||
[CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw,
|
||||
[CLKID_AUDIO_GATE_TORAM] = &audio_toram.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw,
|
||||
[CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED2] = &audio_reserved2.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED3] = &audio_reserved3.hw,
|
||||
[CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw,
|
||||
[CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw,
|
||||
[CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED4] = &audio_reserved4.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED5] = &audio_reserved5.hw,
|
||||
|
||||
[CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw,
|
||||
[CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw,
|
||||
[CLKID_AUDIO_GATE_EARCRX] = &audio_earc.hw,
|
||||
};
|
||||
|
||||
static int sm1_clk_gates_init(struct clk **clks, void __iomem *iobase)
|
||||
{
|
||||
int clkid;
|
||||
|
||||
if (ARRAY_SIZE(sm1_audio_clk_gates) != MCLK_BASE) {
|
||||
pr_err("check clk gates number\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (clkid = 0; clkid < MCLK_BASE; clkid++) {
|
||||
sm1_audio_clk_gates[clkid]->reg = iobase;
|
||||
clks[clkid] = clk_register(NULL, sm1_audio_clk_hws[clkid]);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[clkid]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mclk_a */
|
||||
CLOCK_COM_MUX(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 31);
|
||||
/* mclk_b */
|
||||
CLOCK_COM_MUX(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 31);
|
||||
/* mclk_c */
|
||||
CLOCK_COM_MUX(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 31);
|
||||
/* mclk_d */
|
||||
CLOCK_COM_MUX(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 31);
|
||||
/* mclk_e */
|
||||
CLOCK_COM_MUX(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 31);
|
||||
/* mclk_f */
|
||||
CLOCK_COM_MUX(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0x7, 24);
|
||||
CLOCK_COM_DIV(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0, 16);
|
||||
CLOCK_COM_GATE(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 31);
|
||||
/* spdifin */
|
||||
CLOCK_COM_MUX(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31);
|
||||
/* spdifout */
|
||||
CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10);
|
||||
CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31);
|
||||
/* audio resample_a */
|
||||
CLOCK_COM_MUX(resample_a,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31);
|
||||
/* audio locker_out */
|
||||
CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8);
|
||||
CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31);
|
||||
/* audio locker_in */
|
||||
CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8);
|
||||
CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15);
|
||||
/* pdmin0 */
|
||||
CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24);
|
||||
CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16);
|
||||
CLOCK_COM_GATE(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 31);
|
||||
/* pdmin1 */
|
||||
CLOCK_COM_MUX(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0x7, 24);
|
||||
CLOCK_COM_DIV(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0, 16);
|
||||
CLOCK_COM_GATE(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 31);
|
||||
/* spdifout b*/
|
||||
CLOCK_COM_MUX(spdifout_b,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10);
|
||||
CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31);
|
||||
/* audio resample_b */
|
||||
CLOCK_COM_MUX(resample_b,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31);
|
||||
/* spdifin_lb, div is a fake */
|
||||
CLOCK_COM_MUX(spdifin_lb,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30);
|
||||
CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29);
|
||||
CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31);
|
||||
/* audio eqdrc */
|
||||
CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24);
|
||||
CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16);
|
||||
CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31);
|
||||
/* audio vad */
|
||||
CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31);
|
||||
/* EARC TX CMDC */
|
||||
CLOCK_COM_MUX(earctx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(earctx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(earctx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 31);
|
||||
/* EARC TX DMAC */
|
||||
CLOCK_COM_MUX(earctx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(earctx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(earctx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 31);
|
||||
/* EARC RX CMDC */
|
||||
CLOCK_COM_MUX(earcrx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(earcrx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(earcrx_cmdc,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 31);
|
||||
/* EARC RX DMAC */
|
||||
CLOCK_COM_MUX(earcrx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(earcrx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(earcrx_dmac,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 31);
|
||||
|
||||
static int sm1_clks_init(struct clk **clks, void __iomem *iobase)
|
||||
{
|
||||
IOMAP_COM_CLK(mclk_a, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_A] = REGISTER_CLK_COM(mclk_a);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_A]));
|
||||
|
||||
IOMAP_COM_CLK(mclk_b, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_B] = REGISTER_CLK_COM(mclk_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_B]));
|
||||
|
||||
IOMAP_COM_CLK(mclk_c, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_C] = REGISTER_CLK_COM(mclk_c);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_C]));
|
||||
|
||||
IOMAP_COM_CLK(mclk_d, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_D] = REGISTER_CLK_COM(mclk_d);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_D]));
|
||||
|
||||
IOMAP_COM_CLK(mclk_e, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_E] = REGISTER_CLK_COM(mclk_e);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_E]));
|
||||
|
||||
IOMAP_COM_CLK(mclk_f, iobase);
|
||||
clks[CLKID_AUDIO_MCLK_F] = REGISTER_CLK_COM(mclk_f);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F]));
|
||||
|
||||
IOMAP_COM_CLK(spdifin, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN]));
|
||||
|
||||
IOMAP_COM_CLK(spdifout, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A]));
|
||||
|
||||
IOMAP_COM_CLK(resample_a, iobase);
|
||||
clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A]));
|
||||
|
||||
IOMAP_COM_CLK(locker_out, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT]));
|
||||
|
||||
IOMAP_COM_CLK(locker_in, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN]));
|
||||
|
||||
IOMAP_COM_CLK(pdmin0, iobase);
|
||||
clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN0]));
|
||||
|
||||
IOMAP_COM_CLK(pdmin1, iobase);
|
||||
clks[CLKID_AUDIO_PDMIN1] = REGISTER_CLK_COM(pdmin1);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1]));
|
||||
|
||||
IOMAP_COM_CLK(spdifout_b, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B]));
|
||||
|
||||
IOMAP_COM_CLK(resample_b, iobase);
|
||||
clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B]));
|
||||
|
||||
IOMAP_COM_CLK(spdifin_lb, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB]));
|
||||
|
||||
IOMAP_COM_CLK(eqdrc, iobase);
|
||||
clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC]));
|
||||
|
||||
IOMAP_COM_CLK(vad, iobase);
|
||||
clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD]));
|
||||
|
||||
IOMAP_COM_CLK(earctx_cmdc, iobase);
|
||||
clks[CLKID_EARCTX_CMDC] = REGISTER_CLK_COM(earctx_cmdc);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_CMDC]));
|
||||
|
||||
IOMAP_COM_CLK(earctx_dmac, iobase);
|
||||
clks[CLKID_EARCTX_DMAC] = REGISTER_CLK_COM(earctx_dmac);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_DMAC]));
|
||||
|
||||
IOMAP_COM_CLK(earcrx_cmdc, iobase);
|
||||
clks[CLKID_EARCRX_CMDC] = REGISTER_CLK_COM(earcrx_cmdc);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_CMDC]));
|
||||
|
||||
IOMAP_COM_CLK(earcrx_dmac, iobase);
|
||||
clks[CLKID_EARCRX_DMAC] = REGISTER_CLK_COM(earcrx_dmac);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_DMAC]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct audio_clk_init sm1_audio_clks_init = {
|
||||
.clk_num = NUM_AUDIO_CLKS,
|
||||
.clk_gates = sm1_clk_gates_init,
|
||||
.clks = sm1_clks_init,
|
||||
};
|
||||
@@ -33,17 +33,14 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
|
||||
#include "ddr_mngr.h"
|
||||
#include "spdif_hw.h"
|
||||
#include "spdif_match_table.c"
|
||||
#include "audio_utils.h"
|
||||
#include "resample.h"
|
||||
#include "resample_hw.h"
|
||||
|
||||
#define DRV_NAME "aml_spdif"
|
||||
|
||||
#define SPDIF_A 0
|
||||
#define SPDIF_B 1
|
||||
#define DRV_NAME "snd_spdif"
|
||||
|
||||
/* Debug by PTM when bringup */
|
||||
/*#define __PTM_SPDIF_CLK__*/
|
||||
@@ -56,29 +53,6 @@
|
||||
static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir);
|
||||
|
||||
struct spdif_chipinfo {
|
||||
unsigned int id;
|
||||
|
||||
/* add ch_cnt to ch_num */
|
||||
bool chnum_en;
|
||||
/*
|
||||
* axg, clear all irq bits
|
||||
* after axg, such as g12a, clear each bits
|
||||
* Reg_clr_interrupt[7:0] for each bit of irq_status[7:0];
|
||||
*/
|
||||
bool clr_irq_all_bits;
|
||||
/* no PaPb irq */
|
||||
bool irq_no_papb;
|
||||
/* reg_hold_start_en; 1: add delay to match TDM out when share buff; */
|
||||
bool hold_start;
|
||||
/* eq/drc */
|
||||
bool eq_drc_en;
|
||||
/* pc, pd interrupt is separated. */
|
||||
bool pcpd_separated;
|
||||
/* same source, spdif re-enable */
|
||||
bool same_src_spdif_reen;
|
||||
};
|
||||
|
||||
enum SPDIF_SRC {
|
||||
SPDIFIN_PAD = 0,
|
||||
SPDIFOUT,
|
||||
@@ -1531,70 +1505,6 @@ static int aml_spdif_parse_of(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spdif_chipinfo axg_spdif_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.irq_no_papb = true,
|
||||
.clr_irq_all_bits = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo tl1_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.same_src_spdif_reen = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo tl1_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.same_src_spdif_reen = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_spdif_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-spdif",
|
||||
.data = &axg_spdif_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-spdif-a",
|
||||
.data = &g12a_spdif_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-spdif-b",
|
||||
.data = &g12a_spdif_b_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-spdif-a",
|
||||
.data = &tl1_spdif_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-spdif-b",
|
||||
.data = &tl1_spdif_b_chipinfo,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_spdif_device_id);
|
||||
|
||||
static int aml_spdif_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
126
sound/soc/amlogic/auge/spdif_match_table.c
Normal file
126
sound/soc/amlogic/auge/spdif_match_table.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/spdif_match_table.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SPDIF_A 0
|
||||
#define SPDIF_B 1
|
||||
|
||||
struct spdif_chipinfo {
|
||||
unsigned int id;
|
||||
|
||||
/* add ch_cnt to ch_num */
|
||||
bool chnum_en;
|
||||
/*
|
||||
* axg, clear all irq bits
|
||||
* after axg, such as g12a, clear each bits
|
||||
* Reg_clr_interrupt[7:0] for each bit of irq_status[7:0];
|
||||
*/
|
||||
bool clr_irq_all_bits;
|
||||
/* no PaPb irq */
|
||||
bool irq_no_papb;
|
||||
/* reg_hold_start_en; 1: add delay to match TDM out when share buff; */
|
||||
bool hold_start;
|
||||
/* eq/drc */
|
||||
bool eq_drc_en;
|
||||
/* pc, pd interrupt is separated. */
|
||||
bool pcpd_separated;
|
||||
/* same source, spdif re-enable */
|
||||
bool same_src_spdif_reen;
|
||||
};
|
||||
|
||||
struct spdif_chipinfo axg_spdif_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.irq_no_papb = true,
|
||||
.clr_irq_all_bits = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo tl1_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo tl1_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo sm1_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo sm1_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_spdif_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-spdif",
|
||||
.data = &axg_spdif_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-spdif-a",
|
||||
.data = &g12a_spdif_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-spdif-b",
|
||||
.data = &g12a_spdif_b_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-spdif-a",
|
||||
.data = &tl1_spdif_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-spdif-b",
|
||||
.data = &tl1_spdif_b_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-spdif-a",
|
||||
.data = &sm1_spdif_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-spdif-b",
|
||||
.data = &sm1_spdif_b_chipinfo,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_spdif_device_id);
|
||||
@@ -42,15 +42,12 @@
|
||||
#include "vad.h"
|
||||
#include "spdif_hw.h"
|
||||
|
||||
#include "tdm_match_table.c"
|
||||
|
||||
/*#define __PTM_TDM_CLK__*/
|
||||
|
||||
|
||||
#define DRV_NAME "aml_tdm"
|
||||
|
||||
#define TDM_A 0
|
||||
#define TDM_B 1
|
||||
#define TDM_C 2
|
||||
#define LANE_MAX 4
|
||||
#define DRV_NAME "snd_tdm"
|
||||
|
||||
static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir);
|
||||
@@ -78,29 +75,6 @@ static void dump_pcm_setting(struct pcm_setting *setting)
|
||||
pr_debug("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in);
|
||||
}
|
||||
|
||||
struct tdm_chipinfo {
|
||||
/* device id */
|
||||
unsigned int id;
|
||||
|
||||
/* no eco, sclk_ws_inv for out */
|
||||
bool sclk_ws_inv;
|
||||
|
||||
/* output en (oe) for pinmux */
|
||||
bool oe_fn;
|
||||
|
||||
/* clk pad */
|
||||
bool clk_pad_ctl;
|
||||
|
||||
/* same source */
|
||||
bool same_src_fn;
|
||||
|
||||
/* same source, spdif re-enable */
|
||||
bool same_src_spdif_reen;
|
||||
|
||||
/* ACODEC_ADC function */
|
||||
bool adc_fn;
|
||||
};
|
||||
|
||||
struct aml_tdm {
|
||||
struct pcm_setting setting;
|
||||
struct pinctrl *pin_ctl;
|
||||
@@ -123,6 +97,7 @@ struct aml_tdm {
|
||||
int samesource_sel;
|
||||
/* share buffer lane setting from DTS */
|
||||
int lane_ss;
|
||||
int mclk_pad;
|
||||
/* virtual link for i2s to hdmitx */
|
||||
int i2s2hdmitx;
|
||||
int acodec_adc;
|
||||
@@ -131,6 +106,7 @@ struct aml_tdm {
|
||||
uint last_fmt;
|
||||
|
||||
bool en_share;
|
||||
unsigned int lane_cnt;
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware aml_tdm_hardware = {
|
||||
@@ -724,6 +700,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
unsigned int lane_mask;
|
||||
unsigned int set_num = 0;
|
||||
unsigned int i;
|
||||
//unsigned int swap0_val = 0, swap1_val = 0, lane_chs = 0;
|
||||
|
||||
pr_debug("asoc channels:%d, slots:%d\n", channels, setting->slots);
|
||||
|
||||
@@ -735,6 +712,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
// set lanes mask acordingly
|
||||
if (p_tdm->chipinfo
|
||||
@@ -752,7 +730,7 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
}
|
||||
swap_val = 0x76543210;
|
||||
aml_tdm_set_lane_channel_swap(p_tdm->actrl,
|
||||
stream, p_tdm->id, swap_val);
|
||||
stream, p_tdm->id, swap_val, 0x0);
|
||||
} else {
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->oe_fn
|
||||
@@ -774,29 +752,83 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm,
|
||||
}
|
||||
|
||||
aml_tdm_set_lane_channel_swap(p_tdm->actrl,
|
||||
stream, p_tdm->id, swap_val);
|
||||
stream, p_tdm->id, swap_val, 0x0);
|
||||
}
|
||||
|
||||
#else
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->oe_fn
|
||||
&& p_tdm->setting.lane_oe_mask_out)
|
||||
lane_mask = setting->lane_oe_mask_out;
|
||||
else
|
||||
lane_mask = setting->lane_mask_out;
|
||||
} else {
|
||||
if (p_tdm->chipinfo
|
||||
&& p_tdm->chipinfo->oe_fn
|
||||
&& p_tdm->setting.lane_oe_mask_in)
|
||||
lane_mask = setting->lane_oe_mask_in;
|
||||
else
|
||||
lane_mask = setting->lane_mask_in;
|
||||
}
|
||||
|
||||
/* lane mask */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (((1 << i) & lane_mask) && lanes) {
|
||||
aml_tdm_set_channel_mask(p_tdm->actrl,
|
||||
stream, p_tdm->id, i, setting->tx_mask);
|
||||
lanes--;
|
||||
}
|
||||
}
|
||||
|
||||
/* channel swap */
|
||||
for (i = 0; i < p_tdm->lane_cnt; i++) {
|
||||
if ((1 << i) & lane_mask) {
|
||||
swap0_val |= (1 << (2 * i)) - 1;
|
||||
lane_chs += 1;
|
||||
if (lane_chs >= channels)
|
||||
break;
|
||||
swap0_val |= (1 << (2 * i + 1)) - 1;
|
||||
lane_chs += 1;
|
||||
if (lane_chs >= channels)
|
||||
break;
|
||||
|
||||
if (i >= LANE_MAX1) {
|
||||
swap1_val |= (1 << (2 * (i - LANE_MAX1))) - 1;
|
||||
lane_chs += 1;
|
||||
if (lane_chs >= channels)
|
||||
break;
|
||||
swap1_val |= (1 << (2 * (i - LANE_MAX1) + 1))
|
||||
- 1;
|
||||
lane_chs += 1;
|
||||
if (lane_chs >= channels)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
aml_tdm_set_lane_channel_swap(p_tdm->actrl,
|
||||
stream, p_tdm->id, swap0_val, swap1_val);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_tdm_set_clk_pad(struct aml_tdm *p_tdm)
|
||||
{
|
||||
unsigned int mpad, mclk_sel;
|
||||
int mpad_offset = 0;
|
||||
/* mclk pad
|
||||
* does mclk need?
|
||||
* mclk from which mclk source, mclk_a/b/c/d/e/f
|
||||
* mclk pad controlled by dts, mclk source according to id
|
||||
*/
|
||||
if (p_tdm->chipinfo && (!p_tdm->chipinfo->mclkpad_no_offset))
|
||||
mpad_offset = 1;
|
||||
|
||||
// TODO: update pad
|
||||
if (p_tdm->id >= 1) {
|
||||
mpad = p_tdm->id - 1;
|
||||
mclk_sel = p_tdm->id;
|
||||
} else {
|
||||
mpad = 0;
|
||||
mclk_sel = 0;
|
||||
}
|
||||
|
||||
/* clk pad */
|
||||
aml_tdm_clk_pad_select(p_tdm->actrl, mpad, mclk_sel,
|
||||
p_tdm->id, p_tdm->clk_sel);
|
||||
aml_tdm_clk_pad_select(p_tdm->actrl,
|
||||
p_tdm->mclk_pad,
|
||||
mpad_offset,
|
||||
p_tdm->id,
|
||||
p_tdm->id,
|
||||
p_tdm->clk_sel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -833,7 +865,7 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (p_tdm->chipinfo && p_tdm->chipinfo->clk_pad_ctl) {
|
||||
if (p_tdm->chipinfo && (!p_tdm->chipinfo->no_mclkpad_ctrl)) {
|
||||
ret = aml_tdm_set_clk_pad(p_tdm);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -870,7 +902,7 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) {
|
||||
pr_debug("%s(), enable mclk for %s", __func__, cpu_dai->name);
|
||||
pr_debug("%s(), enable mclk for %s\n", __func__, cpu_dai->name);
|
||||
ret = clk_prepare_enable(p_tdm->mclk);
|
||||
if (ret) {
|
||||
pr_err("Can't enable mclk: %d\n", ret);
|
||||
@@ -1298,113 +1330,6 @@ static const struct snd_soc_component_driver aml_tdm_component = {
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
.same_src_spdif_reen = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
.same_src_spdif_reen = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.clk_pad_ctl = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
.same_src_spdif_reen = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_tdm_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdma",
|
||||
.data = &axg_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdmb",
|
||||
.data = &axg_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdmc",
|
||||
.data = &axg_tdmc_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdma",
|
||||
.data = &g12a_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdmb",
|
||||
.data = &g12a_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdmc",
|
||||
.data = &g12a_tdmc_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdma",
|
||||
.data = &tl1_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdmb",
|
||||
.data = &tl1_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdmc",
|
||||
.data = &tl1_tdmc_chipinfo,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_tdm_device_id);
|
||||
|
||||
static int check_channel_mask(const char *str)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -1474,6 +1399,10 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
|
||||
}
|
||||
p_tdm->chipinfo = p_chipinfo;
|
||||
p_tdm->id = p_chipinfo->id;
|
||||
if (!p_chipinfo->lane_cnt)
|
||||
p_chipinfo->lane_cnt = LANE_MAX1;
|
||||
else
|
||||
p_tdm->lane_cnt = p_chipinfo->lane_cnt;
|
||||
pr_info("%s, tdm ID = %u\n", __func__, p_tdm->id);
|
||||
|
||||
/* get audio controller */
|
||||
@@ -1605,6 +1534,12 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
|
||||
/*return PTR_ERR(p_tdm->pin_ctl);*/
|
||||
}
|
||||
|
||||
/* mclk pad ctrl */
|
||||
ret = of_property_read_u32(node, "mclk_pad",
|
||||
&p_tdm->mclk_pad);
|
||||
if (ret < 0)
|
||||
p_tdm->mclk_pad = -1; /* not use mclk in defalut. */
|
||||
|
||||
p_tdm->dev = dev;
|
||||
/* For debug to disable share buffer */
|
||||
p_tdm->en_share = 1;
|
||||
|
||||
@@ -545,10 +545,20 @@ void aml_tdm_set_channel_mask(
|
||||
unsigned int offset, reg;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0;
|
||||
if (lane >= LANE_MAX1)
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK4
|
||||
- EE_AUDIO_TDMOUT_A_MASK4;
|
||||
else
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK0
|
||||
- EE_AUDIO_TDMOUT_A_MASK0;
|
||||
reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index;
|
||||
} else {
|
||||
offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0;
|
||||
if (lane >= LANE_MAX1)
|
||||
offset = EE_AUDIO_TDMIN_B_MASK4
|
||||
- EE_AUDIO_TDMIN_A_MASK4;
|
||||
else
|
||||
offset = EE_AUDIO_TDMIN_B_MASK0
|
||||
- EE_AUDIO_TDMIN_A_MASK0;
|
||||
reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index;
|
||||
}
|
||||
|
||||
@@ -557,27 +567,39 @@ void aml_tdm_set_channel_mask(
|
||||
|
||||
void aml_tdm_set_lane_channel_swap(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream, int index, int swap)
|
||||
int stream, int index, int swap0, int swap1)
|
||||
{
|
||||
unsigned int offset, reg;
|
||||
|
||||
pr_debug("\t %s swap0 = %#x, swap1 = %#x\n",
|
||||
(stream == SNDRV_PCM_STREAM_PLAYBACK) ? "tdmout" : "tdmin",
|
||||
swap0,
|
||||
swap1);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
// set lanes mask acordingly
|
||||
offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0;
|
||||
reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index;
|
||||
offset = EE_AUDIO_TDMOUT_B_SWAP0
|
||||
- EE_AUDIO_TDMOUT_A_SWAP0;
|
||||
reg = EE_AUDIO_TDMOUT_A_SWAP0 + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap0);
|
||||
|
||||
pr_debug("\ttdmout swap val = %#x\n", swap);
|
||||
offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP;
|
||||
reg = EE_AUDIO_TDMOUT_A_SWAP + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap);
|
||||
if (swap1) {
|
||||
offset = EE_AUDIO_TDMOUT_B_SWAP1
|
||||
- EE_AUDIO_TDMOUT_A_SWAP1;
|
||||
reg = EE_AUDIO_TDMOUT_A_SWAP1 + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap1);
|
||||
}
|
||||
} else {
|
||||
offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0;
|
||||
reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index;
|
||||
offset = EE_AUDIO_TDMIN_B_SWAP0
|
||||
- EE_AUDIO_TDMIN_A_SWAP0;
|
||||
reg = EE_AUDIO_TDMIN_A_SWAP0 + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap0);
|
||||
|
||||
pr_debug("\ttdmin swap val = %#x\n", swap);
|
||||
offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP;
|
||||
reg = EE_AUDIO_TDMIN_A_SWAP + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap);
|
||||
if (swap1) {
|
||||
offset = EE_AUDIO_TDMIN_B_SWAP1
|
||||
- EE_AUDIO_TDMIN_A_SWAP1;
|
||||
reg = EE_AUDIO_TDMIN_A_SWAP1 + offset * index;
|
||||
aml_audiobus_write(actrl, reg, swap1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,27 +671,39 @@ void aml_tdmout_enable_gain(int tdmout_id, int en)
|
||||
|
||||
void aml_tdm_clk_pad_select(
|
||||
struct aml_audio_controller *actrl,
|
||||
int mpad, int mclk_sel,
|
||||
int mpad, int mpad_offset, int mclk_sel,
|
||||
int tdm_index, int clk_sel)
|
||||
{
|
||||
unsigned int reg, mask_offset, val_offset;
|
||||
|
||||
// TODO: fix mclk
|
||||
if (mpad == 0) {
|
||||
mask_offset = 0x7 << 0;
|
||||
val_offset = mclk_sel << 0;
|
||||
} else if (mpad == 1) {
|
||||
mask_offset = 0x7 << 4;
|
||||
val_offset = mclk_sel << 4;
|
||||
} else {
|
||||
pr_err("unknown tdm mpad:%d\n", mpad);
|
||||
return;
|
||||
}
|
||||
reg = EE_AUDIO_MST_PAD_CTRL0(0);
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
mask_offset, val_offset);
|
||||
if (mpad >= 0) {
|
||||
switch (mpad) {
|
||||
case 0:
|
||||
mask_offset = 0x7 << 0;
|
||||
val_offset = mclk_sel << 0;
|
||||
break;
|
||||
case 1:
|
||||
mask_offset = 0x7 << 4;
|
||||
val_offset = mclk_sel << 4;
|
||||
break;
|
||||
default:
|
||||
mask_offset = 0;
|
||||
val_offset = 0;
|
||||
pr_info("unknown tdm mpad:%d\n", mpad);
|
||||
break;
|
||||
}
|
||||
|
||||
reg = EE_AUDIO_MST_PAD_CTRL1(0);
|
||||
reg = EE_AUDIO_MST_PAD_CTRL0(mpad_offset);
|
||||
if (actrl)
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
mask_offset, val_offset);
|
||||
else
|
||||
audiobus_update_bits(reg,
|
||||
mask_offset, val_offset);
|
||||
} else
|
||||
pr_warn("mclk is not configured\n");
|
||||
|
||||
reg = EE_AUDIO_MST_PAD_CTRL1(mpad_offset);
|
||||
switch (tdm_index) {
|
||||
case 0:
|
||||
mask_offset = 0x7 << 16 | 0x7 << 0;
|
||||
@@ -684,12 +718,15 @@ void aml_tdm_clk_pad_select(
|
||||
val_offset = clk_sel << 24 | clk_sel << 8;
|
||||
break;
|
||||
default:
|
||||
pr_err("unknown tdm index:%d\n", tdm_index);
|
||||
pr_err("unknown mclk pad, tdm index:%d\n", tdm_index);
|
||||
return;
|
||||
}
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
mask_offset, val_offset);
|
||||
|
||||
if (actrl)
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
mask_offset, val_offset);
|
||||
else
|
||||
audiobus_update_bits(reg,
|
||||
mask_offset, val_offset);
|
||||
}
|
||||
|
||||
void i2s_to_hdmitx_ctrl(int tdm_index)
|
||||
|
||||
@@ -21,6 +21,15 @@
|
||||
#include "audio_io.h"
|
||||
#include "regs.h"
|
||||
|
||||
#define TDM_A 0
|
||||
#define TDM_B 1
|
||||
#define TDM_C 2
|
||||
|
||||
#define LANE_MAX0 2
|
||||
#define LANE_MAX1 4
|
||||
#define LANE_MAX2 6
|
||||
#define LANE_MAX3 8
|
||||
|
||||
// TODO: fix me, now based by tl1
|
||||
enum tdmin_src {
|
||||
PAD_TDMINA_DIN = 0,
|
||||
@@ -118,7 +127,7 @@ extern void aml_tdm_set_channel_mask(
|
||||
|
||||
extern void aml_tdm_set_lane_channel_swap(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream, int index, int swap);
|
||||
int stream, int index, int swap0, int swap1);
|
||||
|
||||
extern void aml_tdm_set_bclk_ratio(
|
||||
struct aml_audio_controller *actrl,
|
||||
@@ -139,7 +148,7 @@ extern void aml_tdmout_get_aed_info(int tdmout_id,
|
||||
|
||||
extern void aml_tdm_clk_pad_select(
|
||||
struct aml_audio_controller *actrl,
|
||||
int mpad, int mclk_sel,
|
||||
int mpad, int mpad_offset, int mclk_sel,
|
||||
int tdm_index, int clk_sel);
|
||||
|
||||
extern void i2s_to_hdmitx_ctrl(int tdm_index);
|
||||
|
||||
186
sound/soc/amlogic/auge/tdm_match_table.c
Normal file
186
sound/soc/amlogic/auge/tdm_match_table.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/tdm_match_table.c
|
||||
*
|
||||
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
struct tdm_chipinfo {
|
||||
/* device id */
|
||||
unsigned int id;
|
||||
|
||||
/* lane max count */
|
||||
unsigned int lane_cnt;
|
||||
|
||||
/* no eco, sclk_ws_inv for out */
|
||||
bool sclk_ws_inv;
|
||||
|
||||
/* output en (oe) for pinmux */
|
||||
bool oe_fn;
|
||||
|
||||
/* clk pad */
|
||||
bool no_mclkpad_ctrl;
|
||||
|
||||
/* same source */
|
||||
bool same_src_fn;
|
||||
|
||||
/* same source, spdif re-enable */
|
||||
bool same_src_spdif_reen;
|
||||
|
||||
/* ACODEC_ADC function */
|
||||
bool adc_fn;
|
||||
|
||||
/* mclk pad offset */
|
||||
bool mclkpad_no_offset;
|
||||
};
|
||||
|
||||
|
||||
struct tdm_chipinfo axg_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.no_mclkpad_ctrl = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.no_mclkpad_ctrl = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.no_mclkpad_ctrl = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.mclkpad_no_offset = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.mclkpad_no_offset = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo g12a_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.mclkpad_no_offset = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo tl1_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.adc_fn = true,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo sm1_tdma_chipinfo = {
|
||||
.id = TDM_A,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.lane_cnt = LANE_MAX0,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo sm1_tdmb_chipinfo = {
|
||||
.id = TDM_B,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.lane_cnt = LANE_MAX3,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo sm1_tdmc_chipinfo = {
|
||||
.id = TDM_C,
|
||||
.sclk_ws_inv = true,
|
||||
.oe_fn = true,
|
||||
.same_src_fn = true,
|
||||
.lane_cnt = LANE_MAX1,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_tdm_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdma",
|
||||
.data = &axg_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdmb",
|
||||
.data = &axg_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, axg-snd-tdmc",
|
||||
.data = &axg_tdmc_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdma",
|
||||
.data = &g12a_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdmb",
|
||||
.data = &g12a_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, g12a-snd-tdmc",
|
||||
.data = &g12a_tdmc_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdma",
|
||||
.data = &tl1_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdmb",
|
||||
.data = &tl1_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-snd-tdmc",
|
||||
.data = &tl1_tdmc_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-tdma",
|
||||
.data = &sm1_tdma_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-tdmb",
|
||||
.data = &sm1_tdmb_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, sm1-snd-tdmc",
|
||||
.data = &sm1_tdmc_chipinfo,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_tdm_device_id);
|
||||
@@ -155,7 +155,7 @@ static int __init vad_init(void)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
pr_info("Register %s", DRV_NAME);
|
||||
pr_info("Register %s\n", DRV_NAME);
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
|
||||
Reference in New Issue
Block a user