1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2018 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <power/pmic.h> 9 #include <power/rk8xx_pmic.h> 10 #include <sound.h> 11 #include "rk817_codec.h" 12 13 #define DBG(format, ...) \ 14 printf("RK817: " format, ## __VA_ARGS__) 15 16 /* For route */ 17 #define RK817_CODEC_PLAYBACK 1 18 #define RK817_CODEC_CAPTURE 2 19 #define RK817_CODEC_INCALL 4 20 #define RK817_CODEC_ALL (RK817_CODEC_PLAYBACK |\ 21 RK817_CODEC_CAPTURE | RK817_CODEC_INCALL) 22 23 /* 24 * DDAC L/R volume setting 25 * 0db~-95db,0.375db/step,for example: 26 * 0: 0dB 27 * 0x0a: -3.75dB 28 * 0x7d: -46dB 29 * 0xff: -95dB 30 */ 31 #define OUT_VOLUME (0x03) 32 33 #define CODEC_SET_SPK 1 34 #define CODEC_SET_HP 2 35 #define INITIAL_VOLUME 3 36 37 struct rk817_codec_priv { 38 struct udevice *dev; 39 struct rk8xx_priv *rk817; 40 unsigned int stereo_sysclk; 41 unsigned int rate; 42 unsigned int spk_volume; 43 unsigned int hp_volume; 44 bool use_ext_amplifier; 45 long int playback_path; 46 int spk_mute_delay; 47 int hp_mute_delay; 48 }; 49 50 static int snd_soc_write(struct udevice *dev, unsigned int reg, 51 unsigned int val) 52 { 53 return pmic_reg_write(dev, reg, val); 54 } 55 56 static int snd_soc_update_bits(struct udevice *dev, unsigned int reg, 57 unsigned int mask, unsigned int value) 58 { 59 return pmic_clrsetbits(dev, reg, mask, value); 60 } 61 62 static int rk817_reset(struct rk817_codec_priv *priv) 63 { 64 struct udevice *codec = priv->dev->parent; 65 66 snd_soc_write(codec, RK817_CODEC_DTOP_LPT_SRST, 0x40); 67 snd_soc_write(codec, RK817_CODEC_DDAC_POPD_DACST, 0x02); 68 69 return 0; 70 } 71 72 static struct rk817_reg_val_typ playback_power_up_list[] = { 73 {RK817_CODEC_AREF_RTCFG1, 0x40}, 74 {RK817_CODEC_DDAC_POPD_DACST, 0x02}, 75 {RK817_CODEC_DDAC_SR_LMT0, 0x02}, 76 /* {RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f}, */ 77 /* APLL */ 78 {RK817_CODEC_APLL_CFG0, 0x04}, 79 {RK817_CODEC_APLL_CFG1, 0x58}, 80 {RK817_CODEC_APLL_CFG2, 0x2d}, 81 {RK817_CODEC_APLL_CFG3, 0x0c}, 82 {RK817_CODEC_APLL_CFG4, 0xa5}, 83 {RK817_CODEC_APLL_CFG5, 0x00}, 84 85 {RK817_CODEC_DI2S_RXCMD_TSD, 0x00}, 86 {RK817_CODEC_DI2S_RSD, 0x00}, 87 /* {RK817_CODEC_DI2S_CKM, 0x00}, */ 88 {RK817_CODEC_DI2S_RXCR1, 0x00}, 89 {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, 90 {RK817_CODEC_DTOP_VUCTIME, 0xf4}, 91 {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00}, 92 93 {RK817_CODEC_DDAC_VOLL, 0x0a}, 94 {RK817_CODEC_DDAC_VOLR, 0x0a}, 95 }; 96 97 #define RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN \ 98 ARRAY_SIZE(playback_power_up_list) 99 100 static struct rk817_reg_val_typ playback_power_down_list[] = { 101 {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x01}, 102 {RK817_CODEC_ADAC_CFG1, 0x0f}, 103 /* HP */ 104 {RK817_CODEC_AHP_CFG0, 0xe0}, 105 {RK817_CODEC_AHP_CP, 0x09}, 106 /* SPK */ 107 {RK817_CODEC_ACLASSD_CFG1, 0x69}, 108 }; 109 110 #define RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN \ 111 ARRAY_SIZE(playback_power_down_list) 112 113 static int rk817_codec_power_up(struct rk817_codec_priv *rk817, int type) 114 { 115 struct udevice *codec = rk817->dev->parent; 116 int i; 117 118 DBG("%s : power up %s %s %s\n", __func__, 119 type & RK817_CODEC_PLAYBACK ? "playback" : "", 120 type & RK817_CODEC_CAPTURE ? "capture" : "", 121 type & RK817_CODEC_INCALL ? "incall" : ""); 122 123 if (type & RK817_CODEC_PLAYBACK) { 124 snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, 125 DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); 126 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) { 127 snd_soc_write(codec, playback_power_up_list[i].reg, 128 playback_power_up_list[i].value); 129 } 130 } 131 132 return 0; 133 } 134 135 static int rk817_codec_power_down(struct rk817_codec_priv *rk817, int type) 136 { 137 struct udevice *codec = rk817->dev->parent; 138 int i; 139 140 DBG("%s : power down %s %s %s\n", __func__, 141 type & RK817_CODEC_PLAYBACK ? "playback" : "", 142 type & RK817_CODEC_CAPTURE ? "capture" : "", 143 type & RK817_CODEC_INCALL ? "incall" : ""); 144 145 /* mute output for pop noise */ 146 if ((type & RK817_CODEC_PLAYBACK) || 147 (type & RK817_CODEC_INCALL)) { 148 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 149 DACMT_ENABLE, DACMT_ENABLE); 150 } 151 152 if (type & RK817_CODEC_PLAYBACK) { 153 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) { 154 snd_soc_write(codec, playback_power_down_list[i].reg, 155 playback_power_down_list[i].value); 156 } 157 snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, 158 DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); 159 } 160 161 if (type == RK817_CODEC_ALL) { 162 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) { 163 snd_soc_write(codec, playback_power_down_list[i].reg, 164 playback_power_down_list[i].value); 165 } 166 snd_soc_write(codec, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00); 167 snd_soc_write(codec, RK817_CODEC_APLL_CFG5, 0x01); 168 snd_soc_write(codec, RK817_CODEC_AREF_RTCFG1, 0x06); 169 } 170 171 return 0; 172 } 173 174 static int rk817_playback_path_put(struct rk817_codec_priv *rk817, int path) 175 { 176 struct udevice *codec = rk817->dev->parent; 177 long int pre_path; 178 179 if (rk817->playback_path == path) { 180 DBG("%s : playback_path is not changed!\n", __func__); 181 return 0; 182 } 183 184 pre_path = rk817->playback_path; 185 rk817->playback_path = path; 186 187 DBG("%s : set playback_path %ld, pre_path %ld\n", 188 __func__, rk817->playback_path, pre_path); 189 190 switch (rk817->playback_path) { 191 case OFF: 192 rk817_codec_power_down(rk817, RK817_CODEC_PLAYBACK); 193 break; 194 case RCV: 195 case SPK_PATH: 196 case RING_SPK: 197 if (pre_path == OFF) 198 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK); 199 if (!rk817->use_ext_amplifier) { 200 /* power on dac ibias/l/r */ 201 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, 202 PWD_DACBIAS_ON | PWD_DACD_ON | 203 PWD_DACL_ON | PWD_DACR_ON); 204 /* CLASS D mode */ 205 snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); 206 /* CLASS D enable */ 207 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); 208 /* restart CLASS D, OCPP/N */ 209 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); 210 } else { 211 /* HP_CP_EN , CP 2.3V */ 212 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); 213 /* power on HP two stage opamp ,HP amplitude 0db */ 214 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); 215 /* power on dac ibias/l/r */ 216 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, 217 PWD_DACBIAS_ON | PWD_DACD_DOWN | 218 PWD_DACL_ON | PWD_DACR_ON); 219 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 220 DACMT_ENABLE, DACMT_DISABLE); 221 } 222 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume); 223 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->spk_volume); 224 break; 225 case HP_PATH: 226 case HP_NO_MIC: 227 case RING_HP: 228 case RING_HP_NO_MIC: 229 if (pre_path == OFF) 230 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK); 231 /* HP_CP_EN , CP 2.3V */ 232 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); 233 /* power on HP two stage opamp ,HP amplitude 0db */ 234 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); 235 /* power on dac ibias/l/r */ 236 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, 237 PWD_DACBIAS_ON | PWD_DACD_DOWN | 238 PWD_DACL_ON | PWD_DACR_ON); 239 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 240 DACMT_ENABLE, DACMT_DISABLE); 241 242 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); 243 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); 244 break; 245 case BT: 246 break; 247 case SPK_HP: 248 case RING_SPK_HP: 249 if (pre_path == OFF) 250 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK); 251 252 /* HP_CP_EN , CP 2.3V */ 253 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); 254 /* power on HP two stage opamp ,HP amplitude 0db */ 255 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); 256 257 /* power on dac ibias/l/r */ 258 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, 259 PWD_DACBIAS_ON | PWD_DACD_ON | 260 PWD_DACL_ON | PWD_DACR_ON); 261 262 if (!rk817->use_ext_amplifier) { 263 /* CLASS D mode */ 264 snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); 265 /* CLASS D enable */ 266 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); 267 /* restart CLASS D, OCPP/N */ 268 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); 269 } 270 271 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); 272 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); 273 break; 274 default: 275 return -EINVAL; 276 } 277 278 return 0; 279 } 280 281 static int rk817_hw_params(struct udevice *dev, unsigned int samplerate, 282 unsigned int fmt, unsigned int channels) 283 { 284 struct rk817_codec_priv *rk817 = dev_get_priv(dev); 285 struct udevice *codec = rk817->dev->parent; 286 287 snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM, 288 RK817_I2S_MODE_MASK, RK817_I2S_MODE_SLV); 289 snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_16BITS); 290 snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_16BITS); 291 292 return 0; 293 } 294 295 static int rk817_digital_mute(struct rk817_codec_priv *rk817, int mute) 296 { 297 struct udevice *codec = rk817->dev->parent; 298 299 if (mute) 300 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 301 DACMT_ENABLE, DACMT_ENABLE); 302 else 303 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 304 DACMT_ENABLE, DACMT_DISABLE); 305 306 return 0; 307 } 308 309 static int rk817_startup(struct udevice *dev) 310 { 311 struct rk817_codec_priv *rk817 = dev_get_priv(dev); 312 313 rk817_playback_path_put(rk817, SPK_HP); 314 rk817_digital_mute(rk817, 0); 315 316 return 0; 317 } 318 319 static const struct snd_soc_dai_ops rk817_codec_ops = { 320 .hw_params = rk817_hw_params, 321 .startup = rk817_startup, 322 }; 323 324 static int rk817_codec_probe(struct udevice *dev) 325 { 326 struct rk8xx_priv *rk817 = dev_get_priv(dev->parent); 327 struct rk817_codec_priv *rk817_codec = dev_get_priv(dev); 328 329 if (!rk817) { 330 printf("%s : rk817 is null\n", __func__); 331 return -EINVAL; 332 } 333 334 switch (rk817->variant) { 335 case RK809_ID: 336 case RK817_ID: 337 break; 338 default: 339 return -EINVAL; 340 } 341 342 rk817_codec->dev = dev; 343 rk817_codec->hp_volume = INITIAL_VOLUME; 344 rk817_codec->spk_volume = INITIAL_VOLUME; 345 rk817_codec->playback_path = OFF; 346 rk817_reset(rk817_codec); 347 348 return 0; 349 } 350 351 static const struct udevice_id rk817_codec_ids[] = { 352 { .compatible = "rockchip,rk817-codec" }, 353 { } 354 }; 355 356 U_BOOT_DRIVER(rk817) = { 357 .name = "rk817_codec", 358 .id = UCLASS_CODEC, 359 .of_match = rk817_codec_ids, 360 .probe = rk817_codec_probe, 361 .priv_auto_alloc_size = sizeof(struct rk817_codec_priv), 362 .ops = &rk817_codec_ops, 363 }; 364 365 UCLASS_DRIVER(codec) = { 366 .id = UCLASS_CODEC, 367 .name = "codec", 368 }; 369