summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxminath Kasam <lkasam@codeaurora.org>2017-11-28 12:40:22 +0530
committerMeng Wang <mwang@codeaurora.org>2018-03-01 16:02:06 +0800
commit30ad751aacb9f348e895d2fe110660d5bc440d0b (patch)
tree2a8d7b0ace994696875a4e08e2cf2062f01525e5
parentda56c67bc43cbf42d1004d9e1499fbe9a28f3dd2 (diff)
downloadmsm-extra-30ad751aacb9f348e895d2fe110660d5bc440d0b.tar.gz
ASoC: rmmod fixes for audio drivers
For remove module(rmmod), update drivers to cleanup resources and allow insert module again without any issue. Change-Id: Iddc6e5e11d986359afd3100bf3c5eab70cb1c1eb Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org> Signed-off-by: Meng Wang <mwang@codeaurora.org>
-rw-r--r--asoc/codecs/msm_sdw/msm_sdw.h6
-rw-r--r--asoc/codecs/msm_sdw/msm_sdw_cdc.c17
-rw-r--r--asoc/codecs/sdm660_cdc/msm-analog-cdc.c15
-rw-r--r--asoc/codecs/sdm660_cdc/msm-analog-cdc.h6
-rw-r--r--asoc/codecs/sdm660_cdc/sdm660-cdc-irq.c7
-rw-r--r--asoc/codecs/sdm660_cdc/sdm660-cdc-irq.h3
-rw-r--r--asoc/msm-dai-q6-v2.c3
-rw-r--r--dsp/audio_slimslave.c4
-rw-r--r--dsp/q6adm.c118
-rw-r--r--dsp/q6afe.c6
-rw-r--r--soc/swr-wcd-ctrl.c7
11 files changed, 120 insertions, 72 deletions
diff --git a/asoc/codecs/msm_sdw/msm_sdw.h b/asoc/codecs/msm_sdw/msm_sdw.h
index d4ac4333..3c7a07dc 100644
--- a/asoc/codecs/msm_sdw/msm_sdw.h
+++ b/asoc/codecs/msm_sdw/msm_sdw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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,7 @@
#include "msm_sdw_registers.h"
#define MSM_SDW_MAX_REGISTER 0x400
+#define MSM_SDW_CHILD_DEVICES_MAX 1
extern const struct regmap_config msm_sdw_regmap_config;
extern const u8 msm_sdw_page_map[MSM_SDW_MAX_REGISTER];
@@ -154,6 +155,9 @@ struct msm_sdw_priv {
/* Entry for version info */
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
+ struct platform_device *pdev_child_devices
+ [MSM_SDW_CHILD_DEVICES_MAX];
+ int child_count;
};
#if IS_ENABLED(CONFIG_SND_SOC_MSM_SDW)
diff --git a/asoc/codecs/msm_sdw/msm_sdw_cdc.c b/asoc/codecs/msm_sdw/msm_sdw_cdc.c
index 7a5ba8f0..3e4921d1 100644
--- a/asoc/codecs/msm_sdw/msm_sdw_cdc.c
+++ b/asoc/codecs/msm_sdw/msm_sdw_cdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -1251,7 +1251,13 @@ static int msm_sdw_swrm_write(void *handle, int reg, int val)
static int msm_sdw_swrm_clock(void *handle, bool enable)
{
- struct msm_sdw_priv *msm_sdw = (struct msm_sdw_priv *) handle;
+ struct msm_sdw_priv *msm_sdw;
+
+ if (!handle) {
+ pr_err("%s: NULL handle\n", __func__);
+ return -EINVAL;
+ }
+ msm_sdw = (struct msm_sdw_priv *)handle;
mutex_lock(&msm_sdw->sdw_clk_lock);
@@ -1934,6 +1940,7 @@ static void msm_sdw_add_child_devices(struct work_struct *work)
msm_sdw->nr = ctrl_num;
msm_sdw->sdw_ctrl_data = sdw_ctrl_data;
}
+ msm_sdw->pdev_child_devices[msm_sdw->child_count++] = pdev;
}
return;
@@ -2050,15 +2057,21 @@ err_sdw_cdc:
static int msm_sdw_remove(struct platform_device *pdev)
{
struct msm_sdw_priv *msm_sdw;
+ int count;
msm_sdw = dev_get_drvdata(&pdev->dev);
+ for (count = 0; count < msm_sdw->child_count &&
+ count < MSM_SDW_CHILD_DEVICES_MAX; count++)
+ platform_device_unregister(msm_sdw->pdev_child_devices[count]);
+
mutex_destroy(&msm_sdw->io_lock);
mutex_destroy(&msm_sdw->sdw_read_lock);
mutex_destroy(&msm_sdw->sdw_write_lock);
mutex_destroy(&msm_sdw->sdw_clk_lock);
mutex_destroy(&msm_sdw->codec_mutex);
mutex_destroy(&msm_sdw->cdc_int_mclk1_mutex);
+
devm_kfree(&pdev->dev, msm_sdw);
snd_soc_unregister_codec(&pdev->dev);
return 0;
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
index 9121baf0..64b99561 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -4396,7 +4396,7 @@ static int msm_anlg_cdc_init_supplies(struct sdm660_cdc_priv *sdm660_cdc,
return ret;
err_supplies:
- kfree(sdm660_cdc->supplies);
+ devm_kfree(sdm660_cdc->dev, sdm660_cdc->supplies);
err:
return ret;
}
@@ -4442,9 +4442,6 @@ static void msm_anlg_cdc_disable_supplies(struct sdm660_cdc_priv *sdm660_cdc,
pdata->regulator[i].max_uv);
regulator_set_load(sdm660_cdc->supplies[i].consumer, 0);
}
- regulator_bulk_free(sdm660_cdc->num_of_supplies,
- sdm660_cdc->supplies);
- kfree(sdm660_cdc->supplies);
}
static const struct of_device_id sdm660_codec_of_match[] = {
@@ -4531,6 +4528,7 @@ static void msm_anlg_add_child_devices(struct work_struct *work)
__func__);
pdata->dig_ctrl_data = dig_ctrl_data;
}
+ pdata->pdev_child_devices[pdata->child_count++] = pdev;
}
return;
@@ -4639,9 +4637,16 @@ static int msm_anlg_cdc_remove(struct platform_device *pdev)
{
struct sdm660_cdc_priv *sdm660_cdc = dev_get_drvdata(&pdev->dev);
struct sdm660_cdc_pdata *pdata = sdm660_cdc->dev->platform_data;
+ int count;
+ for (count = 0; count < sdm660_cdc->child_count &&
+ count < ANLG_CDC_CHILD_DEVICES_MAX; count++)
+ platform_device_unregister(
+ sdm660_cdc->pdev_child_devices[count]);
snd_soc_unregister_codec(&pdev->dev);
msm_anlg_cdc_disable_supplies(sdm660_cdc, pdata);
+ wcd9xxx_spmi_irq_exit();
+ devm_kfree(&pdev->dev, sdm660_cdc);
return 0;
}
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.h b/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
index 3ee3dee7..71d555f3 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -21,6 +21,7 @@
#define MICBIAS_EXT_BYP_CAP 0x00
#define MICBIAS_NO_EXT_BYP_CAP 0x01
+#define ANLG_CDC_CHILD_DEVICES_MAX 1
#define MSM89XX_NUM_IRQ_REGS 2
#define MAX_REGULATOR 7
@@ -215,6 +216,9 @@ struct sdm660_cdc_priv {
/* Entry for version info */
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
+ struct platform_device *pdev_child_devices
+ [ANLG_CDC_CHILD_DEVICES_MAX];
+ int child_count;
};
struct sdm660_cdc_pdata {
diff --git a/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.c b/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.c
index ee4ec34f..673b738b 100644
--- a/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.c
+++ b/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -409,5 +409,10 @@ int wcd9xxx_spmi_irq_init(void)
return 0;
}
+void wcd9xxx_spmi_irq_exit(void)
+{
+ pm_qos_remove_request(&map.pm_qos_req);
+ mutex_destroy(&map.pm_lock);
+}
MODULE_DESCRIPTION("MSM8x16 SPMI IRQ driver");
MODULE_LICENSE("GPL v2");
diff --git a/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.h b/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.h
index d0f48d0c..0b9b56e1 100644
--- a/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.h
+++ b/asoc/codecs/sdm660_cdc/sdm660-cdc-irq.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -26,6 +26,7 @@ extern int wcd9xxx_spmi_free_irq(int irq, void *priv);
extern void wcd9xxx_spmi_set_codec(struct snd_soc_codec *codec);
extern void wcd9xxx_spmi_set_dev(struct platform_device *spmi, int i);
extern int wcd9xxx_spmi_irq_init(void);
+extern void wcd9xxx_spmi_irq_exit(void);
extern int wcd9xxx_spmi_suspend(pm_message_t pmesg);
extern int wcd9xxx_spmi_resume(void);
bool wcd9xxx_spmi_lock_sleep(void);
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index bec7fcfb..d0df70c5 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -8978,6 +8978,7 @@ fail:
void msm_dai_q6_exit(void)
{
+ platform_driver_unregister(&msm_dai_tdm_q6);
platform_driver_unregister(&msm_dai_q6_tdm_driver);
platform_driver_unregister(&msm_dai_q6_spdif_driver);
platform_driver_unregister(&msm_dai_mi2s_q6);
diff --git a/dsp/audio_slimslave.c b/dsp/audio_slimslave.c
index 25866d12..55982f33 100644
--- a/dsp/audio_slimslave.c
+++ b/dsp/audio_slimslave.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2017-2018 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
@@ -167,7 +167,7 @@ int __init audio_slimslave_init(void)
void audio_slimslave_exit(void)
{
-
+ slim_driver_unregister(&audio_slimslave_driver);
}
/* Module information */
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index dc900edb..f8aef943 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -1440,10 +1440,68 @@ int adm_get_multi_ch_map(char *channel_map, int path)
}
EXPORT_SYMBOL(adm_get_multi_ch_map);
+static void adm_reset_data(void)
+{
+ int i, j;
+
+ apr_reset(this_adm.apr);
+ for (i = 0; i < AFE_MAX_PORTS; i++) {
+ for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
+ atomic_set(&this_adm.copp.id[i][j],
+ RESET_COPP_ID);
+ atomic_set(&this_adm.copp.cnt[i][j], 0);
+ atomic_set(
+ &this_adm.copp.topology[i][j], 0);
+ atomic_set(&this_adm.copp.mode[i][j],
+ 0);
+ atomic_set(&this_adm.copp.stat[i][j],
+ 0);
+ atomic_set(&this_adm.copp.rate[i][j],
+ 0);
+ atomic_set(
+ &this_adm.copp.channels[i][j],
+ 0);
+ atomic_set(
+ &this_adm.copp.bit_width[i][j], 0);
+ atomic_set(
+ &this_adm.copp.app_type[i][j], 0);
+ atomic_set(
+ &this_adm.copp.acdb_id[i][j], 0);
+ this_adm.copp.adm_status[i][j] =
+ ADM_STATUS_CALIBRATION_REQUIRED;
+ }
+ }
+ this_adm.apr = NULL;
+ cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
+ this_adm.cal_data);
+ mutex_lock(&this_adm.cal_data
+ [ADM_CUSTOM_TOP_CAL]->lock);
+ this_adm.set_custom_topology = 1;
+ mutex_unlock(&this_adm.cal_data[
+ ADM_CUSTOM_TOP_CAL]->lock);
+ rtac_clear_mapping(ADM_RTAC_CAL);
+ /*
+ * Free the ION memory and clear the map handles
+ * for Source Tracking
+ */
+ if (this_adm.sourceTrackingData.memmap.paddr != 0) {
+ msm_audio_ion_free(
+ this_adm.sourceTrackingData.dma_buf);
+ this_adm.sourceTrackingData.dma_buf = NULL;
+ this_adm.sourceTrackingData.memmap.size = 0;
+ this_adm.sourceTrackingData.memmap.kvaddr =
+ NULL;
+ this_adm.sourceTrackingData.memmap.paddr = 0;
+ this_adm.sourceTrackingData.apr_cmd_status = -1;
+ atomic_set(&this_adm.mem_map_handles[
+ ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
+ }
+}
+
static int32_t adm_callback(struct apr_client_data *data, void *priv)
{
uint32_t *payload;
- int i, j, port_idx, copp_idx, idx, client_id;
+ int i, port_idx, copp_idx, idx, client_id;
if (data == NULL) {
pr_err("%s: data parameter is null\n", __func__);
@@ -1456,60 +1514,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
pr_debug("%s: Reset event is received: %d %d apr[%pK]\n",
__func__,
data->reset_event, data->reset_proc, this_adm.apr);
- if (this_adm.apr) {
- apr_reset(this_adm.apr);
- for (i = 0; i < AFE_MAX_PORTS; i++) {
- for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
- atomic_set(&this_adm.copp.id[i][j],
- RESET_COPP_ID);
- atomic_set(&this_adm.copp.cnt[i][j], 0);
- atomic_set(
- &this_adm.copp.topology[i][j], 0);
- atomic_set(&this_adm.copp.mode[i][j],
- 0);
- atomic_set(&this_adm.copp.stat[i][j],
- 0);
- atomic_set(&this_adm.copp.rate[i][j],
- 0);
- atomic_set(
- &this_adm.copp.channels[i][j],
- 0);
- atomic_set(
- &this_adm.copp.bit_width[i][j], 0);
- atomic_set(
- &this_adm.copp.app_type[i][j], 0);
- atomic_set(
- &this_adm.copp.acdb_id[i][j], 0);
- this_adm.copp.adm_status[i][j] =
- ADM_STATUS_CALIBRATION_REQUIRED;
- }
- }
- this_adm.apr = NULL;
- cal_utils_clear_cal_block_q6maps(ADM_MAX_CAL_TYPES,
- this_adm.cal_data);
- mutex_lock(&this_adm.cal_data
- [ADM_CUSTOM_TOP_CAL]->lock);
- this_adm.set_custom_topology = 1;
- mutex_unlock(&this_adm.cal_data[
- ADM_CUSTOM_TOP_CAL]->lock);
- rtac_clear_mapping(ADM_RTAC_CAL);
- /*
- * Free the ION memory and clear the map handles
- * for Source Tracking
- */
- if (this_adm.sourceTrackingData.memmap.paddr != 0) {
- msm_audio_ion_free(
- this_adm.sourceTrackingData.dma_buf);
- this_adm.sourceTrackingData.dma_buf = NULL;
- this_adm.sourceTrackingData.memmap.size = 0;
- this_adm.sourceTrackingData.memmap.kvaddr =
- NULL;
- this_adm.sourceTrackingData.memmap.paddr = 0;
- this_adm.sourceTrackingData.apr_cmd_status = -1;
- atomic_set(&this_adm.mem_map_handles[
- ADM_MEM_MAP_INDEX_SOURCE_TRACKING], 0);
- }
- }
+ if (this_adm.apr)
+ adm_reset_data();
return 0;
}
@@ -5256,6 +5262,8 @@ int __init adm_init(void)
void adm_exit(void)
{
+ if (this_adm.apr)
+ adm_reset_data();
mutex_destroy(&dts_srs_lock);
adm_delete_cal_data();
}
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index f926efbd..60e8e27b 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -7636,6 +7636,12 @@ int __init afe_init(void)
void afe_exit(void)
{
+ if (this_afe.apr) {
+ apr_reset(this_afe.apr);
+ atomic_set(&this_afe.state, 0);
+ this_afe.apr = NULL;
+ rtac_set_afe_handle(this_afe.apr);
+ }
afe_delete_cal_data();
config_debug_fs_exit();
diff --git a/soc/swr-wcd-ctrl.c b/soc/swr-wcd-ctrl.c
index dc1f7866..c2edb7a6 100644
--- a/soc/swr-wcd-ctrl.c
+++ b/soc/swr-wcd-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -1538,8 +1538,9 @@ static int swrm_remove(struct platform_device *pdev)
{
struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
- swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
- swrm, SWR_IRQ_FREE);
+ if (swrm->reg_irq)
+ swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
+ swrm, SWR_IRQ_FREE);
if (swrm->mstr_port) {
kfree(swrm->mstr_port->port);
swrm->mstr_port->port = NULL;