1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Internal adc codec for cv1800b compatible SoC 4 * 5 */ 6 #include <linux/module.h> 7 #include <linux/platform_device.h> 8 #include <sound/soc.h> 9 #include <linux/bitfield.h> 10 #include <linux/bits.h> 11 #include <sound/tlv.h> 12 #include <sound/soc-component.h> 13 #include <sound/control.h> 14 #include <linux/io.h> 15 #include <linux/kernel.h> 16 #include <linux/bitops.h> 17 18 #define CV1800B_RXADC_WORD_LEN 16 19 #define CV1800B_RXADC_CHANNELS 2 20 21 #define CV1800B_RXADC_CTRL0 0x00 22 #define CV1800B_RXADCC_CTRL1 0x04 23 #define CV1800B_RXADC_STATUS 0x08 24 #define CV1800B_RXADC_CLK 0x0c 25 #define CV1800B_RXADC_ANA0 0x10 26 #define CV1800B_RXADC_ANA1 0x14 27 #define CV1800B_RXADC_ANA2 0x18 28 #define CV1800B_RXADC_ANA3 0x1c 29 #define CV1800B_RXADC_ANA4 0x20 30 31 /* CV1800B_RXADC_CTRL0 */ 32 #define REG_RXADC_EN GENMASK(0, 0) 33 #define REG_I2S_TX_EN GENMASK(1, 1) 34 35 /* CV1800B_RXADCC_CTRL1 */ 36 #define REG_RXADC_CIC_OPT GENMASK(1, 0) 37 #define REG_RXADC_IGR_INIT GENMASK(8, 8) 38 39 /* CV1800B_RXADC_ANA0 */ 40 #define REG_GSTEPL_RXPGA GENMASK(12, 0) 41 #define REG_G6DBL_RXPGA GENMASK(13, 13) 42 #define REG_GAINL_RXADC GENMASK(15, 14) 43 #define REG_GSTEPR_RXPGA GENMASK(28, 16) 44 #define REG_G6DBR_RXPGA GENMASK(29, 29) 45 #define REG_GAINR_RXADC GENMASK(31, 30) 46 #define REG_COMB_LEFT_VOLUME GENMASK(15, 0) 47 #define REG_COMB_RIGHT_VOLUME GENMASK(31, 16) 48 49 /* CV1800B_RXADC_ANA2 */ 50 #define REG_MUTEL_RXPGA GENMASK(0, 0) 51 #define REG_MUTER_RXPGA GENMASK(1, 1) 52 53 /* CV1800B_RXADC_CLK */ 54 #define REG_RXADC_CLK_INV GENMASK(0, 0) 55 #define REG_RXADC_SCK_DIV GENMASK(15, 8) 56 #define REG_RXADC_DLYEN GENMASK(23, 16) 57 58 enum decimation_values { 59 DECIMATION_64 = 0, 60 DECIMATION_128, 61 DECIMATION_256, 62 DECIMATION_512, 63 }; 64 65 static const u32 cv1800b_gains[] = { 66 0x0001, /* 0dB */ 67 0x0002, /* 2dB */ 68 0x0004, /* 4dB */ 69 0x0008, /* 6dB */ 70 0x0010, /* 8dB */ 71 0x0020, /* 10dB */ 72 0x0040, /* 12dB */ 73 0x0080, /* 14dB */ 74 0x0100, /* 16dB */ 75 0x0200, /* 18dB */ 76 0x0400, /* 20dB */ 77 0x0800, /* 22dB */ 78 0x1000, /* 24dB */ 79 0x2400, /* 26dB */ 80 0x2800, /* 28dB */ 81 0x3000, /* 30dB */ 82 0x6400, /* 32dB */ 83 0x6800, /* 34dB */ 84 0x7000, /* 36dB */ 85 0xA400, /* 38dB */ 86 0xA800, /* 40dB */ 87 0xB000, /* 42dB */ 88 0xE400, /* 44dB */ 89 0xE800, /* 46dB */ 90 0xF000, /* 48dB */ 91 }; 92 93 struct cv1800b_priv { 94 void __iomem *regs; 95 struct device *dev; 96 unsigned int mclk_rate; 97 }; 98 99 static int cv1800b_adc_setbclk_div(struct cv1800b_priv *priv, unsigned int rate) 100 { 101 u32 val; 102 u32 bclk_div; 103 u64 tmp; 104 105 if (!priv->mclk_rate || !rate) 106 return -EINVAL; 107 108 tmp = div_u64(priv->mclk_rate, CV1800B_RXADC_WORD_LEN * 109 CV1800B_RXADC_CHANNELS * rate * 2); 110 111 if (!tmp) { 112 dev_err(priv->dev, "computed BCLK divider is zero\n"); 113 return -EINVAL; 114 } 115 116 if (tmp > 256) { 117 dev_err(priv->dev, "BCLK divider %llu out of range\n", tmp); 118 return -EINVAL; 119 } 120 121 bclk_div = tmp - 1; 122 val = readl(priv->regs + CV1800B_RXADC_CLK); 123 val = u32_replace_bits(val, bclk_div, REG_RXADC_SCK_DIV); 124 /* Vendor value for 48kHz, tested on SG2000/SG2002 */ 125 val = u32_replace_bits(val, 0x19, REG_RXADC_DLYEN); 126 writel(val, priv->regs + CV1800B_RXADC_CLK); 127 128 return 0; 129 } 130 131 static void cv1800b_adc_enable(struct cv1800b_priv *priv, bool enable) 132 { 133 u32 val; 134 135 val = readl(priv->regs + CV1800B_RXADC_CTRL0); 136 val = u32_replace_bits(val, enable, REG_RXADC_EN); 137 val = u32_replace_bits(val, enable, REG_I2S_TX_EN); 138 writel(val, priv->regs + CV1800B_RXADC_CTRL0); 139 } 140 141 static unsigned int cv1800b_adc_calc_db(u32 ana0, bool right) 142 { 143 u32 step_mask = right ? FIELD_GET(REG_GSTEPR_RXPGA, ana0) : 144 FIELD_GET(REG_GSTEPL_RXPGA, ana0); 145 u32 coarse = right ? FIELD_GET(REG_GAINR_RXADC, ana0) : 146 FIELD_GET(REG_GAINL_RXADC, ana0); 147 bool g6db = right ? FIELD_GET(REG_G6DBR_RXPGA, ana0) : 148 FIELD_GET(REG_G6DBL_RXPGA, ana0); 149 150 u32 step = step_mask ? __ffs(step_mask) : 0; 151 152 step = min(step, 12U); 153 coarse = min(coarse, 3U); 154 155 return 2 * step + 6 * coarse + (g6db ? 6 : 0); 156 } 157 158 static int cv1800b_adc_hw_params(struct snd_pcm_substream *substream, 159 struct snd_pcm_hw_params *params, 160 struct snd_soc_dai *dai) 161 { 162 struct cv1800b_priv *priv = snd_soc_dai_get_drvdata(dai); 163 unsigned int rate = params_rate(params); 164 u32 val; 165 int ret; 166 167 ret = cv1800b_adc_setbclk_div(priv, rate); 168 if (ret) { 169 dev_err(priv->dev, 170 "could not set rate, check DT node for fixed clock\n"); 171 return ret; 172 } 173 174 /* init adc */ 175 val = readl(priv->regs + CV1800B_RXADCC_CTRL1); 176 val = u32_replace_bits(val, 1, REG_RXADC_IGR_INIT); 177 val = u32_replace_bits(val, DECIMATION_64, REG_RXADC_CIC_OPT); 178 writel(val, priv->regs + CV1800B_RXADCC_CTRL1); 179 return 0; 180 } 181 182 static int cv1800b_adc_dai_trigger(struct snd_pcm_substream *substream, int cmd, 183 struct snd_soc_dai *dai) 184 { 185 struct cv1800b_priv *priv = snd_soc_dai_get_drvdata(dai); 186 187 switch (cmd) { 188 case SNDRV_PCM_TRIGGER_START: 189 case SNDRV_PCM_TRIGGER_RESUME: 190 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 191 cv1800b_adc_enable(priv, true); 192 break; 193 case SNDRV_PCM_TRIGGER_STOP: 194 case SNDRV_PCM_TRIGGER_SUSPEND: 195 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 196 cv1800b_adc_enable(priv, false); 197 break; 198 default: 199 return -EINVAL; 200 } 201 202 return 0; 203 } 204 205 static int cv1800b_adc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 206 unsigned int freq, int dir) 207 { 208 struct cv1800b_priv *priv = snd_soc_dai_get_drvdata(dai); 209 210 priv->mclk_rate = freq; 211 dev_dbg(priv->dev, "mclk is set to %u\n", freq); 212 return 0; 213 } 214 215 static const struct snd_soc_dai_ops cv1800b_adc_dai_ops = { 216 .hw_params = cv1800b_adc_hw_params, 217 .set_sysclk = cv1800b_adc_dai_set_sysclk, 218 .trigger = cv1800b_adc_dai_trigger, 219 }; 220 221 static struct snd_soc_dai_driver cv1800b_adc_dai = { 222 .name = "adc-hifi", 223 .capture = { .stream_name = "ADC Capture", 224 .channels_min = 1, 225 .channels_max = 2, 226 .rates = SNDRV_PCM_RATE_48000, 227 .formats = SNDRV_PCM_FMTBIT_S16_LE }, 228 .ops = &cv1800b_adc_dai_ops, 229 }; 230 231 static int cv1800b_adc_volume_get(struct snd_kcontrol *kcontrol, 232 struct snd_ctl_elem_value *ucontrol) 233 { 234 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 235 struct cv1800b_priv *priv = snd_soc_component_get_drvdata(component); 236 u32 ana0 = readl(priv->regs + CV1800B_RXADC_ANA0); 237 238 unsigned int left = cv1800b_adc_calc_db(ana0, false); 239 unsigned int right = cv1800b_adc_calc_db(ana0, true); 240 241 ucontrol->value.integer.value[0] = min(left / 2, 24U); 242 ucontrol->value.integer.value[1] = min(right / 2, 24U); 243 return 0; 244 } 245 246 static int cv1800b_adc_volume_set(struct snd_kcontrol *kcontrol, 247 struct snd_ctl_elem_value *ucontrol) 248 { 249 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 250 struct cv1800b_priv *priv = snd_soc_component_get_drvdata(component); 251 252 u32 v_left = clamp_t(u32, ucontrol->value.integer.value[0], 0, 24); 253 u32 v_right = clamp_t(u32, ucontrol->value.integer.value[1], 0, 24); 254 u32 val; 255 256 val = readl(priv->regs + CV1800B_RXADC_ANA0); 257 val = u32_replace_bits(val, cv1800b_gains[v_left], 258 REG_COMB_LEFT_VOLUME); 259 val = u32_replace_bits(val, cv1800b_gains[v_right], 260 REG_COMB_RIGHT_VOLUME); 261 writel(val, priv->regs + CV1800B_RXADC_ANA0); 262 263 return 0; 264 } 265 266 static DECLARE_TLV_DB_SCALE(cv1800b_volume_tlv, 0, 200, 0); 267 268 static const struct snd_kcontrol_new cv1800b_adc_controls[] = { 269 SOC_DOUBLE_EXT_TLV("Internal I2S Capture Volume", SND_SOC_NOPM, 0, 16, 24, false, 270 cv1800b_adc_volume_get, cv1800b_adc_volume_set, 271 cv1800b_volume_tlv), 272 }; 273 274 static const struct snd_soc_component_driver cv1800b_adc_component = { 275 .name = "cv1800b-adc-codec", 276 .controls = cv1800b_adc_controls, 277 .num_controls = ARRAY_SIZE(cv1800b_adc_controls), 278 }; 279 280 static int cv1800b_adc_probe(struct platform_device *pdev) 281 { 282 struct device *dev = &pdev->dev; 283 struct cv1800b_priv *priv; 284 285 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 286 if (!priv) 287 return -ENOMEM; 288 289 priv->dev = dev; 290 priv->regs = devm_platform_ioremap_resource(pdev, 0); 291 if (IS_ERR(priv->regs)) 292 return PTR_ERR(priv->regs); 293 294 platform_set_drvdata(pdev, priv); 295 return devm_snd_soc_register_component(&pdev->dev, 296 &cv1800b_adc_component, 297 &cv1800b_adc_dai, 1); 298 } 299 300 static const struct of_device_id cv1800b_adc_of_match[] = { 301 { .compatible = "sophgo,cv1800b-sound-adc" }, 302 { /* sentinel */ } 303 }; 304 305 MODULE_DEVICE_TABLE(of, cv1800b_adc_of_match); 306 307 static struct platform_driver cv1800b_adc_driver = { 308 .probe = cv1800b_adc_probe, 309 .driver = { 310 .name = "cv1800b-sound-adc", 311 .of_match_table = cv1800b_adc_of_match, 312 }, 313 }; 314 315 module_platform_driver(cv1800b_adc_driver); 316 317 MODULE_DESCRIPTION("ADC codec for CV1800B"); 318 MODULE_AUTHOR("Anton D. Stavinskii <stavinsky@gmail.com>"); 319 MODULE_LICENSE("GPL"); 320