summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-03-29 16:51:29 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-04-13 18:05:38 -0700
commita12a3c264124e02232e2b102bfc718682cb374b6 (patch)
tree236080eeedb819a4166d60f52bffe592156da282
parent574e119e6d68811bc34f58c2cf83a860fe17c250 (diff)
ARM: tegra: DAS: Support new DAS driver APIs
Added three new APIs in DAS driver. These APIs can be used to query which dap/i2s port is master and supported data format of a certain codec for the current set of das connections. ALSA driver will be using these APIs. Adding all the required board specific data in tegra_das_pdata structure. Disabling all audio related clocks from board file. This is required for ALSA to be able to disable audio clocks when they are not in use. Change-Id: Idc49b4723f10e1e48530273f993f29983b48f324 Reviewed-on: http://git-master/r/24676 Tested-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-ventana.c63
-rw-r--r--arch/arm/mach-tegra/board-whistler.c97
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_das.h55
-rw-r--r--arch/arm/mach-tegra/tegra_das.c125
4 files changed, 247 insertions, 93 deletions
diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c
index 6473838686c9..01141d50c160 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -235,12 +235,12 @@ static __initdata struct tegra_clk_init_table ventana_clk_init_table[] = {
{ "blink", "clk_32k", 32768, false},
{ "pll_p_out4", "pll_p", 24000000, true },
{ "pwm", "clk_32k", 32768, false},
- { "pll_a", NULL, 56448000, true},
- { "pll_a_out0", NULL, 11289600, true},
- { "i2s1", "pll_a_out0", 11289600, true},
- { "i2s2", "pll_a_out0", 11289600, true},
- { "audio", "pll_a_out0", 11289600, true},
- { "audio_2x", "audio", 22579200, true},
+ { "pll_a", NULL, 56448000, false},
+ { "pll_a_out0", NULL, 11289600, false},
+ { "i2s1", "pll_a_out0", 11289600, false},
+ { "i2s2", "pll_a_out0", 11289600, false},
+ { "audio", "pll_a_out0", 11289600, false},
+ { "audio_2x", "audio", 22579200, false},
{ "spdif_out", "pll_a_out0", 5644800, false},
{ "kbc", "clk_32k", 32768, true},
{ NULL, NULL, 0, 0},
@@ -436,30 +436,24 @@ static struct tegra_audio_platform_data tegra_audio_pdata[] = {
};
static struct tegra_das_platform_data tegra_das_pdata = {
+ .dap_clk = "clk_dev1",
.tegra_dap_port_info_table = {
- [0] = {
- .dac_port = tegra_das_port_none,
- .codec_type = tegra_audio_codec_type_none,
- .device_property = {
- .num_channels = 0,
- .bits_per_sample = 0,
- .rate = 0,
- .dac_dap_data_comm_format = 0,
- },
- },
/* I2S1 <--> DAC1 <--> DAP1 <--> Hifi Codec */
- [1] = {
+ [0] = {
.dac_port = tegra_das_port_i2s1,
+ .dap_port = tegra_das_port_dap1,
.codec_type = tegra_audio_codec_type_hifi,
.device_property = {
.num_channels = 2,
.bits_per_sample = 16,
.rate = 44100,
- .dac_dap_data_comm_format = dac_dap_data_format_i2s,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_all,
},
},
- [2] = {
+ [1] = {
.dac_port = tegra_das_port_none,
+ .dap_port = tegra_das_port_none,
.codec_type = tegra_audio_codec_type_none,
.device_property = {
.num_channels = 0,
@@ -468,8 +462,9 @@ static struct tegra_das_platform_data tegra_das_pdata = {
.dac_dap_data_comm_format = 0,
},
},
- [3] = {
+ [2] = {
.dac_port = tegra_das_port_none,
+ .dap_port = tegra_das_port_none,
.codec_type = tegra_audio_codec_type_none,
.device_property = {
.num_channels = 0,
@@ -478,8 +473,22 @@ static struct tegra_das_platform_data tegra_das_pdata = {
.dac_dap_data_comm_format = 0,
},
},
+ /* I2S2 <--> DAC2 <--> DAP4 <--> BT SCO Codec */
+ [3] = {
+ .dac_port = tegra_das_port_i2s2,
+ .dap_port = tegra_das_port_dap4,
+ .codec_type = tegra_audio_codec_type_bluetooth,
+ .device_property = {
+ .num_channels = 1,
+ .bits_per_sample = 16,
+ .rate = 8000,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_dsp,
+ },
+ },
[4] = {
.dac_port = tegra_das_port_none,
+ .dap_port = tegra_das_port_none,
.codec_type = tegra_audio_codec_type_none,
.device_property = {
.num_channels = 0,
@@ -493,12 +502,20 @@ static struct tegra_das_platform_data tegra_das_pdata = {
.tegra_das_con_table = {
[0] = {
.con_id = tegra_das_port_con_id_hifi,
- .num_entries = 4,
+ .num_entries = 2,
.con_line = {
[0] = {tegra_das_port_i2s1, tegra_das_port_dap1, true},
[1] = {tegra_das_port_dap1, tegra_das_port_i2s1, false},
- [2] = {tegra_das_port_i2s2, tegra_das_port_dap4, true},
- [3] = {tegra_das_port_dap4, tegra_das_port_i2s2, false},
+ },
+ },
+ [1] = {
+ .con_id = tegra_das_port_con_id_bt_codec,
+ .num_entries = 4,
+ .con_line = {
+ [0] = {tegra_das_port_i2s2, tegra_das_port_dap4, true},
+ [1] = {tegra_das_port_dap4, tegra_das_port_i2s2, false},
+ [2] = {tegra_das_port_i2s1, tegra_das_port_dap1, true},
+ [3] = {tegra_das_port_dap1, tegra_das_port_i2s1, false},
},
},
}
diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c
index 5329b76ccfe1..348e5a6c4a6d 100644
--- a/arch/arm/mach-tegra/board-whistler.c
+++ b/arch/arm/mach-tegra/board-whistler.c
@@ -143,12 +143,12 @@ static __initdata struct tegra_clk_init_table whistler_clk_init_table[] = {
{ "uartc", "pll_m", 600000000, false},
{ "pwm", "clk_32k", 32768, false},
{ "kbc", "clk_32k", 32768, true},
- { "pll_a", NULL, 56448000, true},
- { "pll_a_out0", NULL, 11289600, true},
- { "i2s1", "pll_a_out0", 11289600, true},
- { "i2s2", "pll_a_out0", 11289600, true},
- { "audio", "pll_a_out0", 11289600, true},
- { "audio_2x", "audio", 22579200, true},
+ { "pll_a", NULL, 56448000, false},
+ { "pll_a_out0", NULL, 11289600, false},
+ { "i2s1", "pll_a_out0", 11289600, false},
+ { "i2s2", "pll_a_out0", 11289600, false},
+ { "audio", "pll_a_out0", 11289600, false},
+ { "audio_2x", "audio", 22579200, false},
{ "spdif_out", "pll_a_out0", 5644800, false},
{ "sdmmc2", "pll_p", 25000000, false},
{ NULL, NULL, 0, 0},
@@ -229,50 +229,63 @@ static struct tegra_i2c_platform_data whistler_dvc_platform_data = {
};
static struct tegra_das_platform_data tegra_das_pdata = {
+ .dap_clk = "clk_dev1",
.tegra_dap_port_info_table = {
- [0] = {
- .dac_port = tegra_das_port_none,
- .codec_type = tegra_audio_codec_type_none,
- .device_property = {
- .num_channels = 0,
- .bits_per_sample = 0,
- .rate = 0,
- .dac_dap_data_comm_format = 0,
- },
- },
/* I2S1 <--> DAC1 <--> DAP1 <--> Hifi Codec */
- [1] = {
+ [0] = {
.dac_port = tegra_das_port_i2s1,
+ .dap_port = tegra_das_port_dap1,
.codec_type = tegra_audio_codec_type_hifi,
.device_property = {
.num_channels = 2,
.bits_per_sample = 16,
.rate = 44100,
- .dac_dap_data_comm_format = dac_dap_data_format_i2s,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_all,
+ },
+ },
+ /* I2S2 <--> DAC2 <--> DAP2 <--> Voice Codec */
+ [1] = {
+ .dac_port = tegra_das_port_i2s2,
+ .dap_port = tegra_das_port_dap2,
+ .codec_type = tegra_audio_codec_type_voice,
+ .device_property = {
+ .num_channels = 1,
+ .bits_per_sample = 16,
+ .rate = 8000,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_all,
},
},
+ /* I2S2 <--> DAC2 <--> DAP3 <--> Baseband Codec */
[2] = {
- .dac_port = tegra_das_port_none,
- .codec_type = tegra_audio_codec_type_none,
+ .dac_port = tegra_das_port_i2s2,
+ .dap_port = tegra_das_port_dap3,
+ .codec_type = tegra_audio_codec_type_baseband,
.device_property = {
- .num_channels = 0,
- .bits_per_sample = 0,
- .rate = 0,
- .dac_dap_data_comm_format = 0,
+ .num_channels = 1,
+ .bits_per_sample = 16,
+ .rate = 8000,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_dsp,
},
},
+ /* I2S2 <--> DAC2 <--> DAP4 <--> BT SCO Codec */
[3] = {
- .dac_port = tegra_das_port_none,
- .codec_type = tegra_audio_codec_type_none,
+ .dac_port = tegra_das_port_i2s2,
+ .dap_port = tegra_das_port_dap4,
+ .codec_type = tegra_audio_codec_type_bluetooth,
.device_property = {
- .num_channels = 0,
- .bits_per_sample = 0,
- .rate = 0,
- .dac_dap_data_comm_format = 0,
+ .num_channels = 1,
+ .bits_per_sample = 16,
+ .rate = 8000,
+ .dac_dap_data_comm_format =
+ dac_dap_data_format_dsp,
},
},
[4] = {
.dac_port = tegra_das_port_none,
+ .dap_port = tegra_das_port_none,
.codec_type = tegra_audio_codec_type_none,
.device_property = {
.num_channels = 0,
@@ -286,12 +299,30 @@ static struct tegra_das_platform_data tegra_das_pdata = {
.tegra_das_con_table = {
[0] = {
.con_id = tegra_das_port_con_id_hifi,
- .num_entries = 4,
+ .num_entries = 2,
.con_line = {
[0] = {tegra_das_port_i2s1, tegra_das_port_dap1, true},
[1] = {tegra_das_port_dap1, tegra_das_port_i2s1, false},
- [2] = {tegra_das_port_i2s2, tegra_das_port_dap4, true},
- [3] = {tegra_das_port_dap4, tegra_das_port_i2s2, false},
+ },
+ },
+ [1] = {
+ .con_id = tegra_das_port_con_id_bt_codec,
+ .num_entries = 4,
+ .con_line = {
+ [0] = {tegra_das_port_i2s2, tegra_das_port_dap4, true},
+ [1] = {tegra_das_port_dap4, tegra_das_port_i2s2, false},
+ [2] = {tegra_das_port_i2s1, tegra_das_port_dap1, true},
+ [3] = {tegra_das_port_dap1, tegra_das_port_i2s1, false},
+ },
+ },
+ [2] = {
+ .con_id = tegra_das_port_con_id_voicecall_no_bt,
+ .num_entries = 4,
+ .con_line = {
+ [0] = {tegra_das_port_dap2, tegra_das_port_dap3, true},
+ [1] = {tegra_das_port_dap3, tegra_das_port_dap2, false},
+ [2] = {tegra_das_port_i2s1, tegra_das_port_dap1, true},
+ [3] = {tegra_das_port_dap1, tegra_das_port_i2s1, false},
},
},
}
diff --git a/arch/arm/mach-tegra/include/mach/tegra_das.h b/arch/arm/mach-tegra/include/mach/tegra_das.h
index cba71ff38e18..39fe1705324e 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_das.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_das.h
@@ -3,7 +3,7 @@
*
* Declarations of Tegra Digital Audio Switch (das)
*
- * Copyright (c) 2010, NVIDIA Corporation.
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
*
* 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
@@ -120,44 +120,22 @@ enum tegra_das_port_con_id {
tegra_das_port_con_id_max
};
-/* possible list of input/output devices */
-#define audio_dev_none (0x0)
-#define audio_dev_all (0xffffffff)
-
-/* Inputs */
-#define audio_dev_builtin_mic (0x1)
-#define audio_dev_mic (0x2)
-#define audio_dev_lineIn (0x4)
-
-/* Outputs */
-#define audio_dev_speaker (0x100)
-#define audio_dev_earpiece (0x200)
-#define audio_dev_lineout (0x400)
-#define audio_dev_headphone (0x800)
-#define audio_dev_bt_a2dp (0x1000)
-
-/* Both */
-#define audio_dev_aux (0x10000)
-#define audio_dev_headset (0x20000)
-#define audio_dev_radio (0x40000)
-#define audio_dev_bt_sco (0x80000)
-
/* data format supported */
enum dac_dap_data_format {
+ dac_dap_data_format_none = 0x0,
dac_dap_data_format_i2s = 0x1,
- dac_dap_data_format_rjm,
- dac_dap_data_format_ljm,
- dac_dap_data_format_dsp,
- dac_dap_data_format_pcm,
- dac_dap_data_format_nw,
- dac_dap_data_format_tdm,
+ dac_dap_data_format_dsp = 0x2,
+ dac_dap_data_format_rjm = 0x4,
+ dac_dap_data_format_ljm = 0x8,
+
+ dac_dap_data_format_all = 0x7FFFFFFF
};
struct audio_dev_property {
unsigned int num_channels;
unsigned int bits_per_sample;
unsigned int rate;
- enum dac_dap_data_format dac_dap_data_comm_format;
+ unsigned int dac_dap_data_comm_format;
};
/*
@@ -167,6 +145,7 @@ struct audio_dev_property {
*/
struct tegra_dap_property {
tegra_das_port dac_port;
+ tegra_das_port dap_port;
enum tegra_audio_codec_type codec_type;
struct audio_dev_property device_property;
};
@@ -233,6 +212,22 @@ int tegra_das_set_connection(enum tegra_das_port_con_id new_con_id);
int tegra_das_get_connection(void);
/*
+ * Function to query if certain das port need to be
+ * configured as master for current das connection
+ */
+bool tegra_das_is_port_master(enum tegra_audio_codec_type codec_type);
+
+/*
+ * Function to get data format for certain codec for current das connection
+ */
+int tegra_das_get_codec_data_fmt(enum tegra_audio_codec_type codec_type);
+
+/*
+ * Function to get dap Mclk handle
+ */
+struct clk* tegra_das_get_dap_mclk(void);
+
+/*
* Function to set power state on das's dap port
* if is_normal is true then power mode is normal else tristated
*/
diff --git a/arch/arm/mach-tegra/tegra_das.c b/arch/arm/mach-tegra/tegra_das.c
index ace8d301bae8..8e67705fbeeb 100644
--- a/arch/arm/mach-tegra/tegra_das.c
+++ b/arch/arm/mach-tegra/tegra_das.c
@@ -3,7 +3,7 @@
*
* Digital audio switch driver for tegra soc
*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010-2011 NVIDIA Corporation
*
* 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
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
+#include "clock.h"
#include <mach/iomap.h>
#include <mach/pinmux.h>
#include <mach/tegra_das.h>
@@ -377,6 +378,116 @@ int tegra_das_get_connection(void)
}
EXPORT_SYMBOL_GPL(tegra_das_get_connection);
+bool tegra_das_is_port_master(enum tegra_audio_codec_type codec_type)
+{
+ const struct tegra_das_con *con_table =
+ &das_drv_data->pdata->tegra_das_con_table[0];
+ const struct tegra_dap_property *dap_info =
+ &das_drv_data->pdata->tegra_dap_port_info_table[0];
+ int con_id, i;
+ tegra_das_port dap_port = 0;
+
+ con_id = tegra_das_get_connection();
+ for (i = 0; i < tegra_das_port_con_id_max; i++, con_table++) {
+ if (con_id == con_table->con_id)
+ break;
+ }
+
+ if (i == tegra_das_port_con_id_max)
+ return false;
+
+ for (i = 0; i < MAX_DAP_PORTS; i++) {
+ if (dap_info[i].codec_type == codec_type) {
+ dap_port = dap_info[i].dap_port;
+ break;
+ }
+ }
+
+ if (i == MAX_DAP_PORTS)
+ return false;
+
+ for (i = 0; i < con_table->num_entries; i++) {
+ const struct tegra_das_con_line* con = &con_table->con_line[i];
+
+ if ((con->src == dap_port) && con->src_master)
+ return true;
+ else if((con->dest == dap_port) && !con->src_master)
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(tegra_das_is_port_master);
+
+int tegra_das_get_codec_data_fmt(enum tegra_audio_codec_type codec_type)
+{
+ const struct tegra_das_con *con_table =
+ &das_drv_data->pdata->tegra_das_con_table[0];
+ const struct tegra_dap_property *dap_info =
+ das_drv_data->pdata->tegra_dap_port_info_table;
+ int con_id, i;
+ tegra_das_port dap_a = 0, dap_b = 0;
+ enum dac_dap_data_format data_fmt = dac_dap_data_format_all;
+
+ con_id = tegra_das_get_connection();
+ for (i = 0; i < tegra_das_port_con_id_max; i++, con_table++) {
+ if (con_id == con_table->con_id)
+ break;
+ }
+
+ if (i == tegra_das_port_con_id_max)
+ return data_fmt;
+
+ for (i = 0; i < MAX_DAP_PORTS; i++) {
+ if (dap_info[i].codec_type == codec_type) {
+ dap_a = dap_info[i].dap_port;
+ data_fmt = dap_info[i].device_property.
+ dac_dap_data_comm_format;
+ break;
+ }
+ }
+
+ if (i == MAX_DAP_PORTS)
+ return data_fmt;
+
+
+ for (i = 0; i < con_table->num_entries; i++) {
+ const struct tegra_das_con_line* con = &con_table->con_line[i];
+
+ if (con->src == dap_a) {
+ dap_b = con->dest;
+ break;
+ }
+ else if (con->dest == dap_a) {
+ dap_b = con->src;
+ break;
+ }
+ }
+
+ /* For dac-dap connection return codec data format */
+ if (dap_b > tegra_das_port_dap5)
+ return data_fmt;
+
+ /* For dap-dap bypass connection return data format
+ supported by codecs connected to each dap port */
+ for (i = 0; i < MAX_DAP_PORTS; i++) {
+ if (dap_info[i].dap_port == dap_b) {
+ data_fmt &= dap_info[i].device_property.
+ dac_dap_data_comm_format;
+ break;
+ }
+ }
+
+ return data_fmt;
+}
+EXPORT_SYMBOL_GPL(tegra_das_get_codec_data_fmt);
+
+struct clk* tegra_das_get_dap_mclk(void)
+{
+ return tegra_get_clock_by_name(das_drv_data->pdata->dap_clk);
+}
+EXPORT_SYMBOL_GPL(tegra_das_get_dap_mclk);
+
/* if is_normal is true then power mode is normal else tristated */
int tegra_das_power_mode(bool is_normal)
{
@@ -460,26 +571,26 @@ static int tegra_das_probe(struct platform_device *pdev)
/* Obtain the port index for each codec type */
switch(dap_prop->codec_type) {
case tegra_audio_codec_type_hifi:
- das_ctx->hifi_port_idx = i;
+ das_ctx->hifi_port_idx = dap_prop->dap_port;
break;
case tegra_audio_codec_type_voice:
- das_ctx->voice_codec_idx = i;
+ das_ctx->voice_codec_idx = dap_prop->dap_port;
break;
case tegra_audio_codec_type_bluetooth:
- das_ctx->bt_port_idx = i;
+ das_ctx->bt_port_idx = dap_prop->dap_port;
break;
case tegra_audio_codec_type_baseband:
- das_ctx->bb_port_idx = i;
+ das_ctx->bb_port_idx = dap_prop->dap_port;
break;
case tegra_audio_codec_type_fm_radio:
- das_ctx->fm_radio_port_idx = i;
+ das_ctx->fm_radio_port_idx = dap_prop->dap_port;
break;
default:
found = false;
break;
}
if (found) {
- tegra_dap_default_settings(i);
+ tegra_dap_default_settings(dap_prop->dap_port);
}
}