brintos

brintos / linux-shallow public Read only

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