summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt3
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts3
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi1
-rw-r--r--drivers/char/adsprpc.c15
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c19
-rw-r--r--drivers/input/misc/hbtp_input.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c21
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h3
-rw-r--r--drivers/power/supply/qcom/fg-core.h1
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c40
-rw-r--r--drivers/power/supply/qcom/qpnp-qnovo.c11
-rw-r--r--drivers/power/supply/qcom/smb-lib.c13
-rw-r--r--drivers/soc/qcom/qdsp6v2/msm_audio_ion.c84
-rw-r--r--include/linux/msm_audio_ion.h12
-rw-r--r--include/sound/q6asm-v2.h2
-rw-r--r--include/sound/q6core.h16
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c177
-rw-r--r--sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c154
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c21
-rw-r--r--sound/soc/msm/qdsp6v2/q6core.c62
20 files changed, 585 insertions, 77 deletions
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index f419655722d4..376af82381f2 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -11,6 +11,8 @@ Required properties:
Optional properties:
- qcom,fastrpc-glink: Flag to use glink instead of smd for IPC
+- qcom,fastrpc-vmid-heap-shared: Flag for Dynamic heap feature, to
+ share HLOS memory buffer to ADSP
Optional subnodes:
- qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context
@@ -25,6 +27,7 @@ Example:
qcom,msm_fastrpc {
compatible = "qcom,msm-fastrpc-adsp";
qcom,fastrpc-glink;
+ qcom,fastrpc-vmid-heap-shared;
qcom,msm_fastrpc_compute_cb_1 {
compatible = "qcom,msm-fastrpc-compute-cb";
diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
index 48d5cb78611b..f5c33063643d 100644
--- a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
+++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
@@ -42,6 +42,9 @@
i2c@75b6000 { /* BLSP8 */
/* ADV7533 HDMI Bridge Chip removed on ADP Lite */
+ adv7533@3d {
+ status = "disabled";
+ };
adv7533@39 {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index f14c9a32c2f9..105cfe3fbdc4 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -1567,6 +1567,7 @@
qcom,msm_fastrpc {
compatible = "qcom,msm-fastrpc-adsp";
qcom,fastrpc-glink;
+ qcom,fastrpc-vmid-heap-shared;
qcom,msm_fastrpc_compute_cb1 {
compatible = "qcom,msm-fastrpc-compute-cb";
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 8560a2b731b5..774ac3538075 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -58,6 +58,7 @@
#define FASTRPC_ENOSUCH 39
#define VMID_SSC_Q6 5
#define VMID_ADSP_Q6 6
+#define AC_VM_ADSP_HEAP_SHARED 33
#define DEBUGFS_SIZE 1024
#define RPC_TIMEOUT (5 * HZ)
@@ -222,6 +223,7 @@ struct fastrpc_channel_ctx {
int prevssrcount;
int issubsystemup;
int vmid;
+ int heap_vmid;
int ramdumpenabled;
void *remoteheap_ramdump_dev;
struct fastrpc_glink_info link;
@@ -1594,7 +1596,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
struct fastrpc_mmap *file = 0, *mem = 0;
char *proc_name = NULL;
int srcVM[1] = {VMID_HLOS};
- int destVM[1] = {VMID_ADSP_Q6};
+ int destVM[1] = {gcinfo[0].heap_vmid};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
int hlosVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
@@ -1853,7 +1855,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
} else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
int srcVM[1] = {VMID_HLOS};
- int destVM[1] = {VMID_ADSP_Q6};
+ int destVM[1] = {gcinfo[0].heap_vmid};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size,
@@ -1869,7 +1871,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl,
struct fastrpc_mmap *map)
{
int err = 0;
- int srcVM[1] = {VMID_ADSP_Q6};
+ int srcVM[1] = {gcinfo[0].heap_vmid};
int destVM[1] = {VMID_HLOS};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
@@ -2843,6 +2845,7 @@ static int fastrpc_cb_probe(struct device *dev)
chan->sesscount++;
debugfs_global_file = debugfs_create_file("global", 0644, debugfs_root,
NULL, &debugfs_fops);
+
bail:
return err;
}
@@ -2956,6 +2959,12 @@ static int fastrpc_probe(struct platform_device *pdev)
}
return 0;
}
+ if (of_property_read_bool(dev->of_node,
+ "qcom,fastrpc-vmid-heap-shared"))
+ gcinfo[0].heap_vmid = AC_VM_ADSP_HEAP_SHARED;
+ else
+ gcinfo[0].heap_vmid = VMID_ADSP_Q6;
+ pr_info("ADSPRPC: gcinfo[0].heap_vmid %d\n", gcinfo[0].heap_vmid);
me->glink = of_property_read_bool(dev->of_node, "qcom,fastrpc-glink");
VERIFY(err, !of_platform_populate(pdev->dev.of_node,
fastrpc_match_table,
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 78a8b732b0de..69a4237f7b67 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -593,22 +593,33 @@ static void sde_encoder_phys_vid_get_hw_resources(
struct drm_connector_state *conn_state)
{
struct sde_encoder_phys_vid *vid_enc;
+ struct sde_mdss_cfg *vid_catalog;
if (!phys_enc || !hw_res) {
SDE_ERROR("invalid arg(s), enc %d hw_res %d conn_state %d\n",
- phys_enc != 0, hw_res != 0, conn_state != 0);
+ phys_enc != NULL, hw_res != NULL, conn_state != NULL);
return;
}
+ vid_catalog = phys_enc->sde_kms->catalog;
vid_enc = to_sde_encoder_phys_vid(phys_enc);
- if (!vid_enc->hw_intf) {
- SDE_ERROR("invalid arg(s), hw_intf\n");
+ if (!vid_enc->hw_intf || !vid_catalog) {
+ SDE_ERROR("invalid arg(s), hw_intf %d vid_catalog %d\n",
+ vid_enc->hw_intf != NULL, vid_catalog != NULL);
return;
}
SDE_DEBUG_VIDENC(vid_enc, "\n");
+ if (vid_enc->hw_intf->idx > INTF_MAX) {
+ SDE_ERROR("invalid arg(s), idx %d\n",
+ vid_enc->hw_intf->idx);
+ return;
+ }
hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO;
- hw_res->needs_cdm = true;
+
+ if (vid_catalog->intf[vid_enc->hw_intf->idx - INTF_0].type
+ == INTF_HDMI)
+ hw_res->needs_cdm = true;
SDE_DEBUG_DRIVER("[vid] needs_cdm=%d\n", hw_res->needs_cdm);
}
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 30da797a85dc..56f2732334db 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -249,10 +249,6 @@ static int hbtp_input_release(struct inode *inode, struct file *file)
return -ENOTTY;
}
hbtp->count--;
- if (!completion_done(&hbtp->power_suspend_sig))
- complete(&hbtp->power_suspend_sig);
- if (!completion_done(&hbtp->power_resume_sig))
- complete(&hbtp->power_resume_sig);
if (hbtp->power_sig_enabled)
hbtp->power_sig_enabled = false;
mutex_unlock(&hbtp->mutex);
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
index 63c3595a3f85..d881b4aea48f 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
@@ -434,6 +434,7 @@ static int msm_fd_open(struct file *file)
ctx->vb2_q.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
ctx->vb2_q.io_modes = VB2_USERPTR;
ctx->vb2_q.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ mutex_init(&ctx->lock);
ret = vb2_queue_init(&ctx->vb2_q);
if (ret < 0) {
dev_err(device->dev, "Error queue init\n");
@@ -484,7 +485,9 @@ static int msm_fd_release(struct file *file)
msm_cpp_vbif_register_error_handler((void *)ctx,
VBIF_CLIENT_FD, NULL);
+ mutex_lock(&ctx->lock);
vb2_queue_release(&ctx->vb2_q);
+ mutex_unlock(&ctx->lock);
vfree(ctx->stats);
@@ -514,7 +517,9 @@ static unsigned int msm_fd_poll(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data);
unsigned int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_poll(&ctx->vb2_q, file, wait);
+ mutex_unlock(&ctx->lock);
if (atomic_read(&ctx->subscribed_for_event)) {
poll_wait(file, &ctx->fh.wait, wait);
@@ -752,9 +757,9 @@ static int msm_fd_reqbufs(struct file *file,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_reqbufs(&ctx->vb2_q, req);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -770,9 +775,9 @@ static int msm_fd_qbuf(struct file *file, void *fh,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_qbuf(&ctx->vb2_q, pb);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -789,9 +794,9 @@ static int msm_fd_dqbuf(struct file *file,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_dqbuf(&ctx->vb2_q, pb, file->f_flags & O_NONBLOCK);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -807,7 +812,9 @@ static int msm_fd_streamon(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_streamon(&ctx->vb2_q, buf_type);
+ mutex_unlock(&ctx->lock);
if (ret < 0)
dev_err(ctx->fd_device->dev, "Stream on fails\n");
@@ -826,7 +833,9 @@ static int msm_fd_streamoff(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_streamoff(&ctx->vb2_q, buf_type);
+ mutex_unlock(&ctx->lock);
if (ret < 0)
dev_err(ctx->fd_device->dev, "Stream off fails\n");
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
index 6eae2b8d56fb..2b81e5b9ece3 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -174,6 +174,7 @@ struct fd_ctx {
struct msm_fd_mem_pool mem_pool;
struct msm_fd_stats *stats;
struct msm_fd_buf_handle work_buf;
+ struct mutex lock;
};
/*
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index d3932ca1f338..88dcdd8fd7be 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -419,6 +419,7 @@ struct fg_chip {
int maint_soc;
int delta_soc;
int last_msoc;
+ int last_recharge_volt_mv;
int esr_timer_charging_default[NUM_ESR_TIMERS];
enum slope_limit_status slope_limit_sts;
bool profile_available;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 2d407a9e0ed5..361efd4fbbbd 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1637,6 +1637,9 @@ static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv)
if (chip->wa_flags & PMI8998_V1_REV_WA)
return 0;
+ if (voltage_mv == chip->last_recharge_volt_mv)
+ return 0;
+
fg_dbg(chip, FG_STATUS, "Setting recharge voltage to %dmV\n",
voltage_mv);
fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, voltage_mv, &buf);
@@ -1651,6 +1654,7 @@ static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv)
return rc;
}
+ chip->last_recharge_volt_mv = voltage_mv;
return 0;
}
@@ -1961,6 +1965,33 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip)
return 0;
}
+static int fg_adjust_recharge_voltage(struct fg_chip *chip)
+{
+ int rc, recharge_volt_mv;
+
+ if (chip->dt.auto_recharge_soc)
+ return 0;
+
+ fg_dbg(chip, FG_STATUS, "health: %d chg_status: %d chg_done: %d\n",
+ chip->health, chip->charge_status, chip->charge_done);
+
+ recharge_volt_mv = chip->dt.recharge_volt_thr_mv;
+
+ /* Lower the recharge voltage in soft JEITA */
+ if (chip->health == POWER_SUPPLY_HEALTH_WARM ||
+ chip->health == POWER_SUPPLY_HEALTH_COOL)
+ recharge_volt_mv -= 200;
+
+ rc = fg_set_recharge_voltage(chip, recharge_volt_mv);
+ if (rc < 0) {
+ pr_err("Error in setting recharge_voltage, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int fg_slope_limit_config(struct fg_chip *chip, int batt_temp)
{
enum slope_limit_status status;
@@ -2424,6 +2455,10 @@ static void status_change_work(struct work_struct *work)
if (rc < 0)
pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
+ rc = fg_adjust_recharge_voltage(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting recharge_voltage, rc=%d\n", rc);
+
rc = fg_adjust_ki_coeff_dischg(chip);
if (rc < 0)
pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
@@ -3979,6 +4014,11 @@ static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data)
if (rc < 0)
pr_err("Error in adjusting timebase, rc=%d\n", rc);
+ rc = fg_adjust_recharge_voltage(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting recharge_voltage, rc=%d\n",
+ rc);
+
chip->last_batt_temp = batt_temp;
power_supply_changed(chip->batt_psy);
}
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index cf90f9041935..b20807990efc 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -1396,6 +1396,17 @@ static irqreturn_t handle_ptrain_done(int irq, void *data)
union power_supply_propval pval = {0};
/*
+ * In some cases (esp shutting down) the userspace would disable by
+ * setting qnovo_enable=0. Also charger could be removed or there is
+ * an error (i.e. its not okay to run qnovo)-
+ * skip taking ESR measurement in such situations
+ */
+
+ if (get_client_vote(chip->disable_votable, USER_VOTER)
+ || get_effective_result(chip->not_ok_to_qnovo_votable) > 0)
+ return IRQ_HANDLED;
+
+ /*
* hw resets pt_en bit once ptrain_done triggers.
* vote on behalf of QNI to disable it such that
* once QNI enables it, the votable state changes
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 3984a49f51f6..825d49b2fe4f 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2398,16 +2398,9 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
union power_supply_propval *val)
{
- const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
int rc, pulses;
- val->intval = MICRO_5V;
- if (apsd_result == NULL) {
- smblib_err(chg, "APSD result is NULL\n");
- return 0;
- }
-
- switch (apsd_result->pst) {
+ switch (chg->real_charger_type) {
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
rc = smblib_get_pulse_cnt(chg, &pulses);
if (rc < 0) {
@@ -2417,6 +2410,9 @@ int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
}
val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
break;
+ case POWER_SUPPLY_TYPE_USB_PD:
+ val->intval = chg->voltage_min_uv;
+ break;
default:
val->intval = MICRO_5V;
break;
@@ -2664,6 +2660,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
}
chg->voltage_min_uv = min_uv;
+ power_supply_changed(chg->usb_main_psy);
return rc;
}
diff --git a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c
index 83e3775ed533..b119c7a8441d 100644
--- a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c
+++ b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@
#include <linux/export.h>
#include <linux/qcom_iommu.h>
#include <asm/dma-iommu.h>
+#include <soc/qcom/secure_buffer.h>
#define MSM_AUDIO_ION_PROBED (1 << 0)
@@ -178,6 +179,87 @@ err:
}
EXPORT_SYMBOL(msm_audio_ion_alloc);
+static int msm_audio_hyp_assign(ion_phys_addr_t *paddr, size_t *pa_len,
+ u8 assign_type)
+{
+ int srcVM[1] = {VMID_HLOS};
+ int destVM[1] = {VMID_CP_ADSP_SHARED};
+ int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+ int ret = 0;
+
+ switch (assign_type) {
+ case HLOS_TO_ADSP:
+ srcVM[0] = VMID_HLOS;
+ destVM[0] = VMID_CP_ADSP_SHARED;
+ break;
+ case ADSP_TO_HLOS:
+ srcVM[0] = VMID_CP_ADSP_SHARED;
+ destVM[0] = VMID_HLOS;
+ break;
+ default:
+ pr_err("%s: Invalid assign type = %d\n", __func__, assign_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = hyp_assign_phys(*paddr, *pa_len, srcVM, 1, destVM, destVMperm, 1);
+ if (ret)
+ pr_err("%s: hyp_assign_phys failed for type %d, rc = %d\n",
+ __func__, assign_type, ret);
+done:
+ return ret;
+}
+
+int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr,
+ size_t *pa_len, u8 assign_type)
+{
+ struct ion_client *client;
+ struct ion_handle *handle;
+ int ret;
+
+ if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
+ pr_debug("%s:probe is not done, deferred\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ if (!name || !paddr || !pa_len) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
+ client = msm_audio_ion_client_create(name);
+ if (IS_ERR_OR_NULL((void *)(client))) {
+ pr_err("%s: ION create client failed\n", __func__);
+ return -EINVAL;
+ }
+
+ handle = ion_import_dma_buf(client, fd);
+ if (IS_ERR_OR_NULL((void *) (handle))) {
+ pr_err("%s: ion import dma buffer failed\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_destroy_client;
+ }
+
+ ret = ion_phys(client, handle, paddr, pa_len);
+ if (ret) {
+ pr_err("%s: could not get physical address for handle, ret = %d\n",
+ __func__, ret);
+ goto err_ion_handle;
+ }
+ pr_debug("%s: ION Physical address is %x\n", __func__, (u32)*paddr);
+
+ ret = msm_audio_hyp_assign(paddr, pa_len, assign_type);
+
+err_ion_handle:
+ ion_free(client, handle);
+
+err_destroy_client:
+ ion_client_destroy(client);
+
+ return ret;
+}
+
int msm_audio_ion_import(const char *name, struct ion_client **client,
struct ion_handle **handle, int fd,
unsigned long *ionflag, size_t bufsz,
diff --git a/include/linux/msm_audio_ion.h b/include/linux/msm_audio_ion.h
index 0761b880ca88..ff2fd04a3b6c 100644
--- a/include/linux/msm_audio_ion.h
+++ b/include/linux/msm_audio_ion.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,12 @@
#include <sound/pcm.h>
#include <linux/msm_ion.h>
+enum {
+ HLOS_TO_ADSP = 1,
+ ADSP_TO_HLOS,
+};
+
+#define VMID_CP_ADSP_SHARED 33
int msm_audio_ion_alloc(const char *name, struct ion_client **client,
struct ion_handle **handle, size_t bufsz,
@@ -26,6 +32,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client,
struct ion_handle **handle, int fd,
unsigned long *ionflag, size_t bufsz,
ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+
int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
int msm_audio_ion_mmap(struct audio_buffer *substream,
struct vm_area_struct *vma);
@@ -42,4 +49,7 @@ int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
int msm_audio_ion_free_legacy(struct ion_client *client,
struct ion_handle *handle);
u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa);
+
+int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr,
+ size_t *pa_len, u8 assign_type);
#endif /* _LINUX_MSM_AUDIO_ION_H */
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 177c2f4da32e..dcf7dcb4f6e4 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -639,7 +639,7 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
int q6asm_send_stream_cmd(struct audio_client *ac,
struct msm_adsp_event_data *data);
-int q6asm_send_ion_fd(struct audio_client *ac, int fd);
+int q6asm_audio_map_shm_fd(struct audio_client *ac, int fd);
int q6asm_send_rtic_event_ack(struct audio_client *ac,
void *param, uint32_t params_length);
diff --git a/include/sound/q6core.h b/include/sound/q6core.h
index 1d81bda4b513..4f55880d410f 100644
--- a/include/sound/q6core.h
+++ b/include/sound/q6core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D
bool q6core_is_adsp_ready(void);
+int q6core_add_remove_pool_pages(phys_addr_t buf_add, uint32_t bufsz,
+ uint32_t mempool_id, bool add_pages);
#define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
#define DTS_EAGLE_LICENSE_ID 0x00028346
@@ -153,4 +155,16 @@ struct avcs_cmd_deregister_topologies {
int32_t core_set_license(uint32_t key, uint32_t module_id);
int32_t core_get_license_status(uint32_t module_id);
+#define ADSP_MEMORY_MAP_HLOS_PHYSPOOL 4
+#define AVCS_CMD_ADD_POOL_PAGES 0x0001292E
+#define AVCS_CMD_REMOVE_POOL_PAGES 0x0001292F
+
+struct avs_mem_assign_region {
+ struct apr_hdr hdr;
+ u32 pool_id;
+ u32 size;
+ u32 addr_lsw;
+ u32 addr_msw;
+} __packed;
+
#endif /* __Q6CORE_H__ */
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 0acf6e8ffe49..076dbed207a9 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -39,6 +39,7 @@
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
+#include <sound/q6core.h>
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
@@ -103,6 +104,7 @@ struct msm_compr_pdata {
bool use_legacy_api; /* indicates use older asm apis*/
struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
+ int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
};
struct msm_compr_audio {
@@ -156,6 +158,8 @@ struct msm_compr_audio {
uint32_t start_delay_lsw;
uint32_t start_delay_msw;
+ int32_t shm_ion_fd;
+
uint64_t marker_timestamp;
struct msm_compr_gapless_state gapless_state;
@@ -1506,6 +1510,40 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
return ret;
}
+static int msm_compr_map_unmap_fd(int fd, bool add_pages)
+{
+ ion_phys_addr_t paddr;
+ size_t pa_len = 0;
+ int ret = 0;
+ u8 assign_type;
+
+ if (add_pages)
+ assign_type = HLOS_TO_ADSP;
+ else
+ assign_type = ADSP_TO_HLOS;
+
+ ret = msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
+ &paddr, &pa_len, assign_type);
+ if (ret) {
+ pr_err("%s: audio lib ION phys failed, rc = %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ret = q6core_add_remove_pool_pages(paddr, pa_len,
+ ADSP_MEMORY_MAP_HLOS_PHYSPOOL, add_pages);
+ if (ret) {
+ pr_err("%s: add remove pages failed, rc = %d\n", __func__, ret);
+ /* Assign back to HLOS if add pages cmd failed */
+ if (add_pages)
+ msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
+ &paddr, &pa_len, ADSP_TO_HLOS);
+ }
+
+done:
+ return ret;
+}
+
static int msm_compr_playback_open(struct snd_compr_stream *cstream)
{
struct snd_compr_runtime *runtime = cstream->runtime;
@@ -1513,6 +1551,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
struct msm_compr_audio *prtd;
struct msm_compr_pdata *pdata =
snd_soc_platform_get_drvdata(rtd->platform);
+ int ret = 0;
pr_debug("%s\n", __func__);
prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
@@ -1528,19 +1567,16 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
if (!pdata->audio_effects[rtd->dai_link->be_id]) {
pr_err("%s: Could not allocate memory for effects\n", __func__);
- pdata->cstream[rtd->dai_link->be_id] = NULL;
- kfree(prtd);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto effect_err;
}
pdata->dec_params[rtd->dai_link->be_id] =
kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
if (!pdata->dec_params[rtd->dai_link->be_id]) {
pr_err("%s: Could not allocate memory for dec params\n",
__func__);
- kfree(pdata->audio_effects[rtd->dai_link->be_id]);
- pdata->cstream[rtd->dai_link->be_id] = NULL;
- kfree(prtd);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto param_err;
}
prtd->codec = FORMAT_MP3;
prtd->bytes_received = 0;
@@ -1584,19 +1620,32 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
(app_cb)compr_event_handler, prtd);
if (!prtd->audio_client) {
pr_err("%s: Could not allocate memory for client\n", __func__);
- kfree(pdata->audio_effects[rtd->dai_link->be_id]);
- kfree(pdata->dec_params[rtd->dai_link->be_id]);
- pdata->cstream[rtd->dai_link->be_id] = NULL;
- runtime->private_data = NULL;
- kfree(prtd);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto ac_err;
}
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->audio_client->perf_mode = false;
prtd->session_id = prtd->audio_client->session;
msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
-
+ if (pdata->ion_fd[rtd->dai_link->be_id] > 0) {
+ ret = msm_compr_map_unmap_fd(
+ pdata->ion_fd[rtd->dai_link->be_id], true);
+ if (ret < 0)
+ goto map_err;
+ }
return 0;
+
+map_err:
+ q6asm_audio_client_free(prtd->audio_client);
+ac_err:
+ kfree(pdata->dec_params[rtd->dai_link->be_id]);
+param_err:
+ kfree(pdata->audio_effects[rtd->dai_link->be_id]);
+effect_err:
+ pdata->cstream[rtd->dai_link->be_id] = NULL;
+ runtime->private_data = NULL;
+ kfree(prtd);
+ return ret;
}
static int msm_compr_capture_open(struct snd_compr_stream *cstream)
@@ -1675,6 +1724,8 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
int dir = IN, ret = 0, stream_id;
unsigned long flags;
uint32_t stream_index;
+ ion_phys_addr_t paddr;
+ size_t pa_len = 0;
pr_debug("%s\n", __func__);
@@ -1748,6 +1799,15 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
}
q6asm_audio_client_buf_free_contiguous(dir, ac);
+ if (prtd->shm_ion_fd > 0)
+ msm_audio_ion_phys_assign("audio_shm_mem_client",
+ prtd->shm_ion_fd,
+ &paddr, &pa_len, ADSP_TO_HLOS);
+ if (pdata->ion_fd[soc_prtd->dai_link->be_id] > 0) {
+ msm_compr_map_unmap_fd(pdata->ion_fd[soc_prtd->dai_link->be_id],
+ false);
+ pdata->ion_fd[soc_prtd->dai_link->be_id] = 0;
+ }
q6asm_audio_client_free(ac);
msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
@@ -3655,7 +3715,7 @@ done:
return ret;
}
-static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
+static int msm_compr_shm_ion_fd_map_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
@@ -3664,7 +3724,6 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(comp);
struct snd_compr_stream *cstream = NULL;
struct msm_compr_audio *prtd;
- int fd;
int ret = 0;
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3694,10 +3753,34 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
goto done;
}
- memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
- ret = q6asm_send_ion_fd(prtd->audio_client, fd);
+ memcpy(&prtd->shm_ion_fd, ucontrol->value.bytes.data,
+ sizeof(prtd->shm_ion_fd));
+ ret = q6asm_audio_map_shm_fd(prtd->audio_client, prtd->shm_ion_fd);
if (ret < 0)
- pr_err("%s: failed to register ion fd\n", __func__);
+ pr_err("%s: failed to map shm mem\n", __func__);
+done:
+ return ret;
+}
+
+static int msm_compr_lib_ion_fd_map_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ int ret = 0;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds invalid fe_id %lu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ memcpy(&pdata->ion_fd[fe_id], ucontrol->value.bytes.data,
+ sizeof(pdata->ion_fd[fe_id]));
+
done:
return ret;
}
@@ -4329,7 +4412,7 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
+static int msm_compr_add_shm_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
{
const char *mixer_ctl_name = "Playback ION FD";
const char *deviceNo = "NN";
@@ -4341,7 +4424,52 @@ static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
.name = "?",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_adsp_stream_cmd_info,
- .put = msm_compr_ion_fd_map_put,
+ .put = msm_compr_shm_ion_fd_map_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
+ fe_ion_fd_config_control[0].name = mixer_str;
+ fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
+ ret = snd_soc_add_platform_controls(rtd->platform,
+ fe_ion_fd_config_control,
+ ARRAY_SIZE(fe_ion_fd_config_control));
+ if (ret < 0)
+ pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
+
+ kfree(mixer_str);
+done:
+ return ret;
+}
+
+static int msm_compr_add_lib_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Playback ION LIB FD";
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_adsp_stream_cmd_info,
+ .put = msm_compr_lib_ion_fd_map_put,
.private_value = 0,
}
};
@@ -4442,11 +4570,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
__func__);
- rc = msm_compr_add_io_fd_cmd_control(rtd);
+ rc = msm_compr_add_shm_ion_fd_cmd_control(rtd);
if (rc)
pr_err("%s: Could not add Compr ion fd Control\n",
__func__);
+ rc = msm_compr_add_lib_ion_fd_cmd_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr ion lib fd Control\n",
+ __func__);
+
rc = msm_compr_add_event_ack_cmd_control(rtd);
if (rc)
pr_err("%s: Could not add Compr event ack Control\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
index 5c5f7bc482c8..a75de6d1d7c0 100644
--- a/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
@@ -27,6 +27,7 @@
#include <sound/initval.h>
#include <sound/control.h>
#include <sound/q6asm-v2.h>
+#include <sound/q6core.h>
#include <sound/pcm_params.h>
#include <sound/timer.h>
#include <sound/tlv.h>
@@ -45,6 +46,7 @@ static DEFINE_MUTEX(transcode_loopback_session_lock);
struct trans_loopback_pdata {
struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
+ int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
};
struct loopback_stream {
@@ -79,6 +81,7 @@ struct msm_transcode_loopback {
int session_id;
struct audio_client *audio_client;
+ int32_t shm_ion_fd;
};
/* Transcode loopback global info struct */
@@ -179,6 +182,40 @@ static void populate_codec_list(struct msm_transcode_loopback *trans,
}
}
+static int msm_transcode_map_unmap_fd(int fd, bool add_pages)
+{
+ ion_phys_addr_t paddr;
+ size_t pa_len = 0;
+ int ret = 0;
+ u8 assign_type;
+
+ if (add_pages)
+ assign_type = HLOS_TO_ADSP;
+ else
+ assign_type = ADSP_TO_HLOS;
+
+ ret = msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
+ &paddr, &pa_len, assign_type);
+ if (ret) {
+ pr_err("%s: audio lib ION phys failed, rc = %d\n", __func__,
+ ret);
+ goto done;
+ }
+
+ ret = q6core_add_remove_pool_pages(paddr, pa_len,
+ ADSP_MEMORY_MAP_HLOS_PHYSPOOL, add_pages);
+ if (ret) {
+ pr_err("%s: add remove pages failed, rc = %d\n", __func__, ret);
+ /* Assign back to HLOS if add pages cmd failed */
+ if (add_pages)
+ msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
+ &paddr, &pa_len, ADSP_TO_HLOS);
+ }
+
+done:
+ return ret;
+}
+
static int msm_transcode_loopback_open(struct snd_compr_stream *cstream)
{
int ret = 0;
@@ -224,6 +261,13 @@ static int msm_transcode_loopback_open(struct snd_compr_stream *cstream)
goto exit;
}
msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
+ if (pdata->ion_fd[rtd->dai_link->be_id] > 0) {
+ ret = msm_transcode_map_unmap_fd(
+ pdata->ion_fd[rtd->dai_link->be_id],
+ true);
+ if (ret < 0)
+ goto exit;
+ }
}
pr_debug("%s: num stream%d, stream name %s\n", __func__,
@@ -274,7 +318,11 @@ static int msm_transcode_loopback_free(struct snd_compr_stream *cstream)
struct snd_compr_runtime *runtime = cstream->runtime;
struct msm_transcode_loopback *trans = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(cstream);
+ struct trans_loopback_pdata *pdata = snd_soc_platform_get_drvdata(
+ rtd->platform);
int ret = 0;
+ ion_phys_addr_t paddr;
+ size_t pa_len = 0;
mutex_lock(&trans->lock);
@@ -286,6 +334,19 @@ static int msm_transcode_loopback_free(struct snd_compr_stream *cstream)
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
memset(&trans->sink, 0, sizeof(struct loopback_stream));
msm_adsp_clean_mixer_ctl_pp_event_queue(rtd);
+ if (trans->shm_ion_fd > 0) {
+ msm_audio_ion_phys_assign("audio_shm_mem_client",
+ trans->shm_ion_fd,
+ &paddr, &pa_len,
+ ADSP_TO_HLOS);
+ trans->shm_ion_fd = 0;
+ }
+ if (pdata->ion_fd[rtd->dai_link->be_id] > 0) {
+ msm_transcode_map_unmap_fd(
+ pdata->ion_fd[rtd->dai_link->be_id],
+ false);
+ pdata->ion_fd[rtd->dai_link->be_id] = 0;
+ }
} else if (cstream->direction == SND_COMPRESS_CAPTURE) {
memset(&trans->source, 0, sizeof(struct loopback_stream));
}
@@ -557,7 +618,7 @@ done:
return ret;
}
-static int msm_transcode_ion_fd_map_put(struct snd_kcontrol *kcontrol,
+static int msm_transcode_shm_ion_fd_map_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
@@ -566,7 +627,6 @@ static int msm_transcode_ion_fd_map_put(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(comp);
struct snd_compr_stream *cstream = NULL;
struct msm_transcode_loopback *prtd;
- int fd;
int ret = 0;
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -596,10 +656,34 @@ static int msm_transcode_ion_fd_map_put(struct snd_kcontrol *kcontrol,
goto done;
}
- memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
- ret = q6asm_send_ion_fd(prtd->audio_client, fd);
+ memcpy(&prtd->shm_ion_fd, ucontrol->value.bytes.data,
+ sizeof(prtd->shm_ion_fd));
+ ret = q6asm_audio_map_shm_fd(prtd->audio_client, prtd->shm_ion_fd);
if (ret < 0)
- pr_err("%s: failed to register ion fd\n", __func__);
+ pr_err("%s: failed to map shm mem\n", __func__);
+done:
+ return ret;
+}
+
+
+static int msm_transcode_lib_ion_fd_map_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ int ret = 0;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds invalid fe_id %lu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ memcpy(&pdata->ion_fd[fe_id], ucontrol->value.bytes.data,
+ sizeof(pdata->ion_fd[fe_id]));
done:
return ret;
}
@@ -773,7 +857,8 @@ done:
return ret;
}
-static int msm_transcode_add_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
+static int msm_transcode_add_shm_ion_fd_cmd_control(
+ struct snd_soc_pcm_runtime *rtd)
{
const char *mixer_ctl_name = "Playback ION FD";
const char *deviceNo = "NN";
@@ -785,7 +870,53 @@ static int msm_transcode_add_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
.name = "?",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_adsp_stream_cmd_info,
- .put = msm_transcode_ion_fd_map_put,
+ .put = msm_transcode_shm_ion_fd_map_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
+ fe_ion_fd_config_control[0].name = mixer_str;
+ fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
+ ret = snd_soc_add_platform_controls(rtd->platform,
+ fe_ion_fd_config_control,
+ ARRAY_SIZE(fe_ion_fd_config_control));
+ if (ret < 0)
+ pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
+
+ kfree(mixer_str);
+done:
+ return ret;
+}
+
+static int msm_transcode_add_lib_ion_fd_cmd_control(
+ struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Playback ION LIB FD";
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_adsp_stream_cmd_info,
+ .put = msm_transcode_lib_ion_fd_map_put,
.private_value = 0,
}
};
@@ -877,9 +1008,14 @@ static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: ADSP Stream callback Control open failed\n",
__func__);
- rc = msm_transcode_add_ion_fd_cmd_control(rtd);
+ rc = msm_transcode_add_shm_ion_fd_cmd_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add transcode shm ion fd Control\n",
+ __func__);
+
+ rc = msm_transcode_add_lib_ion_fd_cmd_control(rtd);
if (rc)
- pr_err("%s: Could not add transcode ion fd Control\n",
+ pr_err("%s: Could not add transcode lib ion fd Control\n",
__func__);
rc = msm_transcode_add_event_ack_cmd_control(rtd);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index a44569530846..d297acd62665 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -36,6 +36,7 @@
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
+#include <sound/q6core.h>
#include <sound/q6audio-v2.h>
#include <sound/audio_cal_utils.h>
#include <sound/adsp_err.h>
@@ -7117,13 +7118,10 @@ fail_cmd:
return rc;
}
-int q6asm_send_ion_fd(struct audio_client *ac, int fd)
+int q6asm_audio_map_shm_fd(struct audio_client *ac, int fd)
{
- struct ion_client *client;
- struct ion_handle *handle;
ion_phys_addr_t paddr;
size_t pa_len = 0;
- void *vaddr;
int ret;
int sz = 0;
struct avs_rtic_shared_mem_addr shm;
@@ -7139,19 +7137,10 @@ int q6asm_send_ion_fd(struct audio_client *ac, int fd)
goto fail_cmd;
}
- ret = msm_audio_ion_import("audio_mem_client",
- &client,
- &handle,
- fd,
- NULL,
- 0,
- &paddr,
- &pa_len,
- &vaddr);
+ ret = msm_audio_ion_phys_assign("audio_shm_mem_client", fd,
+ &paddr, &pa_len, HLOS_TO_ADSP);
if (ret) {
- pr_err("%s: audio ION import failed, rc = %d\n",
- __func__, ret);
- ret = -ENOMEM;
+ pr_err("%s: shm ION phys failed, rc = %d\n", __func__, ret);
goto fail_cmd;
}
/* get payload length */
diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c
index 4340d31c218c..6fed443186e5 100644
--- a/sound/soc/msm/qdsp6v2/q6core.c
+++ b/sound/soc/msm/qdsp6v2/q6core.c
@@ -119,6 +119,18 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
q6core_lcl.bus_bw_resp_received = 1;
wake_up(&q6core_lcl.bus_bw_req_wait);
break;
+ case AVCS_CMD_ADD_POOL_PAGES:
+ pr_debug("%s: Cmd = AVCS_CMD_ADD_POOL_PAGES status[0x%x]\n",
+ __func__, payload1[1]);
+ q6core_lcl.bus_bw_resp_received = 1;
+ wake_up(&q6core_lcl.bus_bw_req_wait);
+ break;
+ case AVCS_CMD_REMOVE_POOL_PAGES:
+ pr_debug("%s: Cmd = AVCS_CMD_REMOVE_POOL_PAGES status[0x%x]\n",
+ __func__, payload1[1]);
+ q6core_lcl.bus_bw_resp_received = 1;
+ wake_up(&q6core_lcl.bus_bw_req_wait);
+ break;
default:
pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
__func__,
@@ -542,6 +554,56 @@ done:
return ret;
}
+int q6core_add_remove_pool_pages(ion_phys_addr_t buf_add, uint32_t bufsz,
+ uint32_t mempool_id, bool add_pages)
+{
+ struct avs_mem_assign_region mem_pool;
+ int ret = 0, sz;
+
+ if (add_pages)
+ mem_pool.hdr.opcode = AVCS_CMD_ADD_POOL_PAGES;
+ else
+ mem_pool.hdr.opcode = AVCS_CMD_REMOVE_POOL_PAGES;
+
+ /* get payload length */
+ sz = sizeof(struct avs_mem_assign_region);
+ mem_pool.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(sizeof(struct apr_hdr)),
+ APR_PKT_VER);
+ mem_pool.hdr.src_port = 0;
+ mem_pool.hdr.dest_port = 0;
+ mem_pool.hdr.token = 0;
+ mem_pool.hdr.pkt_size = sz;
+ mem_pool.pool_id = mempool_id;
+ mem_pool.size = bufsz;
+ mem_pool.addr_lsw = lower_32_bits(buf_add);
+ mem_pool.addr_msw = msm_audio_populate_upper_32_bits(buf_add);
+ pr_debug("%s: sending memory map, size %d\n",
+ __func__, bufsz);
+
+ q6core_lcl.bus_bw_resp_received = 0;
+ ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *)&mem_pool);
+ if (ret < 0) {
+ pr_err("%s: library map region failed %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = wait_event_timeout(q6core_lcl.bus_bw_req_wait,
+ (q6core_lcl.bus_bw_resp_received == 1),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: timeout. waited for library memory map\n",
+ __func__);
+ ret = -ETIME;
+ goto done;
+ }
+ ret = 0;
+done:
+ return ret;
+}
+
static int q6core_dereg_all_custom_topologies(void)
{
int ret = 0;