diff options
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; |
