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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // Copyright (c) 2020 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) // Author: Jerome Brunet <jbrunet@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define BLOCK_EN	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define  LORN_EN	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define  LORP_EN	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define  LOLN_EN	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define  LOLP_EN	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define  DACR_EN	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define  DACL_EN	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define  DACR_INV	20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define  DACL_INV	21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define  DACR_SRC	22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define  DACL_SRC	23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define  REFP_BUF_EN	BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define  BIAS_CURRENT_EN BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define  VMID_GEN_FAST	BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define  VMID_GEN_EN	BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define  I2S_MODE	BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define VOL_CTRL0	0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define  GAIN_H		31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define  GAIN_L		23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define VOL_CTRL1	0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define  DAC_MONO	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define  RAMP_RATE	10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define  VC_RAMP_MODE	12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define  MUTE_MODE	13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define  UNMUTE_MODE	14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define  DAC_SOFT_MUTE	15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define  DACR_VC	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define  DACL_VC	24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define LINEOUT_CFG	0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define  LORN_POL	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define  LORP_POL	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define  LOLN_POL	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define  LOLP_POL	12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define POWER_CFG	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct t9015 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	struct clk *pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct regulator *avdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static int t9015_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct snd_soc_component *component = dai->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	case SND_SOC_DAIFMT_CBM_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		val = I2S_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	case SND_SOC_DAIFMT_CBS_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	snd_soc_component_update_bits(component, BLOCK_EN, I2S_MODE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	    ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_LEFT_J))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static const struct snd_soc_dai_ops t9015_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	.set_fmt = t9015_dai_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static struct snd_soc_dai_driver t9015_dai = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	.name = "t9015-hifi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	.playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		.stream_name = "Playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		.channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		.channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		.rates = SNDRV_PCM_RATE_8000_96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		.formats = (SNDRV_PCM_FMTBIT_S8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			    SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			    SNDRV_PCM_FMTBIT_S20_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			    SNDRV_PCM_FMTBIT_S24_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	.ops = &t9015_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -9525, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const char * const ramp_rate_txt[] = { "Fast", "Slow" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static SOC_ENUM_SINGLE_DECL(ramp_rate_enum, VOL_CTRL1, RAMP_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			    ramp_rate_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const char * const dacr_in_txt[] = { "Right", "Left" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static SOC_ENUM_SINGLE_DECL(dacr_in_enum, BLOCK_EN, DACR_SRC, dacr_in_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const char * const dacl_in_txt[] = { "Left", "Right" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static SOC_ENUM_SINGLE_DECL(dacl_in_enum, BLOCK_EN, DACL_SRC, dacl_in_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static const char * const mono_txt[] = { "Stereo", "Mono"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static SOC_ENUM_SINGLE_DECL(mono_enum, VOL_CTRL1, DAC_MONO, mono_txt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static const struct snd_kcontrol_new t9015_snd_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	/* Volume Controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	SOC_ENUM("Playback Channel Mode", mono_enum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	SOC_SINGLE("Playback Switch", VOL_CTRL1, DAC_SOFT_MUTE, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	SOC_DOUBLE_TLV("Playback Volume", VOL_CTRL1, DACL_VC, DACR_VC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		       0xff, 0, dac_vol_tlv),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	/* Ramp Controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	SOC_ENUM("Ramp Rate", ramp_rate_enum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	SOC_SINGLE("Volume Ramp Switch", VOL_CTRL1, VC_RAMP_MODE, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	SOC_SINGLE("Mute Ramp Switch", VOL_CTRL1, MUTE_MODE, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	SOC_SINGLE("Unmute Ramp Switch", VOL_CTRL1, UNMUTE_MODE, 1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static const struct snd_kcontrol_new t9015_right_dac_mux =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	SOC_DAPM_ENUM("Right DAC Source", dacr_in_enum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const struct snd_kcontrol_new t9015_left_dac_mux =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	SOC_DAPM_ENUM("Left DAC Source", dacl_in_enum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static const struct snd_soc_dapm_widget t9015_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	SND_SOC_DAPM_AIF_IN("Right IN", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	SND_SOC_DAPM_AIF_IN("Left IN", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	SND_SOC_DAPM_MUX("Right DAC Sel", SND_SOC_NOPM, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			 &t9015_right_dac_mux),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	SND_SOC_DAPM_MUX("Left DAC Sel", SND_SOC_NOPM, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			 &t9015_left_dac_mux),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	SND_SOC_DAPM_DAC("Right DAC", NULL, BLOCK_EN, DACR_EN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	SND_SOC_DAPM_DAC("Left DAC",  NULL, BLOCK_EN, DACL_EN, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	SND_SOC_DAPM_OUT_DRV("Right- Driver", BLOCK_EN, LORN_EN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			 NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	SND_SOC_DAPM_OUT_DRV("Right+ Driver", BLOCK_EN, LORP_EN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			 NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	SND_SOC_DAPM_OUT_DRV("Left- Driver",  BLOCK_EN, LOLN_EN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			 NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	SND_SOC_DAPM_OUT_DRV("Left+ Driver",  BLOCK_EN, LOLP_EN, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			 NULL, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	SND_SOC_DAPM_OUTPUT("LORN"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	SND_SOC_DAPM_OUTPUT("LORP"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	SND_SOC_DAPM_OUTPUT("LOLN"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	SND_SOC_DAPM_OUTPUT("LOLP"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct snd_soc_dapm_route t9015_dapm_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	{ "Right IN", NULL, "Playback" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	{ "Left IN",  NULL, "Playback" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	{ "Right DAC Sel", "Right", "Right IN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	{ "Right DAC Sel", "Left",  "Left IN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	{ "Left DAC Sel",  "Right", "Right IN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	{ "Left DAC Sel",  "Left",  "Left IN" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	{ "Right DAC", NULL, "Right DAC Sel" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	{ "Left DAC",  NULL, "Left DAC Sel" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	{ "Right- Driver", NULL, "Right DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	{ "Right+ Driver", NULL, "Right DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	{ "Left- Driver",  NULL, "Left DAC"  },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	{ "Left+ Driver",  NULL, "Left DAC"  },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	{ "LORN", NULL, "Right- Driver", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	{ "LORP", NULL, "Right+ Driver", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	{ "LOLN", NULL, "Left- Driver",  },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	{ "LOLP", NULL, "Left+ Driver",  },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static int t9015_set_bias_level(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	struct t9015 *priv = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	enum snd_soc_bias_level now =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		snd_soc_component_get_bias_level(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	switch (level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	case SND_SOC_BIAS_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		snd_soc_component_update_bits(component, BLOCK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 					      BIAS_CURRENT_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 					      BIAS_CURRENT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	case SND_SOC_BIAS_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		snd_soc_component_update_bits(component, BLOCK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 					      BIAS_CURRENT_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 					      0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	case SND_SOC_BIAS_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		ret = regulator_enable(priv->avdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			dev_err(component->dev, "AVDD enable failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		if (now == SND_SOC_BIAS_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			snd_soc_component_update_bits(component, BLOCK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 				VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 				VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			mdelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			snd_soc_component_update_bits(component, BLOCK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 						      VMID_GEN_FAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 						      0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	case SND_SOC_BIAS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		snd_soc_component_update_bits(component, BLOCK_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			VMID_GEN_EN | VMID_GEN_FAST | REFP_BUF_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		regulator_disable(priv->avdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const struct snd_soc_component_driver t9015_codec_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	.set_bias_level		= t9015_set_bias_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	.controls		= t9015_snd_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	.num_controls		= ARRAY_SIZE(t9015_snd_controls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	.dapm_widgets		= t9015_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	.num_dapm_widgets	= ARRAY_SIZE(t9015_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	.dapm_routes		= t9015_dapm_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	.num_dapm_routes	= ARRAY_SIZE(t9015_dapm_routes),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	.suspend_bias_off	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	.endianness		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	.non_legacy_dai_naming	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct regmap_config t9015_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.reg_bits		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.reg_stride		= 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.val_bits		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	.max_register		= POWER_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int t9015_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	struct t9015 *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	priv->pclk = devm_clk_get(dev, "pclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (IS_ERR(priv->pclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		if (PTR_ERR(priv->pclk) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			dev_err(dev, "failed to get core clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		return PTR_ERR(priv->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	priv->avdd = devm_regulator_get(dev, "AVDD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	if (IS_ERR(priv->avdd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		if (PTR_ERR(priv->avdd) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			dev_err(dev, "failed to AVDD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		return PTR_ERR(priv->avdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	ret = clk_prepare_enable(priv->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		dev_err(dev, "core clock enable failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	ret = devm_add_action_or_reset(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			(void(*)(void *))clk_disable_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			priv->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	ret = device_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		dev_err(dev, "reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (IS_ERR(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		dev_err(dev, "register map failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	regmap = devm_regmap_init_mmio(dev, regs, &t9015_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		dev_err(dev, "regmap init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		return PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	 * Initialize output polarity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	 * ATM the output polarity is fixed but in the future it might useful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	 * to add DT property to set this depending on the platform needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	regmap_write(regmap, LINEOUT_CFG, 0x1111);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	return devm_snd_soc_register_component(dev, &t9015_codec_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 					       &t9015_dai, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static const struct of_device_id t9015_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	{ .compatible = "amlogic,t9015", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) MODULE_DEVICE_TABLE(of, t9015_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static struct platform_driver t9015_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		.name = "t9015-codec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		.of_match_table = of_match_ptr(t9015_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	.probe = t9015_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) module_platform_driver(t9015_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) MODULE_DESCRIPTION("ASoC Amlogic T9015 codec driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) MODULE_LICENSE("GPL");