#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/device.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
struct snd_soc_component *component = dai->component;
struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);
u16 iface = snd_soc_component_read(component, WM8960_IFACE1) & 0xfff3;
- u16 audio_format = iface & 0x3;
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- int i;
+ u16 audio_format = iface & 0x3;
+ int freq_out, freq_in;
+ int i, j, k;
wm8960->bclk = snd_soc_params_to_bclk(params);
if (params_channels(params) == 1)
/* set iface */
snd_soc_component_write(component, WM8960_IFACE1, iface);
- if (audio_format == 0x3) //TDM Format
- {
+ if (audio_format == 0x3) {//TDM Format
snd_soc_component_write(component, WM8960_POWER1, 0xfe);
snd_soc_component_write(component, WM8960_POWER2, 0x1f8);
snd_soc_component_write(component, WM8960_POWER2, 0x1f9);
snd_soc_component_write(component, WM8960_PLL1, 0x28);
snd_soc_component_write(component, WM8960_PLL1, 0x38);
- snd_soc_component_write(component, WM8960_CLOCK1, 0xdd);
- snd_soc_component_write(component, WM8960_CLOCK2, 0x1cc);
+
+ freq_in = wm8960->freq_in;
+ freq_out = wm8960_configure_pll(component, freq_in, &i, &j, &k);
+ snd_soc_component_update_bits(component, WM8960_CLOCK1, 3 << 1, i << 1);
+ snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x7 << 3, j << 3);
+ snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x7 << 6, j << 6);
+ snd_soc_component_update_bits(component, WM8960_CLOCK2, 0xf, k);
+
snd_soc_component_write(component, WM8960_POWER3, 0x3c);
if (tx) {
snd_soc_component_write(component, WM8960_NOISEG, 0xf9);
snd_soc_component_write(component, WM8960_ALC1, 0x1bb);
snd_soc_component_write(component, WM8960_ALC2, 0x30);
+
+ for (i = 0; i < ARRAY_SIZE(alc_rates); i++)
+ if (alc_rates[i].rate == params_rate(params))
+ snd_soc_component_update_bits(component,
+ WM8960_ADDCTL3, 0x7,
+ alc_rates[i].val);
/* bclk inverted */
snd_soc_component_update_bits(component, WM8960_IFACE1, 0x80, 0x80);
- snd_soc_component_write(component, WM8960_POWER2, 0x1f9);
- } else if (audio_format == 0x2) { //I2S Format
- if (!tx)
- {
+ } else if (audio_format == 0x2) {//I2S Format
+ if (!tx) {
snd_soc_component_update_bits(component, WM8960_LINVOL, 0x3<<7, 0x2<<7);
snd_soc_component_update_bits(component, WM8960_RINVOL, 0x3<<7, 0x2<<7);
snd_soc_component_write(component, WM8960_CLOCK1, 0x00); //0xd8
}
#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
-
+/*
#define WM8960_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+*/
+
+#define WM8960_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100);
- regmap_update_bits(wm8960->regmap, WM8960_LINPATH, 0x138, 0x138);
- regmap_update_bits(wm8960->regmap, WM8960_RINPATH, 0x138, 0x138);
+ regmap_update_bits(wm8960->regmap, WM8960_LINPATH, 0x138, 0x108);
+ regmap_update_bits(wm8960->regmap, WM8960_RINPATH, 0x138, 0x108);
regmap_update_bits(wm8960->regmap, WM8960_POWER1, 0x7E, 0x7E);
regmap_update_bits(wm8960->regmap, WM8960_POWER3, 0x30, 0x30);
regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x1ff, 0x128);
module_i2c_driver(wm8960_i2c_driver);
-
MODULE_DESCRIPTION("ASoC WM8960 driver");
MODULE_AUTHOR("Liam Girdwood");
#include <sound/tlv.h>
#include "starfive_tdm.h"
-#define CLOCK_BASE 0x13020000UL
-
static inline u32 sf_tdm_readl(struct sf_tdm_dev *dev, u16 reg)
{
return readl_relaxed(dev->tdm_base + reg);
struct snd_dmaengine_dai_dma_data *dma_data = NULL;
unsigned int data_width;
unsigned int mclk_rate;
+ unsigned int dma_bus_width;
int ret;
dev->samplerate = params_rate(params);
switch (dev->samplerate) {
+ /* There is a issue with 8k sample rate */
+/*
case 8000:
- mclk_rate = 12288000;
- dev->pcmclk = 256000;
+ mclk_rate = 11289600; //sysclk
+ dev->pcmclk = 352800; //bit clock
+ break;
+*/
+ case 11025:
+ mclk_rate = 11289600; //sysclk
+ dev->pcmclk = 352800; //bit clock, for 16-bit
break;
case 16000:
+ mclk_rate = 12288000; //sysclk
+ dev->pcmclk = 512000; //bit clock
+ break;
+ case 22050:
+ mclk_rate = 11289600;
+ dev->pcmclk = 705600;
+ break;
+ case 32000:
+ mclk_rate = 12288000;
+ dev->pcmclk = 1024000;
+ break;
+ case 44100:
+ mclk_rate = 11289600;
+ dev->pcmclk = 1411200;
+ break;
+ case 48000:
mclk_rate = 12288000;
- dev->pcmclk = 512000;
+ dev->pcmclk = 1536000;
break;
default:
pr_err("TDM: not support sample rate:%d\n", dev->samplerate);
}
data_width = params_width(params);
+
dev->pcmclk = 2 * dev->samplerate * data_width;
switch (params_format(params)) {
+/*
case SNDRV_PCM_FORMAT_S8:
chan_wl = TDM_8BIT_WORD_LEN;
chan_sl = TDM_8BIT_SLOT_LEN;
+ dma_bus_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
+*/
case SNDRV_PCM_FORMAT_S16_LE:
chan_wl = TDM_16BIT_WORD_LEN;
chan_sl = TDM_16BIT_SLOT_LEN;
+ dma_bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
+ /* There is a issue with 24-bit */
+/*
case SNDRV_PCM_FORMAT_S24_LE:
chan_wl = TDM_24BIT_WORD_LEN;
chan_sl = TDM_32BIT_SLOT_LEN;
+ dma_bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
+*/
case SNDRV_PCM_FORMAT_S32_LE:
chan_wl = TDM_32BIT_WORD_LEN;
chan_sl = TDM_32BIT_SLOT_LEN;
+ dma_bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
dev->tx.wl = chan_wl;
dev->tx.sl = chan_sl;
dev->tx.sscale = chan_nr;
+ dev->play_dma_data.addr_width = dma_bus_width;
dma_data = &dev->play_dma_data;
} else {
dev->rx.wl = chan_wl;
dev->rx.sl = chan_sl;
dev->rx.sscale = chan_nr;
+ dev->capture_dma_data.addr_width = dma_bus_width;
dma_data = &dev->capture_dma_data;
}
return 0;
}
-#define SF_TDM_RATE (SNDRV_PCM_RATE_8000 | \
- SNDRV_PCM_RATE_16000 | \
- SNDRV_PCM_RATE_32000)
+#define SF_TDM_RATES (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-#define SF_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
- SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S24_LE | \
+#define SF_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver sf_tdm_dai = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
- .rates = SF_TDM_RATE,
+ .rates = SF_TDM_RATES,
.formats = SF_TDM_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 8,
- .rates = SF_TDM_RATE,
+ .rates = SF_TDM_RATES,
.formats = SF_TDM_FORMATS,
},
.ops = &sf_tdm_dai_ops,
dev->clk_tdm = clks[6].clk;
dev->clk_mclk_inner = clks[7].clk;
- dev->rst_ahb = devm_reset_control_get_exclusive(&pdev->dev, "tdm_ahb");
- if (IS_ERR(dev->rst_ahb)) {
- dev_err(&pdev->dev, "Failed to get tdm_ahb reset control\n");
- ret = PTR_ERR(dev->rst_ahb);
- goto exit;
- }
-
- dev->rst_apb = devm_reset_control_get_exclusive(&pdev->dev, "tdm_apb");
- if (IS_ERR(dev->rst_apb)) {
- dev_err(&pdev->dev, "Failed to get tdm_apb reset control\n");
- ret = PTR_ERR(dev->rst_apb);
- goto exit;
- }
-
- dev->rst_tdm = devm_reset_control_get_exclusive(&pdev->dev, "tdm_rst");
- if (IS_ERR(dev->rst_tdm)) {
- dev_err(&pdev->dev, "Failed to get tdm_rst reset control\n");
- ret = PTR_ERR(dev->rst_tdm);
- goto exit;
- }
-
- ret = reset_control_assert(dev->rst_ahb);
- if (ret) {
- dev_err(&pdev->dev, "failed to assert rst_ahb\n");
- goto exit;
- }
-
- ret = reset_control_assert(dev->rst_apb);
- if (ret) {
- dev_err(&pdev->dev, "failed to assert rst_apb\n");
+ dev->resets = devm_reset_control_array_get_exclusive(&pdev->dev);
+ if (IS_ERR(dev->resets)) {
+ ret = PTR_ERR(dev->resets);
+ dev_err(&pdev->dev, "Failed to get tdm resets");
goto exit;
}
- ret = reset_control_assert(dev->rst_tdm);
+ ret = reset_control_assert(dev->resets);
if (ret) {
- dev_err(&pdev->dev, "failed to assert rst_tdm\n");
+ dev_err(&pdev->dev, "Failed to assert tdm resets\n");
goto exit;
}
goto err_dis_tdm_ext;
}
- ret = reset_control_deassert(dev->rst_ahb);
- if (ret) {
- dev_err(&pdev->dev, "failed to deassert rst_ahb\n");
- goto err_clk_disable;
- }
-
- ret = reset_control_deassert(dev->rst_apb);
- if (ret) {
- dev_err(&pdev->dev, "failed to deassert rst_apb\n");
- goto err_clk_disable;
- }
-
- ret = reset_control_deassert(dev->rst_tdm);
+ ret = reset_control_deassert(dev->resets);
if (ret) {
- dev_err(&pdev->dev, "failed to deassert rst_tdm\n");
+ dev_err(&pdev->dev, "Failed to deassert tdm resets\n");
goto err_clk_disable;
}
/* DMA registers */
#define TDM_FIFO 0x170c0000
-#define TDM_FIFO_DEPTH 16
+//#define TDM_FIFO_DEPTH 16
+#define TDM_FIFO_DEPTH 32
#define TWO_CHANNEL_SUPPORT 2
#define FOUR_CHANNEL_SUPPORT 4
struct clk *clk_tdm_ext;
struct clk *clk_tdm;
struct clk *clk_mclk_inner;
- struct reset_control *rst_ahb;
- struct reset_control *rst_apb;
- struct reset_control *rst_tdm;
+ struct reset_control *resets;
int active;
enum TDM_CLKPOL clkpolity;