Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Power management for audio on multifunction CS5535 companion device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) Jaya Kumar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "cs5535audio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	/* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	we depend on snd_ac97_suspend to tell the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	AC97 codec to shutdown. the amd spec suggests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	that the LNK_SHUTDOWN be done at the same time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	that the codec power-down is issued. instead,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	we do it just after rather than at the same 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	time. excluding codec specific build_ops->suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	ac97 powerdown hits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	0x8000 EAPD 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	0x4000 Headphone amplifier 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	0x0300 ADC & DAC 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	0x0400 Analog Mixer powerdown (Vref on) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	I am not sure if this is the best that we can do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	The remainder to be investigated are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	- analog mixer (vref off) 0x0800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	- AC-link powerdown 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	- codec internal clock 0x2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	/* set LNK_SHUTDOWN to shutdown AC link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct cs5535audio *cs5535au = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	snd_ac97_suspend(cs5535au->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		struct cs5535audio_dma *dma = &cs5535au->dmas[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		if (dma && dma->substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			dma->saved_prd = dma->ops->read_prd(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/* save important regs, then disable aclink in hw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	snd_cs5535audio_stop_hardware(cs5535au);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static int __maybe_unused snd_cs5535audio_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	struct cs5535audio *cs5535au = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/* set LNK_WRM_RST to reset AC link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	timeout = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		if (tmp & PRM_RDY_STS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	} while (--timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		dev_err(cs5535au->card->dev, "Failure getting AC Link ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	/* set up rate regs, dma. actual initiation is done in trig */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		struct cs5535audio_dma *dma = &cs5535au->dmas[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		if (dma && dma->substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			dma->substream->ops->prepare(dma->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			dma->ops->setup_prd(cs5535au, dma->saved_prd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/* we depend on ac97 to perform the codec power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	snd_ac97_resume(cs5535au->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) SIMPLE_DEV_PM_OPS(snd_cs5535audio_pm, snd_cs5535audio_suspend, snd_cs5535audio_resume);