]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
ASoC: tegra-alt: Avoid reg access after shutdown
authorMohan Kumar <mkumard@nvidia.com>
Thu, 4 May 2017 06:45:02 +0000 (12:15 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 10 May 2017 09:32:45 +0000 (02:32 -0700)
Below are the hypothetical scenarios
- Drivers are in suspend state while reboot and PCM Open call from
  userspace is received after driver shutdown [APE is power gated
  already]
- PM domain handling doesn't ensure proper functionality after driver
  shutdown is called

The change handles with the below fix
- ALSA PCM Open API first executes runtime resume of each driver.
  So need to prevent any reg access in runtime resume of drivers.
- ALSA PCM Open executes ADMAIF startup after runtime resume of
  each driver. If ADMAIF startup returns failure based on shutdown,
  PCM Open operation will fail, this will break PCM Open path and
  will ensure no further ALSA APIs/Callbacks are called.

Bug 200289815

Change-Id: Ia03e035569375f37ae4b0faa1a4593ce121d2354
Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Reviewed-on: http://git-master/r/1475208
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sharad Gupta <sharadg@nvidia.com>
Reviewed-by: Dipesh Gandhi <dipeshg@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
24 files changed:
sound/soc/tegra-alt/tegra210_admaif_alt.c
sound/soc/tegra-alt/tegra210_admaif_alt.h
sound/soc/tegra-alt/tegra210_adx_alt.c
sound/soc/tegra-alt/tegra210_adx_alt.h
sound/soc/tegra-alt/tegra210_afc_alt.c
sound/soc/tegra-alt/tegra210_afc_alt.h
sound/soc/tegra-alt/tegra210_amx_alt.c
sound/soc/tegra-alt/tegra210_amx_alt.h
sound/soc/tegra-alt/tegra210_dmic_alt.c
sound/soc/tegra-alt/tegra210_dmic_alt.h
sound/soc/tegra-alt/tegra210_i2s_alt.c
sound/soc/tegra-alt/tegra210_i2s_alt.h
sound/soc/tegra-alt/tegra210_mixer_alt.c
sound/soc/tegra-alt/tegra210_mixer_alt.h
sound/soc/tegra-alt/tegra210_mvc_alt.c
sound/soc/tegra-alt/tegra210_mvc_alt.h
sound/soc/tegra-alt/tegra210_ope_alt.c
sound/soc/tegra-alt/tegra210_ope_alt.h
sound/soc/tegra-alt/tegra210_sfc_alt.c
sound/soc/tegra-alt/tegra210_sfc_alt.h
sound/soc/tegra-alt/tegra210_spdif_alt.c
sound/soc/tegra-alt/tegra210_spdif_alt.h
sound/soc/tegra-alt/tegra210_xbar_alt.c
sound/soc/tegra-alt/tegra210_xbar_alt.h

index e64f9a9d69fd2d8d344a5332056ab36f2f49812b..1741a44300f51563fcdf7f8b021e9a720d1929d1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_admaif_alt.c - Tegra ADMAIF driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -245,7 +245,8 @@ static int tegra210_admaif_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(admaif->regmap, false);
-       regcache_sync(admaif->regmap);
+       if (!admaif->is_shutdown)
+               regcache_sync(admaif->regmap);
 
        return 0;
 }
@@ -303,6 +304,11 @@ static int tegra210_admaif_prepare(struct snd_pcm_substream *substream,
 static int tegra210_admaif_startup(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
+       struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
+
+       if (admaif->is_shutdown)
+               return -ENODEV;
+
        return 0;
 }
 
@@ -948,6 +954,7 @@ static int tegra210_admaif_probe(struct platform_device *pdev)
        admaif->refcnt = 0;
 
        admaif->soc_data = soc_data;
+       admaif->is_shutdown = false;
 
        admaif->capture_dma_data = devm_kzalloc(&pdev->dev,
                        sizeof(struct tegra_alt_pcm_dma_params) *
@@ -1082,6 +1089,13 @@ err:
        return ret;
 }
 
+static void tegra210_admaif_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_admaif *admaif = dev_get_drvdata(&pdev->dev);
+
+       admaif->is_shutdown = true;
+}
+
 static int tegra210_admaif_remove(struct platform_device *pdev)
 {
        tegra_isomgr_adma_unregister();
@@ -1108,6 +1122,7 @@ static const struct dev_pm_ops tegra210_admaif_pm_ops = {
 static struct platform_driver tegra210_admaif_driver = {
        .probe = tegra210_admaif_probe,
        .remove = tegra210_admaif_remove,
+       .shutdown = tegra210_admaif_platform_shutdown,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 3fc84f4b9be11e46b5f79839cde9b69fed9cb401..56fe78db5cf78ce69b30a4fdee390cc658d7c80b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_admaif_alt.h - Tegra210 ADMAIF registers
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -159,6 +159,7 @@ struct tegra210_admaif {
        int override_channels[TEGRA210_ADMAIF_CHANNEL_COUNT];
        int tx_mono_to_stereo[TEGRA210_ADMAIF_CHANNEL_COUNT];
        int rx_stereo_to_mono[TEGRA210_ADMAIF_CHANNEL_COUNT];
+       bool is_shutdown;
 };
 
 #endif
index 83e371231197dc0a09b583e3f3d9642d29ba57d2..71e8a8e6e30f70a44c8e99a3ea1278e2df7350af 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_adx_alt.c - Tegra210 ADX driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -266,11 +266,14 @@ static int tegra210_adx_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(adx->regmap, false);
-       regcache_sync(adx->regmap);
 
-       /* update the map ram */
-       tegra210_adx_update_map_ram(adx);
-       tegra210_adx_set_in_byte_mask(adx);
+       if (!adx->is_shutdown) {
+               regcache_sync(adx->regmap);
+
+               /* update the map ram */
+               tegra210_adx_update_map_ram(adx);
+               tegra210_adx_set_in_byte_mask(adx);
+       }
 
        return 0;
 }
@@ -645,6 +648,7 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
        }
 
        adx->soc_data = soc_data;
+       adx->is_shutdown = false;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -714,6 +718,13 @@ err:
        return ret;
 }
 
+static void tegra210_adx_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_adx *adx = dev_get_drvdata(&pdev->dev);
+
+       adx->is_shutdown = true;
+}
+
 static int tegra210_adx_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -740,6 +751,7 @@ static struct platform_driver tegra210_adx_driver = {
        },
        .probe = tegra210_adx_platform_probe,
        .remove = tegra210_adx_platform_remove,
+       .shutdown = tegra210_adx_platform_shutdown,
 };
 module_platform_driver(tegra210_adx_driver);
 
index 0efebd1bfdfbcaccfcb74dcc0d6cf9d3b30e8048..efb9a3d46f3a040e7999bbbc7d44035bc66ca226 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_adx_alt.h - Definitions for Tegra210 ADX driver
  *
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -170,6 +170,7 @@ struct tegra210_adx {
        unsigned int map[16];
        unsigned int byte_mask[2];
        const struct tegra210_adx_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 #endif
index f9bac51382bd4c02128d22853d691da8cdd33662..542cf24f9d1cfe62eb314256c720e9d17a58fa8c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_afc_alt.c - Tegra210 AFC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -84,7 +84,9 @@ static int tegra210_afc_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(afc->regmap, false);
-       regcache_sync(afc->regmap);
+
+       if (!afc->is_shutdown)
+               regcache_sync(afc->regmap);
 
        return 0;
 }
@@ -393,6 +395,7 @@ static int tegra210_afc_platform_probe(struct platform_device *pdev)
        }
 
        afc->soc_data = soc_data;
+       afc->is_shutdown = false;
 
        /* initialize default destination I2S */
        afc->destination_i2s = 1;
@@ -468,6 +471,13 @@ err:
        return ret;
 }
 
+static void tegra210_afc_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_afc *afc = dev_get_drvdata(&pdev->dev);
+
+       afc->is_shutdown = true;
+}
+
 static int tegra210_afc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -494,6 +504,7 @@ static struct platform_driver tegra210_afc_driver = {
        },
        .probe = tegra210_afc_platform_probe,
        .remove = tegra210_afc_platform_remove,
+       .shutdown = tegra210_afc_platform_shutdown,
 };
 module_platform_driver(tegra210_afc_driver)
 
index 9fec7400c193f25c172aecb8ece2e1370b41d234..db333d0067d75fdba6bc894835e488199c728c70 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_afc_alt.h - Definitions for Tegra210 AFC driver
  *
- * Copyright (c) 2014-2015 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -106,6 +106,7 @@ struct tegra210_afc {
        unsigned int destination_i2s;
        struct regmap *regmap;
        const struct tegra210_afc_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 unsigned int tegra210_afc_get_sfc_id(unsigned int afc_id);
index eaf14b38ad68ce04c4d6cbca213c359909c4eb6e..bb6868423be38ffbe56f375ea182ec3586ff3168 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_amx_alt.c - Tegra210 AMX driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -291,13 +291,16 @@ static int tegra210_amx_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(amx->regmap, false);
-       regcache_sync(amx->regmap);
 
-       /* update map ram */
-       tegra210_amx_set_master_stream(amx, 0,
-                       TEGRA210_AMX_WAIT_ON_ANY);
-       tegra210_amx_update_map_ram(amx);
-       tegra210_amx_set_out_byte_mask(amx);
+       if (!amx->is_shutdown) {
+               regcache_sync(amx->regmap);
+
+               /* update map ram */
+               tegra210_amx_set_master_stream(amx, 0,
+                               TEGRA210_AMX_WAIT_ON_ANY);
+               tegra210_amx_update_map_ram(amx);
+               tegra210_amx_set_out_byte_mask(amx);
+       }
 
        return 0;
 }
@@ -872,6 +875,7 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
        }
 
        amx->soc_data = soc_data;
+       amx->is_shutdown = false;
        memset(amx->map, 0, sizeof(amx->map));
        memset(amx->byte_mask, 0, sizeof(amx->byte_mask));
 
@@ -943,6 +947,13 @@ err:
        return ret;
 }
 
+static void tegra210_amx_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_amx *amx = dev_get_drvdata(&pdev->dev);
+
+       amx->is_shutdown = true;
+}
+
 static int tegra210_amx_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -969,6 +980,7 @@ static struct platform_driver tegra210_amx_driver = {
        },
        .probe = tegra210_amx_platform_probe,
        .remove = tegra210_amx_platform_remove,
+       .shutdown = tegra210_amx_platform_shutdown,
 };
 module_platform_driver(tegra210_amx_driver);
 
index 5669c7a01f819183b20852007dd5bbff228442cf..f0fd50bbd0350ac35d30fc960e9f4b878d2d54b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_amx_alt.h - Definitions for Tegra210 AMX driver
  *
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -186,6 +186,7 @@ struct tegra210_amx {
        int input_channels[TEGRA210_AMX_NUM_INPUTS];
        int output_channels;
        const struct tegra210_amx_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 #endif
index f733d12649d98e785f10d00a9561da1f40cc0f01..3dfd28607a82e65aeb2b19b11622f9375cc3a182 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_dmic_alt.c - Tegra210 DMIC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -123,7 +123,9 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(dmic->regmap, false);
-       regcache_sync(dmic->regmap);
+
+       if (!dmic->is_shutdown)
+               regcache_sync(dmic->regmap);
 
        return 0;
 }
@@ -512,6 +514,7 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
        }
 
        dmic->soc_data = soc_data;
+       dmic->is_shutdown = false;
 
        if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
                dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL);
@@ -654,6 +657,13 @@ err:
        return ret;
 }
 
+static void tegra210_dmic_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_dmic *dmic = dev_get_drvdata(&pdev->dev);
+
+       dmic->is_shutdown = true;
+}
+
 static int tegra210_dmic_platform_remove(struct platform_device *pdev)
 {
        struct tegra210_dmic *dmic;
@@ -685,6 +695,7 @@ static struct platform_driver tegra210_dmic_driver = {
        },
        .probe = tegra210_dmic_platform_probe,
        .remove = tegra210_dmic_platform_remove,
+       .shutdown = tegra210_dmic_platform_shutdown,
 };
 module_platform_driver(tegra210_dmic_driver)
 
index ad0bf4f58b9d9273b40d2710c4a55a1a6c888444..72eb9d8df8acb8c9e91b3f14cbc41399e310a6ba 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_dmic_alt.h - Definitions for Tegra210 DMIC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -132,6 +132,7 @@ struct tegra210_dmic {
        int boost_gain; /* with 100x factor */
        int ch_select;
        int tx_mono_to_stereo;
+       bool is_shutdown;
 };
 
 #endif
index 3b6ac0cd02b051198784680ca7e80b09bbfce8bc..cc8a1fbcc04f95c54283924a35cdabc4974dd564 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_i2s.c - Tegra210 I2S driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -292,7 +292,9 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(i2s->regmap, false);
-       regcache_sync(i2s->regmap);
+
+       if (!i2s->is_shutdown)
+               regcache_sync(i2s->regmap);
 
        return 0;
 }
@@ -1009,6 +1011,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
        i2s->bclk_ratio = 2;
        i2s->enable_cya = false;
        i2s->loopback = 0;
+       i2s->is_shutdown = false;
 
        if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
                i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
@@ -1202,6 +1205,13 @@ err:
        return ret;
 }
 
+static void tegra210_i2s_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_i2s *i2s = dev_get_drvdata(&pdev->dev);
+
+       i2s->is_shutdown = true;
+}
+
 static int tegra210_i2s_platform_remove(struct platform_device *pdev)
 {
        struct tegra210_i2s *i2s = dev_get_drvdata(&pdev->dev);
@@ -1237,6 +1247,7 @@ static struct platform_driver tegra210_i2s_driver = {
        },
        .probe = tegra210_i2s_platform_probe,
        .remove = tegra210_i2s_platform_remove,
+       .shutdown = tegra210_i2s_platform_shutdown,
 };
 module_platform_driver(tegra210_i2s_driver)
 
index 026c00fa00181cfe5083829d242b85e279d63dc3..24a261e8de895c81517759abd3d1e4ee36679bda 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_i2s_alt.h - Definitions for Tegra210 I2S driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -230,6 +230,7 @@ struct tegra210_i2s {
        unsigned int rx_mask;
        unsigned int loopback;
        bool enable_cya;
+       bool is_shutdown;
 };
 
 #endif
index 291efd7f2aa321f376393f8ab3c497e5e7e5189c..7ed3d36d8f72b1008c68d63d26cc77f0c2c5ddf5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_mixer_alt.c - Tegra210 MIXER driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -99,7 +99,9 @@ static int tegra210_mixer_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(mixer->regmap, false);
-       regcache_sync(mixer->regmap);
+
+       if (!mixer->is_shutdown)
+               regcache_sync(mixer->regmap);
 
        return 0;
 }
@@ -718,6 +720,7 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev)
        }
 
        mixer->soc_data = soc_data;
+       mixer->is_shutdown = false;
        mixer->gain_coeff[0] = 0;
        mixer->gain_coeff[1] = 0;
        mixer->gain_coeff[2] = 0;
@@ -804,6 +807,13 @@ err:
        return ret;
 }
 
+static void tegra210_mixer_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_mixer *mixer = dev_get_drvdata(&pdev->dev);
+
+       mixer->is_shutdown = true;
+}
+
 static int tegra210_mixer_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -830,6 +840,7 @@ static struct platform_driver tegra210_mixer_driver = {
        },
        .probe = tegra210_mixer_platform_probe,
        .remove = tegra210_mixer_platform_remove,
+       .shutdown = tegra210_mixer_platform_shutdown,
 };
 module_platform_driver(tegra210_mixer_driver);
 
index efd5cf769c9ca32e57abd550556d728351ae6f39..d4c80d39646c5651732b2b6f0946c9f6ff9a8ddb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_mixer_alt.h - Definitions for Tegra210 MIXER driver
  *
- * Copyright (c) 2015-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2015-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -132,6 +132,7 @@ struct tegra210_mixer {
        int gain_value[TEGRA210_MIXER_AXBAR_RX_MAX];
        const struct tegra210_mixer_soc_data *soc_data;
        unsigned int channels_via_control[TEGRA210_MIXER_TOTAL_PATH];
+       bool is_shutdown;
 };
 
 #endif
index 75c891c4bb3477a4d8193921f40d43f2953b2409..176c19bf6a4ccf7f036510b7aecf6ac079963b75 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_mvc_alt.c - Tegra210 MVC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -77,11 +77,14 @@ static int tegra210_mvc_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(mvc->regmap, false);
-       regcache_sync(mvc->regmap);
 
-       regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL,
-               TEGRA210_MVC_CURVE_TYPE_MASK,
-               mvc->curve_type << TEGRA210_MVC_CURVE_TYPE_SHIFT);
+       if (!mvc->is_shutdown) {
+               regcache_sync(mvc->regmap);
+
+               regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL,
+                       TEGRA210_MVC_CURVE_TYPE_MASK,
+                       mvc->curve_type << TEGRA210_MVC_CURVE_TYPE_SHIFT);
+       }
 
        return 0;
 }
@@ -639,6 +642,7 @@ static int tegra210_mvc_platform_probe(struct platform_device *pdev)
        }
 
        mvc->soc_data = soc_data;
+       mvc->is_shutdown = false;
 
        mvc->poly_n1 = 16;
        mvc->poly_n2 = 63;
@@ -724,6 +728,13 @@ err:
        return ret;
 }
 
+static void tegra210_mvc_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_mvc *mvc = dev_get_drvdata(&pdev->dev);
+
+       mvc->is_shutdown = true;
+}
+
 static int tegra210_mvc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -750,6 +761,7 @@ static struct platform_driver tegra210_mvc_driver = {
        },
        .probe = tegra210_mvc_platform_probe,
        .remove = tegra210_mvc_platform_remove,
+       .shutdown = tegra210_mvc_platform_shutdown,
 };
 module_platform_driver(tegra210_mvc_driver)
 
index dd001cb8241e2804887024dbf67da807b5bd7dc4..1171c371947b71ff68c8770323958c1e7ad5bca1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_mvc_alt.h - Definitions for Tegra210 MVC driver
  *
- * Copyright (c) 2014-2015 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -145,6 +145,7 @@ struct tegra210_mvc {
        unsigned int cif_channels;
        unsigned int audio_bits;
        const struct tegra210_mvc_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 #endif
index 57ec66d318e6e1a766a9b3cf36bfc793db7840c9..95fbc79723c9cce5736f65f0d989a553bfaaff89 100644 (file)
@@ -75,9 +75,12 @@ static int tegra210_ope_runtime_resume(struct device *dev)
        regcache_cache_only(ope->regmap, false);
        regcache_cache_only(ope->peq_regmap, false);
        regcache_cache_only(ope->mbdrc_regmap, false);
-       regcache_sync(ope->regmap);
-       regcache_sync(ope->peq_regmap);
-       regcache_sync(ope->mbdrc_regmap);
+
+       if (!ope->is_shutdown) {
+               regcache_sync(ope->regmap);
+               regcache_sync(ope->peq_regmap);
+               regcache_sync(ope->mbdrc_regmap);
+       }
 
        return 0;
 }
@@ -361,6 +364,7 @@ static int tegra210_ope_platform_probe(struct platform_device *pdev)
        }
 
        ope->soc_data = soc_data;
+       ope->is_shutdown = false;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -448,6 +452,13 @@ err:
        return ret;
 }
 
+static void tegra210_ope_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_ope *ope = dev_get_drvdata(&pdev->dev);
+
+       ope->is_shutdown = true;
+}
+
 static int tegra210_ope_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -474,6 +485,7 @@ static struct platform_driver tegra210_ope_driver = {
        },
        .probe = tegra210_ope_platform_probe,
        .remove = tegra210_ope_platform_remove,
+       .shutdown = tegra210_ope_platform_shutdown,
 };
 module_platform_driver(tegra210_ope_driver)
 
index dc24d1959d8ca7dd3597b8eacc0853b35b9519b8..07d7a652b6b18232f712b7d8ada297c6aa8420a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_ope_alt.h - Definitions for Tegra210 OPE driver
  *
- * Copyright (c) 2014 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -86,6 +86,7 @@ struct tegra210_ope {
        struct regmap *peq_regmap;
        struct regmap *mbdrc_regmap;
        const struct tegra210_ope_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 extern int tegra210_peq_init(struct platform_device *pdev, int id);
index 4fb448a80e6495e34cb03e1169d37218992f8325..31cf971c770b5143557895256cdbb712f80942d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_sfc_alt.c - Tegra210 SFC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -86,7 +86,9 @@ static int tegra210_sfc_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(sfc->regmap, false);
-       regcache_sync(sfc->regmap);
+
+       if (!sfc->is_shutdown)
+               regcache_sync(sfc->regmap);
 
        return 0;
 }
@@ -888,6 +890,7 @@ static int tegra210_sfc_platform_probe(struct platform_device *pdev)
        }
 
        sfc->soc_data = soc_data;
+       sfc->is_shutdown = false;
 
        /* initialize default output srate */
        sfc->srate_out = TEGRA210_SFC_FS48;
@@ -960,6 +963,13 @@ err:
        return ret;
 }
 
+static void tegra210_sfc_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_sfc *sfc = dev_get_drvdata(&pdev->dev);
+
+       sfc->is_shutdown = true;
+}
+
 static int tegra210_sfc_platform_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -986,6 +996,7 @@ static struct platform_driver tegra210_sfc_driver = {
        },
        .probe = tegra210_sfc_platform_probe,
        .remove = tegra210_sfc_platform_remove,
+       .shutdown = tegra210_sfc_platform_shutdown,
 };
 module_platform_driver(tegra210_sfc_driver)
 
index f8f6de5719f5db5ce328851aa4d6f366976664e1..818777c6f7b1dd07ef5e66af3d3fc0826f60c8b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_sfc_alt.h - Definitions for Tegra210 SFC driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -110,6 +110,7 @@ struct tegra210_sfc {
        int mono_conv_output;
        const struct tegra210_sfc_soc_data *soc_data;
        unsigned int channels_via_control;
+       bool is_shutdown;
 };
 
 /* coeff RAM tables required for SFC */
index 2324d64e1864e14e587d34bd621b9a2cf89c9198..1006e12941486ffbb51b4a0500f9c21baf3592bf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_spdif_alt.c - Tegra210 SPDIF driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -116,7 +116,9 @@ static int tegra210_spdif_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(spdif->regmap, false);
-       regcache_sync(spdif->regmap);
+
+       if (!spdif->is_shutdown)
+               regcache_sync(spdif->regmap);
 
        return 0;
 }
@@ -473,6 +475,7 @@ static int tegra210_spdif_platform_probe(struct platform_device *pdev)
        }
 
        spdif->soc_data = soc_data;
+       spdif->is_shutdown = false;
        if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
                spdif->clk_pll_a_out0 = devm_clk_get(&pdev->dev, "pll_a_out0");
@@ -626,6 +629,13 @@ err:
        return ret;
 }
 
+static void tegra210_spdif_platform_shutdown(struct platform_device *pdev)
+{
+       struct tegra210_spdif *spdif = dev_get_drvdata(&pdev->dev);
+
+       spdif->is_shutdown = true;
+}
+
 static int tegra210_spdif_platform_remove(struct platform_device *pdev)
 {
        struct tegra210_spdif *spdif = dev_get_drvdata(&pdev->dev);
@@ -659,6 +669,7 @@ static struct platform_driver tegra210_spdif_driver = {
        },
        .probe = tegra210_spdif_platform_probe,
        .remove = tegra210_spdif_platform_remove,
+       .shutdown = tegra210_spdif_platform_shutdown,
 };
 module_platform_driver(tegra210_spdif_driver);
 
index 2bc897630492e99a5e52ca065605a5e4741207a9..970af7dd5f4801dad24dc52de37c74ffd00d3256 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_spdif.h - Definitions for Tegra210 SPDIF driver
  *
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -263,6 +263,7 @@ struct tegra210_spdif {
        struct pinctrl *pinctrl;
        struct pinctrl_state *pin_active_state;
        struct pinctrl_state *pin_idle_state;
+       bool is_shutdown;
 };
 
 #endif
index 31457beccaee6a2667e660dd62687a0e28338d21..e3269e958eda59f95ebc92e27389bdceacea6f00 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_xbar_alt.c - Tegra210 XBAR driver
  *
- * Copyright (c) 2014-2016 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2017 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -94,7 +94,9 @@ static int tegra210_xbar_runtime_resume(struct device *dev)
        }
 
        regcache_cache_only(xbar->regmap, false);
-       regcache_sync(xbar->regmap);
+
+       if (!xbar->is_shutdown)
+               regcache_sync(xbar->regmap);
 
        return 0;
 }
@@ -881,6 +883,7 @@ static int tegra210_xbar_probe(struct platform_device *pdev)
        }
 
        xbar->soc_data = soc_data;
+       xbar->is_shutdown = false;
 
        if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
                xbar->clk = devm_clk_get(&pdev->dev, "ahub");
@@ -990,6 +993,11 @@ err:
        return ret;
 }
 
+static void tegra210_xbar_shutdown(struct platform_device *pdev)
+{
+       xbar->is_shutdown = true;
+}
+
 static int tegra210_xbar_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
@@ -1017,6 +1025,7 @@ static const struct dev_pm_ops tegra210_xbar_pm_ops = {
 static struct platform_driver tegra210_xbar_driver = {
        .probe = tegra210_xbar_probe,
        .remove = tegra210_xbar_remove,
+       .shutdown = tegra210_xbar_shutdown,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 0641f037befcf930ee8debecbcab59277fdc1bcb..3dbe31ed26617647d8b109a1c3cc07094812dd50 100644 (file)
@@ -223,6 +223,7 @@ struct tegra210_xbar {
        struct clk *clk_apb2ape;
        struct regmap *regmap;
        const struct tegra210_xbar_soc_data *soc_data;
+       bool is_shutdown;
 };
 
 /* Extension of soc_bytes structure defined in sound/soc.h */