summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_i2s.c105
-rw-r--r--sound/soc/tegra/tegra_pcm.c30
-rw-r--r--sound/soc/tegra/tegra_soc.h20
3 files changed, 92 insertions, 63 deletions
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 97034b19e318..92d4f4a2ca65 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -25,6 +25,7 @@ struct tegra_i2s_info {
struct tegra_audio_platform_data *pdata;
struct clk *i2s_clk;
struct clk *dap_mclk;
+ struct clk *audio_sync_clk;
phys_addr_t i2s_phys;
void __iomem *i2s_base;
@@ -36,8 +37,7 @@ struct tegra_i2s_info {
struct i2s_runtime_data i2s_regs;
};
-
-int setup_dma_request(struct snd_pcm_substream *substream,
+void setup_dma_request(struct snd_pcm_substream *substream,
struct tegra_dma_req *req,
void (*dma_callback)(struct tegra_dma_req *req),
void *dma_data)
@@ -52,21 +52,29 @@ int setup_dma_request(struct snd_pcm_substream *substream,
i2s_get_fifo_phy_base(cpu_dai->id, I2S_FIFO_TX);
req->dest_wrap = 4;
req->source_wrap = 0;
+ if (info->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
+ req->dest_bus_width = info->pdata->dsp_bus_width;
+ else
+ req->dest_bus_width = info->pdata->i2s_bus_width;
+ req->source_bus_width = 32;
} else {
req->to_memory = true;
req->source_addr =
i2s_get_fifo_phy_base(cpu_dai->id, I2S_FIFO_RX);
req->dest_wrap = 0;
req->source_wrap = 4;
+ if (info->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP)
+ req->source_bus_width = info->pdata->dsp_bus_width;
+ else
+ req->source_bus_width = info->pdata->i2s_bus_width;
+ req->dest_bus_width = 32;
}
req->complete = dma_callback;
req->dev = dma_data;
- req->source_bus_width = 32;
- req->dest_bus_width = 32;
req->req_sel = info->dma_req_sel;
- return 0;
+ return;
}
@@ -107,8 +115,7 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct tegra_runtime_data *prtd = runtime->private_data;
+ struct tegra_i2s_info *info = dai->private_data;
int ret = 0;
int val;
unsigned int i2s_id = dai->id;
@@ -144,7 +151,7 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
goto err;
}
- i2s_set_channel_bit_count(i2s_id, val, clk_get_rate(prtd->i2s_clk));
+ i2s_set_channel_bit_count(i2s_id, val, clk_get_rate(info->i2s_clk));
return 0;
@@ -282,6 +289,50 @@ static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
+static int i2s_configure(struct tegra_i2s_info *info )
+{
+ struct platform_device *pdev = info->pdev;
+ struct tegra_audio_platform_data *pdata = pdev->dev.platform_data;
+ bool master;
+ struct clk *i2s_clk;
+ int master_clk;
+ unsigned int i2s_id = pdev->id;
+
+ i2s_enable_fifos(i2s_id, 0);
+ i2s_fifo_clear(i2s_id, I2S_FIFO_TX);
+ i2s_fifo_clear(i2s_id, I2S_FIFO_RX);
+ i2s_set_left_right_control_polarity(i2s_id, 0); /* default */
+
+ i2s_clk = clk_get(&pdev->dev, NULL);
+ if (!i2s_clk) {
+ dev_err(&pdev->dev, "%s: could not get i2s clock\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (info->bit_format == TEGRA_AUDIO_BIT_FORMAT_DSP) {
+ master = pdata->dsp_master;
+ master_clk = pdata->dsp_master_clk;
+ } else {
+ master = pdata->i2s_master;
+ master_clk = pdata->i2s_master_clk;
+ }
+
+ if (master && master_clk)
+ i2s_set_channel_bit_count(i2s_id, master_clk,
+ clk_get_rate(i2s_clk));
+ i2s_set_master(i2s_id, master);
+
+ i2s_set_fifo_mode(i2s_id, I2S_FIFO_TX, 1);
+ i2s_set_fifo_mode(i2s_id, I2S_FIFO_RX, 0);
+
+ i2s_set_bit_format(i2s_id, pdata->mode);
+ i2s_set_bit_size(i2s_id, pdata->bit_size);
+ i2s_set_fifo_format(i2s_id, pdata->fifo_fmt);
+
+ return 0;
+}
+
#ifdef CONFIG_PM
int tegra_i2s_suspend(struct snd_soc_dai *cpu_dai)
{
@@ -309,29 +360,28 @@ int tegra_i2s_resume(struct snd_soc_dai *cpu_dai)
static int tegra_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct tegra_i2s_info *info = dai->private_data;
+
+ clk_enable(info->dap_mclk);
+ clk_enable(info->audio_sync_clk);
+
return 0;
}
static void tegra_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct tegra_i2s_info *info = dai->private_data;
+
+ clk_disable(info->dap_mclk);
+ clk_disable(info->audio_sync_clk);
+
return;
}
static int tegra_i2s_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- unsigned int i2s_id = dai->id;
-
- i2s_enable_fifos(i2s_id, 0);
- i2s_set_left_right_control_polarity(i2s_id, 0); /* default */
- i2s_set_master(i2s_id, 1); /* set as master */
- i2s_set_fifo_mode(i2s_id, FIFO1, 1); /* FIFO1 is TX */
- i2s_set_fifo_mode(i2s_id, FIFO2, 0); /* FIFO2 is RX */
- i2s_set_bit_format(i2s_id, I2S_BIT_FORMAT_I2S);
- i2s_set_bit_size(i2s_id, I2S_BIT_SIZE_16);
- i2s_set_fifo_format(i2s_id, I2S_FIFO_PACKED);
-
return 0;
}
@@ -450,6 +500,23 @@ static int tegra_i2s_driver_probe(struct platform_device *pdev)
goto fail_unmap_mem;
}
+ info->dap_mclk = i2s_get_clock_by_name(info->pdata->dap_clk);
+ if (IS_ERR(info->dap_mclk)) {
+ err = PTR_ERR(info->dap_mclk);
+ goto fail_unmap_mem;
+ }
+
+ info->audio_sync_clk = i2s_get_clock_by_name(
+ info->pdata->audio_sync_clk);
+ if (IS_ERR(info->audio_sync_clk)) {
+ err = PTR_ERR(info->audio_sync_clk);
+ goto fail_unmap_mem;
+ }
+
+ info->bit_format = TEGRA_AUDIO_BIT_FORMAT_DEFAULT;
+
+ i2s_configure(info);
+
for (i = 0; i < ARRAY_SIZE(tegra_i2s_dai); i++) {
if (tegra_i2s_dai[i].id == pdev->id) {
tegra_i2s_dai[i].dev = &pdev->dev;
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 5f413c1216e5..1bddb5547c3c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -232,36 +232,6 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
/* set pins state to normal */
tegra_das_power_mode(true);
- /* Setup I2S clocks */
- prtd->i2s_clk = i2s_get_clock_by_name(I2S_NAME);
- if (!prtd->i2s_clk) {
- pr_err("%s: could not get i2s1 clock\n", __func__);
- return -EIO;
- }
-
- clk_set_rate(prtd->i2s_clk, I2S_CLK);
- if (clk_enable(prtd->i2s_clk)) {
- pr_err("%s: failed to enable i2s1 clock\n", __func__);
- return -EIO;
- }
-
- i2s_set_channel_bit_count(I2S_IFC, TEGRA_DEFAULT_SR,
- clk_get_rate(prtd->i2s_clk));
-
- prtd->dap_mclk = i2s_get_clock_by_name("clk_dev1");
- if (!prtd->dap_mclk) {
- pr_err("%s: could not get DAP clock\n", __func__);
- return -EIO;
- }
- clk_enable(prtd->dap_mclk);
-
- prtd->audio_sync_clk = i2s_get_clock_by_name("audio_2x");
- if (!prtd->audio_sync_clk) {
- pr_err("%s: could not get audio_2x clock\n", __func__);
- return -EIO;
- }
- clk_enable(prtd->audio_sync_clk);
-
prtd->state = STATE_INVALID;
setup_dma_request(substream,
diff --git a/sound/soc/tegra/tegra_soc.h b/sound/soc/tegra/tegra_soc.h
index 83b462779ce6..29f4fcf13651 100644
--- a/sound/soc/tegra/tegra_soc.h
+++ b/sound/soc/tegra/tegra_soc.h
@@ -55,22 +55,14 @@
#include <asm/mach-types.h>
#include <asm/hardware/scoop.h>
-#define STATE_INIT 0
-#define STATE_ABORT 1
-#define STATE_EXIT 2
-#define STATE_EXITED 3
-#define STATE_INVALID 4
+#define STATE_INIT 0
+#define STATE_ABORT 1
+#define STATE_EXIT 2
+#define STATE_EXITED 3
+#define STATE_INVALID 4
-#define FIFO1 0
-#define FIFO2 1
-
-#define I2S_IFC 0
-#define I2S_INT INT_I2S1
-#define I2S_NAME "i2s1"
-#define I2S_FIFO_TX FIFO1
#define I2S_I2S_FIFO_TX_BUSY I2S_I2S_STATUS_FIFO1_BSY
#define I2S_I2S_FIFO_TX_QS I2S_I2S_STATUS_QS_FIFO1
-#define I2S_FIFO_RX FIFO2
#define I2S_I2S_FIFO_RX_BUSY I2S_I2S_STATUS_FIFO2_BSY
#define I2S_I2S_FIFO_RX_QS I2S_I2S_STATUS_QS_FIFO2
@@ -108,7 +100,7 @@ struct tegra_audio_data {
int tegra_controls_init(struct snd_soc_codec *codec);
void tegra_controls_exit(void);
-int setup_dma_request(struct snd_pcm_substream *substream,
+void setup_dma_request(struct snd_pcm_substream *substream,
struct tegra_dma_req *req,
void (*dma_callback)(struct tegra_dma_req *req),
void *dma_data);