ASoC: tegra-alt: Avoid reg access after shutdown

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
(cherry picked from commit 3361e95850563f3009a428bb1c01941ed069a7b0)
Reviewed-on: http://git-master/r/1492664
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Dipesh Gandhi <dipeshg@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
This commit is contained in:
Mohan Kumar
2017-05-04 12:15:02 +05:30
committed by Sameer Pujar
parent 6b67bfa9a0
commit 50217466ed
12 changed files with 161 additions and 32 deletions

View File

@@ -258,7 +258,8 @@ static int tegra_admaif_runtime_resume(struct device *dev)
} }
regcache_cache_only(admaif->regmap, false); regcache_cache_only(admaif->regmap, false);
regcache_sync(admaif->regmap); if (!admaif->is_shutdown)
regcache_sync(admaif->regmap);
return 0; return 0;
} }
@@ -319,6 +320,11 @@ static int tegra_admaif_prepare(struct snd_pcm_substream *substream,
static int tegra_admaif_startup(struct snd_pcm_substream *substream, static int tegra_admaif_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
if (admaif->is_shutdown)
return -ENODEV;
return 0; return 0;
} }
@@ -1048,6 +1054,7 @@ static int tegra_admaif_probe(struct platform_device *pdev)
admaif->refcnt = 0; admaif->refcnt = 0;
admaif->soc_data = (struct tegra_admaif_soc_data *)match->data; admaif->soc_data = (struct tegra_admaif_soc_data *)match->data;
admaif->is_shutdown = false;
admaif->capture_dma_data = devm_kzalloc(&pdev->dev, admaif->capture_dma_data = devm_kzalloc(&pdev->dev,
sizeof(struct tegra_alt_pcm_dma_params) * sizeof(struct tegra_alt_pcm_dma_params) *
@@ -1230,6 +1237,13 @@ err:
return ret; return ret;
} }
static void tegra_admaif_platform_shutdown(struct platform_device *pdev)
{
struct tegra_admaif *admaif = dev_get_drvdata(&pdev->dev);
admaif->is_shutdown = true;
}
static int tegra_admaif_remove(struct platform_device *pdev) static int tegra_admaif_remove(struct platform_device *pdev)
{ {
struct tegra_admaif *admaif = dev_get_drvdata(&pdev->dev); struct tegra_admaif *admaif = dev_get_drvdata(&pdev->dev);
@@ -1259,6 +1273,7 @@ static const struct dev_pm_ops tegra_admaif_pm_ops = {
static struct platform_driver tegra_admaif_driver = { static struct platform_driver tegra_admaif_driver = {
.probe = tegra_admaif_probe, .probe = tegra_admaif_probe,
.remove = tegra_admaif_remove, .remove = tegra_admaif_remove,
.shutdown = tegra_admaif_platform_shutdown,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_adx_alt.c - Tegra210 ADX driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(adx->regmap, false);
regcache_sync(adx->regmap);
/* update the map ram */ if (!adx->is_shutdown) {
tegra210_adx_update_map_ram(adx); regcache_sync(adx->regmap);
tegra210_adx_set_in_byte_mask(adx);
/* update the map ram */
tegra210_adx_update_map_ram(adx);
tegra210_adx_set_in_byte_mask(adx);
}
return 0; return 0;
} }
@@ -645,6 +648,7 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
} }
adx->soc_data = soc_data; adx->soc_data = soc_data;
adx->is_shutdown = false;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {
@@ -714,6 +718,13 @@ err:
return ret; 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) static int tegra210_adx_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -740,6 +751,7 @@ static struct platform_driver tegra210_adx_driver = {
}, },
.probe = tegra210_adx_platform_probe, .probe = tegra210_adx_platform_probe,
.remove = tegra210_adx_platform_remove, .remove = tegra210_adx_platform_remove,
.shutdown = tegra210_adx_platform_shutdown,
}; };
module_platform_driver(tegra210_adx_driver); module_platform_driver(tegra210_adx_driver);

View File

@@ -90,7 +90,9 @@ static int tegra210_afc_runtime_resume(struct device *dev)
} }
regcache_cache_only(afc->regmap, false); regcache_cache_only(afc->regmap, false);
regcache_sync(afc->regmap);
if (!afc->is_shutdown)
regcache_sync(afc->regmap);
return 0; return 0;
} }
@@ -559,6 +561,7 @@ static int tegra210_afc_platform_probe(struct platform_device *pdev)
} }
afc->soc_data = soc_data; afc->soc_data = soc_data;
afc->is_shutdown = false;
dev_set_drvdata(&pdev->dev, afc); dev_set_drvdata(&pdev->dev, afc);
@@ -631,6 +634,13 @@ err:
return ret; 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) static int tegra210_afc_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -657,6 +667,7 @@ static struct platform_driver tegra210_afc_driver = {
}, },
.probe = tegra210_afc_platform_probe, .probe = tegra210_afc_platform_probe,
.remove = tegra210_afc_platform_remove, .remove = tegra210_afc_platform_remove,
.shutdown = tegra210_afc_platform_shutdown,
}; };
module_platform_driver(tegra210_afc_driver) module_platform_driver(tegra210_afc_driver)

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_amx_alt.c - Tegra210 AMX driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(amx->regmap, false);
regcache_sync(amx->regmap);
/* update map ram */ if (!amx->is_shutdown) {
tegra210_amx_set_master_stream(amx, 0, regcache_sync(amx->regmap);
TEGRA210_AMX_WAIT_ON_ANY);
tegra210_amx_update_map_ram(amx); /* update map ram */
tegra210_amx_set_out_byte_mask(amx); 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; return 0;
} }
@@ -872,6 +875,7 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
} }
amx->soc_data = soc_data; amx->soc_data = soc_data;
amx->is_shutdown = false;
memset(amx->map, 0, sizeof(amx->map)); memset(amx->map, 0, sizeof(amx->map));
memset(amx->byte_mask, 0, sizeof(amx->byte_mask)); memset(amx->byte_mask, 0, sizeof(amx->byte_mask));
@@ -943,6 +947,13 @@ err:
return ret; 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) static int tegra210_amx_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -969,6 +980,7 @@ static struct platform_driver tegra210_amx_driver = {
}, },
.probe = tegra210_amx_platform_probe, .probe = tegra210_amx_platform_probe,
.remove = tegra210_amx_platform_remove, .remove = tegra210_amx_platform_remove,
.shutdown = tegra210_amx_platform_shutdown,
}; };
module_platform_driver(tegra210_amx_driver); module_platform_driver(tegra210_amx_driver);

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_dmic_alt.c - Tegra210 DMIC driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(dmic->regmap, false);
regcache_sync(dmic->regmap);
if (!dmic->is_shutdown)
regcache_sync(dmic->regmap);
return 0; return 0;
} }
@@ -512,6 +514,7 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
} }
dmic->soc_data = soc_data; dmic->soc_data = soc_data;
dmic->is_shutdown = false;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL); dmic->clk_dmic = devm_clk_get(&pdev->dev, NULL);
@@ -651,6 +654,13 @@ err:
return ret; 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) static int tegra210_dmic_platform_remove(struct platform_device *pdev)
{ {
struct tegra210_dmic *dmic; struct tegra210_dmic *dmic;
@@ -682,6 +692,7 @@ static struct platform_driver tegra210_dmic_driver = {
}, },
.probe = tegra210_dmic_platform_probe, .probe = tegra210_dmic_platform_probe,
.remove = tegra210_dmic_platform_remove, .remove = tegra210_dmic_platform_remove,
.shutdown = tegra210_dmic_platform_shutdown,
}; };
module_platform_driver(tegra210_dmic_driver) module_platform_driver(tegra210_dmic_driver)

View File

@@ -290,7 +290,9 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
} }
regcache_cache_only(i2s->regmap, false); regcache_cache_only(i2s->regmap, false);
regcache_sync(i2s->regmap);
if (!i2s->is_shutdown)
regcache_sync(i2s->regmap);
return 0; return 0;
} }
@@ -1027,6 +1029,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
i2s->bclk_ratio = 2; i2s->bclk_ratio = 2;
i2s->enable_cya = false; i2s->enable_cya = false;
i2s->loopback = 0; i2s->loopback = 0;
i2s->is_shutdown = false;
if (i2s->soc_data->is_soc_t210) { if (i2s->soc_data->is_soc_t210) {
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
@@ -1221,6 +1224,13 @@ err:
return ret; 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) static int tegra210_i2s_platform_remove(struct platform_device *pdev)
{ {
struct tegra210_i2s *i2s = dev_get_drvdata(&pdev->dev); struct tegra210_i2s *i2s = dev_get_drvdata(&pdev->dev);
@@ -1256,6 +1266,7 @@ static struct platform_driver tegra210_i2s_driver = {
}, },
.probe = tegra210_i2s_platform_probe, .probe = tegra210_i2s_platform_probe,
.remove = tegra210_i2s_platform_remove, .remove = tegra210_i2s_platform_remove,
.shutdown = tegra210_i2s_platform_shutdown,
}; };
module_platform_driver(tegra210_i2s_driver) module_platform_driver(tegra210_i2s_driver)

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_mixer_alt.c - Tegra210 MIXER driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(mixer->regmap, false);
regcache_sync(mixer->regmap);
if (!mixer->is_shutdown)
regcache_sync(mixer->regmap);
return 0; return 0;
} }
@@ -718,6 +720,7 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev)
} }
mixer->soc_data = soc_data; mixer->soc_data = soc_data;
mixer->is_shutdown = false;
mixer->gain_coeff[0] = 0; mixer->gain_coeff[0] = 0;
mixer->gain_coeff[1] = 0; mixer->gain_coeff[1] = 0;
mixer->gain_coeff[2] = 0; mixer->gain_coeff[2] = 0;
@@ -804,6 +807,13 @@ err:
return ret; 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) static int tegra210_mixer_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -830,6 +840,7 @@ static struct platform_driver tegra210_mixer_driver = {
}, },
.probe = tegra210_mixer_platform_probe, .probe = tegra210_mixer_platform_probe,
.remove = tegra210_mixer_platform_remove, .remove = tegra210_mixer_platform_remove,
.shutdown = tegra210_mixer_platform_shutdown,
}; };
module_platform_driver(tegra210_mixer_driver); module_platform_driver(tegra210_mixer_driver);

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_mvc_alt.c - Tegra210 MVC driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(mvc->regmap, false);
regcache_sync(mvc->regmap);
regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL, if (!mvc->is_shutdown) {
TEGRA210_MVC_CURVE_TYPE_MASK, regcache_sync(mvc->regmap);
mvc->curve_type << TEGRA210_MVC_CURVE_TYPE_SHIFT);
regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL,
TEGRA210_MVC_CURVE_TYPE_MASK,
mvc->curve_type << TEGRA210_MVC_CURVE_TYPE_SHIFT);
}
return 0; return 0;
} }
@@ -639,6 +642,7 @@ static int tegra210_mvc_platform_probe(struct platform_device *pdev)
} }
mvc->soc_data = soc_data; mvc->soc_data = soc_data;
mvc->is_shutdown = false;
mvc->poly_n1 = 16; mvc->poly_n1 = 16;
mvc->poly_n2 = 63; mvc->poly_n2 = 63;
@@ -724,6 +728,13 @@ err:
return ret; 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) static int tegra210_mvc_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -750,6 +761,7 @@ static struct platform_driver tegra210_mvc_driver = {
}, },
.probe = tegra210_mvc_platform_probe, .probe = tegra210_mvc_platform_probe,
.remove = tegra210_mvc_platform_remove, .remove = tegra210_mvc_platform_remove,
.shutdown = tegra210_mvc_platform_shutdown,
}; };
module_platform_driver(tegra210_mvc_driver) module_platform_driver(tegra210_mvc_driver)

View File

@@ -75,9 +75,12 @@ static int tegra210_ope_runtime_resume(struct device *dev)
regcache_cache_only(ope->regmap, false); regcache_cache_only(ope->regmap, false);
regcache_cache_only(ope->peq_regmap, false); regcache_cache_only(ope->peq_regmap, false);
regcache_cache_only(ope->mbdrc_regmap, false); regcache_cache_only(ope->mbdrc_regmap, false);
regcache_sync(ope->regmap);
regcache_sync(ope->peq_regmap); if (!ope->is_shutdown) {
regcache_sync(ope->mbdrc_regmap); regcache_sync(ope->regmap);
regcache_sync(ope->peq_regmap);
regcache_sync(ope->mbdrc_regmap);
}
return 0; return 0;
} }
@@ -361,6 +364,7 @@ static int tegra210_ope_platform_probe(struct platform_device *pdev)
} }
ope->soc_data = soc_data; ope->soc_data = soc_data;
ope->is_shutdown = false;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) { if (!mem) {
@@ -448,6 +452,13 @@ err:
return ret; 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) static int tegra210_ope_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -474,6 +485,7 @@ static struct platform_driver tegra210_ope_driver = {
}, },
.probe = tegra210_ope_platform_probe, .probe = tegra210_ope_platform_probe,
.remove = tegra210_ope_platform_remove, .remove = tegra210_ope_platform_remove,
.shutdown = tegra210_ope_platform_shutdown,
}; };
module_platform_driver(tegra210_ope_driver) module_platform_driver(tegra210_ope_driver)

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_sfc_alt.c - Tegra210 SFC driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(sfc->regmap, false);
regcache_sync(sfc->regmap);
if (!sfc->is_shutdown)
regcache_sync(sfc->regmap);
return 0; return 0;
} }
@@ -888,6 +890,7 @@ static int tegra210_sfc_platform_probe(struct platform_device *pdev)
} }
sfc->soc_data = soc_data; sfc->soc_data = soc_data;
sfc->is_shutdown = false;
/* initialize default output srate */ /* initialize default output srate */
sfc->srate_out = TEGRA210_SFC_FS48; sfc->srate_out = TEGRA210_SFC_FS48;
@@ -960,6 +963,13 @@ err:
return ret; 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) static int tegra210_sfc_platform_remove(struct platform_device *pdev)
{ {
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
@@ -986,6 +996,7 @@ static struct platform_driver tegra210_sfc_driver = {
}, },
.probe = tegra210_sfc_platform_probe, .probe = tegra210_sfc_platform_probe,
.remove = tegra210_sfc_platform_remove, .remove = tegra210_sfc_platform_remove,
.shutdown = tegra210_sfc_platform_shutdown,
}; };
module_platform_driver(tegra210_sfc_driver) module_platform_driver(tegra210_sfc_driver)

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_spdif_alt.c - Tegra210 SPDIF driver * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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_cache_only(spdif->regmap, false);
regcache_sync(spdif->regmap);
if (!spdif->is_shutdown)
regcache_sync(spdif->regmap);
return 0; return 0;
} }
@@ -471,6 +473,7 @@ static int tegra210_spdif_platform_probe(struct platform_device *pdev)
} }
spdif->soc_data = soc_data; spdif->soc_data = soc_data;
spdif->is_shutdown = false;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
spdif->clk_pll_a_out0 = devm_clk_get(&pdev->dev, "pll_a_out0"); spdif->clk_pll_a_out0 = devm_clk_get(&pdev->dev, "pll_a_out0");
if (IS_ERR(spdif->clk_pll_a_out0)) { if (IS_ERR(spdif->clk_pll_a_out0)) {
@@ -621,6 +624,13 @@ err:
return ret; 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) static int tegra210_spdif_platform_remove(struct platform_device *pdev)
{ {
struct tegra210_spdif *spdif = dev_get_drvdata(&pdev->dev); struct tegra210_spdif *spdif = dev_get_drvdata(&pdev->dev);
@@ -654,6 +664,7 @@ static struct platform_driver tegra210_spdif_driver = {
}, },
.probe = tegra210_spdif_platform_probe, .probe = tegra210_spdif_platform_probe,
.remove = tegra210_spdif_platform_remove, .remove = tegra210_spdif_platform_remove,
.shutdown = tegra210_spdif_platform_shutdown,
}; };
module_platform_driver(tegra210_spdif_driver); module_platform_driver(tegra210_spdif_driver);

View File

@@ -602,7 +602,6 @@ int tegra210_xbar_probe(struct platform_device *pdev)
soc_data = (struct tegra_xbar_soc_data *)match->data; soc_data = (struct tegra_xbar_soc_data *)match->data;
ret = tegra_xbar_probe(pdev, soc_data); ret = tegra_xbar_probe(pdev, soc_data);
err: err:
return ret; return ret;
} }
@@ -616,6 +615,7 @@ static const struct dev_pm_ops tegra210_xbar_pm_ops = {
static struct platform_driver tegra210_xbar_driver = { static struct platform_driver tegra210_xbar_driver = {
.probe = tegra210_xbar_probe, .probe = tegra210_xbar_probe,
.remove = tegra_xbar_remove, .remove = tegra_xbar_remove,
.shutdown = tegra_xbar_shutdown,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,