17ad4d237SShuming Fan // SPDX-License-Identifier: GPL-2.0-only 27ad4d237SShuming Fan // 37ad4d237SShuming Fan // rt711-sdca.c -- rt711 SDCA ALSA SoC audio driver 47ad4d237SShuming Fan // 57ad4d237SShuming Fan // Copyright(c) 2021 Realtek Semiconductor Corp. 67ad4d237SShuming Fan // 77ad4d237SShuming Fan // 87ad4d237SShuming Fan 97ad4d237SShuming Fan #include <linux/module.h> 107ad4d237SShuming Fan #include <linux/moduleparam.h> 117ad4d237SShuming Fan #include <linux/kernel.h> 127ad4d237SShuming Fan #include <linux/init.h> 137ad4d237SShuming Fan #include <linux/delay.h> 147ad4d237SShuming Fan #include <linux/pm_runtime.h> 157ad4d237SShuming Fan #include <linux/soundwire/sdw_registers.h> 167ad4d237SShuming Fan #include <linux/slab.h> 177ad4d237SShuming Fan #include <linux/bitops.h> 187ad4d237SShuming Fan #include <sound/core.h> 197ad4d237SShuming Fan #include <sound/pcm.h> 207ad4d237SShuming Fan #include <sound/pcm_params.h> 217ad4d237SShuming Fan #include <sound/soc-dapm.h> 227ad4d237SShuming Fan #include <sound/initval.h> 237ad4d237SShuming Fan #include <sound/tlv.h> 247ad4d237SShuming Fan #include <sound/jack.h> 257ad4d237SShuming Fan 267ad4d237SShuming Fan #include "rt711-sdca.h" 277ad4d237SShuming Fan 287ad4d237SShuming Fan static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711, 297ad4d237SShuming Fan unsigned int nid, unsigned int reg, unsigned int value) 307ad4d237SShuming Fan { 317ad4d237SShuming Fan int ret; 327ad4d237SShuming Fan struct regmap *regmap = rt711->mbq_regmap; 337ad4d237SShuming Fan unsigned int addr = (nid << 20) | reg; 347ad4d237SShuming Fan 357ad4d237SShuming Fan ret = regmap_write(regmap, addr, value); 367ad4d237SShuming Fan if (ret < 0) 377ad4d237SShuming Fan dev_err(rt711->component->dev, 387ad4d237SShuming Fan "Failed to set private value: %06x <= %04x ret=%d\n", 397ad4d237SShuming Fan addr, value, ret); 407ad4d237SShuming Fan 417ad4d237SShuming Fan return ret; 427ad4d237SShuming Fan } 437ad4d237SShuming Fan 447ad4d237SShuming Fan static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711, 457ad4d237SShuming Fan unsigned int nid, unsigned int reg, unsigned int *value) 467ad4d237SShuming Fan { 477ad4d237SShuming Fan int ret; 487ad4d237SShuming Fan struct regmap *regmap = rt711->mbq_regmap; 497ad4d237SShuming Fan unsigned int addr = (nid << 20) | reg; 507ad4d237SShuming Fan 517ad4d237SShuming Fan ret = regmap_read(regmap, addr, value); 527ad4d237SShuming Fan if (ret < 0) 537ad4d237SShuming Fan dev_err(rt711->component->dev, 547ad4d237SShuming Fan "Failed to get private value: %06x => %04x ret=%d\n", 557ad4d237SShuming Fan addr, *value, ret); 567ad4d237SShuming Fan 577ad4d237SShuming Fan return ret; 587ad4d237SShuming Fan } 597ad4d237SShuming Fan 607ad4d237SShuming Fan static int rt711_sdca_index_update_bits(struct rt711_sdca_priv *rt711, 617ad4d237SShuming Fan unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) 627ad4d237SShuming Fan { 637ad4d237SShuming Fan unsigned int tmp; 647ad4d237SShuming Fan int ret; 657ad4d237SShuming Fan 667ad4d237SShuming Fan ret = rt711_sdca_index_read(rt711, nid, reg, &tmp); 677ad4d237SShuming Fan if (ret < 0) 687ad4d237SShuming Fan return ret; 697ad4d237SShuming Fan 707ad4d237SShuming Fan set_mask_bits(&tmp, mask, val); 717ad4d237SShuming Fan return rt711_sdca_index_write(rt711, nid, reg, tmp); 727ad4d237SShuming Fan } 737ad4d237SShuming Fan 747ad4d237SShuming Fan static void rt711_sdca_reset(struct rt711_sdca_priv *rt711) 757ad4d237SShuming Fan { 767ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 777ad4d237SShuming Fan RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET, 787ad4d237SShuming Fan RT711_HIDDEN_REG_SW_RESET); 797ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 807ad4d237SShuming Fan RT711_HDA_LEGACY_RESET_CTL, 0x1, 0x1); 817ad4d237SShuming Fan } 827ad4d237SShuming Fan 837ad4d237SShuming Fan static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711) 847ad4d237SShuming Fan { 857ad4d237SShuming Fan unsigned int val, loop_rc = 0, loop_dc = 0; 867ad4d237SShuming Fan struct device *dev; 877ad4d237SShuming Fan struct regmap *regmap = rt711->regmap; 887ad4d237SShuming Fan int chk_cnt = 100; 897ad4d237SShuming Fan int ret = 0; 907ad4d237SShuming Fan 917ad4d237SShuming Fan mutex_lock(&rt711->calibrate_mutex); 927ad4d237SShuming Fan dev = regmap_get_device(regmap); 937ad4d237SShuming Fan 947ad4d237SShuming Fan regmap_read(rt711->regmap, RT711_RC_CAL_STATUS, &val); 957ad4d237SShuming Fan /* RC calibration */ 967ad4d237SShuming Fan if (!(val & 0x40)) 977ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, 987ad4d237SShuming Fan RT711_MISC_POWER_CTL0, 0x0010, 0x0010); 997ad4d237SShuming Fan 1007ad4d237SShuming Fan for (loop_rc = 0; loop_rc < chk_cnt && !(val & 0x40); loop_rc++) { 1017ad4d237SShuming Fan usleep_range(10000, 11000); 1027ad4d237SShuming Fan ret = regmap_read(rt711->regmap, RT711_RC_CAL_STATUS, &val); 1037ad4d237SShuming Fan if (ret < 0) 1047ad4d237SShuming Fan goto _cali_fail_; 1057ad4d237SShuming Fan } 1067ad4d237SShuming Fan if (loop_rc == chk_cnt) 1077ad4d237SShuming Fan dev_err(dev, "%s, RC calibration time-out!\n", __func__); 1087ad4d237SShuming Fan 1097ad4d237SShuming Fan /* HP calibration by manual mode setting */ 1107ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 1117ad4d237SShuming Fan RT711_FSM_CTL, 0x2000, 0x2000); 1127ad4d237SShuming Fan 1137ad4d237SShuming Fan /* Calibration manual mode */ 1147ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 1157ad4d237SShuming Fan RT711_FSM_CTL, 0xf, RT711_CALI_CTL); 1167ad4d237SShuming Fan 1177ad4d237SShuming Fan /* reset HP calibration */ 1187ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, 1197ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, 0x00); 1207ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, 1217ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, 1227ad4d237SShuming Fan RT711_DAC_DC_FORCE_CALI_RST); 1237ad4d237SShuming Fan 1247ad4d237SShuming Fan /* cal_clk_en_reg */ 1257ad4d237SShuming Fan if (rt711->hw_ver == RT711_VER_VD0) 1267ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, 1277ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_CLK_EN, 1287ad4d237SShuming Fan RT711_DAC_DC_CALI_CLK_EN); 1297ad4d237SShuming Fan 1307ad4d237SShuming Fan /* trigger */ 1317ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, 1327ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER, 1337ad4d237SShuming Fan RT711_DAC_DC_CALI_TRIGGER); 1347ad4d237SShuming Fan 1357ad4d237SShuming Fan /* wait for calibration process */ 1367ad4d237SShuming Fan rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, 1377ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, &val); 1387ad4d237SShuming Fan 1397ad4d237SShuming Fan for (loop_dc = 0; loop_dc < chk_cnt && 1407ad4d237SShuming Fan (val & RT711_DAC_DC_CALI_TRIGGER); loop_dc++) { 1417ad4d237SShuming Fan usleep_range(10000, 11000); 1427ad4d237SShuming Fan ret = rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, 1437ad4d237SShuming Fan RT711_DAC_DC_CALI_CTL1, &val); 1447ad4d237SShuming Fan if (ret < 0) 1457ad4d237SShuming Fan goto _cali_fail_; 1467ad4d237SShuming Fan } 1477ad4d237SShuming Fan if (loop_dc == chk_cnt) 1487ad4d237SShuming Fan dev_err(dev, "%s, calibration time-out!\n", __func__); 1497ad4d237SShuming Fan 1507ad4d237SShuming Fan if (loop_dc == chk_cnt || loop_rc == chk_cnt) 1517ad4d237SShuming Fan ret = -ETIMEDOUT; 1527ad4d237SShuming Fan 1537ad4d237SShuming Fan _cali_fail_: 1547ad4d237SShuming Fan /* enable impedance sense */ 1557ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 1567ad4d237SShuming Fan RT711_FSM_CTL, RT711_FSM_IMP_EN, RT711_FSM_IMP_EN); 1577ad4d237SShuming Fan 1587ad4d237SShuming Fan /* release HP-JD and trigger FSM */ 1597ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 1607ad4d237SShuming Fan RT711_DIGITAL_MISC_CTRL4, 0x201b); 1617ad4d237SShuming Fan 1627ad4d237SShuming Fan mutex_unlock(&rt711->calibrate_mutex); 1637ad4d237SShuming Fan dev_dbg(dev, "%s calibration complete, ret=%d\n", __func__, ret); 1647ad4d237SShuming Fan return ret; 1657ad4d237SShuming Fan } 1667ad4d237SShuming Fan 1677ad4d237SShuming Fan static unsigned int rt711_sdca_button_detect(struct rt711_sdca_priv *rt711) 1687ad4d237SShuming Fan { 1697ad4d237SShuming Fan unsigned int btn_type = 0, offset, idx, val, owner; 1707ad4d237SShuming Fan int ret; 1717ad4d237SShuming Fan unsigned char buf[3]; 1727ad4d237SShuming Fan 1737ad4d237SShuming Fan /* get current UMP message owner */ 1747ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 1757ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 1767ad4d237SShuming Fan &owner); 1777ad4d237SShuming Fan if (ret < 0) 1787ad4d237SShuming Fan return 0; 1797ad4d237SShuming Fan 1807ad4d237SShuming Fan /* if owner is device then there is no button event from device */ 1817ad4d237SShuming Fan if (owner == 1) 1827ad4d237SShuming Fan return 0; 1837ad4d237SShuming Fan 1847ad4d237SShuming Fan /* read UMP message offset */ 1857ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 1867ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), 1877ad4d237SShuming Fan &offset); 1887ad4d237SShuming Fan if (ret < 0) 1897ad4d237SShuming Fan goto _end_btn_det_; 1907ad4d237SShuming Fan 1917ad4d237SShuming Fan for (idx = 0; idx < sizeof(buf); idx++) { 1927ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 1937ad4d237SShuming Fan RT711_BUF_ADDR_HID1 + offset + idx, &val); 1947ad4d237SShuming Fan if (ret < 0) 1957ad4d237SShuming Fan goto _end_btn_det_; 1967ad4d237SShuming Fan buf[idx] = val & 0xff; 1977ad4d237SShuming Fan } 1987ad4d237SShuming Fan 1997ad4d237SShuming Fan if (buf[0] == 0x11) { 2007ad4d237SShuming Fan switch (buf[1] & 0xf0) { 2017ad4d237SShuming Fan case 0x10: 2027ad4d237SShuming Fan btn_type |= SND_JACK_BTN_2; 2037ad4d237SShuming Fan break; 2047ad4d237SShuming Fan case 0x20: 2057ad4d237SShuming Fan btn_type |= SND_JACK_BTN_3; 2067ad4d237SShuming Fan break; 2077ad4d237SShuming Fan case 0x40: 2087ad4d237SShuming Fan btn_type |= SND_JACK_BTN_0; 2097ad4d237SShuming Fan break; 2107ad4d237SShuming Fan case 0x80: 2117ad4d237SShuming Fan btn_type |= SND_JACK_BTN_1; 2127ad4d237SShuming Fan break; 2137ad4d237SShuming Fan } 2147ad4d237SShuming Fan switch (buf[2]) { 2157ad4d237SShuming Fan case 0x01: 2167ad4d237SShuming Fan case 0x10: 2177ad4d237SShuming Fan btn_type |= SND_JACK_BTN_2; 2187ad4d237SShuming Fan break; 2197ad4d237SShuming Fan case 0x02: 2207ad4d237SShuming Fan case 0x20: 2217ad4d237SShuming Fan btn_type |= SND_JACK_BTN_3; 2227ad4d237SShuming Fan break; 2237ad4d237SShuming Fan case 0x04: 2247ad4d237SShuming Fan case 0x40: 2257ad4d237SShuming Fan btn_type |= SND_JACK_BTN_0; 2267ad4d237SShuming Fan break; 2277ad4d237SShuming Fan case 0x08: 2287ad4d237SShuming Fan case 0x80: 2297ad4d237SShuming Fan btn_type |= SND_JACK_BTN_1; 2307ad4d237SShuming Fan break; 2317ad4d237SShuming Fan } 2327ad4d237SShuming Fan } 2337ad4d237SShuming Fan 2347ad4d237SShuming Fan _end_btn_det_: 2357ad4d237SShuming Fan /* Host is owner, so set back to device */ 2367ad4d237SShuming Fan if (owner == 0) 2377ad4d237SShuming Fan /* set owner to device */ 2387ad4d237SShuming Fan regmap_write(rt711->regmap, 2397ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, 2407ad4d237SShuming Fan RT711_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE, 0), 0x01); 2417ad4d237SShuming Fan 2427ad4d237SShuming Fan return btn_type; 2437ad4d237SShuming Fan } 2447ad4d237SShuming Fan 2457ad4d237SShuming Fan static int rt711_sdca_headset_detect(struct rt711_sdca_priv *rt711) 2467ad4d237SShuming Fan { 2477ad4d237SShuming Fan unsigned int det_mode; 2487ad4d237SShuming Fan int ret; 2497ad4d237SShuming Fan 2507ad4d237SShuming Fan /* get detected_mode */ 2517ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 2527ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), 2537ad4d237SShuming Fan &det_mode); 2547ad4d237SShuming Fan if (ret < 0) 2557ad4d237SShuming Fan goto io_error; 2567ad4d237SShuming Fan 2577ad4d237SShuming Fan switch (det_mode) { 2587ad4d237SShuming Fan case 0x00: 2597ad4d237SShuming Fan rt711->jack_type = 0; 2607ad4d237SShuming Fan break; 2617ad4d237SShuming Fan case 0x03: 2627ad4d237SShuming Fan rt711->jack_type = SND_JACK_HEADPHONE; 2637ad4d237SShuming Fan break; 2647ad4d237SShuming Fan case 0x05: 2657ad4d237SShuming Fan rt711->jack_type = SND_JACK_HEADSET; 2667ad4d237SShuming Fan break; 2677ad4d237SShuming Fan } 2687ad4d237SShuming Fan 2697ad4d237SShuming Fan /* write selected_mode */ 2707ad4d237SShuming Fan if (det_mode) { 2717ad4d237SShuming Fan ret = regmap_write(rt711->regmap, 2727ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_SELECTED_MODE, 0), 2737ad4d237SShuming Fan det_mode); 2747ad4d237SShuming Fan if (ret < 0) 2757ad4d237SShuming Fan goto io_error; 2767ad4d237SShuming Fan } 2777ad4d237SShuming Fan 2787ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, 2797ad4d237SShuming Fan "%s, detected_mode=0x%x\n", __func__, det_mode); 2807ad4d237SShuming Fan 2817ad4d237SShuming Fan return 0; 2827ad4d237SShuming Fan 2837ad4d237SShuming Fan io_error: 2847ad4d237SShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); 2857ad4d237SShuming Fan return ret; 2867ad4d237SShuming Fan } 2877ad4d237SShuming Fan 2887ad4d237SShuming Fan static void rt711_sdca_jack_detect_handler(struct work_struct *work) 2897ad4d237SShuming Fan { 2907ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = 2917ad4d237SShuming Fan container_of(work, struct rt711_sdca_priv, jack_detect_work.work); 2927ad4d237SShuming Fan int btn_type = 0, ret; 2937ad4d237SShuming Fan 2947ad4d237SShuming Fan if (!rt711->hs_jack) 2957ad4d237SShuming Fan return; 2967ad4d237SShuming Fan 29705ba4c00SPierre-Louis Bossart if (!rt711->component->card || !rt711->component->card->instantiated) 2987ad4d237SShuming Fan return; 2997ad4d237SShuming Fan 3007ad4d237SShuming Fan /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ 3017ad4d237SShuming Fan if (rt711->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) { 3027ad4d237SShuming Fan ret = rt711_sdca_headset_detect(rt711); 3037ad4d237SShuming Fan if (ret < 0) 3047ad4d237SShuming Fan return; 3057ad4d237SShuming Fan } 3067ad4d237SShuming Fan 3077ad4d237SShuming Fan /* SDW_SCP_SDCA_INT_SDCA_8 is used for button detection */ 3087ad4d237SShuming Fan if (rt711->scp_sdca_stat2 & SDW_SCP_SDCA_INT_SDCA_8) 3097ad4d237SShuming Fan btn_type = rt711_sdca_button_detect(rt711); 3107ad4d237SShuming Fan 3117ad4d237SShuming Fan if (rt711->jack_type == 0) 3127ad4d237SShuming Fan btn_type = 0; 3137ad4d237SShuming Fan 3147ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, 3157ad4d237SShuming Fan "in %s, jack_type=0x%x\n", __func__, rt711->jack_type); 3167ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, 3177ad4d237SShuming Fan "in %s, btn_type=0x%x\n", __func__, btn_type); 3187ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, 3197ad4d237SShuming Fan "in %s, scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, 3207ad4d237SShuming Fan rt711->scp_sdca_stat1, rt711->scp_sdca_stat2); 3217ad4d237SShuming Fan 3227ad4d237SShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type, 3237ad4d237SShuming Fan SND_JACK_HEADSET | 3247ad4d237SShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 | 3257ad4d237SShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3); 3267ad4d237SShuming Fan 3277ad4d237SShuming Fan if (btn_type) { 3287ad4d237SShuming Fan /* button released */ 3297ad4d237SShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type, 3307ad4d237SShuming Fan SND_JACK_HEADSET | 3317ad4d237SShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 | 3327ad4d237SShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3); 3337ad4d237SShuming Fan 3347ad4d237SShuming Fan mod_delayed_work(system_power_efficient_wq, 3357ad4d237SShuming Fan &rt711->jack_btn_check_work, msecs_to_jiffies(200)); 3367ad4d237SShuming Fan } 3377ad4d237SShuming Fan } 3387ad4d237SShuming Fan 3397ad4d237SShuming Fan static void rt711_sdca_btn_check_handler(struct work_struct *work) 3407ad4d237SShuming Fan { 3417ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = 3427ad4d237SShuming Fan container_of(work, struct rt711_sdca_priv, jack_btn_check_work.work); 3437ad4d237SShuming Fan int btn_type = 0, ret, idx; 3447ad4d237SShuming Fan unsigned int det_mode, offset, val; 3457ad4d237SShuming Fan unsigned char buf[3]; 3467ad4d237SShuming Fan 3477ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 3487ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), 3497ad4d237SShuming Fan &det_mode); 3507ad4d237SShuming Fan if (ret < 0) 3517ad4d237SShuming Fan goto io_error; 3527ad4d237SShuming Fan 3537ad4d237SShuming Fan /* pin attached */ 3547ad4d237SShuming Fan if (det_mode) { 3557ad4d237SShuming Fan /* read UMP message offset */ 3567ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 3577ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), 3587ad4d237SShuming Fan &offset); 3597ad4d237SShuming Fan if (ret < 0) 3607ad4d237SShuming Fan goto io_error; 3617ad4d237SShuming Fan 3627ad4d237SShuming Fan for (idx = 0; idx < sizeof(buf); idx++) { 3637ad4d237SShuming Fan ret = regmap_read(rt711->regmap, 3647ad4d237SShuming Fan RT711_BUF_ADDR_HID1 + offset + idx, &val); 3657ad4d237SShuming Fan if (ret < 0) 3667ad4d237SShuming Fan goto io_error; 3677ad4d237SShuming Fan buf[idx] = val & 0xff; 3687ad4d237SShuming Fan } 3697ad4d237SShuming Fan 3707ad4d237SShuming Fan if (buf[0] == 0x11) { 3717ad4d237SShuming Fan switch (buf[1] & 0xf0) { 3727ad4d237SShuming Fan case 0x10: 3737ad4d237SShuming Fan btn_type |= SND_JACK_BTN_2; 3747ad4d237SShuming Fan break; 3757ad4d237SShuming Fan case 0x20: 3767ad4d237SShuming Fan btn_type |= SND_JACK_BTN_3; 3777ad4d237SShuming Fan break; 3787ad4d237SShuming Fan case 0x40: 3797ad4d237SShuming Fan btn_type |= SND_JACK_BTN_0; 3807ad4d237SShuming Fan break; 3817ad4d237SShuming Fan case 0x80: 3827ad4d237SShuming Fan btn_type |= SND_JACK_BTN_1; 3837ad4d237SShuming Fan break; 3847ad4d237SShuming Fan } 3857ad4d237SShuming Fan switch (buf[2]) { 3867ad4d237SShuming Fan case 0x01: 3877ad4d237SShuming Fan case 0x10: 3887ad4d237SShuming Fan btn_type |= SND_JACK_BTN_2; 3897ad4d237SShuming Fan break; 3907ad4d237SShuming Fan case 0x02: 3917ad4d237SShuming Fan case 0x20: 3927ad4d237SShuming Fan btn_type |= SND_JACK_BTN_3; 3937ad4d237SShuming Fan break; 3947ad4d237SShuming Fan case 0x04: 3957ad4d237SShuming Fan case 0x40: 3967ad4d237SShuming Fan btn_type |= SND_JACK_BTN_0; 3977ad4d237SShuming Fan break; 3987ad4d237SShuming Fan case 0x08: 3997ad4d237SShuming Fan case 0x80: 4007ad4d237SShuming Fan btn_type |= SND_JACK_BTN_1; 4017ad4d237SShuming Fan break; 4027ad4d237SShuming Fan } 4037ad4d237SShuming Fan } 4047ad4d237SShuming Fan } else 4057ad4d237SShuming Fan rt711->jack_type = 0; 4067ad4d237SShuming Fan 4077ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, "%s, btn_type=0x%x\n", __func__, btn_type); 4087ad4d237SShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type, 4097ad4d237SShuming Fan SND_JACK_HEADSET | 4107ad4d237SShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 | 4117ad4d237SShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3); 4127ad4d237SShuming Fan 4137ad4d237SShuming Fan if (btn_type) { 4147ad4d237SShuming Fan /* button released */ 4157ad4d237SShuming Fan snd_soc_jack_report(rt711->hs_jack, rt711->jack_type, 4167ad4d237SShuming Fan SND_JACK_HEADSET | 4177ad4d237SShuming Fan SND_JACK_BTN_0 | SND_JACK_BTN_1 | 4187ad4d237SShuming Fan SND_JACK_BTN_2 | SND_JACK_BTN_3); 4197ad4d237SShuming Fan 4207ad4d237SShuming Fan mod_delayed_work(system_power_efficient_wq, 4217ad4d237SShuming Fan &rt711->jack_btn_check_work, msecs_to_jiffies(200)); 4227ad4d237SShuming Fan } 4237ad4d237SShuming Fan 4247ad4d237SShuming Fan return; 4257ad4d237SShuming Fan 4267ad4d237SShuming Fan io_error: 4277ad4d237SShuming Fan pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); 4287ad4d237SShuming Fan } 4297ad4d237SShuming Fan 4307ad4d237SShuming Fan static void rt711_sdca_jack_init(struct rt711_sdca_priv *rt711) 4317ad4d237SShuming Fan { 4327ad4d237SShuming Fan mutex_lock(&rt711->calibrate_mutex); 4337ad4d237SShuming Fan 4347ad4d237SShuming Fan if (rt711->hs_jack) { 4357ad4d237SShuming Fan /* Enable HID1 event & set button RTC mode */ 4367ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 4377ad4d237SShuming Fan RT711_PUSH_BTN_INT_CTL6, 0x80f0, 0x8000); 4387ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 4397ad4d237SShuming Fan RT711_PUSH_BTN_INT_CTL2, 0x11dd, 0x11dd); 4407ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, 4417ad4d237SShuming Fan RT711_PUSH_BTN_INT_CTL7, 0xffff); 4427ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 4437ad4d237SShuming Fan RT711_PUSH_BTN_INT_CTL9, 0xf000, 0x0000); 4447ad4d237SShuming Fan 4457ad4d237SShuming Fan /* GE_mode_change_event_en & Hid1_push_button_event_en */ 4467ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 4477ad4d237SShuming Fan RT711_GE_MODE_RELATED_CTL, 0x0c00, 0x0c00); 4487ad4d237SShuming Fan 4497ad4d237SShuming Fan switch (rt711->jd_src) { 4507ad4d237SShuming Fan case RT711_JD1: 4517ad4d237SShuming Fan /* default settings was already for JD1 */ 4527ad4d237SShuming Fan break; 4537ad4d237SShuming Fan case RT711_JD2: 4547ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 4557ad4d237SShuming Fan RT711_JD_CTL1, RT711_JD2_DIGITAL_MODE_SEL, 4567ad4d237SShuming Fan RT711_JD2_DIGITAL_MODE_SEL); 4577ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 4587ad4d237SShuming Fan RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2, 4597ad4d237SShuming Fan RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2); 4607ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 4617ad4d237SShuming Fan RT711_CC_DET1, 4627ad4d237SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12, 4637ad4d237SShuming Fan RT711_HP_JD_FINAL_RESULT_CTL_JD12); 4647ad4d237SShuming Fan break; 4657ad4d237SShuming Fan default: 4667ad4d237SShuming Fan dev_warn(rt711->component->dev, "Wrong JD source\n"); 4677ad4d237SShuming Fan break; 4687ad4d237SShuming Fan } 4697ad4d237SShuming Fan 4707ad4d237SShuming Fan /* set SCP_SDCA_IntMask1[0]=1 */ 4717ad4d237SShuming Fan sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0); 4727ad4d237SShuming Fan /* set SCP_SDCA_IntMask2[0]=1 */ 4737ad4d237SShuming Fan sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); 4747ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, "in %s enable\n", __func__); 4757ad4d237SShuming Fan } else { 4767ad4d237SShuming Fan /* disable HID 1/2 event */ 4777ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 4787ad4d237SShuming Fan RT711_GE_MODE_RELATED_CTL, 0x0c00, 0x0000); 4797ad4d237SShuming Fan 4807ad4d237SShuming Fan dev_dbg(&rt711->slave->dev, "in %s disable\n", __func__); 4817ad4d237SShuming Fan } 4827ad4d237SShuming Fan 4837ad4d237SShuming Fan mutex_unlock(&rt711->calibrate_mutex); 4847ad4d237SShuming Fan } 4857ad4d237SShuming Fan 4867ad4d237SShuming Fan static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, 4877ad4d237SShuming Fan struct snd_soc_jack *hs_jack, void *data) 4887ad4d237SShuming Fan { 4897ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 490e02b99e9SPierre-Louis Bossart int ret; 4917ad4d237SShuming Fan 4927ad4d237SShuming Fan rt711->hs_jack = hs_jack; 4937ad4d237SShuming Fan 494e02b99e9SPierre-Louis Bossart ret = pm_runtime_resume_and_get(component->dev); 495e02b99e9SPierre-Louis Bossart if (ret < 0) { 496e02b99e9SPierre-Louis Bossart if (ret != -EACCES) { 497e02b99e9SPierre-Louis Bossart dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); 498e02b99e9SPierre-Louis Bossart return ret; 499e02b99e9SPierre-Louis Bossart } 500e02b99e9SPierre-Louis Bossart 501e02b99e9SPierre-Louis Bossart /* pm_runtime not enabled yet */ 502e02b99e9SPierre-Louis Bossart dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); 5037ad4d237SShuming Fan return 0; 5047ad4d237SShuming Fan } 5057ad4d237SShuming Fan 5067ad4d237SShuming Fan rt711_sdca_jack_init(rt711); 507e02b99e9SPierre-Louis Bossart 508e02b99e9SPierre-Louis Bossart pm_runtime_mark_last_busy(component->dev); 509e02b99e9SPierre-Louis Bossart pm_runtime_put_autosuspend(component->dev); 510e02b99e9SPierre-Louis Bossart 5117ad4d237SShuming Fan return 0; 5127ad4d237SShuming Fan } 5137ad4d237SShuming Fan 5147ad4d237SShuming Fan /* For SDCA control DAC/ADC Gain */ 5157ad4d237SShuming Fan static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, 5167ad4d237SShuming Fan struct snd_ctl_elem_value *ucontrol) 5177ad4d237SShuming Fan { 5187ad4d237SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 5197ad4d237SShuming Fan struct soc_mixer_control *mc = 5207ad4d237SShuming Fan (struct soc_mixer_control *)kcontrol->private_value; 5217ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 5227ad4d237SShuming Fan unsigned int read_l, read_r, gain_l_val, gain_r_val; 523a1aee7f7SShuming Fan unsigned int i, adc_vol_flag = 0, changed = 0; 524a1aee7f7SShuming Fan unsigned int lvalue, rvalue; 5257ad4d237SShuming Fan 5267ad4d237SShuming Fan if (strstr(ucontrol->id.name, "FU1E Capture Volume") || 5277ad4d237SShuming Fan strstr(ucontrol->id.name, "FU0F Capture Volume")) 5287ad4d237SShuming Fan adc_vol_flag = 1; 5297ad4d237SShuming Fan 530a1aee7f7SShuming Fan regmap_read(rt711->mbq_regmap, mc->reg, &lvalue); 531a1aee7f7SShuming Fan regmap_read(rt711->mbq_regmap, mc->rreg, &rvalue); 532a1aee7f7SShuming Fan 5337ad4d237SShuming Fan /* control value to 2's complement value */ 5347ad4d237SShuming Fan /* L Channel */ 5357ad4d237SShuming Fan gain_l_val = ucontrol->value.integer.value[0]; 5367ad4d237SShuming Fan if (gain_l_val > mc->max) 5377ad4d237SShuming Fan gain_l_val = mc->max; 5387ad4d237SShuming Fan read_l = gain_l_val; 5397ad4d237SShuming Fan 5407ad4d237SShuming Fan if (mc->shift == 8) /* boost gain */ 5417ad4d237SShuming Fan gain_l_val = (gain_l_val * 10) << mc->shift; 5427ad4d237SShuming Fan else { /* ADC/DAC gain */ 5437ad4d237SShuming Fan if (adc_vol_flag && gain_l_val > mc->shift) 5447ad4d237SShuming Fan gain_l_val = (gain_l_val - mc->shift) * 75; 5457ad4d237SShuming Fan else 5467ad4d237SShuming Fan gain_l_val = (mc->shift - gain_l_val) * 75; 5477ad4d237SShuming Fan gain_l_val <<= 8; 5487ad4d237SShuming Fan gain_l_val /= 100; 5497ad4d237SShuming Fan if (!(adc_vol_flag && read_l > mc->shift)) { 5507ad4d237SShuming Fan gain_l_val = ~gain_l_val; 5517ad4d237SShuming Fan gain_l_val += 1; 5527ad4d237SShuming Fan } 5537ad4d237SShuming Fan gain_l_val &= 0xffff; 5547ad4d237SShuming Fan } 5557ad4d237SShuming Fan 5567ad4d237SShuming Fan /* R Channel */ 5577ad4d237SShuming Fan gain_r_val = ucontrol->value.integer.value[1]; 5587ad4d237SShuming Fan if (gain_r_val > mc->max) 5597ad4d237SShuming Fan gain_r_val = mc->max; 5607ad4d237SShuming Fan read_r = gain_r_val; 5617ad4d237SShuming Fan 5627ad4d237SShuming Fan if (mc->shift == 8) /* boost gain */ 5637ad4d237SShuming Fan gain_r_val = (gain_r_val * 10) << mc->shift; 5647ad4d237SShuming Fan else { /* ADC/DAC gain */ 5657ad4d237SShuming Fan if (adc_vol_flag && gain_r_val > mc->shift) 5667ad4d237SShuming Fan gain_r_val = (gain_r_val - mc->shift) * 75; 5677ad4d237SShuming Fan else 5687ad4d237SShuming Fan gain_r_val = (mc->shift - gain_r_val) * 75; 5697ad4d237SShuming Fan gain_r_val <<= 8; 5707ad4d237SShuming Fan gain_r_val /= 100; 5717ad4d237SShuming Fan if (!(adc_vol_flag && read_r > mc->shift)) { 5727ad4d237SShuming Fan gain_r_val = ~gain_r_val; 5737ad4d237SShuming Fan gain_r_val += 1; 5747ad4d237SShuming Fan } 5757ad4d237SShuming Fan gain_r_val &= 0xffff; 5767ad4d237SShuming Fan } 5777ad4d237SShuming Fan 578a1aee7f7SShuming Fan if (lvalue != gain_l_val || rvalue != gain_r_val) 579a1aee7f7SShuming Fan changed = 1; 580a1aee7f7SShuming Fan else 581a1aee7f7SShuming Fan return 0; 582a1aee7f7SShuming Fan 5837ad4d237SShuming Fan for (i = 0; i < 3; i++) { /* retry 3 times at most */ 5847ad4d237SShuming Fan /* Lch*/ 5857ad4d237SShuming Fan regmap_write(rt711->mbq_regmap, mc->reg, gain_l_val); 5867ad4d237SShuming Fan 5877ad4d237SShuming Fan /* Rch */ 5887ad4d237SShuming Fan regmap_write(rt711->mbq_regmap, mc->rreg, gain_r_val); 5897ad4d237SShuming Fan 5907ad4d237SShuming Fan regmap_read(rt711->mbq_regmap, mc->reg, &read_l); 5917ad4d237SShuming Fan regmap_read(rt711->mbq_regmap, mc->rreg, &read_r); 5927ad4d237SShuming Fan if (read_r == gain_r_val && read_l == gain_l_val) 5937ad4d237SShuming Fan break; 5947ad4d237SShuming Fan } 5957ad4d237SShuming Fan 596a1aee7f7SShuming Fan return i == 3 ? -EIO : changed; 5977ad4d237SShuming Fan } 5987ad4d237SShuming Fan 5997ad4d237SShuming Fan static int rt711_sdca_set_gain_get(struct snd_kcontrol *kcontrol, 6007ad4d237SShuming Fan struct snd_ctl_elem_value *ucontrol) 6017ad4d237SShuming Fan { 6027ad4d237SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6037ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 6047ad4d237SShuming Fan struct soc_mixer_control *mc = 6057ad4d237SShuming Fan (struct soc_mixer_control *)kcontrol->private_value; 6067ad4d237SShuming Fan unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; 6077ad4d237SShuming Fan unsigned int adc_vol_flag = 0, neg_flag = 0; 6087ad4d237SShuming Fan 6097ad4d237SShuming Fan if (strstr(ucontrol->id.name, "FU1E Capture Volume") || 6107ad4d237SShuming Fan strstr(ucontrol->id.name, "FU0F Capture Volume")) 6117ad4d237SShuming Fan adc_vol_flag = 1; 6127ad4d237SShuming Fan 6137ad4d237SShuming Fan regmap_read(rt711->mbq_regmap, mc->reg, &read_l); 6147ad4d237SShuming Fan regmap_read(rt711->mbq_regmap, mc->rreg, &read_r); 6157ad4d237SShuming Fan 6167ad4d237SShuming Fan /* 2's complement value to control value */ 6177ad4d237SShuming Fan if (mc->shift == 8) /* boost gain */ 6187ad4d237SShuming Fan ctl_l = (read_l >> mc->shift) / 10; 6197ad4d237SShuming Fan else { /* ADC/DAC gain */ 6207ad4d237SShuming Fan ctl_l = read_l; 6217ad4d237SShuming Fan if (read_l & BIT(15)) { 6227ad4d237SShuming Fan ctl_l = 0xffff & ~(read_l - 1); 6237ad4d237SShuming Fan neg_flag = 1; 6247ad4d237SShuming Fan } 6257ad4d237SShuming Fan ctl_l *= 100; 6267ad4d237SShuming Fan ctl_l >>= 8; 6277ad4d237SShuming Fan if (adc_vol_flag) { 6287ad4d237SShuming Fan if (neg_flag) 6297ad4d237SShuming Fan ctl_l = mc->shift - (ctl_l / 75); 6307ad4d237SShuming Fan else 6317ad4d237SShuming Fan ctl_l = mc->shift + (ctl_l / 75); 6327ad4d237SShuming Fan } else 6337ad4d237SShuming Fan ctl_l = mc->max - (ctl_l / 75); 6347ad4d237SShuming Fan } 6357ad4d237SShuming Fan 6367ad4d237SShuming Fan neg_flag = 0; 6377ad4d237SShuming Fan if (read_l != read_r) { 6387ad4d237SShuming Fan if (mc->shift == 8) /* boost gain */ 6397ad4d237SShuming Fan ctl_r = (read_r >> mc->shift) / 10; 6407ad4d237SShuming Fan else { /* ADC/DAC gain */ 6417ad4d237SShuming Fan ctl_r = read_r; 6427ad4d237SShuming Fan if (read_r & BIT(15)) { 6437ad4d237SShuming Fan ctl_r = 0xffff & ~(read_r - 1); 6447ad4d237SShuming Fan neg_flag = 1; 6457ad4d237SShuming Fan } 6467ad4d237SShuming Fan ctl_r *= 100; 6477ad4d237SShuming Fan ctl_r >>= 8; 6487ad4d237SShuming Fan if (adc_vol_flag) { 6497ad4d237SShuming Fan if (neg_flag) 6507ad4d237SShuming Fan ctl_r = mc->shift - (ctl_r / 75); 6517ad4d237SShuming Fan else 6527ad4d237SShuming Fan ctl_r = mc->shift + (ctl_r / 75); 6537ad4d237SShuming Fan } else 6547ad4d237SShuming Fan ctl_r = mc->max - (ctl_r / 75); 6557ad4d237SShuming Fan } 6567ad4d237SShuming Fan } else 6577ad4d237SShuming Fan ctl_r = ctl_l; 6587ad4d237SShuming Fan 6597ad4d237SShuming Fan ucontrol->value.integer.value[0] = ctl_l; 6607ad4d237SShuming Fan ucontrol->value.integer.value[1] = ctl_r; 6617ad4d237SShuming Fan 6627ad4d237SShuming Fan return 0; 6637ad4d237SShuming Fan } 6647ad4d237SShuming Fan 665ca5118c0SShuming Fan static int rt711_sdca_set_fu0f_capture_ctl(struct rt711_sdca_priv *rt711) 666ca5118c0SShuming Fan { 667ca5118c0SShuming Fan int err; 668ca5118c0SShuming Fan unsigned int ch_l, ch_r; 669ca5118c0SShuming Fan 670ca5118c0SShuming Fan ch_l = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_l_mute) ? 0x01 : 0x00; 671ca5118c0SShuming Fan ch_r = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_r_mute) ? 0x01 : 0x00; 672ca5118c0SShuming Fan 673ca5118c0SShuming Fan err = regmap_write(rt711->regmap, 674ca5118c0SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, 675ca5118c0SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_L), ch_l); 676ca5118c0SShuming Fan if (err < 0) 677ca5118c0SShuming Fan return err; 678ca5118c0SShuming Fan 679ca5118c0SShuming Fan err = regmap_write(rt711->regmap, 680ca5118c0SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, 681ca5118c0SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_R), ch_r); 682ca5118c0SShuming Fan if (err < 0) 683ca5118c0SShuming Fan return err; 684ca5118c0SShuming Fan 685ca5118c0SShuming Fan return 0; 686ca5118c0SShuming Fan } 687ca5118c0SShuming Fan 688ca5118c0SShuming Fan static int rt711_sdca_set_fu1e_capture_ctl(struct rt711_sdca_priv *rt711) 689ca5118c0SShuming Fan { 690ca5118c0SShuming Fan int err; 691ca5118c0SShuming Fan unsigned int ch_l, ch_r; 692ca5118c0SShuming Fan 693ca5118c0SShuming Fan ch_l = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_l_mute) ? 0x01 : 0x00; 694ca5118c0SShuming Fan ch_r = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_r_mute) ? 0x01 : 0x00; 695ca5118c0SShuming Fan 696ca5118c0SShuming Fan err = regmap_write(rt711->regmap, 697682ae59cSShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, 698ca5118c0SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_L), ch_l); 699ca5118c0SShuming Fan if (err < 0) 700ca5118c0SShuming Fan return err; 701ca5118c0SShuming Fan 702ca5118c0SShuming Fan err = regmap_write(rt711->regmap, 703682ae59cSShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, 704ca5118c0SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_R), ch_r); 705ca5118c0SShuming Fan if (err < 0) 706ca5118c0SShuming Fan return err; 707ca5118c0SShuming Fan 708ca5118c0SShuming Fan return 0; 709ca5118c0SShuming Fan } 710ca5118c0SShuming Fan 711ca5118c0SShuming Fan static int rt711_sdca_fu1e_capture_get(struct snd_kcontrol *kcontrol, 712ca5118c0SShuming Fan struct snd_ctl_elem_value *ucontrol) 713ca5118c0SShuming Fan { 714ca5118c0SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 715ca5118c0SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 716ca5118c0SShuming Fan 717ca5118c0SShuming Fan ucontrol->value.integer.value[0] = !rt711->fu1e_mixer_l_mute; 718ca5118c0SShuming Fan ucontrol->value.integer.value[1] = !rt711->fu1e_mixer_r_mute; 719ca5118c0SShuming Fan return 0; 720ca5118c0SShuming Fan } 721ca5118c0SShuming Fan 722ca5118c0SShuming Fan static int rt711_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol, 723ca5118c0SShuming Fan struct snd_ctl_elem_value *ucontrol) 724ca5118c0SShuming Fan { 725ca5118c0SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 726ca5118c0SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 727ca5118c0SShuming Fan int err, changed = 0; 728ca5118c0SShuming Fan 729ca5118c0SShuming Fan if (rt711->fu1e_mixer_l_mute != !ucontrol->value.integer.value[0] || 730ca5118c0SShuming Fan rt711->fu1e_mixer_r_mute != !ucontrol->value.integer.value[1]) 731ca5118c0SShuming Fan changed = 1; 732ca5118c0SShuming Fan 733ca5118c0SShuming Fan rt711->fu1e_mixer_l_mute = !ucontrol->value.integer.value[0]; 734ca5118c0SShuming Fan rt711->fu1e_mixer_r_mute = !ucontrol->value.integer.value[1]; 735ca5118c0SShuming Fan err = rt711_sdca_set_fu1e_capture_ctl(rt711); 736ca5118c0SShuming Fan if (err < 0) 737ca5118c0SShuming Fan return err; 738ca5118c0SShuming Fan 739ca5118c0SShuming Fan return changed; 740ca5118c0SShuming Fan } 741ca5118c0SShuming Fan 742ca5118c0SShuming Fan static int rt711_sdca_fu0f_capture_get(struct snd_kcontrol *kcontrol, 743ca5118c0SShuming Fan struct snd_ctl_elem_value *ucontrol) 744ca5118c0SShuming Fan { 745ca5118c0SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 746ca5118c0SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 747ca5118c0SShuming Fan 748ca5118c0SShuming Fan ucontrol->value.integer.value[0] = !rt711->fu0f_mixer_l_mute; 749ca5118c0SShuming Fan ucontrol->value.integer.value[1] = !rt711->fu0f_mixer_r_mute; 750ca5118c0SShuming Fan return 0; 751ca5118c0SShuming Fan } 752ca5118c0SShuming Fan 753ca5118c0SShuming Fan static int rt711_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol, 754ca5118c0SShuming Fan struct snd_ctl_elem_value *ucontrol) 755ca5118c0SShuming Fan { 756ca5118c0SShuming Fan struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 757ca5118c0SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 758ca5118c0SShuming Fan int err, changed = 0; 759ca5118c0SShuming Fan 760ca5118c0SShuming Fan if (rt711->fu0f_mixer_l_mute != !ucontrol->value.integer.value[0] || 761ca5118c0SShuming Fan rt711->fu0f_mixer_r_mute != !ucontrol->value.integer.value[1]) 762ca5118c0SShuming Fan changed = 1; 763ca5118c0SShuming Fan 764ca5118c0SShuming Fan rt711->fu0f_mixer_l_mute = !ucontrol->value.integer.value[0]; 765ca5118c0SShuming Fan rt711->fu0f_mixer_r_mute = !ucontrol->value.integer.value[1]; 766ca5118c0SShuming Fan err = rt711_sdca_set_fu0f_capture_ctl(rt711); 767ca5118c0SShuming Fan if (err < 0) 768ca5118c0SShuming Fan return err; 769ca5118c0SShuming Fan 770ca5118c0SShuming Fan return changed; 771ca5118c0SShuming Fan } 772ca5118c0SShuming Fan 7737ad4d237SShuming Fan static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); 7747ad4d237SShuming Fan static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); 7757ad4d237SShuming Fan static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); 7767ad4d237SShuming Fan 7777ad4d237SShuming Fan static const struct snd_kcontrol_new rt711_sdca_snd_controls[] = { 7787ad4d237SShuming Fan SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume", 7797ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_L), 7807ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R), 7817ad4d237SShuming Fan 0x57, 0x57, 0, 7827ad4d237SShuming Fan rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, out_vol_tlv), 783ca5118c0SShuming Fan SOC_DOUBLE_EXT("FU1E Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, 784ca5118c0SShuming Fan rt711_sdca_fu1e_capture_get, rt711_sdca_fu1e_capture_put), 785ca5118c0SShuming Fan SOC_DOUBLE_EXT("FU0F Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, 786ca5118c0SShuming Fan rt711_sdca_fu0f_capture_get, rt711_sdca_fu0f_capture_put), 7877ad4d237SShuming Fan SOC_DOUBLE_R_EXT_TLV("FU1E Capture Volume", 7887ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L), 7897ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R), 7907ad4d237SShuming Fan 0x17, 0x3f, 0, 7917ad4d237SShuming Fan rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), 7927ad4d237SShuming Fan SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume", 7937ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_L), 7947ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_R), 7957ad4d237SShuming Fan 0x17, 0x3f, 0, 7967ad4d237SShuming Fan rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), 7977ad4d237SShuming Fan SOC_DOUBLE_R_EXT_TLV("FU44 Gain Volume", 7987ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), 7997ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), 8007ad4d237SShuming Fan 8, 3, 0, 8017ad4d237SShuming Fan rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), 8027ad4d237SShuming Fan SOC_DOUBLE_R_EXT_TLV("FU15 Gain Volume", 8037ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), 8047ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), 8057ad4d237SShuming Fan 8, 3, 0, 8067ad4d237SShuming Fan rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), 8077ad4d237SShuming Fan }; 8087ad4d237SShuming Fan 8097ad4d237SShuming Fan static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol, 8107ad4d237SShuming Fan struct snd_ctl_elem_value *ucontrol) 8117ad4d237SShuming Fan { 8127ad4d237SShuming Fan struct snd_soc_component *component = 8137ad4d237SShuming Fan snd_soc_dapm_kcontrol_component(kcontrol); 8147ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 8157ad4d237SShuming Fan unsigned int val = 0, mask_sft; 8167ad4d237SShuming Fan 8177ad4d237SShuming Fan if (strstr(ucontrol->id.name, "ADC 22 Mux")) 8187ad4d237SShuming Fan mask_sft = 10; 8197ad4d237SShuming Fan else if (strstr(ucontrol->id.name, "ADC 23 Mux")) 8207ad4d237SShuming Fan mask_sft = 13; 8217ad4d237SShuming Fan else 8227ad4d237SShuming Fan return -EINVAL; 8237ad4d237SShuming Fan 8247ad4d237SShuming Fan rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, 8257ad4d237SShuming Fan RT711_HDA_LEGACY_MUX_CTL1, &val); 8267ad4d237SShuming Fan 8277ad4d237SShuming Fan ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; 8287ad4d237SShuming Fan 8297ad4d237SShuming Fan return 0; 8307ad4d237SShuming Fan } 8317ad4d237SShuming Fan 8327ad4d237SShuming Fan static int rt711_sdca_mux_put(struct snd_kcontrol *kcontrol, 8337ad4d237SShuming Fan struct snd_ctl_elem_value *ucontrol) 8347ad4d237SShuming Fan { 8357ad4d237SShuming Fan struct snd_soc_component *component = 8367ad4d237SShuming Fan snd_soc_dapm_kcontrol_component(kcontrol); 8377ad4d237SShuming Fan struct snd_soc_dapm_context *dapm = 8387ad4d237SShuming Fan snd_soc_dapm_kcontrol_dapm(kcontrol); 8397ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 8407ad4d237SShuming Fan struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 8417ad4d237SShuming Fan unsigned int *item = ucontrol->value.enumerated.item; 8427ad4d237SShuming Fan unsigned int val, val2 = 0, change, mask_sft; 8437ad4d237SShuming Fan 8447ad4d237SShuming Fan if (item[0] >= e->items) 8457ad4d237SShuming Fan return -EINVAL; 8467ad4d237SShuming Fan 8477ad4d237SShuming Fan if (strstr(ucontrol->id.name, "ADC 22 Mux")) 8487ad4d237SShuming Fan mask_sft = 10; 8497ad4d237SShuming Fan else if (strstr(ucontrol->id.name, "ADC 23 Mux")) 8507ad4d237SShuming Fan mask_sft = 13; 8517ad4d237SShuming Fan else 8527ad4d237SShuming Fan return -EINVAL; 8537ad4d237SShuming Fan 8547ad4d237SShuming Fan val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 8557ad4d237SShuming Fan 8567ad4d237SShuming Fan rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, 8577ad4d237SShuming Fan RT711_HDA_LEGACY_MUX_CTL1, &val2); 8587ad4d237SShuming Fan val2 = (val2 >> mask_sft) & 0x7; 8597ad4d237SShuming Fan 8607ad4d237SShuming Fan if (val == val2) 8617ad4d237SShuming Fan change = 0; 8627ad4d237SShuming Fan else 8637ad4d237SShuming Fan change = 1; 8647ad4d237SShuming Fan 8657ad4d237SShuming Fan if (change) 8667ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 8677ad4d237SShuming Fan RT711_HDA_LEGACY_MUX_CTL1, 0x7 << mask_sft, 8687ad4d237SShuming Fan val << mask_sft); 8697ad4d237SShuming Fan 8707ad4d237SShuming Fan snd_soc_dapm_mux_update_power(dapm, kcontrol, 8717ad4d237SShuming Fan item[0], e, NULL); 8727ad4d237SShuming Fan 8737ad4d237SShuming Fan return change; 8747ad4d237SShuming Fan } 8757ad4d237SShuming Fan 8767ad4d237SShuming Fan static const char * const adc_mux_text[] = { 8777ad4d237SShuming Fan "MIC2", 8787ad4d237SShuming Fan "LINE1", 8797ad4d237SShuming Fan "LINE2", 8807ad4d237SShuming Fan "DMIC", 8817ad4d237SShuming Fan }; 8827ad4d237SShuming Fan 8837ad4d237SShuming Fan static SOC_ENUM_SINGLE_DECL( 8847ad4d237SShuming Fan rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text); 8857ad4d237SShuming Fan 8867ad4d237SShuming Fan static SOC_ENUM_SINGLE_DECL( 8877ad4d237SShuming Fan rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text); 8887ad4d237SShuming Fan 8897ad4d237SShuming Fan static const struct snd_kcontrol_new rt711_sdca_adc22_mux = 8907ad4d237SShuming Fan SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt711_adc22_enum, 8917ad4d237SShuming Fan rt711_sdca_mux_get, rt711_sdca_mux_put); 8927ad4d237SShuming Fan 8937ad4d237SShuming Fan static const struct snd_kcontrol_new rt711_sdca_adc23_mux = 8947ad4d237SShuming Fan SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt711_adc23_enum, 8957ad4d237SShuming Fan rt711_sdca_mux_get, rt711_sdca_mux_put); 8967ad4d237SShuming Fan 8977ad4d237SShuming Fan static int rt711_sdca_fu05_event(struct snd_soc_dapm_widget *w, 8987ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 8997ad4d237SShuming Fan { 9007ad4d237SShuming Fan struct snd_soc_component *component = 9017ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 9027ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 9037ad4d237SShuming Fan unsigned char unmute = 0x0, mute = 0x1; 9047ad4d237SShuming Fan 9057ad4d237SShuming Fan switch (event) { 9067ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 9077ad4d237SShuming Fan regmap_write(rt711->regmap, 9087ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, 9097ad4d237SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_L), 9107ad4d237SShuming Fan unmute); 9117ad4d237SShuming Fan regmap_write(rt711->regmap, 9127ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, 9137ad4d237SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_R), 9147ad4d237SShuming Fan unmute); 9157ad4d237SShuming Fan break; 9167ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 9177ad4d237SShuming Fan regmap_write(rt711->regmap, 9187ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, 9197ad4d237SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_L), 9207ad4d237SShuming Fan mute); 9217ad4d237SShuming Fan regmap_write(rt711->regmap, 9227ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, 9237ad4d237SShuming Fan RT711_SDCA_CTL_FU_MUTE, CH_R), 9247ad4d237SShuming Fan mute); 9257ad4d237SShuming Fan break; 9267ad4d237SShuming Fan } 9277ad4d237SShuming Fan return 0; 9287ad4d237SShuming Fan } 9297ad4d237SShuming Fan 9307ad4d237SShuming Fan static int rt711_sdca_fu0f_event(struct snd_soc_dapm_widget *w, 9317ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 9327ad4d237SShuming Fan { 9337ad4d237SShuming Fan struct snd_soc_component *component = 9347ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 9357ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 9367ad4d237SShuming Fan 9377ad4d237SShuming Fan switch (event) { 9387ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 939ca5118c0SShuming Fan rt711->fu0f_dapm_mute = false; 940ca5118c0SShuming Fan rt711_sdca_set_fu0f_capture_ctl(rt711); 9417ad4d237SShuming Fan break; 9427ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 943ca5118c0SShuming Fan rt711->fu0f_dapm_mute = true; 944ca5118c0SShuming Fan rt711_sdca_set_fu0f_capture_ctl(rt711); 9457ad4d237SShuming Fan break; 9467ad4d237SShuming Fan } 9477ad4d237SShuming Fan return 0; 9487ad4d237SShuming Fan } 9497ad4d237SShuming Fan 9507ad4d237SShuming Fan static int rt711_sdca_fu1e_event(struct snd_soc_dapm_widget *w, 9517ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 9527ad4d237SShuming Fan { 9537ad4d237SShuming Fan struct snd_soc_component *component = 9547ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 9557ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 9567ad4d237SShuming Fan 9577ad4d237SShuming Fan switch (event) { 9587ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 959ca5118c0SShuming Fan rt711->fu1e_dapm_mute = false; 960ca5118c0SShuming Fan rt711_sdca_set_fu1e_capture_ctl(rt711); 9617ad4d237SShuming Fan break; 9627ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 963ca5118c0SShuming Fan rt711->fu1e_dapm_mute = true; 964ca5118c0SShuming Fan rt711_sdca_set_fu1e_capture_ctl(rt711); 9657ad4d237SShuming Fan break; 9667ad4d237SShuming Fan } 9677ad4d237SShuming Fan return 0; 9687ad4d237SShuming Fan } 9697ad4d237SShuming Fan 9707ad4d237SShuming Fan static int rt711_sdca_pde28_event(struct snd_soc_dapm_widget *w, 9717ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 9727ad4d237SShuming Fan { 9737ad4d237SShuming Fan struct snd_soc_component *component = 9747ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 9757ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 9767ad4d237SShuming Fan unsigned char ps0 = 0x0, ps3 = 0x3; 9777ad4d237SShuming Fan 9787ad4d237SShuming Fan switch (event) { 9797ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 9807ad4d237SShuming Fan regmap_write(rt711->regmap, 9817ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, 9827ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 9837ad4d237SShuming Fan ps0); 9847ad4d237SShuming Fan break; 9857ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 9867ad4d237SShuming Fan regmap_write(rt711->regmap, 9877ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, 9887ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 9897ad4d237SShuming Fan ps3); 9907ad4d237SShuming Fan break; 9917ad4d237SShuming Fan } 9927ad4d237SShuming Fan return 0; 9937ad4d237SShuming Fan } 9947ad4d237SShuming Fan 9957ad4d237SShuming Fan static int rt711_sdca_pde29_event(struct snd_soc_dapm_widget *w, 9967ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 9977ad4d237SShuming Fan { 9987ad4d237SShuming Fan struct snd_soc_component *component = 9997ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 10007ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 10017ad4d237SShuming Fan unsigned char ps0 = 0x0, ps3 = 0x3; 10027ad4d237SShuming Fan 10037ad4d237SShuming Fan switch (event) { 10047ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 10057ad4d237SShuming Fan regmap_write(rt711->regmap, 10067ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, 10077ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 10087ad4d237SShuming Fan ps0); 10097ad4d237SShuming Fan break; 10107ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 10117ad4d237SShuming Fan regmap_write(rt711->regmap, 10127ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, 10137ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 10147ad4d237SShuming Fan ps3); 10157ad4d237SShuming Fan break; 10167ad4d237SShuming Fan } 10177ad4d237SShuming Fan return 0; 10187ad4d237SShuming Fan } 10197ad4d237SShuming Fan 10207ad4d237SShuming Fan static int rt711_sdca_pde2a_event(struct snd_soc_dapm_widget *w, 10217ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 10227ad4d237SShuming Fan { 10237ad4d237SShuming Fan struct snd_soc_component *component = 10247ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 10257ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 10267ad4d237SShuming Fan unsigned char ps0 = 0x0, ps3 = 0x3; 10277ad4d237SShuming Fan 10287ad4d237SShuming Fan switch (event) { 10297ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 10307ad4d237SShuming Fan regmap_write(rt711->regmap, 10317ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, 10327ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 10337ad4d237SShuming Fan ps0); 10347ad4d237SShuming Fan break; 10357ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 10367ad4d237SShuming Fan regmap_write(rt711->regmap, 10377ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, 10387ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 10397ad4d237SShuming Fan ps3); 10407ad4d237SShuming Fan break; 10417ad4d237SShuming Fan } 10427ad4d237SShuming Fan return 0; 10437ad4d237SShuming Fan } 10447ad4d237SShuming Fan 10457ad4d237SShuming Fan static int rt711_sdca_line1_power_event(struct snd_soc_dapm_widget *w, 10467ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 10477ad4d237SShuming Fan { 10487ad4d237SShuming Fan struct snd_soc_component *component = 10497ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 10507ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 10517ad4d237SShuming Fan static unsigned int sel_mode = 0xffff; 10527ad4d237SShuming Fan 10537ad4d237SShuming Fan switch (event) { 10547ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 10557ad4d237SShuming Fan regmap_read(rt711->regmap, 10567ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, 10577ad4d237SShuming Fan RT711_SDCA_CTL_SELECTED_MODE, 0), 10587ad4d237SShuming Fan &sel_mode); 10597ad4d237SShuming Fan regmap_write(rt711->regmap, 10607ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, 10617ad4d237SShuming Fan RT711_SDCA_CTL_VENDOR_DEF, 0), 10627ad4d237SShuming Fan 0x1); 10637ad4d237SShuming Fan regmap_write(rt711->regmap, 10647ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, 10657ad4d237SShuming Fan RT711_SDCA_CTL_SELECTED_MODE, 0), 10667ad4d237SShuming Fan 0x7); 10677ad4d237SShuming Fan break; 10687ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 10697ad4d237SShuming Fan regmap_write(rt711->regmap, 10707ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, 10717ad4d237SShuming Fan RT711_SDCA_CTL_VENDOR_DEF, 0), 10727ad4d237SShuming Fan 0x0); 10737ad4d237SShuming Fan if (sel_mode != 0xffff) 10747ad4d237SShuming Fan regmap_write(rt711->regmap, 10757ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, 10767ad4d237SShuming Fan RT711_SDCA_CTL_SELECTED_MODE, 0), 10777ad4d237SShuming Fan sel_mode); 10787ad4d237SShuming Fan break; 10797ad4d237SShuming Fan } 10807ad4d237SShuming Fan 10817ad4d237SShuming Fan return 0; 10827ad4d237SShuming Fan } 10837ad4d237SShuming Fan 10847ad4d237SShuming Fan static int rt711_sdca_line2_power_event(struct snd_soc_dapm_widget *w, 10857ad4d237SShuming Fan struct snd_kcontrol *kcontrol, int event) 10867ad4d237SShuming Fan { 10877ad4d237SShuming Fan struct snd_soc_component *component = 10887ad4d237SShuming Fan snd_soc_dapm_to_component(w->dapm); 10897ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 10907ad4d237SShuming Fan unsigned char ps0 = 0x0, ps3 = 0x3; 10917ad4d237SShuming Fan 10927ad4d237SShuming Fan switch (event) { 10937ad4d237SShuming Fan case SND_SOC_DAPM_POST_PMU: 10947ad4d237SShuming Fan regmap_write(rt711->regmap, 10957ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, 10967ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 10977ad4d237SShuming Fan ps0); 10987ad4d237SShuming Fan regmap_write(rt711->regmap, 10997ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, 11007ad4d237SShuming Fan RT711_SDCA_CTL_VENDOR_DEF, 0), 11017ad4d237SShuming Fan 0x1); 11027ad4d237SShuming Fan break; 11037ad4d237SShuming Fan case SND_SOC_DAPM_PRE_PMD: 11047ad4d237SShuming Fan regmap_write(rt711->regmap, 11057ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, 11067ad4d237SShuming Fan RT711_SDCA_CTL_VENDOR_DEF, 0), 11077ad4d237SShuming Fan 0x0); 11087ad4d237SShuming Fan regmap_write(rt711->regmap, 11097ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, 11107ad4d237SShuming Fan RT711_SDCA_CTL_REQ_POWER_STATE, 0), 11117ad4d237SShuming Fan ps3); 11127ad4d237SShuming Fan break; 11137ad4d237SShuming Fan } 11147ad4d237SShuming Fan 11157ad4d237SShuming Fan return 0; 11167ad4d237SShuming Fan } 11177ad4d237SShuming Fan 11187ad4d237SShuming Fan static const struct snd_soc_dapm_widget rt711_sdca_dapm_widgets[] = { 11197ad4d237SShuming Fan SND_SOC_DAPM_OUTPUT("HP"), 11207ad4d237SShuming Fan SND_SOC_DAPM_INPUT("MIC2"), 11217ad4d237SShuming Fan SND_SOC_DAPM_INPUT("DMIC1"), 11227ad4d237SShuming Fan SND_SOC_DAPM_INPUT("DMIC2"), 11237ad4d237SShuming Fan SND_SOC_DAPM_INPUT("LINE1"), 11247ad4d237SShuming Fan SND_SOC_DAPM_INPUT("LINE2"), 11257ad4d237SShuming Fan 11267ad4d237SShuming Fan SND_SOC_DAPM_PGA_E("LINE1 Power", SND_SOC_NOPM, 11277ad4d237SShuming Fan 0, 0, NULL, 0, rt711_sdca_line1_power_event, 11287ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11297ad4d237SShuming Fan SND_SOC_DAPM_PGA_E("LINE2 Power", SND_SOC_NOPM, 11307ad4d237SShuming Fan 0, 0, NULL, 0, rt711_sdca_line2_power_event, 11317ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11327ad4d237SShuming Fan 11337ad4d237SShuming Fan SND_SOC_DAPM_SUPPLY("PDE 28", SND_SOC_NOPM, 0, 0, 11347ad4d237SShuming Fan rt711_sdca_pde28_event, 11357ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11367ad4d237SShuming Fan SND_SOC_DAPM_SUPPLY("PDE 29", SND_SOC_NOPM, 0, 0, 11377ad4d237SShuming Fan rt711_sdca_pde29_event, 11387ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11397ad4d237SShuming Fan SND_SOC_DAPM_SUPPLY("PDE 2A", SND_SOC_NOPM, 0, 0, 11407ad4d237SShuming Fan rt711_sdca_pde2a_event, 11417ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11427ad4d237SShuming Fan 11437ad4d237SShuming Fan SND_SOC_DAPM_DAC_E("FU 05", NULL, SND_SOC_NOPM, 0, 0, 11447ad4d237SShuming Fan rt711_sdca_fu05_event, 11457ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11467ad4d237SShuming Fan SND_SOC_DAPM_ADC_E("FU 0F", NULL, SND_SOC_NOPM, 0, 0, 11477ad4d237SShuming Fan rt711_sdca_fu0f_event, 11487ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11497ad4d237SShuming Fan SND_SOC_DAPM_ADC_E("FU 1E", NULL, SND_SOC_NOPM, 0, 0, 11507ad4d237SShuming Fan rt711_sdca_fu1e_event, 11517ad4d237SShuming Fan SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11527ad4d237SShuming Fan SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0, 11537ad4d237SShuming Fan &rt711_sdca_adc22_mux), 11547ad4d237SShuming Fan SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0, 11557ad4d237SShuming Fan &rt711_sdca_adc23_mux), 11567ad4d237SShuming Fan 11577ad4d237SShuming Fan SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0), 11587ad4d237SShuming Fan SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), 11597ad4d237SShuming Fan SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), 11607ad4d237SShuming Fan }; 11617ad4d237SShuming Fan 11627ad4d237SShuming Fan static const struct snd_soc_dapm_route rt711_sdca_audio_map[] = { 11637ad4d237SShuming Fan {"FU 05", NULL, "DP3RX"}, 11647ad4d237SShuming Fan {"DP2TX", NULL, "FU 0F"}, 11657ad4d237SShuming Fan {"DP4TX", NULL, "FU 1E"}, 11667ad4d237SShuming Fan 11677ad4d237SShuming Fan {"LINE1 Power", NULL, "LINE1"}, 11687ad4d237SShuming Fan {"LINE2 Power", NULL, "LINE2"}, 11697ad4d237SShuming Fan {"HP", NULL, "PDE 28"}, 11707ad4d237SShuming Fan {"FU 0F", NULL, "PDE 29"}, 11717ad4d237SShuming Fan {"FU 1E", NULL, "PDE 2A"}, 11727ad4d237SShuming Fan 11737ad4d237SShuming Fan {"FU 0F", NULL, "ADC 22 Mux"}, 11747ad4d237SShuming Fan {"FU 1E", NULL, "ADC 23 Mux"}, 11757ad4d237SShuming Fan {"ADC 22 Mux", "DMIC", "DMIC1"}, 11767ad4d237SShuming Fan {"ADC 22 Mux", "LINE1", "LINE1 Power"}, 11777ad4d237SShuming Fan {"ADC 22 Mux", "LINE2", "LINE2 Power"}, 11787ad4d237SShuming Fan {"ADC 22 Mux", "MIC2", "MIC2"}, 11797ad4d237SShuming Fan {"ADC 23 Mux", "DMIC", "DMIC2"}, 11807ad4d237SShuming Fan {"ADC 23 Mux", "LINE1", "LINE1 Power"}, 11817ad4d237SShuming Fan {"ADC 23 Mux", "LINE2", "LINE2 Power"}, 11827ad4d237SShuming Fan {"ADC 23 Mux", "MIC2", "MIC2"}, 11837ad4d237SShuming Fan 11847ad4d237SShuming Fan {"HP", NULL, "FU 05"}, 11857ad4d237SShuming Fan }; 11867ad4d237SShuming Fan 11877ad4d237SShuming Fan static int rt711_sdca_parse_dt(struct rt711_sdca_priv *rt711, struct device *dev) 11887ad4d237SShuming Fan { 11897ad4d237SShuming Fan device_property_read_u32(dev, "realtek,jd-src", &rt711->jd_src); 11907ad4d237SShuming Fan 11917ad4d237SShuming Fan return 0; 11927ad4d237SShuming Fan } 11937ad4d237SShuming Fan 11947ad4d237SShuming Fan static int rt711_sdca_probe(struct snd_soc_component *component) 11957ad4d237SShuming Fan { 11967ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 1197*011e397fSPierre-Louis Bossart int ret; 11987ad4d237SShuming Fan 11997ad4d237SShuming Fan rt711_sdca_parse_dt(rt711, &rt711->slave->dev); 12007ad4d237SShuming Fan rt711->component = component; 12017ad4d237SShuming Fan 1202*011e397fSPierre-Louis Bossart ret = pm_runtime_resume(component->dev); 1203*011e397fSPierre-Louis Bossart if (ret < 0 && ret != -EACCES) 1204*011e397fSPierre-Louis Bossart return ret; 1205*011e397fSPierre-Louis Bossart 12067ad4d237SShuming Fan return 0; 12077ad4d237SShuming Fan } 12087ad4d237SShuming Fan 12097ad4d237SShuming Fan static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { 12107ad4d237SShuming Fan .probe = rt711_sdca_probe, 12117ad4d237SShuming Fan .controls = rt711_sdca_snd_controls, 12127ad4d237SShuming Fan .num_controls = ARRAY_SIZE(rt711_sdca_snd_controls), 12137ad4d237SShuming Fan .dapm_widgets = rt711_sdca_dapm_widgets, 12147ad4d237SShuming Fan .num_dapm_widgets = ARRAY_SIZE(rt711_sdca_dapm_widgets), 12157ad4d237SShuming Fan .dapm_routes = rt711_sdca_audio_map, 12167ad4d237SShuming Fan .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), 12177ad4d237SShuming Fan .set_jack = rt711_sdca_set_jack_detect, 12183e50a500SCharles Keepax .endianness = 1, 12197ad4d237SShuming Fan }; 12207ad4d237SShuming Fan 12217ad4d237SShuming Fan static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, 12227ad4d237SShuming Fan int direction) 12237ad4d237SShuming Fan { 12247ad4d237SShuming Fan struct sdw_stream_data *stream; 12257ad4d237SShuming Fan 12267ad4d237SShuming Fan if (!sdw_stream) 12277ad4d237SShuming Fan return 0; 12287ad4d237SShuming Fan 12297ad4d237SShuming Fan stream = kzalloc(sizeof(*stream), GFP_KERNEL); 12307ad4d237SShuming Fan if (!stream) 12317ad4d237SShuming Fan return -ENOMEM; 12327ad4d237SShuming Fan 12337ad4d237SShuming Fan stream->sdw_stream = sdw_stream; 12347ad4d237SShuming Fan 12357ad4d237SShuming Fan /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ 12367ad4d237SShuming Fan if (direction == SNDRV_PCM_STREAM_PLAYBACK) 12377ad4d237SShuming Fan dai->playback_dma_data = stream; 12387ad4d237SShuming Fan else 12397ad4d237SShuming Fan dai->capture_dma_data = stream; 12407ad4d237SShuming Fan 12417ad4d237SShuming Fan return 0; 12427ad4d237SShuming Fan } 12437ad4d237SShuming Fan 12447ad4d237SShuming Fan static void rt711_sdca_shutdown(struct snd_pcm_substream *substream, 12457ad4d237SShuming Fan struct snd_soc_dai *dai) 12467ad4d237SShuming Fan { 12477ad4d237SShuming Fan struct sdw_stream_data *stream; 12487ad4d237SShuming Fan 12497ad4d237SShuming Fan stream = snd_soc_dai_get_dma_data(dai, substream); 12507ad4d237SShuming Fan snd_soc_dai_set_dma_data(dai, substream, NULL); 12517ad4d237SShuming Fan kfree(stream); 12527ad4d237SShuming Fan } 12537ad4d237SShuming Fan 12547ad4d237SShuming Fan static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, 12557ad4d237SShuming Fan struct snd_pcm_hw_params *params, 12567ad4d237SShuming Fan struct snd_soc_dai *dai) 12577ad4d237SShuming Fan { 12587ad4d237SShuming Fan struct snd_soc_component *component = dai->component; 12597ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 12607ad4d237SShuming Fan struct sdw_stream_config stream_config; 12617ad4d237SShuming Fan struct sdw_port_config port_config; 12627ad4d237SShuming Fan enum sdw_data_direction direction; 12637ad4d237SShuming Fan struct sdw_stream_data *stream; 12647ad4d237SShuming Fan int retval, port, num_channels; 12657ad4d237SShuming Fan unsigned int sampling_rate; 12667ad4d237SShuming Fan 12677ad4d237SShuming Fan dev_dbg(dai->dev, "%s %s", __func__, dai->name); 12687ad4d237SShuming Fan stream = snd_soc_dai_get_dma_data(dai, substream); 12697ad4d237SShuming Fan 12707ad4d237SShuming Fan if (!stream) 12717ad4d237SShuming Fan return -EINVAL; 12727ad4d237SShuming Fan 12737ad4d237SShuming Fan if (!rt711->slave) 12747ad4d237SShuming Fan return -EINVAL; 12757ad4d237SShuming Fan 12767ad4d237SShuming Fan /* SoundWire specific configuration */ 12777ad4d237SShuming Fan if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 12787ad4d237SShuming Fan direction = SDW_DATA_DIR_RX; 12797ad4d237SShuming Fan port = 3; 12807ad4d237SShuming Fan } else { 12817ad4d237SShuming Fan direction = SDW_DATA_DIR_TX; 12827ad4d237SShuming Fan if (dai->id == RT711_AIF1) 12837ad4d237SShuming Fan port = 2; 12847ad4d237SShuming Fan else if (dai->id == RT711_AIF2) 12857ad4d237SShuming Fan port = 4; 12867ad4d237SShuming Fan else 12877ad4d237SShuming Fan return -EINVAL; 12887ad4d237SShuming Fan } 12897ad4d237SShuming Fan 12907ad4d237SShuming Fan stream_config.frame_rate = params_rate(params); 12917ad4d237SShuming Fan stream_config.ch_count = params_channels(params); 12927ad4d237SShuming Fan stream_config.bps = snd_pcm_format_width(params_format(params)); 12937ad4d237SShuming Fan stream_config.direction = direction; 12947ad4d237SShuming Fan 12957ad4d237SShuming Fan num_channels = params_channels(params); 12967ad4d237SShuming Fan port_config.ch_mask = GENMASK(num_channels - 1, 0); 12977ad4d237SShuming Fan port_config.num = port; 12987ad4d237SShuming Fan 12997ad4d237SShuming Fan retval = sdw_stream_add_slave(rt711->slave, &stream_config, 13007ad4d237SShuming Fan &port_config, 1, stream->sdw_stream); 13017ad4d237SShuming Fan if (retval) { 13027ad4d237SShuming Fan dev_err(dai->dev, "Unable to configure port\n"); 13037ad4d237SShuming Fan return retval; 13047ad4d237SShuming Fan } 13057ad4d237SShuming Fan 13067ad4d237SShuming Fan if (params_channels(params) > 16) { 13077ad4d237SShuming Fan dev_err(component->dev, "Unsupported channels %d\n", 13087ad4d237SShuming Fan params_channels(params)); 13097ad4d237SShuming Fan return -EINVAL; 13107ad4d237SShuming Fan } 13117ad4d237SShuming Fan 13127ad4d237SShuming Fan /* sampling rate configuration */ 13137ad4d237SShuming Fan switch (params_rate(params)) { 13147ad4d237SShuming Fan case 44100: 13157ad4d237SShuming Fan sampling_rate = RT711_SDCA_RATE_44100HZ; 13167ad4d237SShuming Fan break; 13177ad4d237SShuming Fan case 48000: 13187ad4d237SShuming Fan sampling_rate = RT711_SDCA_RATE_48000HZ; 13197ad4d237SShuming Fan break; 13207ad4d237SShuming Fan case 96000: 13217ad4d237SShuming Fan sampling_rate = RT711_SDCA_RATE_96000HZ; 13227ad4d237SShuming Fan break; 13237ad4d237SShuming Fan case 192000: 13247ad4d237SShuming Fan sampling_rate = RT711_SDCA_RATE_192000HZ; 13257ad4d237SShuming Fan break; 13267ad4d237SShuming Fan default: 13277ad4d237SShuming Fan dev_err(component->dev, "Rate %d is not supported\n", 13287ad4d237SShuming Fan params_rate(params)); 13297ad4d237SShuming Fan return -EINVAL; 13307ad4d237SShuming Fan } 13317ad4d237SShuming Fan 13327ad4d237SShuming Fan /* set sampling frequency */ 13337ad4d237SShuming Fan regmap_write(rt711->regmap, 13347ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS01, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 13357ad4d237SShuming Fan sampling_rate); 13367ad4d237SShuming Fan regmap_write(rt711->regmap, 13377ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS11, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 13387ad4d237SShuming Fan sampling_rate); 13397ad4d237SShuming Fan regmap_write(rt711->regmap, 13407ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_CS1F, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 13417ad4d237SShuming Fan sampling_rate); 13427ad4d237SShuming Fan 13437ad4d237SShuming Fan return 0; 13447ad4d237SShuming Fan } 13457ad4d237SShuming Fan 13467ad4d237SShuming Fan static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, 13477ad4d237SShuming Fan struct snd_soc_dai *dai) 13487ad4d237SShuming Fan { 13497ad4d237SShuming Fan struct snd_soc_component *component = dai->component; 13507ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 13517ad4d237SShuming Fan struct sdw_stream_data *stream = 13527ad4d237SShuming Fan snd_soc_dai_get_dma_data(dai, substream); 13537ad4d237SShuming Fan 13547ad4d237SShuming Fan if (!rt711->slave) 13557ad4d237SShuming Fan return -EINVAL; 13567ad4d237SShuming Fan 13577ad4d237SShuming Fan sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); 13587ad4d237SShuming Fan return 0; 13597ad4d237SShuming Fan } 13607ad4d237SShuming Fan 13617ad4d237SShuming Fan #define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ 13627ad4d237SShuming Fan SNDRV_PCM_RATE_192000) 13637ad4d237SShuming Fan #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 13647ad4d237SShuming Fan SNDRV_PCM_FMTBIT_S24_LE) 13657ad4d237SShuming Fan 13663cab801eSYe Bin static const struct snd_soc_dai_ops rt711_sdca_ops = { 13677ad4d237SShuming Fan .hw_params = rt711_sdca_pcm_hw_params, 13687ad4d237SShuming Fan .hw_free = rt711_sdca_pcm_hw_free, 1369e8444560SPierre-Louis Bossart .set_stream = rt711_sdca_set_sdw_stream, 13707ad4d237SShuming Fan .shutdown = rt711_sdca_shutdown, 13717ad4d237SShuming Fan }; 13727ad4d237SShuming Fan 13737ad4d237SShuming Fan static struct snd_soc_dai_driver rt711_sdca_dai[] = { 13747ad4d237SShuming Fan { 13757ad4d237SShuming Fan .name = "rt711-sdca-aif1", 13767ad4d237SShuming Fan .id = RT711_AIF1, 13777ad4d237SShuming Fan .playback = { 13787ad4d237SShuming Fan .stream_name = "DP3 Playback", 13797ad4d237SShuming Fan .channels_min = 1, 13807ad4d237SShuming Fan .channels_max = 2, 13817ad4d237SShuming Fan .rates = RT711_STEREO_RATES, 13827ad4d237SShuming Fan .formats = RT711_FORMATS, 13837ad4d237SShuming Fan }, 13847ad4d237SShuming Fan .capture = { 13857ad4d237SShuming Fan .stream_name = "DP2 Capture", 13867ad4d237SShuming Fan .channels_min = 1, 13877ad4d237SShuming Fan .channels_max = 2, 13887ad4d237SShuming Fan .rates = RT711_STEREO_RATES, 13897ad4d237SShuming Fan .formats = RT711_FORMATS, 13907ad4d237SShuming Fan }, 13917ad4d237SShuming Fan .ops = &rt711_sdca_ops, 13927ad4d237SShuming Fan }, 13937ad4d237SShuming Fan { 13947ad4d237SShuming Fan .name = "rt711-sdca-aif2", 13957ad4d237SShuming Fan .id = RT711_AIF2, 13967ad4d237SShuming Fan .capture = { 13977ad4d237SShuming Fan .stream_name = "DP4 Capture", 13987ad4d237SShuming Fan .channels_min = 1, 13997ad4d237SShuming Fan .channels_max = 2, 14007ad4d237SShuming Fan .rates = RT711_STEREO_RATES, 14017ad4d237SShuming Fan .formats = RT711_FORMATS, 14027ad4d237SShuming Fan }, 14037ad4d237SShuming Fan .ops = &rt711_sdca_ops, 14047ad4d237SShuming Fan } 14057ad4d237SShuming Fan }; 14067ad4d237SShuming Fan 14077ad4d237SShuming Fan int rt711_sdca_init(struct device *dev, struct regmap *regmap, 14087ad4d237SShuming Fan struct regmap *mbq_regmap, struct sdw_slave *slave) 14097ad4d237SShuming Fan { 14107ad4d237SShuming Fan struct rt711_sdca_priv *rt711; 14117ad4d237SShuming Fan int ret; 14127ad4d237SShuming Fan 14137ad4d237SShuming Fan rt711 = devm_kzalloc(dev, sizeof(*rt711), GFP_KERNEL); 14147ad4d237SShuming Fan if (!rt711) 14157ad4d237SShuming Fan return -ENOMEM; 14167ad4d237SShuming Fan 14177ad4d237SShuming Fan dev_set_drvdata(dev, rt711); 14187ad4d237SShuming Fan rt711->slave = slave; 14197ad4d237SShuming Fan rt711->regmap = regmap; 14207ad4d237SShuming Fan rt711->mbq_regmap = mbq_regmap; 14217ad4d237SShuming Fan 1422716c2e7eSPierre-Louis Bossart mutex_init(&rt711->calibrate_mutex); 1423d2bf75f4SPierre-Louis Bossart mutex_init(&rt711->disable_irq_lock); 1424d2bf75f4SPierre-Louis Bossart 1425a49267a3SPierre-Louis Bossart INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler); 1426a49267a3SPierre-Louis Bossart INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); 1427a49267a3SPierre-Louis Bossart 14287ad4d237SShuming Fan /* 14297ad4d237SShuming Fan * Mark hw_init to false 14307ad4d237SShuming Fan * HW init will be performed when device reports present 14317ad4d237SShuming Fan */ 14327ad4d237SShuming Fan rt711->hw_init = false; 14337ad4d237SShuming Fan rt711->first_hw_init = false; 1434ca5118c0SShuming Fan rt711->fu0f_dapm_mute = true; 1435ca5118c0SShuming Fan rt711->fu1e_dapm_mute = true; 1436ca5118c0SShuming Fan rt711->fu0f_mixer_l_mute = rt711->fu0f_mixer_r_mute = true; 1437ca5118c0SShuming Fan rt711->fu1e_mixer_l_mute = rt711->fu1e_mixer_r_mute = true; 14387ad4d237SShuming Fan 14397ad4d237SShuming Fan /* JD source uses JD2 in default */ 14407ad4d237SShuming Fan rt711->jd_src = RT711_JD2; 14417ad4d237SShuming Fan 14427ad4d237SShuming Fan ret = devm_snd_soc_register_component(dev, 14437ad4d237SShuming Fan &soc_sdca_dev_rt711, 14447ad4d237SShuming Fan rt711_sdca_dai, 14457ad4d237SShuming Fan ARRAY_SIZE(rt711_sdca_dai)); 14467ad4d237SShuming Fan 14477ad4d237SShuming Fan dev_dbg(&slave->dev, "%s\n", __func__); 14487ad4d237SShuming Fan 14497ad4d237SShuming Fan return ret; 14507ad4d237SShuming Fan } 14517ad4d237SShuming Fan 14527ad4d237SShuming Fan static void rt711_sdca_vd0_io_init(struct rt711_sdca_priv *rt711) 14537ad4d237SShuming Fan { 14547ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14557ad4d237SShuming Fan RT711_GPIO_TEST_MODE_CTL2, 0x0e00); 14567ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, 14577ad4d237SShuming Fan RT711_HDA_LEGACY_GPIO_CTL, 0x0008); 14587ad4d237SShuming Fan 14597ad4d237SShuming Fan regmap_write(rt711->regmap, 0x2f5a, 0x01); 14607ad4d237SShuming Fan 14617ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14627ad4d237SShuming Fan RT711_ADC27_VOL_SET, 0x8728); 14637ad4d237SShuming Fan 14647ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14657ad4d237SShuming Fan RT711_COMBO_JACK_AUTO_CTL3, 0xa472); 14667ad4d237SShuming Fan 14677ad4d237SShuming Fan regmap_write(rt711->regmap, 0x2f50, 0x02); 14687ad4d237SShuming Fan 14697ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, 14707ad4d237SShuming Fan RT711_MISC_POWER_CTL4, 0x6000, 0x6000); 14717ad4d237SShuming Fan 14727ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 14737ad4d237SShuming Fan RT711_COMBO_JACK_AUTO_CTL3, 0x000c, 0x000c); 14747ad4d237SShuming Fan 14757ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, 14767ad4d237SShuming Fan RT711_HDA_LEGACY_CONFIG_CTL, 0x0000); 14777ad4d237SShuming Fan 14787ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, 14797ad4d237SShuming Fan RT711_VAD_SRAM_CTL1, 0x0050); 14807ad4d237SShuming Fan } 14817ad4d237SShuming Fan 14827ad4d237SShuming Fan static void rt711_sdca_vd1_io_init(struct rt711_sdca_priv *rt711) 14837ad4d237SShuming Fan { 14847ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 14857ad4d237SShuming Fan RT711_HDA_LEGACY_UNSOLICITED_CTL, 0x0300, 0x0000); 14867ad4d237SShuming Fan 14877ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14887ad4d237SShuming Fan RT711_COMBO_JACK_AUTO_CTL3, 0xa43e); 14897ad4d237SShuming Fan 14907ad4d237SShuming Fan regmap_write(rt711->regmap, 0x2f5a, 0x05); 14917ad4d237SShuming Fan 14927ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14937ad4d237SShuming Fan RT711_JD_CTRL6, 0x0500); 14947ad4d237SShuming Fan 14957ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_REG, 14967ad4d237SShuming Fan RT711_DMIC_CTL1, 0x6173); 14977ad4d237SShuming Fan 14987ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, 14997ad4d237SShuming Fan RT711_HDA_LEGACY_CONFIG_CTL, 0x0000); 15007ad4d237SShuming Fan 15017ad4d237SShuming Fan rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, 15027ad4d237SShuming Fan RT711_VAD_SRAM_CTL1, 0x0050); 15037ad4d237SShuming Fan } 15047ad4d237SShuming Fan 15057ad4d237SShuming Fan int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) 15067ad4d237SShuming Fan { 15077ad4d237SShuming Fan struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); 15087ad4d237SShuming Fan int ret = 0; 15097ad4d237SShuming Fan unsigned int val; 15107ad4d237SShuming Fan 1511d2bf75f4SPierre-Louis Bossart rt711->disable_irq = false; 1512d2bf75f4SPierre-Louis Bossart 15137ad4d237SShuming Fan if (rt711->hw_init) 15147ad4d237SShuming Fan return 0; 15157ad4d237SShuming Fan 15167ad4d237SShuming Fan if (rt711->first_hw_init) { 15177ad4d237SShuming Fan regcache_cache_only(rt711->regmap, false); 15187ad4d237SShuming Fan regcache_cache_bypass(rt711->regmap, true); 1519bcc0f0c0SBard Liao regcache_cache_only(rt711->mbq_regmap, false); 1520bcc0f0c0SBard Liao regcache_cache_bypass(rt711->mbq_regmap, true); 15217ad4d237SShuming Fan } else { 15227ad4d237SShuming Fan /* 15237ad4d237SShuming Fan * PM runtime is only enabled when a Slave reports as Attached 15247ad4d237SShuming Fan */ 15257ad4d237SShuming Fan 15267ad4d237SShuming Fan /* set autosuspend parameters */ 15277ad4d237SShuming Fan pm_runtime_set_autosuspend_delay(&slave->dev, 3000); 15287ad4d237SShuming Fan pm_runtime_use_autosuspend(&slave->dev); 15297ad4d237SShuming Fan 15307ad4d237SShuming Fan /* update count of parent 'active' children */ 15317ad4d237SShuming Fan pm_runtime_set_active(&slave->dev); 15327ad4d237SShuming Fan 15337ad4d237SShuming Fan /* make sure the device does not suspend immediately */ 15347ad4d237SShuming Fan pm_runtime_mark_last_busy(&slave->dev); 15357ad4d237SShuming Fan 15367ad4d237SShuming Fan pm_runtime_enable(&slave->dev); 15377ad4d237SShuming Fan } 15387ad4d237SShuming Fan 15397ad4d237SShuming Fan pm_runtime_get_noresume(&slave->dev); 15407ad4d237SShuming Fan 15417ad4d237SShuming Fan rt711_sdca_reset(rt711); 15427ad4d237SShuming Fan 15437ad4d237SShuming Fan rt711_sdca_index_read(rt711, RT711_VENDOR_REG, RT711_JD_PRODUCT_NUM, &val); 15447ad4d237SShuming Fan rt711->hw_ver = val & 0xf; 15457ad4d237SShuming Fan 15467ad4d237SShuming Fan if (rt711->hw_ver == RT711_VER_VD0) 15477ad4d237SShuming Fan rt711_sdca_vd0_io_init(rt711); 15487ad4d237SShuming Fan else 15497ad4d237SShuming Fan rt711_sdca_vd1_io_init(rt711); 15507ad4d237SShuming Fan 15517ad4d237SShuming Fan /* DP4 mux select from 08_filter_Out_pri */ 15527ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, 15537ad4d237SShuming Fan RT711_FILTER_SRC_SEL, 0x1800, 0x0800); 15547ad4d237SShuming Fan 15557ad4d237SShuming Fan /* ge_exclusive_inbox_en disable */ 15567ad4d237SShuming Fan rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, 15577ad4d237SShuming Fan RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); 15587ad4d237SShuming Fan 15597ad4d237SShuming Fan /* calibration */ 15607ad4d237SShuming Fan ret = rt711_sdca_calibration(rt711); 15617ad4d237SShuming Fan if (ret < 0) 15627ad4d237SShuming Fan dev_err(dev, "%s, calibration failed!\n", __func__); 15637ad4d237SShuming Fan 15647ad4d237SShuming Fan /* HP output enable */ 15657ad4d237SShuming Fan regmap_write(rt711->regmap, 15667ad4d237SShuming Fan SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_OT1, RT711_SDCA_CTL_VENDOR_DEF, 0), 0x4); 15677ad4d237SShuming Fan 15687ad4d237SShuming Fan /* 15697ad4d237SShuming Fan * if set_jack callback occurred early than io_init, 15707ad4d237SShuming Fan * we set up the jack detection function now 15717ad4d237SShuming Fan */ 15727ad4d237SShuming Fan if (rt711->hs_jack) 15737ad4d237SShuming Fan rt711_sdca_jack_init(rt711); 15747ad4d237SShuming Fan 15757ad4d237SShuming Fan if (rt711->first_hw_init) { 15767ad4d237SShuming Fan regcache_cache_bypass(rt711->regmap, false); 15777ad4d237SShuming Fan regcache_mark_dirty(rt711->regmap); 1578bcc0f0c0SBard Liao regcache_cache_bypass(rt711->mbq_regmap, false); 1579bcc0f0c0SBard Liao regcache_mark_dirty(rt711->mbq_regmap); 15807ad4d237SShuming Fan } else 15817ad4d237SShuming Fan rt711->first_hw_init = true; 15827ad4d237SShuming Fan 15837ad4d237SShuming Fan /* Mark Slave initialization complete */ 15847ad4d237SShuming Fan rt711->hw_init = true; 15857ad4d237SShuming Fan 15867ad4d237SShuming Fan pm_runtime_mark_last_busy(&slave->dev); 15877ad4d237SShuming Fan pm_runtime_put_autosuspend(&slave->dev); 15887ad4d237SShuming Fan 15897ad4d237SShuming Fan dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); 15907ad4d237SShuming Fan return 0; 15917ad4d237SShuming Fan } 15927ad4d237SShuming Fan 15937ad4d237SShuming Fan MODULE_DESCRIPTION("ASoC RT711 SDCA SDW driver"); 15947ad4d237SShuming Fan MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>"); 15957ad4d237SShuming Fan MODULE_LICENSE("GPL"); 1596