18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * rt298.c -- RT298 ALSA SoC audio codec driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2015 Realtek Semiconductor Corp. 68c2ecf20Sopenharmony_ci * Author: Bard Liao <bardliao@realtek.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/pm.h> 148c2ecf20Sopenharmony_ci#include <linux/i2c.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 178c2ecf20Sopenharmony_ci#include <linux/dmi.h> 188c2ecf20Sopenharmony_ci#include <linux/acpi.h> 198c2ecf20Sopenharmony_ci#include <sound/core.h> 208c2ecf20Sopenharmony_ci#include <sound/pcm.h> 218c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 228c2ecf20Sopenharmony_ci#include <sound/soc.h> 238c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h> 248c2ecf20Sopenharmony_ci#include <sound/initval.h> 258c2ecf20Sopenharmony_ci#include <sound/tlv.h> 268c2ecf20Sopenharmony_ci#include <sound/jack.h> 278c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 288c2ecf20Sopenharmony_ci#include <sound/rt298.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include "rl6347a.h" 318c2ecf20Sopenharmony_ci#include "rt298.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define RT298_VENDOR_ID 0x10ec0298 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct rt298_priv { 368c2ecf20Sopenharmony_ci struct reg_default *index_cache; 378c2ecf20Sopenharmony_ci int index_cache_size; 388c2ecf20Sopenharmony_ci struct regmap *regmap; 398c2ecf20Sopenharmony_ci struct snd_soc_component *component; 408c2ecf20Sopenharmony_ci struct rt298_platform_data pdata; 418c2ecf20Sopenharmony_ci struct i2c_client *i2c; 428c2ecf20Sopenharmony_ci struct snd_soc_jack *jack; 438c2ecf20Sopenharmony_ci struct delayed_work jack_detect_work; 448c2ecf20Sopenharmony_ci int sys_clk; 458c2ecf20Sopenharmony_ci int clk_id; 468c2ecf20Sopenharmony_ci int is_hp_in; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic const struct reg_default rt298_index_def[] = { 508c2ecf20Sopenharmony_ci { 0x01, 0xa5a8 }, 518c2ecf20Sopenharmony_ci { 0x02, 0x8e95 }, 528c2ecf20Sopenharmony_ci { 0x03, 0x0002 }, 538c2ecf20Sopenharmony_ci { 0x04, 0xaf67 }, 548c2ecf20Sopenharmony_ci { 0x08, 0x200f }, 558c2ecf20Sopenharmony_ci { 0x09, 0xd010 }, 568c2ecf20Sopenharmony_ci { 0x0a, 0x0100 }, 578c2ecf20Sopenharmony_ci { 0x0b, 0x0000 }, 588c2ecf20Sopenharmony_ci { 0x0d, 0x2800 }, 598c2ecf20Sopenharmony_ci { 0x0f, 0x0022 }, 608c2ecf20Sopenharmony_ci { 0x19, 0x0217 }, 618c2ecf20Sopenharmony_ci { 0x20, 0x0020 }, 628c2ecf20Sopenharmony_ci { 0x33, 0x0208 }, 638c2ecf20Sopenharmony_ci { 0x46, 0x0300 }, 648c2ecf20Sopenharmony_ci { 0x49, 0x4004 }, 658c2ecf20Sopenharmony_ci { 0x4f, 0x50c9 }, 668c2ecf20Sopenharmony_ci { 0x50, 0x3000 }, 678c2ecf20Sopenharmony_ci { 0x63, 0x1b02 }, 688c2ecf20Sopenharmony_ci { 0x67, 0x1111 }, 698c2ecf20Sopenharmony_ci { 0x68, 0x1016 }, 708c2ecf20Sopenharmony_ci { 0x69, 0x273f }, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci#define INDEX_CACHE_SIZE ARRAY_SIZE(rt298_index_def) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic const struct reg_default rt298_reg[] = { 758c2ecf20Sopenharmony_ci { 0x00170500, 0x00000400 }, 768c2ecf20Sopenharmony_ci { 0x00220000, 0x00000031 }, 778c2ecf20Sopenharmony_ci { 0x00239000, 0x0000007f }, 788c2ecf20Sopenharmony_ci { 0x0023a000, 0x0000007f }, 798c2ecf20Sopenharmony_ci { 0x00270500, 0x00000400 }, 808c2ecf20Sopenharmony_ci { 0x00370500, 0x00000400 }, 818c2ecf20Sopenharmony_ci { 0x00870500, 0x00000400 }, 828c2ecf20Sopenharmony_ci { 0x00920000, 0x00000031 }, 838c2ecf20Sopenharmony_ci { 0x00935000, 0x000000c3 }, 848c2ecf20Sopenharmony_ci { 0x00936000, 0x000000c3 }, 858c2ecf20Sopenharmony_ci { 0x00970500, 0x00000400 }, 868c2ecf20Sopenharmony_ci { 0x00b37000, 0x00000097 }, 878c2ecf20Sopenharmony_ci { 0x00b37200, 0x00000097 }, 888c2ecf20Sopenharmony_ci { 0x00b37300, 0x00000097 }, 898c2ecf20Sopenharmony_ci { 0x00c37000, 0x00000000 }, 908c2ecf20Sopenharmony_ci { 0x00c37100, 0x00000080 }, 918c2ecf20Sopenharmony_ci { 0x01270500, 0x00000400 }, 928c2ecf20Sopenharmony_ci { 0x01370500, 0x00000400 }, 938c2ecf20Sopenharmony_ci { 0x01371f00, 0x411111f0 }, 948c2ecf20Sopenharmony_ci { 0x01439000, 0x00000080 }, 958c2ecf20Sopenharmony_ci { 0x0143a000, 0x00000080 }, 968c2ecf20Sopenharmony_ci { 0x01470700, 0x00000000 }, 978c2ecf20Sopenharmony_ci { 0x01470500, 0x00000400 }, 988c2ecf20Sopenharmony_ci { 0x01470c00, 0x00000000 }, 998c2ecf20Sopenharmony_ci { 0x01470100, 0x00000000 }, 1008c2ecf20Sopenharmony_ci { 0x01837000, 0x00000000 }, 1018c2ecf20Sopenharmony_ci { 0x01870500, 0x00000400 }, 1028c2ecf20Sopenharmony_ci { 0x02050000, 0x00000000 }, 1038c2ecf20Sopenharmony_ci { 0x02139000, 0x00000080 }, 1048c2ecf20Sopenharmony_ci { 0x0213a000, 0x00000080 }, 1058c2ecf20Sopenharmony_ci { 0x02170100, 0x00000000 }, 1068c2ecf20Sopenharmony_ci { 0x02170500, 0x00000400 }, 1078c2ecf20Sopenharmony_ci { 0x02170700, 0x00000000 }, 1088c2ecf20Sopenharmony_ci { 0x02270100, 0x00000000 }, 1098c2ecf20Sopenharmony_ci { 0x02370100, 0x00000000 }, 1108c2ecf20Sopenharmony_ci { 0x01870700, 0x00000020 }, 1118c2ecf20Sopenharmony_ci { 0x00830000, 0x000000c3 }, 1128c2ecf20Sopenharmony_ci { 0x00930000, 0x000000c3 }, 1138c2ecf20Sopenharmony_ci { 0x01270700, 0x00000000 }, 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic bool rt298_volatile_register(struct device *dev, unsigned int reg) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci switch (reg) { 1198c2ecf20Sopenharmony_ci case 0 ... 0xff: 1208c2ecf20Sopenharmony_ci case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 1218c2ecf20Sopenharmony_ci case RT298_GET_HP_SENSE: 1228c2ecf20Sopenharmony_ci case RT298_GET_MIC1_SENSE: 1238c2ecf20Sopenharmony_ci case RT298_PROC_COEF: 1248c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): 1258c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): 1268c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): 1278c2ecf20Sopenharmony_ci return true; 1288c2ecf20Sopenharmony_ci default: 1298c2ecf20Sopenharmony_ci return false; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic bool rt298_readable_register(struct device *dev, unsigned int reg) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci switch (reg) { 1388c2ecf20Sopenharmony_ci case 0 ... 0xff: 1398c2ecf20Sopenharmony_ci case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 1408c2ecf20Sopenharmony_ci case RT298_GET_HP_SENSE: 1418c2ecf20Sopenharmony_ci case RT298_GET_MIC1_SENSE: 1428c2ecf20Sopenharmony_ci case RT298_SET_AUDIO_POWER: 1438c2ecf20Sopenharmony_ci case RT298_SET_HPO_POWER: 1448c2ecf20Sopenharmony_ci case RT298_SET_SPK_POWER: 1458c2ecf20Sopenharmony_ci case RT298_SET_DMIC1_POWER: 1468c2ecf20Sopenharmony_ci case RT298_SPK_MUX: 1478c2ecf20Sopenharmony_ci case RT298_HPO_MUX: 1488c2ecf20Sopenharmony_ci case RT298_ADC0_MUX: 1498c2ecf20Sopenharmony_ci case RT298_ADC1_MUX: 1508c2ecf20Sopenharmony_ci case RT298_SET_MIC1: 1518c2ecf20Sopenharmony_ci case RT298_SET_PIN_HPO: 1528c2ecf20Sopenharmony_ci case RT298_SET_PIN_SPK: 1538c2ecf20Sopenharmony_ci case RT298_SET_PIN_DMIC1: 1548c2ecf20Sopenharmony_ci case RT298_SPK_EAPD: 1558c2ecf20Sopenharmony_ci case RT298_SET_AMP_GAIN_HPO: 1568c2ecf20Sopenharmony_ci case RT298_SET_DMIC2_DEFAULT: 1578c2ecf20Sopenharmony_ci case RT298_DACL_GAIN: 1588c2ecf20Sopenharmony_ci case RT298_DACR_GAIN: 1598c2ecf20Sopenharmony_ci case RT298_ADCL_GAIN: 1608c2ecf20Sopenharmony_ci case RT298_ADCR_GAIN: 1618c2ecf20Sopenharmony_ci case RT298_MIC_GAIN: 1628c2ecf20Sopenharmony_ci case RT298_SPOL_GAIN: 1638c2ecf20Sopenharmony_ci case RT298_SPOR_GAIN: 1648c2ecf20Sopenharmony_ci case RT298_HPOL_GAIN: 1658c2ecf20Sopenharmony_ci case RT298_HPOR_GAIN: 1668c2ecf20Sopenharmony_ci case RT298_F_DAC_SWITCH: 1678c2ecf20Sopenharmony_ci case RT298_F_RECMIX_SWITCH: 1688c2ecf20Sopenharmony_ci case RT298_REC_MIC_SWITCH: 1698c2ecf20Sopenharmony_ci case RT298_REC_I2S_SWITCH: 1708c2ecf20Sopenharmony_ci case RT298_REC_LINE_SWITCH: 1718c2ecf20Sopenharmony_ci case RT298_REC_BEEP_SWITCH: 1728c2ecf20Sopenharmony_ci case RT298_DAC_FORMAT: 1738c2ecf20Sopenharmony_ci case RT298_ADC_FORMAT: 1748c2ecf20Sopenharmony_ci case RT298_COEF_INDEX: 1758c2ecf20Sopenharmony_ci case RT298_PROC_COEF: 1768c2ecf20Sopenharmony_ci case RT298_SET_AMP_GAIN_ADC_IN1: 1778c2ecf20Sopenharmony_ci case RT298_SET_AMP_GAIN_ADC_IN2: 1788c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_DAC_OUT1): 1798c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_DAC_OUT2): 1808c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_ADC_IN1): 1818c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_ADC_IN2): 1828c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_DMIC2): 1838c2ecf20Sopenharmony_ci case RT298_SET_POWER(RT298_MIC1): 1848c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): 1858c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): 1868c2ecf20Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): 1878c2ecf20Sopenharmony_ci return true; 1888c2ecf20Sopenharmony_ci default: 1898c2ecf20Sopenharmony_ci return false; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1948c2ecf20Sopenharmony_cistatic void rt298_index_sync(struct snd_soc_component *component) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 1978c2ecf20Sopenharmony_ci int i; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) { 2008c2ecf20Sopenharmony_ci snd_soc_component_write(component, rt298->index_cache[i].reg, 2018c2ecf20Sopenharmony_ci rt298->index_cache[i].def); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci#endif 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic int rt298_support_power_controls[] = { 2078c2ecf20Sopenharmony_ci RT298_DAC_OUT1, 2088c2ecf20Sopenharmony_ci RT298_DAC_OUT2, 2098c2ecf20Sopenharmony_ci RT298_ADC_IN1, 2108c2ecf20Sopenharmony_ci RT298_ADC_IN2, 2118c2ecf20Sopenharmony_ci RT298_MIC1, 2128c2ecf20Sopenharmony_ci RT298_DMIC1, 2138c2ecf20Sopenharmony_ci RT298_DMIC2, 2148c2ecf20Sopenharmony_ci RT298_SPK_OUT, 2158c2ecf20Sopenharmony_ci RT298_HP_OUT, 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci#define RT298_POWER_REG_LEN ARRAY_SIZE(rt298_support_power_controls) 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct snd_soc_dapm_context *dapm; 2228c2ecf20Sopenharmony_ci unsigned int val, buf; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci *hp = false; 2258c2ecf20Sopenharmony_ci *mic = false; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (!rt298->component) 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci dapm = snd_soc_component_get_dapm(rt298->component); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (rt298->pdata.cbj_en) { 2338c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); 2348c2ecf20Sopenharmony_ci *hp = buf & 0x80000000; 2358c2ecf20Sopenharmony_ci if (*hp == rt298->is_hp_in) 2368c2ecf20Sopenharmony_ci return -1; 2378c2ecf20Sopenharmony_ci rt298->is_hp_in = *hp; 2388c2ecf20Sopenharmony_ci if (*hp) { 2398c2ecf20Sopenharmony_ci /* power on HV,VERF */ 2408c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2418c2ecf20Sopenharmony_ci RT298_DC_GAIN, 0x200, 0x200); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "HV"); 2448c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "VREF"); 2458c2ecf20Sopenharmony_ci /* power LDO1 */ 2468c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "LDO1"); 2478c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2508c2ecf20Sopenharmony_ci RT298_POWER_CTRL1, 0x1001, 0); 2518c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2528c2ecf20Sopenharmony_ci RT298_POWER_CTRL2, 0x4, 0x4); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); 2558c2ecf20Sopenharmony_ci msleep(50); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2588c2ecf20Sopenharmony_ci RT298_CBJ_CTRL1, 0xfcc0, 0xd400); 2598c2ecf20Sopenharmony_ci msleep(300); 2608c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (0x0070 == (val & 0x0070)) { 2638c2ecf20Sopenharmony_ci *mic = true; 2648c2ecf20Sopenharmony_ci } else { 2658c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2668c2ecf20Sopenharmony_ci RT298_CBJ_CTRL1, 0xfcc0, 0xe400); 2678c2ecf20Sopenharmony_ci msleep(300); 2688c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, 2698c2ecf20Sopenharmony_ci RT298_CBJ_CTRL2, &val); 2708c2ecf20Sopenharmony_ci if (0x0070 == (val & 0x0070)) 2718c2ecf20Sopenharmony_ci *mic = true; 2728c2ecf20Sopenharmony_ci else 2738c2ecf20Sopenharmony_ci *mic = false; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2768c2ecf20Sopenharmony_ci RT298_DC_GAIN, 0x200, 0x0); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci } else { 2798c2ecf20Sopenharmony_ci *mic = false; 2808c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); 2818c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 2828c2ecf20Sopenharmony_ci RT298_CBJ_CTRL1, 0x0400, 0x0000); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci } else { 2858c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); 2868c2ecf20Sopenharmony_ci *hp = buf & 0x80000000; 2878c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_MIC1_SENSE, &buf); 2888c2ecf20Sopenharmony_ci *mic = buf & 0x80000000; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci if (!*mic) { 2918c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "HV"); 2928c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "VREF"); 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci if (!*hp) 2958c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 2968c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci pr_debug("*hp = %d *mic = %d\n", *hp, *mic); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic void rt298_jack_detect_work(struct work_struct *work) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = 3068c2ecf20Sopenharmony_ci container_of(work, struct rt298_priv, jack_detect_work.work); 3078c2ecf20Sopenharmony_ci int status = 0; 3088c2ecf20Sopenharmony_ci bool hp = false; 3098c2ecf20Sopenharmony_ci bool mic = false; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (rt298_jack_detect(rt298, &hp, &mic) < 0) 3128c2ecf20Sopenharmony_ci return; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (hp) 3158c2ecf20Sopenharmony_ci status |= SND_JACK_HEADPHONE; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (mic) 3188c2ecf20Sopenharmony_ci status |= SND_JACK_MICROPHONE; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci snd_soc_jack_report(rt298->jack, status, 3218c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ciint rt298_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 3278c2ecf20Sopenharmony_ci struct snd_soc_dapm_context *dapm; 3288c2ecf20Sopenharmony_ci bool hp = false; 3298c2ecf20Sopenharmony_ci bool mic = false; 3308c2ecf20Sopenharmony_ci int status = 0; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* If jack in NULL, disable HS jack */ 3338c2ecf20Sopenharmony_ci if (!jack) { 3348c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x0); 3358c2ecf20Sopenharmony_ci dapm = snd_soc_component_get_dapm(component); 3368c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 3378c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 3388c2ecf20Sopenharmony_ci return 0; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci rt298->jack = jack; 3428c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci rt298_jack_detect(rt298, &hp, &mic); 3458c2ecf20Sopenharmony_ci if (hp) 3468c2ecf20Sopenharmony_ci status |= SND_JACK_HEADPHONE; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci if (mic) 3498c2ecf20Sopenharmony_ci status |= SND_JACK_MICROPHONE; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci snd_soc_jack_report(rt298->jack, status, 3528c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci return 0; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rt298_mic_detect); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic int is_mclk_mode(struct snd_soc_dapm_widget *source, 3598c2ecf20Sopenharmony_ci struct snd_soc_dapm_widget *sink) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 3628c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (rt298->clk_id == RT298_SCLK_S_MCLK) 3658c2ecf20Sopenharmony_ci return 1; 3668c2ecf20Sopenharmony_ci else 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); 3718c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_snd_controls[] = { 3748c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT298_DACL_GAIN, 3758c2ecf20Sopenharmony_ci RT298_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), 3768c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT298_ADCL_GAIN, 3778c2ecf20Sopenharmony_ci RT298_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), 3788c2ecf20Sopenharmony_ci SOC_SINGLE_TLV("AMIC Volume", RT298_MIC_GAIN, 3798c2ecf20Sopenharmony_ci 0, 0x3, 0, mic_vol_tlv), 3808c2ecf20Sopenharmony_ci SOC_DOUBLE_R("Speaker Playback Switch", RT298_SPOL_GAIN, 3818c2ecf20Sopenharmony_ci RT298_SPOR_GAIN, RT298_MUTE_SFT, 1, 1), 3828c2ecf20Sopenharmony_ci}; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci/* Digital Mixer */ 3858c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_front_mix[] = { 3868c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DAC Switch", RT298_F_DAC_SWITCH, 3878c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 3888c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("RECMIX Switch", RT298_F_RECMIX_SWITCH, 3898c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 3908c2ecf20Sopenharmony_ci}; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci/* Analog Input Mixer */ 3938c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_rec_mix[] = { 3948c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Mic1 Switch", RT298_REC_MIC_SWITCH, 3958c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 3968c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("I2S Switch", RT298_REC_I2S_SWITCH, 3978c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 3988c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Line1 Switch", RT298_REC_LINE_SWITCH, 3998c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 4008c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Beep Switch", RT298_REC_BEEP_SWITCH, 4018c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 4028c2ecf20Sopenharmony_ci}; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new spo_enable_control = 4058c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Switch", RT298_SET_PIN_SPK, 4068c2ecf20Sopenharmony_ci RT298_SET_PIN_SFT, 1, 0); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hpol_enable_control = 4098c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOL_GAIN, 4108c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hpor_enable_control = 4138c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOR_GAIN, 4148c2ecf20Sopenharmony_ci RT298_MUTE_SFT, 1, 1); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci/* ADC0 source */ 4178c2ecf20Sopenharmony_cistatic const char * const rt298_adc_src[] = { 4188c2ecf20Sopenharmony_ci "Mic", "RECMIX", "Dmic" 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic const int rt298_adc_values[] = { 4228c2ecf20Sopenharmony_ci 0, 4, 5, 4238c2ecf20Sopenharmony_ci}; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 4268c2ecf20Sopenharmony_ci rt298_adc0_enum, RT298_ADC0_MUX, RT298_ADC_SEL_SFT, 4278c2ecf20Sopenharmony_ci RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_adc0_mux = 4308c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("ADC 0 source", rt298_adc0_enum); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 4338c2ecf20Sopenharmony_ci rt298_adc1_enum, RT298_ADC1_MUX, RT298_ADC_SEL_SFT, 4348c2ecf20Sopenharmony_ci RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_adc1_mux = 4378c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("ADC 1 source", rt298_adc1_enum); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic const char * const rt298_dac_src[] = { 4408c2ecf20Sopenharmony_ci "Front", "Surround" 4418c2ecf20Sopenharmony_ci}; 4428c2ecf20Sopenharmony_ci/* HP-OUT source */ 4438c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt298_hpo_enum, RT298_HPO_MUX, 4448c2ecf20Sopenharmony_ci 0, rt298_dac_src); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_hpo_mux = 4478c2ecf20Sopenharmony_ciSOC_DAPM_ENUM("HPO source", rt298_hpo_enum); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci/* SPK-OUT source */ 4508c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt298_spo_enum, RT298_SPK_MUX, 4518c2ecf20Sopenharmony_ci 0, rt298_dac_src); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt298_spo_mux = 4548c2ecf20Sopenharmony_ciSOC_DAPM_ENUM("SPO source", rt298_spo_enum); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic int rt298_spk_event(struct snd_soc_dapm_widget *w, 4578c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci switch (event) { 4628c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 4638c2ecf20Sopenharmony_ci snd_soc_component_write(component, 4648c2ecf20Sopenharmony_ci RT298_SPK_EAPD, RT298_SET_EAPD_HIGH); 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 4678c2ecf20Sopenharmony_ci snd_soc_component_write(component, 4688c2ecf20Sopenharmony_ci RT298_SPK_EAPD, RT298_SET_EAPD_LOW); 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci default: 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return 0; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic int rt298_set_dmic1_event(struct snd_soc_dapm_widget *w, 4798c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci switch (event) { 4848c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 4858c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT298_SET_PIN_DMIC1, 0x20); 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 4888c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT298_SET_PIN_DMIC1, 0); 4898c2ecf20Sopenharmony_ci break; 4908c2ecf20Sopenharmony_ci default: 4918c2ecf20Sopenharmony_ci return 0; 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic int rt298_adc_event(struct snd_soc_dapm_widget *w, 4988c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 5018c2ecf20Sopenharmony_ci unsigned int nid; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci nid = (w->reg >> 20) & 0xff; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci switch (event) { 5068c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 5078c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5088c2ecf20Sopenharmony_ci VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 5098c2ecf20Sopenharmony_ci 0x7080, 0x7000); 5108c2ecf20Sopenharmony_ci /* If MCLK doesn't exist, reset AD filter */ 5118c2ecf20Sopenharmony_ci if (!(snd_soc_component_read(component, RT298_VAD_CTRL) & 0x200)) { 5128c2ecf20Sopenharmony_ci pr_info("NO MCLK\n"); 5138c2ecf20Sopenharmony_ci switch (nid) { 5148c2ecf20Sopenharmony_ci case RT298_ADC_IN1: 5158c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5168c2ecf20Sopenharmony_ci RT298_D_FILTER_CTRL, 0x2, 0x2); 5178c2ecf20Sopenharmony_ci mdelay(10); 5188c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5198c2ecf20Sopenharmony_ci RT298_D_FILTER_CTRL, 0x2, 0x0); 5208c2ecf20Sopenharmony_ci break; 5218c2ecf20Sopenharmony_ci case RT298_ADC_IN2: 5228c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5238c2ecf20Sopenharmony_ci RT298_D_FILTER_CTRL, 0x4, 0x4); 5248c2ecf20Sopenharmony_ci mdelay(10); 5258c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5268c2ecf20Sopenharmony_ci RT298_D_FILTER_CTRL, 0x4, 0x0); 5278c2ecf20Sopenharmony_ci break; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci break; 5318c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 5328c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5338c2ecf20Sopenharmony_ci VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 5348c2ecf20Sopenharmony_ci 0x7080, 0x7080); 5358c2ecf20Sopenharmony_ci break; 5368c2ecf20Sopenharmony_ci default: 5378c2ecf20Sopenharmony_ci return 0; 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci return 0; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic int rt298_mic1_event(struct snd_soc_dapm_widget *w, 5448c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci switch (event) { 5498c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 5508c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5518c2ecf20Sopenharmony_ci RT298_A_BIAS_CTRL3, 0xc000, 0x8000); 5528c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5538c2ecf20Sopenharmony_ci RT298_A_BIAS_CTRL2, 0xc000, 0x8000); 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 5568c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5578c2ecf20Sopenharmony_ci RT298_A_BIAS_CTRL3, 0xc000, 0x0000); 5588c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5598c2ecf20Sopenharmony_ci RT298_A_BIAS_CTRL2, 0xc000, 0x0000); 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci default: 5628c2ecf20Sopenharmony_ci return 0; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci return 0; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, 5718c2ecf20Sopenharmony_ci 12, 1, NULL, 0), 5728c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, 5738c2ecf20Sopenharmony_ci 0, 1, NULL, 0), 5748c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, 5758c2ecf20Sopenharmony_ci 1, 0, NULL, 0), 5768c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, 5778c2ecf20Sopenharmony_ci 2, 0, NULL, 0), 5788c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT298_POWER_CTRL2, 5798c2ecf20Sopenharmony_ci 3, 0, NULL, 0), 5808c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("VREF1", 1, RT298_POWER_CTRL2, 5818c2ecf20Sopenharmony_ci 4, 1, NULL, 0), 5828c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LV", 2, RT298_POWER_CTRL1, 5838c2ecf20Sopenharmony_ci 13, 1, NULL, 0), 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MCLK MODE", RT298_PLL_CTRL1, 5878c2ecf20Sopenharmony_ci 5, 0, NULL, 0), 5888c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, 5898c2ecf20Sopenharmony_ci 0, 0, rt298_mic1_event, SND_SOC_DAPM_PRE_PMU | 5908c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMD), 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci /* Input Lines */ 5938c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1 Pin"), 5948c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2 Pin"), 5958c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC1"), 5968c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("LINE1"), 5978c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("Beep"), 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* DMIC */ 6008c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("DMIC1", RT298_SET_POWER(RT298_DMIC1), 0, 1, 6018c2ecf20Sopenharmony_ci NULL, 0, rt298_set_dmic1_event, 6028c2ecf20Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 6038c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("DMIC2", RT298_SET_POWER(RT298_DMIC2), 0, 1, 6048c2ecf20Sopenharmony_ci NULL, 0), 6058c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, 6068c2ecf20Sopenharmony_ci 0, 0, NULL, 0), 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci /* REC Mixer */ 6098c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, 6108c2ecf20Sopenharmony_ci rt298_rec_mix, ARRAY_SIZE(rt298_rec_mix)), 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* ADCs */ 6138c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), 6148c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* ADC Mux */ 6178c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT298_SET_POWER(RT298_ADC_IN1), 0, 1, 6188c2ecf20Sopenharmony_ci &rt298_adc0_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | 6198c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU), 6208c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT298_SET_POWER(RT298_ADC_IN2), 0, 1, 6218c2ecf20Sopenharmony_ci &rt298_adc1_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | 6228c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU), 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci /* Audio Interface */ 6258c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 6268c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 6278c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), 6288c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci /* Output Side */ 6318c2ecf20Sopenharmony_ci /* DACs */ 6328c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), 6338c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* Output Mux */ 6368c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt298_spo_mux), 6378c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt298_hpo_mux), 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("HP Power", RT298_SET_PIN_HPO, 6408c2ecf20Sopenharmony_ci RT298_SET_PIN_SFT, 0, NULL, 0), 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* Output Mixer */ 6438c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Front", RT298_SET_POWER(RT298_DAC_OUT1), 0, 1, 6448c2ecf20Sopenharmony_ci rt298_front_mix, ARRAY_SIZE(rt298_front_mix)), 6458c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("Surround", RT298_SET_POWER(RT298_DAC_OUT2), 0, 1, 6468c2ecf20Sopenharmony_ci NULL, 0), 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* Output Pga */ 6498c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, 6508c2ecf20Sopenharmony_ci &spo_enable_control, rt298_spk_event, 6518c2ecf20Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 6528c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, 6538c2ecf20Sopenharmony_ci &hpol_enable_control), 6548c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, 6558c2ecf20Sopenharmony_ci &hpor_enable_control), 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Output Lines */ 6588c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOL"), 6598c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOR"), 6608c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPO Pin"), 6618c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPDIF"), 6628c2ecf20Sopenharmony_ci}; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt298_dapm_routes[] = { 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, 6678c2ecf20Sopenharmony_ci {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, 6688c2ecf20Sopenharmony_ci {"Front", NULL, "MCLK MODE", is_mclk_mode}, 6698c2ecf20Sopenharmony_ci {"Surround", NULL, "MCLK MODE", is_mclk_mode}, 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci {"HP Power", NULL, "LDO1"}, 6728c2ecf20Sopenharmony_ci {"HP Power", NULL, "LDO2"}, 6738c2ecf20Sopenharmony_ci {"HP Power", NULL, "LV"}, 6748c2ecf20Sopenharmony_ci {"HP Power", NULL, "VREF1"}, 6758c2ecf20Sopenharmony_ci {"HP Power", NULL, "BG_MBIAS"}, 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci {"MIC1", NULL, "LDO1"}, 6788c2ecf20Sopenharmony_ci {"MIC1", NULL, "LDO2"}, 6798c2ecf20Sopenharmony_ci {"MIC1", NULL, "HV"}, 6808c2ecf20Sopenharmony_ci {"MIC1", NULL, "LV"}, 6818c2ecf20Sopenharmony_ci {"MIC1", NULL, "VREF"}, 6828c2ecf20Sopenharmony_ci {"MIC1", NULL, "VREF1"}, 6838c2ecf20Sopenharmony_ci {"MIC1", NULL, "BG_MBIAS"}, 6848c2ecf20Sopenharmony_ci {"MIC1", NULL, "MIC1 Input Buffer"}, 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci {"SPO", NULL, "LDO1"}, 6878c2ecf20Sopenharmony_ci {"SPO", NULL, "LDO2"}, 6888c2ecf20Sopenharmony_ci {"SPO", NULL, "HV"}, 6898c2ecf20Sopenharmony_ci {"SPO", NULL, "LV"}, 6908c2ecf20Sopenharmony_ci {"SPO", NULL, "VREF"}, 6918c2ecf20Sopenharmony_ci {"SPO", NULL, "VREF1"}, 6928c2ecf20Sopenharmony_ci {"SPO", NULL, "BG_MBIAS"}, 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci {"DMIC1", NULL, "DMIC1 Pin"}, 6958c2ecf20Sopenharmony_ci {"DMIC2", NULL, "DMIC2 Pin"}, 6968c2ecf20Sopenharmony_ci {"DMIC1", NULL, "DMIC Receiver"}, 6978c2ecf20Sopenharmony_ci {"DMIC2", NULL, "DMIC Receiver"}, 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci {"RECMIX", "Beep Switch", "Beep"}, 7008c2ecf20Sopenharmony_ci {"RECMIX", "Line1 Switch", "LINE1"}, 7018c2ecf20Sopenharmony_ci {"RECMIX", "Mic1 Switch", "MIC1"}, 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci {"ADC 0 Mux", "Dmic", "DMIC1"}, 7048c2ecf20Sopenharmony_ci {"ADC 0 Mux", "RECMIX", "RECMIX"}, 7058c2ecf20Sopenharmony_ci {"ADC 0 Mux", "Mic", "MIC1"}, 7068c2ecf20Sopenharmony_ci {"ADC 1 Mux", "Dmic", "DMIC2"}, 7078c2ecf20Sopenharmony_ci {"ADC 1 Mux", "RECMIX", "RECMIX"}, 7088c2ecf20Sopenharmony_ci {"ADC 1 Mux", "Mic", "MIC1"}, 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci {"ADC 0", NULL, "ADC 0 Mux"}, 7118c2ecf20Sopenharmony_ci {"ADC 1", NULL, "ADC 1 Mux"}, 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci {"AIF1TX", NULL, "ADC 0"}, 7148c2ecf20Sopenharmony_ci {"AIF2TX", NULL, "ADC 1"}, 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci {"DAC 0", NULL, "AIF1RX"}, 7178c2ecf20Sopenharmony_ci {"DAC 1", NULL, "AIF2RX"}, 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci {"Front", "DAC Switch", "DAC 0"}, 7208c2ecf20Sopenharmony_ci {"Front", "RECMIX Switch", "RECMIX"}, 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci {"Surround", NULL, "DAC 1"}, 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci {"SPK Mux", "Front", "Front"}, 7258c2ecf20Sopenharmony_ci {"SPK Mux", "Surround", "Surround"}, 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci {"HPO Mux", "Front", "Front"}, 7288c2ecf20Sopenharmony_ci {"HPO Mux", "Surround", "Surround"}, 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci {"SPO", "Switch", "SPK Mux"}, 7318c2ecf20Sopenharmony_ci {"HPO L", "Switch", "HPO Mux"}, 7328c2ecf20Sopenharmony_ci {"HPO R", "Switch", "HPO Mux"}, 7338c2ecf20Sopenharmony_ci {"HPO L", NULL, "HP Power"}, 7348c2ecf20Sopenharmony_ci {"HPO R", NULL, "HP Power"}, 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci {"SPOL", NULL, "SPO"}, 7378c2ecf20Sopenharmony_ci {"SPOR", NULL, "SPO"}, 7388c2ecf20Sopenharmony_ci {"HPO Pin", NULL, "HPO L"}, 7398c2ecf20Sopenharmony_ci {"HPO Pin", NULL, "HPO R"}, 7408c2ecf20Sopenharmony_ci}; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic int rt298_hw_params(struct snd_pcm_substream *substream, 7438c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 7448c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 7478c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 7488c2ecf20Sopenharmony_ci unsigned int val = 0; 7498c2ecf20Sopenharmony_ci int d_len_code; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci switch (params_rate(params)) { 7528c2ecf20Sopenharmony_ci /* bit 14 0:48K 1:44.1K */ 7538c2ecf20Sopenharmony_ci case 44100: 7548c2ecf20Sopenharmony_ci case 48000: 7558c2ecf20Sopenharmony_ci break; 7568c2ecf20Sopenharmony_ci default: 7578c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported sample rate %d\n", 7588c2ecf20Sopenharmony_ci params_rate(params)); 7598c2ecf20Sopenharmony_ci return -EINVAL; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci switch (rt298->sys_clk) { 7628c2ecf20Sopenharmony_ci case 12288000: 7638c2ecf20Sopenharmony_ci case 24576000: 7648c2ecf20Sopenharmony_ci if (params_rate(params) != 48000) { 7658c2ecf20Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 7668c2ecf20Sopenharmony_ci params_rate(params), rt298->sys_clk); 7678c2ecf20Sopenharmony_ci return -EINVAL; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci break; 7708c2ecf20Sopenharmony_ci case 11289600: 7718c2ecf20Sopenharmony_ci case 22579200: 7728c2ecf20Sopenharmony_ci if (params_rate(params) != 44100) { 7738c2ecf20Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 7748c2ecf20Sopenharmony_ci params_rate(params), rt298->sys_clk); 7758c2ecf20Sopenharmony_ci return -EINVAL; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci break; 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci if (params_channels(params) <= 16) { 7818c2ecf20Sopenharmony_ci /* bit 3:0 Number of Channel */ 7828c2ecf20Sopenharmony_ci val |= (params_channels(params) - 1); 7838c2ecf20Sopenharmony_ci } else { 7848c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported channels %d\n", 7858c2ecf20Sopenharmony_ci params_channels(params)); 7868c2ecf20Sopenharmony_ci return -EINVAL; 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci d_len_code = 0; 7908c2ecf20Sopenharmony_ci switch (params_width(params)) { 7918c2ecf20Sopenharmony_ci /* bit 6:4 Bits per Sample */ 7928c2ecf20Sopenharmony_ci case 16: 7938c2ecf20Sopenharmony_ci d_len_code = 0; 7948c2ecf20Sopenharmony_ci val |= (0x1 << 4); 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci case 32: 7978c2ecf20Sopenharmony_ci d_len_code = 2; 7988c2ecf20Sopenharmony_ci val |= (0x4 << 4); 7998c2ecf20Sopenharmony_ci break; 8008c2ecf20Sopenharmony_ci case 20: 8018c2ecf20Sopenharmony_ci d_len_code = 1; 8028c2ecf20Sopenharmony_ci val |= (0x2 << 4); 8038c2ecf20Sopenharmony_ci break; 8048c2ecf20Sopenharmony_ci case 24: 8058c2ecf20Sopenharmony_ci d_len_code = 2; 8068c2ecf20Sopenharmony_ci val |= (0x3 << 4); 8078c2ecf20Sopenharmony_ci break; 8088c2ecf20Sopenharmony_ci case 8: 8098c2ecf20Sopenharmony_ci d_len_code = 3; 8108c2ecf20Sopenharmony_ci break; 8118c2ecf20Sopenharmony_ci default: 8128c2ecf20Sopenharmony_ci return -EINVAL; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8168c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x0018, d_len_code << 3); 8178c2ecf20Sopenharmony_ci dev_dbg(component->dev, "format val = 0x%x\n", val); 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT298_DAC_FORMAT, 0x407f, val); 8208c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT298_ADC_FORMAT, 0x407f, val); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci return 0; 8238c2ecf20Sopenharmony_ci} 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_cistatic int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 8268c2ecf20Sopenharmony_ci{ 8278c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 8308c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 8318c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8328c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x800, 0x800); 8338c2ecf20Sopenharmony_ci break; 8348c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 8358c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8368c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x800, 0x0); 8378c2ecf20Sopenharmony_ci break; 8388c2ecf20Sopenharmony_ci default: 8398c2ecf20Sopenharmony_ci return -EINVAL; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 8438c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 8448c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8458c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x0); 8468c2ecf20Sopenharmony_ci break; 8478c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 8488c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8498c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x1 << 8); 8508c2ecf20Sopenharmony_ci break; 8518c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 8528c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8538c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x2 << 8); 8548c2ecf20Sopenharmony_ci break; 8558c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 8568c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8578c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x3 << 8); 8588c2ecf20Sopenharmony_ci break; 8598c2ecf20Sopenharmony_ci default: 8608c2ecf20Sopenharmony_ci return -EINVAL; 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci /* bit 15 Stream Type 0:PCM 1:Non-PCM */ 8638c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT298_DAC_FORMAT, 0x8000, 0); 8648c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT298_ADC_FORMAT, 0x8000, 0); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci return 0; 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int rt298_set_dai_sysclk(struct snd_soc_dai *dai, 8708c2ecf20Sopenharmony_ci int clk_id, unsigned int freq, int dir) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8738c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci dev_dbg(component->dev, "%s freq=%d\n", __func__, freq); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 8788c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8798c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x0100, 0x0); 8808c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8818c2ecf20Sopenharmony_ci RT298_PLL_CTRL1, 0x20, 0x20); 8828c2ecf20Sopenharmony_ci } else { 8838c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8848c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x0100, 0x0100); 8858c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8868c2ecf20Sopenharmony_ci RT298_PLL_CTRL1, 0x20, 0x0); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci switch (freq) { 8908c2ecf20Sopenharmony_ci case 19200000: 8918c2ecf20Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 8928c2ecf20Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 8938c2ecf20Sopenharmony_ci return -EINVAL; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8968c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x40, 0x40); 8978c2ecf20Sopenharmony_ci break; 8988c2ecf20Sopenharmony_ci case 24000000: 8998c2ecf20Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 9008c2ecf20Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 9018c2ecf20Sopenharmony_ci return -EINVAL; 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9048c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x40, 0x0); 9058c2ecf20Sopenharmony_ci break; 9068c2ecf20Sopenharmony_ci case 12288000: 9078c2ecf20Sopenharmony_ci case 11289600: 9088c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9098c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x8, 0x0); 9108c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9118c2ecf20Sopenharmony_ci RT298_CLK_DIV, 0xfc1e, 0x0004); 9128c2ecf20Sopenharmony_ci break; 9138c2ecf20Sopenharmony_ci case 24576000: 9148c2ecf20Sopenharmony_ci case 22579200: 9158c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9168c2ecf20Sopenharmony_ci RT298_I2S_CTRL2, 0x8, 0x8); 9178c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9188c2ecf20Sopenharmony_ci RT298_CLK_DIV, 0xfc1e, 0x5406); 9198c2ecf20Sopenharmony_ci break; 9208c2ecf20Sopenharmony_ci default: 9218c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported system clock\n"); 9228c2ecf20Sopenharmony_ci return -EINVAL; 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci rt298->sys_clk = freq; 9268c2ecf20Sopenharmony_ci rt298->clk_id = clk_id; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci return 0; 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic int rt298_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) 9328c2ecf20Sopenharmony_ci{ 9338c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); 9368c2ecf20Sopenharmony_ci if (50 == ratio) 9378c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9388c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x1000, 0x1000); 9398c2ecf20Sopenharmony_ci else 9408c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 9418c2ecf20Sopenharmony_ci RT298_I2S_CTRL1, 0x1000, 0x0); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci return 0; 9458c2ecf20Sopenharmony_ci} 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_cistatic int rt298_set_bias_level(struct snd_soc_component *component, 9488c2ecf20Sopenharmony_ci enum snd_soc_bias_level level) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci switch (level) { 9518c2ecf20Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 9528c2ecf20Sopenharmony_ci if (SND_SOC_BIAS_STANDBY == 9538c2ecf20Sopenharmony_ci snd_soc_component_get_bias_level(component)) { 9548c2ecf20Sopenharmony_ci snd_soc_component_write(component, 9558c2ecf20Sopenharmony_ci RT298_SET_AUDIO_POWER, AC_PWRST_D0); 9568c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 0x0d, 0x200, 0x200); 9578c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 0x52, 0x80, 0x0); 9588c2ecf20Sopenharmony_ci mdelay(20); 9598c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 0x0d, 0x200, 0x0); 9608c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 0x52, 0x80, 0x80); 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci break; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 9658c2ecf20Sopenharmony_ci snd_soc_component_write(component, 9668c2ecf20Sopenharmony_ci RT298_SET_AUDIO_POWER, AC_PWRST_D3); 9678c2ecf20Sopenharmony_ci break; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci default: 9708c2ecf20Sopenharmony_ci break; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci return 0; 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic irqreturn_t rt298_irq(int irq, void *data) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = data; 9798c2ecf20Sopenharmony_ci bool hp = false; 9808c2ecf20Sopenharmony_ci bool mic = false; 9818c2ecf20Sopenharmony_ci int ret, status = 0; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci ret = rt298_jack_detect(rt298, &hp, &mic); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci /* Clear IRQ */ 9868c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (ret == 0) { 9898c2ecf20Sopenharmony_ci if (hp) 9908c2ecf20Sopenharmony_ci status |= SND_JACK_HEADPHONE; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci if (mic) 9938c2ecf20Sopenharmony_ci status |= SND_JACK_MICROPHONE; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci snd_soc_jack_report(rt298->jack, status, 9968c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci pm_wakeup_event(&rt298->i2c->dev, 300); 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci return IRQ_HANDLED; 10028c2ecf20Sopenharmony_ci} 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_cistatic int rt298_probe(struct snd_soc_component *component) 10058c2ecf20Sopenharmony_ci{ 10068c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci rt298->component = component; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (rt298->i2c->irq) { 10118c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 10128c2ecf20Sopenharmony_ci RT298_IRQ_CTRL, 0x2, 0x2); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rt298->jack_detect_work, 10158c2ecf20Sopenharmony_ci rt298_jack_detect_work); 10168c2ecf20Sopenharmony_ci schedule_delayed_work(&rt298->jack_detect_work, 10178c2ecf20Sopenharmony_ci msecs_to_jiffies(1250)); 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci return 0; 10218c2ecf20Sopenharmony_ci} 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_cistatic void rt298_remove(struct snd_soc_component *component) 10248c2ecf20Sopenharmony_ci{ 10258c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rt298->jack_detect_work); 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 10318c2ecf20Sopenharmony_cistatic int rt298_suspend(struct snd_soc_component *component) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci rt298->is_hp_in = -1; 10368c2ecf20Sopenharmony_ci regcache_cache_only(rt298->regmap, true); 10378c2ecf20Sopenharmony_ci regcache_mark_dirty(rt298->regmap); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci return 0; 10408c2ecf20Sopenharmony_ci} 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cistatic int rt298_resume(struct snd_soc_component *component) 10438c2ecf20Sopenharmony_ci{ 10448c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci regcache_cache_only(rt298->regmap, false); 10478c2ecf20Sopenharmony_ci rt298_index_sync(component); 10488c2ecf20Sopenharmony_ci regcache_sync(rt298->regmap); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci return 0; 10518c2ecf20Sopenharmony_ci} 10528c2ecf20Sopenharmony_ci#else 10538c2ecf20Sopenharmony_ci#define rt298_suspend NULL 10548c2ecf20Sopenharmony_ci#define rt298_resume NULL 10558c2ecf20Sopenharmony_ci#endif 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci#define RT298_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 10588c2ecf20Sopenharmony_ci#define RT298_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 10598c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops rt298_aif_dai_ops = { 10628c2ecf20Sopenharmony_ci .hw_params = rt298_hw_params, 10638c2ecf20Sopenharmony_ci .set_fmt = rt298_set_dai_fmt, 10648c2ecf20Sopenharmony_ci .set_sysclk = rt298_set_dai_sysclk, 10658c2ecf20Sopenharmony_ci .set_bclk_ratio = rt298_set_bclk_ratio, 10668c2ecf20Sopenharmony_ci}; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver rt298_dai[] = { 10698c2ecf20Sopenharmony_ci { 10708c2ecf20Sopenharmony_ci .name = "rt298-aif1", 10718c2ecf20Sopenharmony_ci .id = RT298_AIF1, 10728c2ecf20Sopenharmony_ci .playback = { 10738c2ecf20Sopenharmony_ci .stream_name = "AIF1 Playback", 10748c2ecf20Sopenharmony_ci .channels_min = 1, 10758c2ecf20Sopenharmony_ci .channels_max = 2, 10768c2ecf20Sopenharmony_ci .rates = RT298_STEREO_RATES, 10778c2ecf20Sopenharmony_ci .formats = RT298_FORMATS, 10788c2ecf20Sopenharmony_ci }, 10798c2ecf20Sopenharmony_ci .capture = { 10808c2ecf20Sopenharmony_ci .stream_name = "AIF1 Capture", 10818c2ecf20Sopenharmony_ci .channels_min = 1, 10828c2ecf20Sopenharmony_ci .channels_max = 2, 10838c2ecf20Sopenharmony_ci .rates = RT298_STEREO_RATES, 10848c2ecf20Sopenharmony_ci .formats = RT298_FORMATS, 10858c2ecf20Sopenharmony_ci }, 10868c2ecf20Sopenharmony_ci .ops = &rt298_aif_dai_ops, 10878c2ecf20Sopenharmony_ci .symmetric_rates = 1, 10888c2ecf20Sopenharmony_ci }, 10898c2ecf20Sopenharmony_ci { 10908c2ecf20Sopenharmony_ci .name = "rt298-aif2", 10918c2ecf20Sopenharmony_ci .id = RT298_AIF2, 10928c2ecf20Sopenharmony_ci .playback = { 10938c2ecf20Sopenharmony_ci .stream_name = "AIF2 Playback", 10948c2ecf20Sopenharmony_ci .channels_min = 1, 10958c2ecf20Sopenharmony_ci .channels_max = 2, 10968c2ecf20Sopenharmony_ci .rates = RT298_STEREO_RATES, 10978c2ecf20Sopenharmony_ci .formats = RT298_FORMATS, 10988c2ecf20Sopenharmony_ci }, 10998c2ecf20Sopenharmony_ci .capture = { 11008c2ecf20Sopenharmony_ci .stream_name = "AIF2 Capture", 11018c2ecf20Sopenharmony_ci .channels_min = 1, 11028c2ecf20Sopenharmony_ci .channels_max = 2, 11038c2ecf20Sopenharmony_ci .rates = RT298_STEREO_RATES, 11048c2ecf20Sopenharmony_ci .formats = RT298_FORMATS, 11058c2ecf20Sopenharmony_ci }, 11068c2ecf20Sopenharmony_ci .ops = &rt298_aif_dai_ops, 11078c2ecf20Sopenharmony_ci .symmetric_rates = 1, 11088c2ecf20Sopenharmony_ci }, 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci}; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt298 = { 11138c2ecf20Sopenharmony_ci .probe = rt298_probe, 11148c2ecf20Sopenharmony_ci .remove = rt298_remove, 11158c2ecf20Sopenharmony_ci .suspend = rt298_suspend, 11168c2ecf20Sopenharmony_ci .resume = rt298_resume, 11178c2ecf20Sopenharmony_ci .set_bias_level = rt298_set_bias_level, 11188c2ecf20Sopenharmony_ci .controls = rt298_snd_controls, 11198c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(rt298_snd_controls), 11208c2ecf20Sopenharmony_ci .dapm_widgets = rt298_dapm_widgets, 11218c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), 11228c2ecf20Sopenharmony_ci .dapm_routes = rt298_dapm_routes, 11238c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), 11248c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 11258c2ecf20Sopenharmony_ci .endianness = 1, 11268c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 11278c2ecf20Sopenharmony_ci}; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic const struct regmap_config rt298_regmap = { 11308c2ecf20Sopenharmony_ci .reg_bits = 32, 11318c2ecf20Sopenharmony_ci .val_bits = 32, 11328c2ecf20Sopenharmony_ci .max_register = 0x02370100, 11338c2ecf20Sopenharmony_ci .volatile_reg = rt298_volatile_register, 11348c2ecf20Sopenharmony_ci .readable_reg = rt298_readable_register, 11358c2ecf20Sopenharmony_ci .reg_write = rl6347a_hw_write, 11368c2ecf20Sopenharmony_ci .reg_read = rl6347a_hw_read, 11378c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 11388c2ecf20Sopenharmony_ci .reg_defaults = rt298_reg, 11398c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt298_reg), 11408c2ecf20Sopenharmony_ci}; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic const struct i2c_device_id rt298_i2c_id[] = { 11438c2ecf20Sopenharmony_ci {"rt298", 0}, 11448c2ecf20Sopenharmony_ci {} 11458c2ecf20Sopenharmony_ci}; 11468c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt298_i2c_id); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 11498c2ecf20Sopenharmony_cistatic const struct acpi_device_id rt298_acpi_match[] = { 11508c2ecf20Sopenharmony_ci { "INT343A", 0 }, 11518c2ecf20Sopenharmony_ci {}, 11528c2ecf20Sopenharmony_ci}; 11538c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt298_acpi_match); 11548c2ecf20Sopenharmony_ci#endif 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic const struct dmi_system_id force_combo_jack_table[] = { 11578c2ecf20Sopenharmony_ci { 11588c2ecf20Sopenharmony_ci .ident = "Intel Broxton P", 11598c2ecf20Sopenharmony_ci .matches = { 11608c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"), 11618c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Broxton P") 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci }, 11648c2ecf20Sopenharmony_ci { 11658c2ecf20Sopenharmony_ci .ident = "Intel Gemini Lake", 11668c2ecf20Sopenharmony_ci .matches = { 11678c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"), 11688c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Geminilake") 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci }, 11718c2ecf20Sopenharmony_ci { 11728c2ecf20Sopenharmony_ci .ident = "Intel Kabylake R RVP", 11738c2ecf20Sopenharmony_ci .matches = { 11748c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 11758c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci }, 11788c2ecf20Sopenharmony_ci { } 11798c2ecf20Sopenharmony_ci}; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_cistatic int rt298_i2c_probe(struct i2c_client *i2c, 11828c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 11838c2ecf20Sopenharmony_ci{ 11848c2ecf20Sopenharmony_ci struct rt298_platform_data *pdata = dev_get_platdata(&i2c->dev); 11858c2ecf20Sopenharmony_ci struct rt298_priv *rt298; 11868c2ecf20Sopenharmony_ci struct device *dev = &i2c->dev; 11878c2ecf20Sopenharmony_ci const struct acpi_device_id *acpiid; 11888c2ecf20Sopenharmony_ci int i, ret; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci rt298 = devm_kzalloc(&i2c->dev, sizeof(*rt298), 11918c2ecf20Sopenharmony_ci GFP_KERNEL); 11928c2ecf20Sopenharmony_ci if (NULL == rt298) 11938c2ecf20Sopenharmony_ci return -ENOMEM; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci rt298->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt298_regmap); 11968c2ecf20Sopenharmony_ci if (IS_ERR(rt298->regmap)) { 11978c2ecf20Sopenharmony_ci ret = PTR_ERR(rt298->regmap); 11988c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 11998c2ecf20Sopenharmony_ci ret); 12008c2ecf20Sopenharmony_ci return ret; 12018c2ecf20Sopenharmony_ci } 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci regmap_read(rt298->regmap, 12048c2ecf20Sopenharmony_ci RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); 12058c2ecf20Sopenharmony_ci if (ret != RT298_VENDOR_ID) { 12068c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 12078c2ecf20Sopenharmony_ci "Device with ID register %#x is not rt298\n", ret); 12088c2ecf20Sopenharmony_ci return -ENODEV; 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci rt298->index_cache = devm_kmemdup(&i2c->dev, rt298_index_def, 12128c2ecf20Sopenharmony_ci sizeof(rt298_index_def), GFP_KERNEL); 12138c2ecf20Sopenharmony_ci if (!rt298->index_cache) 12148c2ecf20Sopenharmony_ci return -ENOMEM; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci rt298->index_cache_size = INDEX_CACHE_SIZE; 12178c2ecf20Sopenharmony_ci rt298->i2c = i2c; 12188c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, rt298); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci /* restore codec default */ 12218c2ecf20Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) 12228c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, rt298->index_cache[i].reg, 12238c2ecf20Sopenharmony_ci rt298->index_cache[i].def); 12248c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rt298_reg); i++) 12258c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, rt298_reg[i].reg, 12268c2ecf20Sopenharmony_ci rt298_reg[i].def); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (pdata) 12298c2ecf20Sopenharmony_ci rt298->pdata = *pdata; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* enable jack combo mode on supported devices */ 12328c2ecf20Sopenharmony_ci acpiid = acpi_match_device(dev->driver->acpi_match_table, dev); 12338c2ecf20Sopenharmony_ci if (acpiid && acpiid->driver_data) { 12348c2ecf20Sopenharmony_ci rt298->pdata = *(struct rt298_platform_data *) 12358c2ecf20Sopenharmony_ci acpiid->driver_data; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci if (dmi_check_system(force_combo_jack_table)) { 12398c2ecf20Sopenharmony_ci rt298->pdata.cbj_en = true; 12408c2ecf20Sopenharmony_ci rt298->pdata.gpio2_en = false; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci /* VREF Charging */ 12448c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80); 12458c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860); 12468c2ecf20Sopenharmony_ci /* Vref2 */ 12478c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x08, 0x20, 0x20); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_AUDIO_POWER, AC_PWRST_D3); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci for (i = 0; i < RT298_POWER_REG_LEN; i++) 12528c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, 12538c2ecf20Sopenharmony_ci RT298_SET_POWER(rt298_support_power_controls[i]), 12548c2ecf20Sopenharmony_ci AC_PWRST_D1); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (!rt298->pdata.cbj_en) { 12578c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_CBJ_CTRL2, 0x0000); 12588c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_MIC1_DET_CTRL, 0x0816); 12598c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 12608c2ecf20Sopenharmony_ci RT298_CBJ_CTRL1, 0xf000, 0xb000); 12618c2ecf20Sopenharmony_ci } else { 12628c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 12638c2ecf20Sopenharmony_ci RT298_CBJ_CTRL1, 0xf000, 0x5000); 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci mdelay(10); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (!rt298->pdata.gpio2_en) 12698c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40); 12708c2ecf20Sopenharmony_ci else 12718c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0); 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci mdelay(10); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_MISC_CTRL1, 0x0000); 12768c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, 12778c2ecf20Sopenharmony_ci RT298_WIND_FILTER_CTRL, 0x0082, 0x0082); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_INLINE_CMD, 0x81); 12808c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_HP_OUT, 0x82); 12818c2ecf20Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_MIC1, 0x84); 12828c2ecf20Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_FLAG_CTRL, 0x2, 0x2); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci rt298->is_hp_in = -1; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci if (rt298->i2c->irq) { 12878c2ecf20Sopenharmony_ci ret = request_threaded_irq(rt298->i2c->irq, NULL, rt298_irq, 12888c2ecf20Sopenharmony_ci IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt298", rt298); 12898c2ecf20Sopenharmony_ci if (ret != 0) { 12908c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 12918c2ecf20Sopenharmony_ci "Failed to reguest IRQ: %d\n", ret); 12928c2ecf20Sopenharmony_ci return ret; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 12978c2ecf20Sopenharmony_ci &soc_component_dev_rt298, 12988c2ecf20Sopenharmony_ci rt298_dai, ARRAY_SIZE(rt298_dai)); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci return ret; 13018c2ecf20Sopenharmony_ci} 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic int rt298_i2c_remove(struct i2c_client *i2c) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct rt298_priv *rt298 = i2c_get_clientdata(i2c); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci if (i2c->irq) 13088c2ecf20Sopenharmony_ci free_irq(i2c->irq, rt298); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci return 0; 13118c2ecf20Sopenharmony_ci} 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_cistatic struct i2c_driver rt298_i2c_driver = { 13158c2ecf20Sopenharmony_ci .driver = { 13168c2ecf20Sopenharmony_ci .name = "rt298", 13178c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt298_acpi_match), 13188c2ecf20Sopenharmony_ci }, 13198c2ecf20Sopenharmony_ci .probe = rt298_i2c_probe, 13208c2ecf20Sopenharmony_ci .remove = rt298_i2c_remove, 13218c2ecf20Sopenharmony_ci .id_table = rt298_i2c_id, 13228c2ecf20Sopenharmony_ci}; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_cimodule_i2c_driver(rt298_i2c_driver); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT298 driver"); 13278c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); 13288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1329