diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-03-29 16:51:29 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-04-13 18:05:38 -0700 |
commit | a12a3c264124e02232e2b102bfc718682cb374b6 (patch) | |
tree | 236080eeedb819a4166d60f52bffe592156da282 /arch | |
parent | 574e119e6d68811bc34f58c2cf83a860fe17c250 (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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/board-ventana.c | 63 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-whistler.c | 97 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra_das.h | 55 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_das.c | 125 |
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); } } |