Merge "ASoC: qdsp6v2: Add support of ULL and LL"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 0a45ede..6277054 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -21,6 +21,12 @@
- qti,msm-pcm-low-latency : Flag indicating whether
the device node is of type low latency.
+ - qti,latency-level : Flag indicating whether the device node
+ is of type regular low latency or ultra
+ low latency.
+ regular : regular low latency stream
+ ultra : ultra low latency stream
+
* msm-pcm-routing
Required properties:
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index ca06adc..5941f71 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -31,7 +31,7 @@
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params);
int adm_open(int port, int path, int rate, int mode, int topology,
- bool perf_mode, uint16_t bits_per_sample);
+ int perf_mode, uint16_t bits_per_sample);
int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
uint32_t params_length, char *params);
@@ -40,7 +40,7 @@
uint32_t params_length);
int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
- int topology, bool perf_mode, uint16_t bits_per_sample);
+ int topology, int perf_mode, uint16_t bits_per_sample);
int adm_unmap_cal_blocks(void);
@@ -53,10 +53,10 @@
int adm_memory_unmap_regions(int port_id);
-int adm_close(int port, bool perf_mode);
+int adm_close(int port, int perf_mode);
int adm_matrix_map(int session_id, int path, int num_copps,
- unsigned int *port_id, int copp_id, bool perf_mode);
+ unsigned int *port_id, int copp_id, int perf_mode);
int adm_connect_afe_port(int mode, int session_id, int port_id);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index b00cfc9..a78c333 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -175,7 +175,7 @@
struct audio_port_data port[2];
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
- bool perf_mode;
+ int perf_mode;
int stream_id;
/* audio cache operations fptr*/
int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op);
diff --git a/include/sound/q6audio-v2.h b/include/sound/q6audio-v2.h
index fd6a490..8ac835c 100644
--- a/include/sound/q6audio-v2.h
+++ b/include/sound/q6audio-v2.h
@@ -15,6 +15,13 @@
#include <mach/qdsp6v2/apr.h>
+enum {
+ LEGACY_PCM_MODE = 0,
+ LOW_LATENCY_PCM_MODE,
+ ULTRA_LOW_LATENCY_PCM_MODE,
+};
+
+
int q6audio_get_port_index(u16 port_id);
int q6audio_convert_virtual_to_portid(u16 port_id);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index a13b3f2..3ddc3e0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -25,6 +25,7 @@
#include <sound/pcm.h>
#include <sound/initval.h>
#include <sound/control.h>
+#include <sound/q6audio-v2.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
@@ -916,6 +917,7 @@
int rc;
int id;
struct msm_plat_data *pdata;
+ const char *latency_level;
rc = of_property_read_u32(pdev->dev.of_node,
"qti,msm-pcm-dsp-id", &id);
@@ -932,10 +934,17 @@
}
if (of_property_read_bool(pdev->dev.of_node,
- "qti,msm-pcm-low-latency"))
- pdata->perf_mode = 1;
- else
- pdata->perf_mode = 0;
+ "qti,msm-pcm-low-latency")) {
+
+ pdata->perf_mode = LOW_LATENCY_PCM_MODE;
+ rc = of_property_read_string(pdev->dev.of_node,
+ "qti,latency-level", &latency_level);
+ if (!rc) {
+ if (!strcmp(latency_level, "ultra"))
+ pdata->perf_mode = ULTRA_LOW_LATENCY_PCM_MODE;
+ }
+ } else
+ pdata->perf_mode = LEGACY_PCM_MODE;
dev_set_drvdata(&pdev->dev, pdata);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 711291da..91c0744 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -290,7 +290,7 @@
/* Track performance mode of all front-end multimedia sessions.
* Performance mode is only valid when session is valid.
*/
-static bool fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
+static int fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
static uint8_t is_be_dai_extproc(int be_dai)
{
@@ -303,7 +303,7 @@
}
static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
- int path_type, bool perf_mode)
+ int path_type, int perf_mode)
{
int i, port_type;
struct route_payload payload;
@@ -365,7 +365,7 @@
mutex_unlock(&routing_lock);
}
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
int dspst_id, int stream_type)
{
int i, session_type, path_type, port_type, port_id, topology;
@@ -437,7 +437,7 @@
port_id = srs_port_id = msm_bedais[i].port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!perf_mode))
+ (perf_mode == LEGACY_PCM_MODE))
if (dolby_dap_init(port_id,
msm_bedais[i].channel) < 0)
pr_err("%s: Err init dolby dap\n",
@@ -494,7 +494,8 @@
adm_close(msm_bedais[i].port_id,
fe_dai_perf_mode[fedai_id][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[fedai_id][session_type] == false))
+ (fe_dai_perf_mode[fedai_id][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(msm_bedais[i].port_id);
}
}
@@ -604,7 +605,8 @@
port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[val][session_type] == false))
+ (fe_dai_perf_mode[val][session_type] ==
+ LEGACY_PCM_MODE))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
@@ -621,7 +623,8 @@
adm_close(msm_bedais[reg].port_id,
fe_dai_perf_mode[val][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[val][session_type] == false))
+ (fe_dai_perf_mode[val][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fdai->strm_id, path_type,
@@ -3960,7 +3963,8 @@
fe_dai_perf_mode[i][session_type]);
srs_port_id = -1;
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[i][session_type] == false))
+ (fe_dai_perf_mode[i][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(bedai->port_id);
}
}
@@ -4060,7 +4064,8 @@
port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[i][session_type] == false))
+ (fe_dai_perf_mode[i][session_type] ==
+ LEGACY_PCM_MODE))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4f7c4e3..54f5e4a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -143,7 +143,7 @@
* dspst_id: DSP audio stream ID
* stream_type: playback or capture
*/
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, int dspst_id,
int stream_type);
void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
int stream_type);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index d837f06..54b1263 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -733,7 +733,7 @@
adm_params.hdr.dest_svc = APR_SVC_ADM;
adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
- if (!perf_mode)
+ if (perf_mode == LEGACY_PCM_MODE)
adm_params.hdr.dest_port =
atomic_read(&this_adm.copp_id[index]);
else
@@ -1056,7 +1056,7 @@
}
int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
- bool perf_mode, uint16_t bits_per_sample)
+ int perf_mode, uint16_t bits_per_sample)
{
struct adm_cmd_device_open_v5 open;
int ret = 0;
@@ -1087,7 +1087,7 @@
rtac_set_adm_handle(this_adm.apr);
}
- if (!perf_mode) {
+ if (perf_mode == LEGACY_PCM_MODE) {
atomic_set(&this_adm.copp_perf_mode[index], 0);
send_adm_custom_topology(port_id);
} else {
@@ -1095,8 +1095,9 @@
}
/* Create a COPP if port id are not enabled */
- if ((!perf_mode && (atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
- (perf_mode &&
+ if ((perf_mode == LEGACY_PCM_MODE &&
+ (atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
+ (perf_mode != LEGACY_PCM_MODE &&
(atomic_read(&this_adm.copp_low_latency_cnt[index]) == 0))) {
pr_debug("%s:opening ADM: perf_mode: %d\n", __func__,
perf_mode);
@@ -1111,12 +1112,12 @@
open.hdr.dest_port = tmp_port;
open.hdr.token = port_id;
open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
- open.flags = 0x00;
- if (perf_mode) {
- open.flags |= ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
- } else {
- open.flags |= ADM_LEGACY_DEVICE_SESSION;
- }
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
+ open.flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
+ else if (perf_mode == LOW_LATENCY_PCM_MODE)
+ open.flags = ADM_LOW_LATENCY_DEVICE_SESSION;
+ else
+ open.flags = ADM_LEGACY_DEVICE_SESSION;
open.mode_of_operation = path;
open.endpoint_id_1 = tmp_port;
@@ -1133,7 +1134,7 @@
(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
open.topology_id = NULL_COPP_TOPOLOGY;
rate = ULL_SUPPORTED_SAMPLE_RATE;
if(channel_mode > ULL_MAX_SUPPORTED_CHANNEL)
@@ -1141,7 +1142,8 @@
}
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
- WARN_ON(perf_mode && (rate != 48000));
+ WARN_ON(perf_mode == ULTRA_LOW_LATENCY_PCM_MODE &&
+ (rate != 48000));
open.sample_rate = rate;
memset(open.dev_channel_mapping, 0, 8);
@@ -1216,7 +1218,8 @@
goto fail_cmd;
}
}
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
atomic_inc(&this_adm.copp_low_latency_cnt[index]);
pr_debug("%s: index: %d coppid: %d", __func__, index,
atomic_read(&this_adm.copp_low_latency_id[index]));
@@ -1233,7 +1236,7 @@
}
int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
- int topology, bool perf_mode, uint16_t bits_per_sample)
+ int topology, int perf_mode, uint16_t bits_per_sample)
{
int ret = 0;
@@ -1244,7 +1247,7 @@
}
int adm_matrix_map(int session_id, int path, int num_copps,
- unsigned int *port_id, int copp_id, bool perf_mode)
+ unsigned int *port_id, int copp_id, int perf_mode)
{
struct adm_cmd_matrix_map_routings_v5 *route;
struct adm_session_map_node_v5 *node;
@@ -1283,7 +1286,8 @@
route->hdr.src_port = copp_id;
route->hdr.dest_svc = APR_SVC_ADM;
route->hdr.dest_domain = APR_DOMAIN_ADSP;
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
route->hdr.dest_port =
atomic_read(&this_adm.copp_low_latency_id[index]);
} else {
@@ -1321,7 +1325,8 @@
if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
- if (perf_mode)
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE)
copps_list[i] =
atomic_read(&this_adm.copp_low_latency_id[tmp]);
else
@@ -1352,23 +1357,27 @@
goto fail_cmd;
}
- for (i = 0; i < num_copps; i++)
- send_adm_cal(port_id[i], path, perf_mode);
+ if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
+ for (i = 0; i < num_copps; i++)
+ send_adm_cal(port_id[i], path, perf_mode);
- for (i = 0; i < num_copps; i++) {
- int tmp, copp_id;
- tmp = afe_get_port_index(port_id[i]);
- if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
- if (!perf_mode)
- copp_id = atomic_read(&this_adm.copp_id[tmp]);
- else
- copp_id =
- atomic_read(&this_adm.copp_low_latency_id[tmp]);
- rtac_add_adm_device(port_id[i],
+ for (i = 0; i < num_copps; i++) {
+ int tmp, copp_id;
+ tmp = afe_get_port_index(port_id[i]);
+ if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
+ if (perf_mode == LEGACY_PCM_MODE)
+ copp_id = atomic_read(
+ &this_adm.copp_id[tmp]);
+ else
+ copp_id = atomic_read(
+ &this_adm.copp_low_latency_id[tmp]);
+ rtac_add_adm_device(port_id[i],
copp_id, path, session_id);
- pr_debug("%s, copp_id: %d\n", __func__, copp_id);
- } else {
- pr_debug("%s: Invalid port index %d", __func__, tmp);
+ pr_debug("%s, copp_id: %d\n",
+ __func__, copp_id);
+ } else
+ pr_debug("%s: Invalid port index %d",
+ __func__, tmp);
}
}
@@ -1570,7 +1579,7 @@
pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
}
-int adm_close(int port_id, bool perf_mode)
+int adm_close(int port_id, int perf_mode)
{
struct apr_hdr close;
@@ -1587,7 +1596,8 @@
pr_debug("%s port_id=%#x index %d perf_mode: %d\n", __func__, port_id,
index, perf_mode);
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
if (!(atomic_read(&this_adm.copp_low_latency_cnt[index]))) {
pr_err("%s: copp count for port[%#x]is 0\n", __func__,
port_id);
@@ -1602,8 +1612,9 @@
}
atomic_dec(&this_adm.copp_cnt[index]);
}
- if ((!perf_mode && !(atomic_read(&this_adm.copp_cnt[index]))) ||
- (perf_mode &&
+ if ((perf_mode == LEGACY_PCM_MODE &&
+ !(atomic_read(&this_adm.copp_cnt[index]))) ||
+ ((perf_mode != LEGACY_PCM_MODE) &&
!(atomic_read(&this_adm.copp_low_latency_cnt[index])))) {
pr_debug("%s:Closing ADM: perf_mode: %d\n", __func__,
@@ -1616,7 +1627,8 @@
close.src_port = port_id;
close.dest_svc = APR_SVC_ADM;
close.dest_domain = APR_DOMAIN_ADSP;
- if (perf_mode)
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE)
close.dest_port =
atomic_read(&this_adm.copp_low_latency_id[index]);
else
@@ -1626,7 +1638,8 @@
atomic_set(&this_adm.copp_stat[index], 0);
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
copp_id = atomic_read(
&this_adm.copp_low_latency_id[index]);
pr_debug("%s:coppid %d portid=%#x index=%d coppcnt=%d\n",
@@ -1666,8 +1679,10 @@
}
}
- pr_debug("%s: remove adm device from rtac\n", __func__);
- rtac_remove_adm_device(port_id, copp_id);
+ if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
+ pr_debug("%s: remove adm device from rtac\n", __func__);
+ rtac_remove_adm_device(port_id, copp_id);
+ }
fail_cmd:
return ret;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 631e9bd..24f5f3b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -39,6 +39,7 @@
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
+#include <sound/q6audio-v2.h>
#include "audio_acdb.h"
@@ -354,7 +355,7 @@
session[ac->session] = 0;
mutex_unlock(&session_lock);
ac->session = 0;
- ac->perf_mode = 0;
+ ac->perf_mode = LEGACY_PCM_MODE;
ac->fptr_cache_ops = NULL;
return;
}
@@ -810,7 +811,7 @@
ac->cb = cb;
ac->priv = priv;
ac->io_mode = SYNC_IO_MODE;
- ac->perf_mode = false;
+ ac->perf_mode = LEGACY_PCM_MODE;
ac->fptr_cache_ops = NULL;
ac->apr = apr_register("ADSP", "ASM", \
(apr_fn)q6asm_callback,\
@@ -1695,7 +1696,7 @@
open.bits_per_sample = bits_per_sample;
open.mode_flags = 0x0;
- if (ac->perf_mode) {
+ if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION <<
ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
} else {
@@ -1781,8 +1782,10 @@
open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
open.mode_flags = 0x00;
- if (ac->perf_mode)
+ if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
+ else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
+ open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
else {
open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
if (is_gapless_mode)