1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Internal DAC codec for cv1800b based CPUs 4 */ 5 6 #include <linux/module.h> 7 #include <linux/platform_device.h> 8 #include <linux/bitfield.h> 9 #include <linux/bits.h> 10 #include <sound/soc.h> 11 #include <linux/io.h> 12 13 #define CV1800B_TXDAC_CTRL0 0x00 14 #define CV1800B_TXDAC_CTRL1 0x04 15 #define CV1800B_TXDAC_STATUS 0x08 16 #define CV1800B_TXDAC_AFE0 0x0c 17 #define CV1800B_TXDAC_AFE1 0x10 18 #define CV1800B_TXDAC_ANA0 0x20 19 #define CV1800B_TXDAC_ANA1 0x24 20 #define CV1800B_TXDAC_ANA2 0x28 21 22 /* cv1800b_TXDAC_CTRL0 */ 23 #define REG_TXDAC_EN GENMASK(0, 0) 24 #define REG_I2S_RX_EN GENMASK(1, 1) 25 26 /* cv1800b_TXDAC_CTRL1 */ 27 #define REG_TXDAC_CIC_OPT GENMASK(1, 0) 28 29 /* cv1800b_TXDAC_AFE0 */ 30 #define REG_TXDAC_INIT_DLY_CNT GENMASK(5, 0) 31 32 /* cv1800b_TXDAC_ANA2 */ 33 #define TXDAC_OW_VAL_L_MASK GENMASK(7, 0) 34 #define TXDAC_OW_VAL_R_MASK GENMASK(15, 8) 35 #define TXDAC_OW_EN_L_MASK GENMASK(16, 16) 36 #define TXDAC_OW_EN_R_MASK GENMASK(17, 17) 37 38 struct cv1800b_priv { 39 void __iomem *regs; 40 struct device *dev; 41 }; 42 43 enum decimation_values { 44 DECIMATION_64 = 0, 45 DECIMATION_128, 46 DECIMATION_256, 47 DECIMATION_512, 48 }; 49 50 static void cv1800b_dac_enable(struct cv1800b_priv *priv, bool enable) 51 { 52 u32 val; 53 54 val = readl(priv->regs + CV1800B_TXDAC_CTRL0); 55 val = u32_replace_bits(val, enable, REG_TXDAC_EN); 56 val = u32_replace_bits(val, enable, REG_I2S_RX_EN); 57 writel(val, priv->regs + CV1800B_TXDAC_CTRL0); 58 } 59 60 /* 61 * Control the DAC overwrite bits. When enabled, the DAC outputs the fixed 62 * overwrite value instead of samples from the I2S input. 63 */ 64 static void cv1800b_dac_mute(struct cv1800b_priv *priv, bool enable) 65 { 66 u32 val; 67 68 val = readl(priv->regs + CV1800B_TXDAC_ANA2); 69 val = u32_replace_bits(val, enable, TXDAC_OW_EN_L_MASK); 70 val = u32_replace_bits(val, enable, TXDAC_OW_EN_R_MASK); 71 writel(val, priv->regs + CV1800B_TXDAC_ANA2); 72 } 73 74 static int cv1800b_dac_decimation(struct cv1800b_priv *priv, u8 dec) 75 { 76 u32 val; 77 78 if (dec > 3) 79 return -EINVAL; 80 81 val = readl(priv->regs + CV1800B_TXDAC_CTRL1); 82 val = u32_replace_bits(val, dec, REG_TXDAC_CIC_OPT); 83 writel(val, priv->regs + CV1800B_TXDAC_CTRL1); 84 return 0; 85 } 86 87 static int cv1800b_dac_dly(struct cv1800b_priv *priv, u32 dly) 88 { 89 u32 val; 90 91 if (dly > 63) 92 return -EINVAL; 93 94 val = readl(priv->regs + CV1800B_TXDAC_AFE0); 95 val = u32_replace_bits(val, dly, REG_TXDAC_INIT_DLY_CNT); 96 writel(val, priv->regs + CV1800B_TXDAC_AFE0); 97 return 0; 98 } 99 100 static int cv1800b_dac_hw_params(struct snd_pcm_substream *substream, 101 struct snd_pcm_hw_params *params, 102 struct snd_soc_dai *dai) 103 { 104 struct cv1800b_priv *priv = snd_soc_dai_get_drvdata(dai); 105 int ret; 106 unsigned int rate = params_rate(params); 107 108 if (rate != 48000) { 109 dev_err(priv->dev, "rate %u is not supported\n", rate); 110 return -EINVAL; 111 } 112 /* Clear DAC overwrite so playback uses I2S data. */ 113 cv1800b_dac_mute(priv, false); 114 /* minimal decimation for 48kHz is 64*/ 115 ret = cv1800b_dac_decimation(priv, DECIMATION_64); 116 if (ret) 117 return ret; 118 119 /* value is taken from vendors driver 48kHz 120 * tested on sg2000 and sg2002. 121 */ 122 ret = cv1800b_dac_dly(priv, 0x19); 123 if (ret) 124 return ret; 125 126 return 0; 127 } 128 129 static int cv1800b_dac_dai_trigger(struct snd_pcm_substream *substream, int cmd, 130 struct snd_soc_dai *dai) 131 { 132 struct cv1800b_priv *priv = snd_soc_dai_get_drvdata(dai); 133 134 switch (cmd) { 135 case SNDRV_PCM_TRIGGER_START: 136 case SNDRV_PCM_TRIGGER_RESUME: 137 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 138 cv1800b_dac_enable(priv, true); 139 break; 140 case SNDRV_PCM_TRIGGER_STOP: 141 case SNDRV_PCM_TRIGGER_SUSPEND: 142 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 143 cv1800b_dac_enable(priv, false); 144 break; 145 default: 146 return -EINVAL; 147 } 148 149 return 0; 150 } 151 152 static const struct snd_soc_dai_ops cv1800b_dac_dai_ops = { 153 .hw_params = cv1800b_dac_hw_params, 154 .trigger = cv1800b_dac_dai_trigger, 155 }; 156 157 static struct snd_soc_dai_driver cv1800b_dac_dai = { 158 .name = "dac-hifi", 159 .playback = { .stream_name = "DAC Playback", 160 .channels_min = 2, 161 .channels_max = 2, 162 .rates = SNDRV_PCM_RATE_48000, 163 .formats = SNDRV_PCM_FMTBIT_S16_LE }, 164 .ops = &cv1800b_dac_dai_ops, 165 }; 166 167 static const struct snd_soc_component_driver cv1800b_dac_component = { 168 .name = "cv1800b-dac-codec", 169 }; 170 171 static int cv1800b_dac_probe(struct platform_device *pdev) 172 { 173 struct device *dev = &pdev->dev; 174 struct cv1800b_priv *priv; 175 176 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 177 if (!priv) 178 return -ENOMEM; 179 180 priv->dev = dev; 181 priv->regs = devm_platform_ioremap_resource(pdev, 0); 182 if (IS_ERR(priv->regs)) 183 return PTR_ERR(priv->regs); 184 185 platform_set_drvdata(pdev, priv); 186 return devm_snd_soc_register_component(&pdev->dev, 187 &cv1800b_dac_component, 188 &cv1800b_dac_dai, 1); 189 } 190 191 static const struct of_device_id cv1800b_dac_of_match[] = { 192 { .compatible = "sophgo,cv1800b-sound-dac" }, 193 { /* sentinel */ } 194 }; 195 MODULE_DEVICE_TABLE(of, cv1800b_dac_of_match); 196 197 static struct platform_driver cv1800b_dac_driver = { 198 .probe = cv1800b_dac_probe, 199 .driver = { 200 .name = "cv1800b-dac-codec", 201 .of_match_table = cv1800b_dac_of_match, 202 }, 203 }; 204 module_platform_driver(cv1800b_dac_driver); 205 206 MODULE_DESCRIPTION("DAC codec for CV1800B"); 207 MODULE_AUTHOR("Anton D. Stavinskii <stavinsky@gmail.com>"); 208 MODULE_LICENSE("GPL"); 209