summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2019-08-16 01:03:14 -0400
committerMark Brown <broonie@kernel.org>2019-08-16 08:12:03 -0400
commit8661ab5b23d6d30d8687fc05bc1dba8f9a64b444 (patch)
treef03d9a32aff3fff720dbb47f2262cfd2f1903268
parent554b75bde64bcad9662530726d1483f7ef012069 (diff)
ASoC: imx-audmux: Add driver suspend and resume to support MEGA Fast
For i.MX6 SoloX, there is a mode of the SoC to shutdown all power source of modules during system suspend and resume procedure. Thus, AUDMUX needs to save all the values of registers before the system suspend and restore them after the system resume. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Link: https://lore.kernel.org/r/1565931794-7218-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/fsl/imx-audmux.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index b2351cd33b0f..16ede3b5cb32 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -23,6 +23,8 @@
23 23
24static struct clk *audmux_clk; 24static struct clk *audmux_clk;
25static void __iomem *audmux_base; 25static void __iomem *audmux_base;
26static u32 *regcache;
27static u32 reg_max;
26 28
27#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8) 29#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8)
28#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) 30#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
@@ -317,8 +319,23 @@ static int imx_audmux_probe(struct platform_device *pdev)
317 if (of_id) 319 if (of_id)
318 pdev->id_entry = of_id->data; 320 pdev->id_entry = of_id->data;
319 audmux_type = pdev->id_entry->driver_data; 321 audmux_type = pdev->id_entry->driver_data;
320 if (audmux_type == IMX31_AUDMUX) 322
323 switch (audmux_type) {
324 case IMX31_AUDMUX:
321 audmux_debugfs_init(); 325 audmux_debugfs_init();
326 reg_max = 14;
327 break;
328 case IMX21_AUDMUX:
329 reg_max = 6;
330 break;
331 default:
332 dev_err(&pdev->dev, "unsupported version!\n");
333 return -EINVAL;
334 }
335
336 regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL);
337 if (!regcache)
338 return -ENOMEM;
322 339
323 if (of_id) 340 if (of_id)
324 imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node); 341 imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
@@ -334,12 +351,47 @@ static int imx_audmux_remove(struct platform_device *pdev)
334 return 0; 351 return 0;
335} 352}
336 353
354#ifdef CONFIG_PM_SLEEP
355static int imx_audmux_suspend(struct device *dev)
356{
357 int i;
358
359 clk_prepare_enable(audmux_clk);
360
361 for (i = 0; i < reg_max; i++)
362 regcache[i] = readl(audmux_base + i * 4);
363
364 clk_disable_unprepare(audmux_clk);
365
366 return 0;
367}
368
369static int imx_audmux_resume(struct device *dev)
370{
371 int i;
372
373 clk_prepare_enable(audmux_clk);
374
375 for (i = 0; i < reg_max; i++)
376 writel(regcache[i], audmux_base + i * 4);
377
378 clk_disable_unprepare(audmux_clk);
379
380 return 0;
381}
382#endif /* CONFIG_PM_SLEEP */
383
384static const struct dev_pm_ops imx_audmux_pm = {
385 SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume)
386};
387
337static struct platform_driver imx_audmux_driver = { 388static struct platform_driver imx_audmux_driver = {
338 .probe = imx_audmux_probe, 389 .probe = imx_audmux_probe,
339 .remove = imx_audmux_remove, 390 .remove = imx_audmux_remove,
340 .id_table = imx_audmux_ids, 391 .id_table = imx_audmux_ids,
341 .driver = { 392 .driver = {
342 .name = DRIVER_NAME, 393 .name = DRIVER_NAME,
394 .pm = &imx_audmux_pm,
343 .of_match_table = imx_audmux_dt_ids, 395 .of_match_table = imx_audmux_dt_ids,
344 } 396 }
345}; 397};