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) 2015 - 2016 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) // Authors: Inha Song <ideal.song@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) //          Sylwester Nawrocki <s.nawrocki@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "i2s.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "../codecs/wm5110.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * The source clock is XCLKOUT with its mux set to the external fixed rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * oscillator (XXTI).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define MCLK_RATE	24000000U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define TM2_DAI_AIF1	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define TM2_DAI_AIF2	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) struct tm2_machine_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	unsigned int sysclk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct gpio_desc *gpio_mic_bias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int tm2_start_sysclk(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct snd_soc_component *component = priv->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	ret = snd_soc_component_set_pll(component, WM5110_FLL1_REFCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 				    ARIZONA_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 				    MCLK_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 				    priv->sysclk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		dev_err(component->dev, "Failed to set FLL1 source: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	ret = snd_soc_component_set_pll(component, WM5110_FLL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 				    ARIZONA_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 				    MCLK_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 				    priv->sysclk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		dev_err(component->dev, "Failed to start FLL1: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 				       ARIZONA_CLK_SRC_FLL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 				       priv->sysclk_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 				       SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		dev_err(component->dev, "Failed to set SYSCLK source: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static int tm2_stop_sysclk(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct snd_soc_component *component = priv->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	ret = snd_soc_component_set_pll(component, WM5110_FLL1, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		dev_err(component->dev, "Failed to stop FLL1: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		return ret;
^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) 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				       ARIZONA_CLK_SRC_FLL1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		dev_err(component->dev, "Failed to stop SYSCLK: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return 0;
^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) static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 				struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	switch (params_rate(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	case 4000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	case 8000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	case 12000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	case 16000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	case 24000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	case 32000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		/* Highest possible SYSCLK frequency: 147.456MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		priv->sysclk_rate = 147456000U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	case 11025:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	case 22050:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	case 88200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	case 176400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		/* Highest possible SYSCLK frequency: 135.4752 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		priv->sysclk_rate = 135475200U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		dev_err(component->dev, "Not supported sample rate: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return tm2_start_sysclk(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct snd_soc_ops tm2_aif1_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	.hw_params = tm2_aif1_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int tm2_aif2_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 				struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	unsigned int asyncclk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	switch (params_rate(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	case 8000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	case 12000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	case 16000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		/* Highest possible ASYNCCLK frequency: 49.152MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		asyncclk_rate = 49152000U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	case 11025:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		/* Highest possible ASYNCCLK frequency: 45.1584 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		asyncclk_rate = 45158400U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		dev_err(component->dev, "Not supported sample rate: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		return -EINVAL;
^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) 	ret = snd_soc_component_set_pll(component, WM5110_FLL2_REFCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 				    ARIZONA_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 				    MCLK_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 				    asyncclk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		dev_err(component->dev, "Failed to set FLL2 source: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	ret = snd_soc_component_set_pll(component, WM5110_FLL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				    ARIZONA_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				    MCLK_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				    asyncclk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		dev_err(component->dev, "Failed to start FLL2: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 				       ARIZONA_CLK_SRC_FLL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				       asyncclk_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				       SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		dev_err(component->dev, "Failed to set ASYNCCLK source: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	/* disable FLL2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	ret = snd_soc_component_set_pll(component, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 				    0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		dev_err(component->dev, "Failed to stop FLL2: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^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) static struct snd_soc_ops tm2_aif2_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	.hw_params = tm2_aif2_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	.hw_free = tm2_aif2_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			      struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	unsigned int bfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	int bitwidth, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	bitwidth = snd_pcm_format_width(params_format(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	if (bitwidth < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		dev_err(rtd->card->dev, "Invalid bit-width: %d\n", bitwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		return bitwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	switch (bitwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	case 48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		bfs = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		bfs = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		dev_err(rtd->card->dev, "Unsupported bit-width: %d\n", bitwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	switch (params_rate(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		dev_err(rtd->card->dev, "Unsupported sample rate: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 					0, SAMSUNG_I2S_OPCLK_PCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static struct snd_soc_ops tm2_hdmi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	.hw_params = tm2_hdmi_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int tm2_mic_bias(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 				struct snd_kcontrol *kcontrol, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	struct snd_soc_card *card = w->dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	case SND_SOC_DAPM_PRE_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	case SND_SOC_DAPM_POST_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		gpiod_set_value_cansleep(priv->gpio_mic_bias,  0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int tm2_set_bias_level(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 				struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 				enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (dapm->dev != asoc_rtd_to_codec(rtd, 0)->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	switch (level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	case SND_SOC_BIAS_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			tm2_start_sysclk(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	case SND_SOC_BIAS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		tm2_stop_sysclk(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	return 0;
^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) static struct snd_soc_aux_dev tm2_speaker_amp_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static int tm2_late_probe(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	unsigned int ch_map[] = { 0, 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	struct snd_soc_dai *amp_pdm_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	struct snd_soc_dai *aif1_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct snd_soc_dai *aif2_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[TM2_DAI_AIF1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	aif1_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	priv->component = asoc_rtd_to_codec(rtd, 0)->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[TM2_DAI_AIF2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	aif2_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	amp_pdm_dai = snd_soc_find_dai(&tm2_speaker_amp_dev.dlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (!amp_pdm_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	/* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 					  ch_map, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static const struct snd_kcontrol_new tm2_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	SOC_DAPM_PIN_SWITCH("HP"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	SOC_DAPM_PIN_SWITCH("SPK"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	SOC_DAPM_PIN_SWITCH("RCV"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	SOC_DAPM_PIN_SWITCH("VPS"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	SOC_DAPM_PIN_SWITCH("HDMI"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	SOC_DAPM_PIN_SWITCH("Main Mic"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	SOC_DAPM_PIN_SWITCH("Sub Mic"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	SOC_DAPM_PIN_SWITCH("Third Mic"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static const struct snd_soc_dapm_widget tm2_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	SND_SOC_DAPM_HP("HP", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	SND_SOC_DAPM_SPK("SPK", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	SND_SOC_DAPM_SPK("RCV", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	SND_SOC_DAPM_LINE("VPS", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	SND_SOC_DAPM_LINE("HDMI", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	SND_SOC_DAPM_MIC("Sub Mic", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	SND_SOC_DAPM_MIC("Third Mic", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static const struct snd_soc_component_driver tm2_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	.name	= "tm2-audio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static struct snd_soc_dai_driver tm2_ext_dai[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		.name = "Voice call",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		.playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			.channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			.channels_max = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			.rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 			.rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 					SNDRV_PCM_RATE_48000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		.capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			.channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 			.channels_max = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			.rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			.rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 					SNDRV_PCM_RATE_48000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		.name = "Bluetooth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		.playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 			.channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			.channels_max = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 			.rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			.rate_max = 16000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		.capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 			.channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			.channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			.rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			.rate_max = 16000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			.formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) SND_SOC_DAILINK_DEFS(aif1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) SND_SOC_DAILINK_DEFS(voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) SND_SOC_DAILINK_DEFS(bt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) SND_SOC_DAILINK_DEFS(hdmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static struct snd_soc_dai_link tm2_dai_links[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		.name		= "WM5110 AIF1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		.stream_name	= "HiFi Primary",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		.ops		= &tm2_aif1_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 				  SND_SOC_DAIFMT_CBM_CFM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		SND_SOC_DAILINK_REG(aif1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		.name		= "WM5110 Voice",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		.stream_name	= "Voice call",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		.ops		= &tm2_aif2_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 				  SND_SOC_DAIFMT_CBM_CFM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		.ignore_suspend = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		SND_SOC_DAILINK_REG(voice),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		.name		= "WM5110 BT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		.stream_name	= "Bluetooth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 				  SND_SOC_DAIFMT_CBM_CFM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		.ignore_suspend = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		SND_SOC_DAILINK_REG(bt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		.name		= "HDMI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		.stream_name	= "i2s1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		.ops		= &tm2_hdmi_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 				  SND_SOC_DAIFMT_CBS_CFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		SND_SOC_DAILINK_REG(hdmi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static struct snd_soc_card tm2_card = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	.owner			= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	.dai_link		= tm2_dai_links,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	.controls		= tm2_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	.num_controls		= ARRAY_SIZE(tm2_controls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	.dapm_widgets		= tm2_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	.num_dapm_widgets	= ARRAY_SIZE(tm2_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	.aux_dev		= &tm2_speaker_amp_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	.num_aux_devs		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	.late_probe		= tm2_late_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	.set_bias_level		= tm2_set_bias_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int tm2_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	struct device_node *cpu_dai_node[2] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	struct device_node *codec_dai_node[2] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	const char *cells_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	struct snd_soc_card *card = &tm2_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	struct tm2_machine_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	struct snd_soc_dai_link *dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	int num_codecs, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	snd_soc_card_set_drvdata(card, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	card->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	if (IS_ERR(priv->gpio_mic_bias)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		dev_err(dev, "Failed to get mic bias gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		return PTR_ERR(priv->gpio_mic_bias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	ret = snd_soc_of_parse_card_name(card, "model");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		dev_err(dev, "Card name is not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		dev_err(dev, "Audio routing is not specified or invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	card->aux_dev[0].dlc.of_node = of_parse_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 							"audio-amplifier", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	if (!card->aux_dev[0].dlc.of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		dev_err(dev, "audio-amplifier property invalid or missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	num_codecs = of_count_phandle_with_args(dev->of_node, "audio-codec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 						 NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	/* Skip the HDMI link if not specified in DT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (num_codecs > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		card->num_links = ARRAY_SIZE(tm2_dai_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		cells_name = "#sound-dai-cells";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		card->num_links = ARRAY_SIZE(tm2_dai_links) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	for (i = 0; i < num_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 						 cells_name, i, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			dev_err(dev, "i2s-controller property parse error: %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 			goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		cpu_dai_node[i] = args.np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		codec_dai_node[i] = of_parse_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 						     "audio-codec", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		if (!codec_dai_node[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			dev_err(dev, "audio-codec property parse error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 			goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	/* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	for_each_card_prelinks(card, i, dai_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		unsigned int dai_index = 0; /* WM5110 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		dai_link->cpus->name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		dai_link->platforms->name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		if (num_codecs > 1 && i == card->num_links - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			dai_index = 1; /* HDMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		dai_link->codecs->of_node = codec_dai_node[dai_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		dai_link->cpus->of_node = cpu_dai_node[dai_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		dai_link->platforms->of_node = cpu_dai_node[dai_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	if (num_codecs > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		/* HDMI DAI link (I2S1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		i = card->num_links - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		ret = of_parse_phandle_with_fixed_args(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 						"audio-codec", 0, 1, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 			dev_err(dev, "audio-codec property parse error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 		ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codecs->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			dev_err(dev, "Unable to get codec_dai_name\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	ret = devm_snd_soc_register_component(dev, &tm2_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		dev_err(dev, "Failed to register component: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	ret = devm_snd_soc_register_card(dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 			dev_err(dev, "Failed to register card: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		goto dai_node_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) dai_node_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	for (i = 0; i < num_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		of_node_put(codec_dai_node[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		of_node_put(cpu_dai_node[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	of_node_put(card->aux_dev[0].dlc.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int tm2_pm_prepare(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	struct snd_soc_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	return tm2_stop_sysclk(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void tm2_pm_complete(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	struct snd_soc_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	tm2_start_sysclk(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static const struct dev_pm_ops tm2_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	.prepare	= tm2_pm_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	.suspend	= snd_soc_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	.resume		= snd_soc_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	.complete	= tm2_pm_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	.freeze		= snd_soc_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	.thaw		= snd_soc_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	.poweroff	= snd_soc_poweroff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	.restore	= snd_soc_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static const struct of_device_id tm2_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	{ .compatible = "samsung,tm2-audio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) MODULE_DEVICE_TABLE(of, tm2_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static struct platform_driver tm2_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		.name		= "tm2-audio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		.pm		= &tm2_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		.of_match_table	= tm2_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	.probe	= tm2_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) module_platform_driver(tm2_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) MODULE_LICENSE("GPL v2");