18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * rt286.c -- RT286 ALSA SoC audio codec driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2013 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/rt286.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include "rl6347a.h" 318c2ecf20Sopenharmony_ci#include "rt286.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define RT286_VENDOR_ID 0x10ec0286 348c2ecf20Sopenharmony_ci#define RT288_VENDOR_ID 0x10ec0288 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct rt286_priv { 378c2ecf20Sopenharmony_ci struct reg_default *index_cache; 388c2ecf20Sopenharmony_ci int index_cache_size; 398c2ecf20Sopenharmony_ci struct regmap *regmap; 408c2ecf20Sopenharmony_ci struct snd_soc_component *component; 418c2ecf20Sopenharmony_ci struct rt286_platform_data pdata; 428c2ecf20Sopenharmony_ci struct i2c_client *i2c; 438c2ecf20Sopenharmony_ci struct snd_soc_jack *jack; 448c2ecf20Sopenharmony_ci struct delayed_work jack_detect_work; 458c2ecf20Sopenharmony_ci int sys_clk; 468c2ecf20Sopenharmony_ci int clk_id; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic const struct reg_default rt286_index_def[] = { 508c2ecf20Sopenharmony_ci { 0x01, 0xaaaa }, 518c2ecf20Sopenharmony_ci { 0x02, 0x8aaa }, 528c2ecf20Sopenharmony_ci { 0x03, 0x0002 }, 538c2ecf20Sopenharmony_ci { 0x04, 0xaf01 }, 548c2ecf20Sopenharmony_ci { 0x08, 0x000d }, 558c2ecf20Sopenharmony_ci { 0x09, 0xd810 }, 568c2ecf20Sopenharmony_ci { 0x0a, 0x0120 }, 578c2ecf20Sopenharmony_ci { 0x0b, 0x0000 }, 588c2ecf20Sopenharmony_ci { 0x0d, 0x2800 }, 598c2ecf20Sopenharmony_ci { 0x0f, 0x0000 }, 608c2ecf20Sopenharmony_ci { 0x19, 0x0a17 }, 618c2ecf20Sopenharmony_ci { 0x20, 0x0020 }, 628c2ecf20Sopenharmony_ci { 0x33, 0x0208 }, 638c2ecf20Sopenharmony_ci { 0x49, 0x0004 }, 648c2ecf20Sopenharmony_ci { 0x4f, 0x50e9 }, 658c2ecf20Sopenharmony_ci { 0x50, 0x2000 }, 668c2ecf20Sopenharmony_ci { 0x63, 0x2902 }, 678c2ecf20Sopenharmony_ci { 0x67, 0x1111 }, 688c2ecf20Sopenharmony_ci { 0x68, 0x1016 }, 698c2ecf20Sopenharmony_ci { 0x69, 0x273f }, 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci#define INDEX_CACHE_SIZE ARRAY_SIZE(rt286_index_def) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic const struct reg_default rt286_reg[] = { 748c2ecf20Sopenharmony_ci { 0x00170500, 0x00000400 }, 758c2ecf20Sopenharmony_ci { 0x00220000, 0x00000031 }, 768c2ecf20Sopenharmony_ci { 0x00239000, 0x0000007f }, 778c2ecf20Sopenharmony_ci { 0x0023a000, 0x0000007f }, 788c2ecf20Sopenharmony_ci { 0x00270500, 0x00000400 }, 798c2ecf20Sopenharmony_ci { 0x00370500, 0x00000400 }, 808c2ecf20Sopenharmony_ci { 0x00870500, 0x00000400 }, 818c2ecf20Sopenharmony_ci { 0x00920000, 0x00000031 }, 828c2ecf20Sopenharmony_ci { 0x00935000, 0x000000c3 }, 838c2ecf20Sopenharmony_ci { 0x00936000, 0x000000c3 }, 848c2ecf20Sopenharmony_ci { 0x00970500, 0x00000400 }, 858c2ecf20Sopenharmony_ci { 0x00b37000, 0x00000097 }, 868c2ecf20Sopenharmony_ci { 0x00b37200, 0x00000097 }, 878c2ecf20Sopenharmony_ci { 0x00b37300, 0x00000097 }, 888c2ecf20Sopenharmony_ci { 0x00c37000, 0x00000000 }, 898c2ecf20Sopenharmony_ci { 0x00c37100, 0x00000080 }, 908c2ecf20Sopenharmony_ci { 0x01270500, 0x00000400 }, 918c2ecf20Sopenharmony_ci { 0x01370500, 0x00000400 }, 928c2ecf20Sopenharmony_ci { 0x01371f00, 0x411111f0 }, 938c2ecf20Sopenharmony_ci { 0x01439000, 0x00000080 }, 948c2ecf20Sopenharmony_ci { 0x0143a000, 0x00000080 }, 958c2ecf20Sopenharmony_ci { 0x01470700, 0x00000000 }, 968c2ecf20Sopenharmony_ci { 0x01470500, 0x00000400 }, 978c2ecf20Sopenharmony_ci { 0x01470c00, 0x00000000 }, 988c2ecf20Sopenharmony_ci { 0x01470100, 0x00000000 }, 998c2ecf20Sopenharmony_ci { 0x01837000, 0x00000000 }, 1008c2ecf20Sopenharmony_ci { 0x01870500, 0x00000400 }, 1018c2ecf20Sopenharmony_ci { 0x02050000, 0x00000000 }, 1028c2ecf20Sopenharmony_ci { 0x02139000, 0x00000080 }, 1038c2ecf20Sopenharmony_ci { 0x0213a000, 0x00000080 }, 1048c2ecf20Sopenharmony_ci { 0x02170100, 0x00000000 }, 1058c2ecf20Sopenharmony_ci { 0x02170500, 0x00000400 }, 1068c2ecf20Sopenharmony_ci { 0x02170700, 0x00000000 }, 1078c2ecf20Sopenharmony_ci { 0x02270100, 0x00000000 }, 1088c2ecf20Sopenharmony_ci { 0x02370100, 0x00000000 }, 1098c2ecf20Sopenharmony_ci { 0x01870700, 0x00000020 }, 1108c2ecf20Sopenharmony_ci { 0x00830000, 0x000000c3 }, 1118c2ecf20Sopenharmony_ci { 0x00930000, 0x000000c3 }, 1128c2ecf20Sopenharmony_ci { 0x01270700, 0x00000000 }, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic bool rt286_volatile_register(struct device *dev, unsigned int reg) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci switch (reg) { 1188c2ecf20Sopenharmony_ci case 0 ... 0xff: 1198c2ecf20Sopenharmony_ci case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 1208c2ecf20Sopenharmony_ci case RT286_GET_HP_SENSE: 1218c2ecf20Sopenharmony_ci case RT286_GET_MIC1_SENSE: 1228c2ecf20Sopenharmony_ci case RT286_PROC_COEF: 1238c2ecf20Sopenharmony_ci return true; 1248c2ecf20Sopenharmony_ci default: 1258c2ecf20Sopenharmony_ci return false; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic bool rt286_readable_register(struct device *dev, unsigned int reg) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci switch (reg) { 1348c2ecf20Sopenharmony_ci case 0 ... 0xff: 1358c2ecf20Sopenharmony_ci case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 1368c2ecf20Sopenharmony_ci case RT286_GET_HP_SENSE: 1378c2ecf20Sopenharmony_ci case RT286_GET_MIC1_SENSE: 1388c2ecf20Sopenharmony_ci case RT286_SET_AUDIO_POWER: 1398c2ecf20Sopenharmony_ci case RT286_SET_HPO_POWER: 1408c2ecf20Sopenharmony_ci case RT286_SET_SPK_POWER: 1418c2ecf20Sopenharmony_ci case RT286_SET_DMIC1_POWER: 1428c2ecf20Sopenharmony_ci case RT286_SPK_MUX: 1438c2ecf20Sopenharmony_ci case RT286_HPO_MUX: 1448c2ecf20Sopenharmony_ci case RT286_ADC0_MUX: 1458c2ecf20Sopenharmony_ci case RT286_ADC1_MUX: 1468c2ecf20Sopenharmony_ci case RT286_SET_MIC1: 1478c2ecf20Sopenharmony_ci case RT286_SET_PIN_HPO: 1488c2ecf20Sopenharmony_ci case RT286_SET_PIN_SPK: 1498c2ecf20Sopenharmony_ci case RT286_SET_PIN_DMIC1: 1508c2ecf20Sopenharmony_ci case RT286_SPK_EAPD: 1518c2ecf20Sopenharmony_ci case RT286_SET_AMP_GAIN_HPO: 1528c2ecf20Sopenharmony_ci case RT286_SET_DMIC2_DEFAULT: 1538c2ecf20Sopenharmony_ci case RT286_DACL_GAIN: 1548c2ecf20Sopenharmony_ci case RT286_DACR_GAIN: 1558c2ecf20Sopenharmony_ci case RT286_ADCL_GAIN: 1568c2ecf20Sopenharmony_ci case RT286_ADCR_GAIN: 1578c2ecf20Sopenharmony_ci case RT286_MIC_GAIN: 1588c2ecf20Sopenharmony_ci case RT286_SPOL_GAIN: 1598c2ecf20Sopenharmony_ci case RT286_SPOR_GAIN: 1608c2ecf20Sopenharmony_ci case RT286_HPOL_GAIN: 1618c2ecf20Sopenharmony_ci case RT286_HPOR_GAIN: 1628c2ecf20Sopenharmony_ci case RT286_F_DAC_SWITCH: 1638c2ecf20Sopenharmony_ci case RT286_F_RECMIX_SWITCH: 1648c2ecf20Sopenharmony_ci case RT286_REC_MIC_SWITCH: 1658c2ecf20Sopenharmony_ci case RT286_REC_I2S_SWITCH: 1668c2ecf20Sopenharmony_ci case RT286_REC_LINE_SWITCH: 1678c2ecf20Sopenharmony_ci case RT286_REC_BEEP_SWITCH: 1688c2ecf20Sopenharmony_ci case RT286_DAC_FORMAT: 1698c2ecf20Sopenharmony_ci case RT286_ADC_FORMAT: 1708c2ecf20Sopenharmony_ci case RT286_COEF_INDEX: 1718c2ecf20Sopenharmony_ci case RT286_PROC_COEF: 1728c2ecf20Sopenharmony_ci case RT286_SET_AMP_GAIN_ADC_IN1: 1738c2ecf20Sopenharmony_ci case RT286_SET_AMP_GAIN_ADC_IN2: 1748c2ecf20Sopenharmony_ci case RT286_SET_GPIO_MASK: 1758c2ecf20Sopenharmony_ci case RT286_SET_GPIO_DIRECTION: 1768c2ecf20Sopenharmony_ci case RT286_SET_GPIO_DATA: 1778c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_DAC_OUT1): 1788c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_DAC_OUT2): 1798c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_ADC_IN1): 1808c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_ADC_IN2): 1818c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_DMIC2): 1828c2ecf20Sopenharmony_ci case RT286_SET_POWER(RT286_MIC1): 1838c2ecf20Sopenharmony_ci return true; 1848c2ecf20Sopenharmony_ci default: 1858c2ecf20Sopenharmony_ci return false; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1908c2ecf20Sopenharmony_cistatic void rt286_index_sync(struct snd_soc_component *component) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 1938c2ecf20Sopenharmony_ci int i; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) { 1968c2ecf20Sopenharmony_ci snd_soc_component_write(component, rt286->index_cache[i].reg, 1978c2ecf20Sopenharmony_ci rt286->index_cache[i].def); 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci#endif 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic int rt286_support_power_controls[] = { 2038c2ecf20Sopenharmony_ci RT286_DAC_OUT1, 2048c2ecf20Sopenharmony_ci RT286_DAC_OUT2, 2058c2ecf20Sopenharmony_ci RT286_ADC_IN1, 2068c2ecf20Sopenharmony_ci RT286_ADC_IN2, 2078c2ecf20Sopenharmony_ci RT286_MIC1, 2088c2ecf20Sopenharmony_ci RT286_DMIC1, 2098c2ecf20Sopenharmony_ci RT286_DMIC2, 2108c2ecf20Sopenharmony_ci RT286_SPK_OUT, 2118c2ecf20Sopenharmony_ci RT286_HP_OUT, 2128c2ecf20Sopenharmony_ci}; 2138c2ecf20Sopenharmony_ci#define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls) 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct snd_soc_dapm_context *dapm; 2188c2ecf20Sopenharmony_ci unsigned int val, buf; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci *hp = false; 2218c2ecf20Sopenharmony_ci *mic = false; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (!rt286->component) 2248c2ecf20Sopenharmony_ci return -EINVAL; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci dapm = snd_soc_component_get_dapm(rt286->component); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (rt286->pdata.cbj_en) { 2298c2ecf20Sopenharmony_ci regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); 2308c2ecf20Sopenharmony_ci *hp = buf & 0x80000000; 2318c2ecf20Sopenharmony_ci if (*hp) { 2328c2ecf20Sopenharmony_ci /* power on HV,VERF */ 2338c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 2348c2ecf20Sopenharmony_ci RT286_DC_GAIN, 0x200, 0x200); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "HV"); 2378c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "VREF"); 2388c2ecf20Sopenharmony_ci /* power LDO1 */ 2398c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "LDO1"); 2408c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); 2438c2ecf20Sopenharmony_ci msleep(50); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 2468c2ecf20Sopenharmony_ci RT286_CBJ_CTRL1, 0xfcc0, 0xd400); 2478c2ecf20Sopenharmony_ci msleep(300); 2488c2ecf20Sopenharmony_ci regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (0x0070 == (val & 0x0070)) { 2518c2ecf20Sopenharmony_ci *mic = true; 2528c2ecf20Sopenharmony_ci } else { 2538c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 2548c2ecf20Sopenharmony_ci RT286_CBJ_CTRL1, 0xfcc0, 0xe400); 2558c2ecf20Sopenharmony_ci msleep(300); 2568c2ecf20Sopenharmony_ci regmap_read(rt286->regmap, 2578c2ecf20Sopenharmony_ci RT286_CBJ_CTRL2, &val); 2588c2ecf20Sopenharmony_ci if (0x0070 == (val & 0x0070)) 2598c2ecf20Sopenharmony_ci *mic = true; 2608c2ecf20Sopenharmony_ci else 2618c2ecf20Sopenharmony_ci *mic = false; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 2648c2ecf20Sopenharmony_ci RT286_DC_GAIN, 0x200, 0x0); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci } else { 2678c2ecf20Sopenharmony_ci *mic = false; 2688c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_SET_MIC1, 0x20); 2698c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 2708c2ecf20Sopenharmony_ci RT286_CBJ_CTRL1, 0x0400, 0x0000); 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci } else { 2738c2ecf20Sopenharmony_ci regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); 2748c2ecf20Sopenharmony_ci *hp = buf & 0x80000000; 2758c2ecf20Sopenharmony_ci regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf); 2768c2ecf20Sopenharmony_ci *mic = buf & 0x80000000; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (!*hp) { 2808c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "HV"); 2818c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "VREF"); 2828c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 2838c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return 0; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic void rt286_jack_detect_work(struct work_struct *work) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = 2928c2ecf20Sopenharmony_ci container_of(work, struct rt286_priv, jack_detect_work.work); 2938c2ecf20Sopenharmony_ci int status = 0; 2948c2ecf20Sopenharmony_ci bool hp = false; 2958c2ecf20Sopenharmony_ci bool mic = false; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci rt286_jack_detect(rt286, &hp, &mic); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (hp) 3008c2ecf20Sopenharmony_ci status |= SND_JACK_HEADPHONE; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (mic) 3038c2ecf20Sopenharmony_ci status |= SND_JACK_MICROPHONE; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci snd_soc_jack_report(rt286->jack, status, 3068c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ciint rt286_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 3128c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci rt286->jack = jack; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (jack) { 3178c2ecf20Sopenharmony_ci /* enable IRQ */ 3188c2ecf20Sopenharmony_ci if (rt286->jack->status & SND_JACK_HEADPHONE) 3198c2ecf20Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "LDO1"); 3208c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x2); 3218c2ecf20Sopenharmony_ci /* Send an initial empty report */ 3228c2ecf20Sopenharmony_ci snd_soc_jack_report(rt286->jack, rt286->jack->status, 3238c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 3248c2ecf20Sopenharmony_ci } else { 3258c2ecf20Sopenharmony_ci /* disable IRQ */ 3268c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x2, 0x0); 3278c2ecf20Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci snd_soc_dapm_sync(dapm); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rt286_mic_detect); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int is_mclk_mode(struct snd_soc_dapm_widget *source, 3368c2ecf20Sopenharmony_ci struct snd_soc_dapm_widget *sink) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 3398c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci if (rt286->clk_id == RT286_SCLK_S_MCLK) 3428c2ecf20Sopenharmony_ci return 1; 3438c2ecf20Sopenharmony_ci else 3448c2ecf20Sopenharmony_ci return 0; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); 3488c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_snd_controls[] = { 3518c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, 3528c2ecf20Sopenharmony_ci RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), 3538c2ecf20Sopenharmony_ci SOC_DOUBLE_R("ADC0 Capture Switch", RT286_ADCL_GAIN, 3548c2ecf20Sopenharmony_ci RT286_ADCR_GAIN, 7, 1, 1), 3558c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, 3568c2ecf20Sopenharmony_ci RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), 3578c2ecf20Sopenharmony_ci SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, 3588c2ecf20Sopenharmony_ci 0, 0x3, 0, mic_vol_tlv), 3598c2ecf20Sopenharmony_ci SOC_DOUBLE_R("Speaker Playback Switch", RT286_SPOL_GAIN, 3608c2ecf20Sopenharmony_ci RT286_SPOR_GAIN, RT286_MUTE_SFT, 1, 1), 3618c2ecf20Sopenharmony_ci}; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci/* Digital Mixer */ 3648c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_front_mix[] = { 3658c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DAC Switch", RT286_F_DAC_SWITCH, 3668c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3678c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("RECMIX Switch", RT286_F_RECMIX_SWITCH, 3688c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3698c2ecf20Sopenharmony_ci}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/* Analog Input Mixer */ 3728c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_rec_mix[] = { 3738c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Mic1 Switch", RT286_REC_MIC_SWITCH, 3748c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3758c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("I2S Switch", RT286_REC_I2S_SWITCH, 3768c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3778c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Line1 Switch", RT286_REC_LINE_SWITCH, 3788c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3798c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Beep Switch", RT286_REC_BEEP_SWITCH, 3808c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1), 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new spo_enable_control = 3848c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("Switch", RT286_SET_PIN_SPK, 3858c2ecf20Sopenharmony_ci RT286_SET_PIN_SFT, 1, 0); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hpol_enable_control = 3888c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOL_GAIN, 3898c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hpor_enable_control = 3928c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOR_GAIN, 3938c2ecf20Sopenharmony_ci RT286_MUTE_SFT, 1, 1); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* ADC0 source */ 3968c2ecf20Sopenharmony_cistatic const char * const rt286_adc_src[] = { 3978c2ecf20Sopenharmony_ci "Mic", "RECMIX", "Dmic" 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic const int rt286_adc_values[] = { 4018c2ecf20Sopenharmony_ci 0, 4, 5, 4028c2ecf20Sopenharmony_ci}; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 4058c2ecf20Sopenharmony_ci rt286_adc0_enum, RT286_ADC0_MUX, RT286_ADC_SEL_SFT, 4068c2ecf20Sopenharmony_ci RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_adc0_mux = 4098c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("ADC 0 source", rt286_adc0_enum); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 4128c2ecf20Sopenharmony_ci rt286_adc1_enum, RT286_ADC1_MUX, RT286_ADC_SEL_SFT, 4138c2ecf20Sopenharmony_ci RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_adc1_mux = 4168c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("ADC 1 source", rt286_adc1_enum); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic const char * const rt286_dac_src[] = { 4198c2ecf20Sopenharmony_ci "Front", "Surround" 4208c2ecf20Sopenharmony_ci}; 4218c2ecf20Sopenharmony_ci/* HP-OUT source */ 4228c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt286_hpo_enum, RT286_HPO_MUX, 4238c2ecf20Sopenharmony_ci 0, rt286_dac_src); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_hpo_mux = 4268c2ecf20Sopenharmony_ciSOC_DAPM_ENUM("HPO source", rt286_hpo_enum); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/* SPK-OUT source */ 4298c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt286_spo_enum, RT286_SPK_MUX, 4308c2ecf20Sopenharmony_ci 0, rt286_dac_src); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt286_spo_mux = 4338c2ecf20Sopenharmony_ciSOC_DAPM_ENUM("SPO source", rt286_spo_enum); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic int rt286_spk_event(struct snd_soc_dapm_widget *w, 4368c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci switch (event) { 4418c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 4428c2ecf20Sopenharmony_ci snd_soc_component_write(component, 4438c2ecf20Sopenharmony_ci RT286_SPK_EAPD, RT286_SET_EAPD_HIGH); 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 4468c2ecf20Sopenharmony_ci snd_soc_component_write(component, 4478c2ecf20Sopenharmony_ci RT286_SPK_EAPD, RT286_SET_EAPD_LOW); 4488c2ecf20Sopenharmony_ci break; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci default: 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, 4588c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci switch (event) { 4638c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 4648c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT286_SET_PIN_DMIC1, 0x20); 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 4678c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT286_SET_PIN_DMIC1, 0); 4688c2ecf20Sopenharmony_ci break; 4698c2ecf20Sopenharmony_ci default: 4708c2ecf20Sopenharmony_ci return 0; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci return 0; 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cistatic int rt286_ldo2_event(struct snd_soc_dapm_widget *w, 4778c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci switch (event) { 4828c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 4838c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_POWER_CTRL2, 0x38, 0x08); 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 4868c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_POWER_CTRL2, 0x38, 0x30); 4878c2ecf20Sopenharmony_ci break; 4888c2ecf20Sopenharmony_ci default: 4898c2ecf20Sopenharmony_ci return 0; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci return 0; 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic int rt286_mic1_event(struct snd_soc_dapm_widget *w, 4968c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci switch (event) { 5018c2ecf20Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 5028c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5038c2ecf20Sopenharmony_ci RT286_A_BIAS_CTRL3, 0xc000, 0x8000); 5048c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5058c2ecf20Sopenharmony_ci RT286_A_BIAS_CTRL2, 0xc000, 0x8000); 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 5088c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5098c2ecf20Sopenharmony_ci RT286_A_BIAS_CTRL3, 0xc000, 0x0000); 5108c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 5118c2ecf20Sopenharmony_ci RT286_A_BIAS_CTRL2, 0xc000, 0x0000); 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci default: 5148c2ecf20Sopenharmony_ci return 0; 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci return 0; 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { 5218c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("HV", 1, RT286_POWER_CTRL1, 5228c2ecf20Sopenharmony_ci 12, 1, NULL, 0), 5238c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF", RT286_POWER_CTRL1, 5248c2ecf20Sopenharmony_ci 0, 1, NULL, 0), 5258c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT286_POWER_CTRL2, 5268c2ecf20Sopenharmony_ci 2, 0, NULL, 0), 5278c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO2", 2, RT286_POWER_CTRL1, 5288c2ecf20Sopenharmony_ci 13, 1, rt286_ldo2_event, SND_SOC_DAPM_PRE_PMD | 5298c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMU), 5308c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MCLK MODE", RT286_PLL_CTRL1, 5318c2ecf20Sopenharmony_ci 5, 0, NULL, 0), 5328c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, 5338c2ecf20Sopenharmony_ci 0, 0, rt286_mic1_event, SND_SOC_DAPM_PRE_PMU | 5348c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMD), 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* Input Lines */ 5378c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1 Pin"), 5388c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2 Pin"), 5398c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC1"), 5408c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("LINE1"), 5418c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("Beep"), 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* DMIC */ 5448c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA_E("DMIC1", RT286_SET_POWER(RT286_DMIC1), 0, 1, 5458c2ecf20Sopenharmony_ci NULL, 0, rt286_set_dmic1_event, 5468c2ecf20Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 5478c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("DMIC2", RT286_SET_POWER(RT286_DMIC2), 0, 1, 5488c2ecf20Sopenharmony_ci NULL, 0), 5498c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, 5508c2ecf20Sopenharmony_ci 0, 0, NULL, 0), 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* REC Mixer */ 5538c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, 5548c2ecf20Sopenharmony_ci rt286_rec_mix, ARRAY_SIZE(rt286_rec_mix)), 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci /* ADCs */ 5578c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), 5588c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci /* ADC Mux */ 5618c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, 5628c2ecf20Sopenharmony_ci &rt286_adc0_mux), 5638c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, 5648c2ecf20Sopenharmony_ci &rt286_adc1_mux), 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* Audio Interface */ 5678c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 5688c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 5698c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), 5708c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* Output Side */ 5738c2ecf20Sopenharmony_ci /* DACs */ 5748c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), 5758c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* Output Mux */ 5788c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt286_spo_mux), 5798c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt286_hpo_mux), 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("HP Power", RT286_SET_PIN_HPO, 5828c2ecf20Sopenharmony_ci RT286_SET_PIN_SFT, 0, NULL, 0), 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* Output Mixer */ 5858c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Front", RT286_SET_POWER(RT286_DAC_OUT1), 0, 1, 5868c2ecf20Sopenharmony_ci rt286_front_mix, ARRAY_SIZE(rt286_front_mix)), 5878c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("Surround", RT286_SET_POWER(RT286_DAC_OUT2), 0, 1, 5888c2ecf20Sopenharmony_ci NULL, 0), 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* Output Pga */ 5918c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, 5928c2ecf20Sopenharmony_ci &spo_enable_control, rt286_spk_event, 5938c2ecf20Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 5948c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, 5958c2ecf20Sopenharmony_ci &hpol_enable_control), 5968c2ecf20Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, 5978c2ecf20Sopenharmony_ci &hpor_enable_control), 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* Output Lines */ 6008c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOL"), 6018c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOR"), 6028c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPO Pin"), 6038c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPDIF"), 6048c2ecf20Sopenharmony_ci}; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt286_dapm_routes[] = { 6078c2ecf20Sopenharmony_ci {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, 6088c2ecf20Sopenharmony_ci {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, 6098c2ecf20Sopenharmony_ci {"Front", NULL, "MCLK MODE", is_mclk_mode}, 6108c2ecf20Sopenharmony_ci {"Surround", NULL, "MCLK MODE", is_mclk_mode}, 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci {"HP Power", NULL, "LDO1"}, 6138c2ecf20Sopenharmony_ci {"HP Power", NULL, "LDO2"}, 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci {"MIC1", NULL, "LDO1"}, 6168c2ecf20Sopenharmony_ci {"MIC1", NULL, "LDO2"}, 6178c2ecf20Sopenharmony_ci {"MIC1", NULL, "HV"}, 6188c2ecf20Sopenharmony_ci {"MIC1", NULL, "VREF"}, 6198c2ecf20Sopenharmony_ci {"MIC1", NULL, "MIC1 Input Buffer"}, 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci {"SPO", NULL, "LDO1"}, 6228c2ecf20Sopenharmony_ci {"SPO", NULL, "LDO2"}, 6238c2ecf20Sopenharmony_ci {"SPO", NULL, "HV"}, 6248c2ecf20Sopenharmony_ci {"SPO", NULL, "VREF"}, 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci {"DMIC1", NULL, "DMIC1 Pin"}, 6278c2ecf20Sopenharmony_ci {"DMIC2", NULL, "DMIC2 Pin"}, 6288c2ecf20Sopenharmony_ci {"DMIC1", NULL, "DMIC Receiver"}, 6298c2ecf20Sopenharmony_ci {"DMIC2", NULL, "DMIC Receiver"}, 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci {"RECMIX", "Beep Switch", "Beep"}, 6328c2ecf20Sopenharmony_ci {"RECMIX", "Line1 Switch", "LINE1"}, 6338c2ecf20Sopenharmony_ci {"RECMIX", "Mic1 Switch", "MIC1"}, 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci {"ADC 0 Mux", "Dmic", "DMIC1"}, 6368c2ecf20Sopenharmony_ci {"ADC 0 Mux", "RECMIX", "RECMIX"}, 6378c2ecf20Sopenharmony_ci {"ADC 0 Mux", "Mic", "MIC1"}, 6388c2ecf20Sopenharmony_ci {"ADC 1 Mux", "Dmic", "DMIC2"}, 6398c2ecf20Sopenharmony_ci {"ADC 1 Mux", "RECMIX", "RECMIX"}, 6408c2ecf20Sopenharmony_ci {"ADC 1 Mux", "Mic", "MIC1"}, 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci {"ADC 0", NULL, "ADC 0 Mux"}, 6438c2ecf20Sopenharmony_ci {"ADC 1", NULL, "ADC 1 Mux"}, 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci {"AIF1TX", NULL, "ADC 0"}, 6468c2ecf20Sopenharmony_ci {"AIF2TX", NULL, "ADC 1"}, 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci {"DAC 0", NULL, "AIF1RX"}, 6498c2ecf20Sopenharmony_ci {"DAC 1", NULL, "AIF2RX"}, 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci {"Front", "DAC Switch", "DAC 0"}, 6528c2ecf20Sopenharmony_ci {"Front", "RECMIX Switch", "RECMIX"}, 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci {"Surround", NULL, "DAC 1"}, 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci {"SPK Mux", "Front", "Front"}, 6578c2ecf20Sopenharmony_ci {"SPK Mux", "Surround", "Surround"}, 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci {"HPO Mux", "Front", "Front"}, 6608c2ecf20Sopenharmony_ci {"HPO Mux", "Surround", "Surround"}, 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci {"SPO", "Switch", "SPK Mux"}, 6638c2ecf20Sopenharmony_ci {"HPO L", "Switch", "HPO Mux"}, 6648c2ecf20Sopenharmony_ci {"HPO R", "Switch", "HPO Mux"}, 6658c2ecf20Sopenharmony_ci {"HPO L", NULL, "HP Power"}, 6668c2ecf20Sopenharmony_ci {"HPO R", NULL, "HP Power"}, 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci {"SPOL", NULL, "SPO"}, 6698c2ecf20Sopenharmony_ci {"SPOR", NULL, "SPO"}, 6708c2ecf20Sopenharmony_ci {"HPO Pin", NULL, "HPO L"}, 6718c2ecf20Sopenharmony_ci {"HPO Pin", NULL, "HPO R"}, 6728c2ecf20Sopenharmony_ci}; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cistatic int rt286_hw_params(struct snd_pcm_substream *substream, 6758c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 6768c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 6798c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 6808c2ecf20Sopenharmony_ci unsigned int val = 0; 6818c2ecf20Sopenharmony_ci int d_len_code; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci switch (params_rate(params)) { 6848c2ecf20Sopenharmony_ci /* bit 14 0:48K 1:44.1K */ 6858c2ecf20Sopenharmony_ci case 44100: 6868c2ecf20Sopenharmony_ci val |= 0x4000; 6878c2ecf20Sopenharmony_ci break; 6888c2ecf20Sopenharmony_ci case 48000: 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci default: 6918c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported sample rate %d\n", 6928c2ecf20Sopenharmony_ci params_rate(params)); 6938c2ecf20Sopenharmony_ci return -EINVAL; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci switch (rt286->sys_clk) { 6968c2ecf20Sopenharmony_ci case 12288000: 6978c2ecf20Sopenharmony_ci case 24576000: 6988c2ecf20Sopenharmony_ci if (params_rate(params) != 48000) { 6998c2ecf20Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 7008c2ecf20Sopenharmony_ci params_rate(params), rt286->sys_clk); 7018c2ecf20Sopenharmony_ci return -EINVAL; 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci break; 7048c2ecf20Sopenharmony_ci case 11289600: 7058c2ecf20Sopenharmony_ci case 22579200: 7068c2ecf20Sopenharmony_ci if (params_rate(params) != 44100) { 7078c2ecf20Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 7088c2ecf20Sopenharmony_ci params_rate(params), rt286->sys_clk); 7098c2ecf20Sopenharmony_ci return -EINVAL; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci break; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (params_channels(params) <= 16) { 7158c2ecf20Sopenharmony_ci /* bit 3:0 Number of Channel */ 7168c2ecf20Sopenharmony_ci val |= (params_channels(params) - 1); 7178c2ecf20Sopenharmony_ci } else { 7188c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported channels %d\n", 7198c2ecf20Sopenharmony_ci params_channels(params)); 7208c2ecf20Sopenharmony_ci return -EINVAL; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci d_len_code = 0; 7248c2ecf20Sopenharmony_ci switch (params_width(params)) { 7258c2ecf20Sopenharmony_ci /* bit 6:4 Bits per Sample */ 7268c2ecf20Sopenharmony_ci case 16: 7278c2ecf20Sopenharmony_ci d_len_code = 0; 7288c2ecf20Sopenharmony_ci val |= (0x1 << 4); 7298c2ecf20Sopenharmony_ci break; 7308c2ecf20Sopenharmony_ci case 32: 7318c2ecf20Sopenharmony_ci d_len_code = 2; 7328c2ecf20Sopenharmony_ci val |= (0x4 << 4); 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci case 20: 7358c2ecf20Sopenharmony_ci d_len_code = 1; 7368c2ecf20Sopenharmony_ci val |= (0x2 << 4); 7378c2ecf20Sopenharmony_ci break; 7388c2ecf20Sopenharmony_ci case 24: 7398c2ecf20Sopenharmony_ci d_len_code = 2; 7408c2ecf20Sopenharmony_ci val |= (0x3 << 4); 7418c2ecf20Sopenharmony_ci break; 7428c2ecf20Sopenharmony_ci case 8: 7438c2ecf20Sopenharmony_ci d_len_code = 3; 7448c2ecf20Sopenharmony_ci break; 7458c2ecf20Sopenharmony_ci default: 7468c2ecf20Sopenharmony_ci return -EINVAL; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7508c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x0018, d_len_code << 3); 7518c2ecf20Sopenharmony_ci dev_dbg(component->dev, "format val = 0x%x\n", val); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_DAC_FORMAT, 0x407f, val); 7548c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_ADC_FORMAT, 0x407f, val); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci return 0; 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 7648c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 7658c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7668c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x800, 0x800); 7678c2ecf20Sopenharmony_ci break; 7688c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 7698c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7708c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x800, 0x0); 7718c2ecf20Sopenharmony_ci break; 7728c2ecf20Sopenharmony_ci default: 7738c2ecf20Sopenharmony_ci return -EINVAL; 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 7778c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 7788c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7798c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x300, 0x0); 7808c2ecf20Sopenharmony_ci break; 7818c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 7828c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7838c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x300, 0x1 << 8); 7848c2ecf20Sopenharmony_ci break; 7858c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 7868c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7878c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x300, 0x2 << 8); 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 7908c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 7918c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x300, 0x3 << 8); 7928c2ecf20Sopenharmony_ci break; 7938c2ecf20Sopenharmony_ci default: 7948c2ecf20Sopenharmony_ci return -EINVAL; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci /* bit 15 Stream Type 0:PCM 1:Non-PCM */ 7978c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_DAC_FORMAT, 0x8000, 0); 7988c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT286_ADC_FORMAT, 0x8000, 0); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci return 0; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_cistatic int rt286_set_dai_sysclk(struct snd_soc_dai *dai, 8048c2ecf20Sopenharmony_ci int clk_id, unsigned int freq, int dir) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8078c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci dev_dbg(component->dev, "%s freq=%d\n", __func__, freq); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci if (RT286_SCLK_S_MCLK == clk_id) { 8128c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8138c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x0100, 0x0); 8148c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8158c2ecf20Sopenharmony_ci RT286_PLL_CTRL1, 0x20, 0x20); 8168c2ecf20Sopenharmony_ci } else { 8178c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8188c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x0100, 0x0100); 8198c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8208c2ecf20Sopenharmony_ci RT286_PLL_CTRL, 0x4, 0x4); 8218c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8228c2ecf20Sopenharmony_ci RT286_PLL_CTRL1, 0x20, 0x0); 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci switch (freq) { 8268c2ecf20Sopenharmony_ci case 19200000: 8278c2ecf20Sopenharmony_ci if (RT286_SCLK_S_MCLK == clk_id) { 8288c2ecf20Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 8298c2ecf20Sopenharmony_ci return -EINVAL; 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8328c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x40, 0x40); 8338c2ecf20Sopenharmony_ci break; 8348c2ecf20Sopenharmony_ci case 24000000: 8358c2ecf20Sopenharmony_ci if (RT286_SCLK_S_MCLK == clk_id) { 8368c2ecf20Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 8378c2ecf20Sopenharmony_ci return -EINVAL; 8388c2ecf20Sopenharmony_ci } 8398c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8408c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x40, 0x0); 8418c2ecf20Sopenharmony_ci break; 8428c2ecf20Sopenharmony_ci case 12288000: 8438c2ecf20Sopenharmony_ci case 11289600: 8448c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8458c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x8, 0x0); 8468c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8478c2ecf20Sopenharmony_ci RT286_CLK_DIV, 0xfc1e, 0x0004); 8488c2ecf20Sopenharmony_ci break; 8498c2ecf20Sopenharmony_ci case 24576000: 8508c2ecf20Sopenharmony_ci case 22579200: 8518c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8528c2ecf20Sopenharmony_ci RT286_I2S_CTRL2, 0x8, 0x8); 8538c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8548c2ecf20Sopenharmony_ci RT286_CLK_DIV, 0xfc1e, 0x5406); 8558c2ecf20Sopenharmony_ci break; 8568c2ecf20Sopenharmony_ci default: 8578c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported system clock\n"); 8588c2ecf20Sopenharmony_ci return -EINVAL; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci rt286->sys_clk = freq; 8628c2ecf20Sopenharmony_ci rt286->clk_id = clk_id; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci return 0; 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_cistatic int rt286_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); 8728c2ecf20Sopenharmony_ci if (50 == ratio) 8738c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8748c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x1000, 0x1000); 8758c2ecf20Sopenharmony_ci else 8768c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8778c2ecf20Sopenharmony_ci RT286_I2S_CTRL1, 0x1000, 0x0); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci return 0; 8818c2ecf20Sopenharmony_ci} 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic int rt286_set_bias_level(struct snd_soc_component *component, 8848c2ecf20Sopenharmony_ci enum snd_soc_bias_level level) 8858c2ecf20Sopenharmony_ci{ 8868c2ecf20Sopenharmony_ci switch (level) { 8878c2ecf20Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 8888c2ecf20Sopenharmony_ci if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { 8898c2ecf20Sopenharmony_ci snd_soc_component_write(component, 8908c2ecf20Sopenharmony_ci RT286_SET_AUDIO_POWER, AC_PWRST_D0); 8918c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8928c2ecf20Sopenharmony_ci RT286_DC_GAIN, 0x200, 0x200); 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci break; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci case SND_SOC_BIAS_ON: 8978c2ecf20Sopenharmony_ci mdelay(10); 8988c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, 8998c2ecf20Sopenharmony_ci RT286_DC_GAIN, 0x200, 0x0); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci break; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 9048c2ecf20Sopenharmony_ci snd_soc_component_write(component, 9058c2ecf20Sopenharmony_ci RT286_SET_AUDIO_POWER, AC_PWRST_D3); 9068c2ecf20Sopenharmony_ci break; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci default: 9098c2ecf20Sopenharmony_ci break; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci return 0; 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic irqreturn_t rt286_irq(int irq, void *data) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = data; 9188c2ecf20Sopenharmony_ci bool hp = false; 9198c2ecf20Sopenharmony_ci bool mic = false; 9208c2ecf20Sopenharmony_ci int status = 0; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci rt286_jack_detect(rt286, &hp, &mic); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci /* Clear IRQ */ 9258c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (hp) 9288c2ecf20Sopenharmony_ci status |= SND_JACK_HEADPHONE; 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci if (mic) 9318c2ecf20Sopenharmony_ci status |= SND_JACK_MICROPHONE; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci snd_soc_jack_report(rt286->jack, status, 9348c2ecf20Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci pm_wakeup_event(&rt286->i2c->dev, 300); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci return IRQ_HANDLED; 9398c2ecf20Sopenharmony_ci} 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_cistatic int rt286_probe(struct snd_soc_component *component) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci rt286->component = component; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (rt286->i2c->irq) { 9488c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 9498c2ecf20Sopenharmony_ci RT286_IRQ_CTRL, 0x2, 0x2); 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rt286->jack_detect_work, 9528c2ecf20Sopenharmony_ci rt286_jack_detect_work); 9538c2ecf20Sopenharmony_ci schedule_delayed_work(&rt286->jack_detect_work, 9548c2ecf20Sopenharmony_ci msecs_to_jiffies(1250)); 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic void rt286_remove(struct snd_soc_component *component) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rt286->jack_detect_work); 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 9688c2ecf20Sopenharmony_cistatic int rt286_suspend(struct snd_soc_component *component) 9698c2ecf20Sopenharmony_ci{ 9708c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci regcache_cache_only(rt286->regmap, true); 9738c2ecf20Sopenharmony_ci regcache_mark_dirty(rt286->regmap); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci return 0; 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic int rt286_resume(struct snd_soc_component *component) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = snd_soc_component_get_drvdata(component); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci regcache_cache_only(rt286->regmap, false); 9838c2ecf20Sopenharmony_ci rt286_index_sync(component); 9848c2ecf20Sopenharmony_ci regcache_sync(rt286->regmap); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci return 0; 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci#else 9898c2ecf20Sopenharmony_ci#define rt286_suspend NULL 9908c2ecf20Sopenharmony_ci#define rt286_resume NULL 9918c2ecf20Sopenharmony_ci#endif 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci#define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 9948c2ecf20Sopenharmony_ci#define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 9958c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops rt286_aif_dai_ops = { 9988c2ecf20Sopenharmony_ci .hw_params = rt286_hw_params, 9998c2ecf20Sopenharmony_ci .set_fmt = rt286_set_dai_fmt, 10008c2ecf20Sopenharmony_ci .set_sysclk = rt286_set_dai_sysclk, 10018c2ecf20Sopenharmony_ci .set_bclk_ratio = rt286_set_bclk_ratio, 10028c2ecf20Sopenharmony_ci}; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver rt286_dai[] = { 10058c2ecf20Sopenharmony_ci { 10068c2ecf20Sopenharmony_ci .name = "rt286-aif1", 10078c2ecf20Sopenharmony_ci .id = RT286_AIF1, 10088c2ecf20Sopenharmony_ci .playback = { 10098c2ecf20Sopenharmony_ci .stream_name = "AIF1 Playback", 10108c2ecf20Sopenharmony_ci .channels_min = 1, 10118c2ecf20Sopenharmony_ci .channels_max = 2, 10128c2ecf20Sopenharmony_ci .rates = RT286_STEREO_RATES, 10138c2ecf20Sopenharmony_ci .formats = RT286_FORMATS, 10148c2ecf20Sopenharmony_ci }, 10158c2ecf20Sopenharmony_ci .capture = { 10168c2ecf20Sopenharmony_ci .stream_name = "AIF1 Capture", 10178c2ecf20Sopenharmony_ci .channels_min = 1, 10188c2ecf20Sopenharmony_ci .channels_max = 2, 10198c2ecf20Sopenharmony_ci .rates = RT286_STEREO_RATES, 10208c2ecf20Sopenharmony_ci .formats = RT286_FORMATS, 10218c2ecf20Sopenharmony_ci }, 10228c2ecf20Sopenharmony_ci .ops = &rt286_aif_dai_ops, 10238c2ecf20Sopenharmony_ci .symmetric_rates = 1, 10248c2ecf20Sopenharmony_ci }, 10258c2ecf20Sopenharmony_ci { 10268c2ecf20Sopenharmony_ci .name = "rt286-aif2", 10278c2ecf20Sopenharmony_ci .id = RT286_AIF2, 10288c2ecf20Sopenharmony_ci .playback = { 10298c2ecf20Sopenharmony_ci .stream_name = "AIF2 Playback", 10308c2ecf20Sopenharmony_ci .channels_min = 1, 10318c2ecf20Sopenharmony_ci .channels_max = 2, 10328c2ecf20Sopenharmony_ci .rates = RT286_STEREO_RATES, 10338c2ecf20Sopenharmony_ci .formats = RT286_FORMATS, 10348c2ecf20Sopenharmony_ci }, 10358c2ecf20Sopenharmony_ci .capture = { 10368c2ecf20Sopenharmony_ci .stream_name = "AIF2 Capture", 10378c2ecf20Sopenharmony_ci .channels_min = 1, 10388c2ecf20Sopenharmony_ci .channels_max = 2, 10398c2ecf20Sopenharmony_ci .rates = RT286_STEREO_RATES, 10408c2ecf20Sopenharmony_ci .formats = RT286_FORMATS, 10418c2ecf20Sopenharmony_ci }, 10428c2ecf20Sopenharmony_ci .ops = &rt286_aif_dai_ops, 10438c2ecf20Sopenharmony_ci .symmetric_rates = 1, 10448c2ecf20Sopenharmony_ci }, 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci}; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt286 = { 10498c2ecf20Sopenharmony_ci .probe = rt286_probe, 10508c2ecf20Sopenharmony_ci .remove = rt286_remove, 10518c2ecf20Sopenharmony_ci .suspend = rt286_suspend, 10528c2ecf20Sopenharmony_ci .resume = rt286_resume, 10538c2ecf20Sopenharmony_ci .set_bias_level = rt286_set_bias_level, 10548c2ecf20Sopenharmony_ci .controls = rt286_snd_controls, 10558c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(rt286_snd_controls), 10568c2ecf20Sopenharmony_ci .dapm_widgets = rt286_dapm_widgets, 10578c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), 10588c2ecf20Sopenharmony_ci .dapm_routes = rt286_dapm_routes, 10598c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), 10608c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 10618c2ecf20Sopenharmony_ci .endianness = 1, 10628c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 10638c2ecf20Sopenharmony_ci}; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic const struct regmap_config rt286_regmap = { 10668c2ecf20Sopenharmony_ci .reg_bits = 32, 10678c2ecf20Sopenharmony_ci .val_bits = 32, 10688c2ecf20Sopenharmony_ci .max_register = 0x02370100, 10698c2ecf20Sopenharmony_ci .volatile_reg = rt286_volatile_register, 10708c2ecf20Sopenharmony_ci .readable_reg = rt286_readable_register, 10718c2ecf20Sopenharmony_ci .reg_write = rl6347a_hw_write, 10728c2ecf20Sopenharmony_ci .reg_read = rl6347a_hw_read, 10738c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 10748c2ecf20Sopenharmony_ci .reg_defaults = rt286_reg, 10758c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt286_reg), 10768c2ecf20Sopenharmony_ci}; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_cistatic const struct i2c_device_id rt286_i2c_id[] = { 10798c2ecf20Sopenharmony_ci {"rt286", 0}, 10808c2ecf20Sopenharmony_ci {"rt288", 0}, 10818c2ecf20Sopenharmony_ci {} 10828c2ecf20Sopenharmony_ci}; 10838c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt286_i2c_id); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 10868c2ecf20Sopenharmony_cistatic const struct acpi_device_id rt286_acpi_match[] = { 10878c2ecf20Sopenharmony_ci { "INT343A", 0 }, 10888c2ecf20Sopenharmony_ci {}, 10898c2ecf20Sopenharmony_ci}; 10908c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt286_acpi_match); 10918c2ecf20Sopenharmony_ci#endif 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic const struct dmi_system_id force_combo_jack_table[] = { 10948c2ecf20Sopenharmony_ci { 10958c2ecf20Sopenharmony_ci .ident = "Intel Wilson Beach", 10968c2ecf20Sopenharmony_ci .matches = { 10978c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Wilson Beach SDS") 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci }, 11008c2ecf20Sopenharmony_ci { 11018c2ecf20Sopenharmony_ci .ident = "Intel Skylake RVP", 11028c2ecf20Sopenharmony_ci .matches = { 11038c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Skylake Client platform") 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci }, 11068c2ecf20Sopenharmony_ci { 11078c2ecf20Sopenharmony_ci .ident = "Intel Kabylake RVP", 11088c2ecf20Sopenharmony_ci .matches = { 11098c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci }, 11128c2ecf20Sopenharmony_ci { 11138c2ecf20Sopenharmony_ci .ident = "Thinkpad Helix 2nd", 11148c2ecf20Sopenharmony_ci .matches = { 11158c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 11168c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix 2nd") 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci }, 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci { } 11218c2ecf20Sopenharmony_ci}; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistatic const struct dmi_system_id dmi_dell[] = { 11248c2ecf20Sopenharmony_ci { 11258c2ecf20Sopenharmony_ci .ident = "Dell", 11268c2ecf20Sopenharmony_ci .matches = { 11278c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci }, 11308c2ecf20Sopenharmony_ci { } 11318c2ecf20Sopenharmony_ci}; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_cistatic int rt286_i2c_probe(struct i2c_client *i2c, 11348c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); 11378c2ecf20Sopenharmony_ci struct rt286_priv *rt286; 11388c2ecf20Sopenharmony_ci int i, ret, vendor_id; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), 11418c2ecf20Sopenharmony_ci GFP_KERNEL); 11428c2ecf20Sopenharmony_ci if (NULL == rt286) 11438c2ecf20Sopenharmony_ci return -ENOMEM; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci rt286->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt286_regmap); 11468c2ecf20Sopenharmony_ci if (IS_ERR(rt286->regmap)) { 11478c2ecf20Sopenharmony_ci ret = PTR_ERR(rt286->regmap); 11488c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 11498c2ecf20Sopenharmony_ci ret); 11508c2ecf20Sopenharmony_ci return ret; 11518c2ecf20Sopenharmony_ci } 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci ret = regmap_read(rt286->regmap, 11548c2ecf20Sopenharmony_ci RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id); 11558c2ecf20Sopenharmony_ci if (ret != 0) { 11568c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "I2C error %d\n", ret); 11578c2ecf20Sopenharmony_ci return ret; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) { 11608c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 11618c2ecf20Sopenharmony_ci "Device with ID register %#x is not rt286\n", 11628c2ecf20Sopenharmony_ci vendor_id); 11638c2ecf20Sopenharmony_ci return -ENODEV; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci rt286->index_cache = devm_kmemdup(&i2c->dev, rt286_index_def, 11678c2ecf20Sopenharmony_ci sizeof(rt286_index_def), GFP_KERNEL); 11688c2ecf20Sopenharmony_ci if (!rt286->index_cache) 11698c2ecf20Sopenharmony_ci return -ENOMEM; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci rt286->index_cache_size = INDEX_CACHE_SIZE; 11728c2ecf20Sopenharmony_ci rt286->i2c = i2c; 11738c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, rt286); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci /* restore codec default */ 11768c2ecf20Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) 11778c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, rt286->index_cache[i].reg, 11788c2ecf20Sopenharmony_ci rt286->index_cache[i].def); 11798c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rt286_reg); i++) 11808c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, rt286_reg[i].reg, 11818c2ecf20Sopenharmony_ci rt286_reg[i].def); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci if (pdata) 11848c2ecf20Sopenharmony_ci rt286->pdata = *pdata; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) || 11878c2ecf20Sopenharmony_ci dmi_check_system(force_combo_jack_table)) 11888c2ecf20Sopenharmony_ci rt286->pdata.cbj_en = true; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci for (i = 0; i < RT286_POWER_REG_LEN; i++) 11938c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, 11948c2ecf20Sopenharmony_ci RT286_SET_POWER(rt286_support_power_controls[i]), 11958c2ecf20Sopenharmony_ci AC_PWRST_D1); 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (!rt286->pdata.cbj_en) { 11988c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); 11998c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); 12008c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12018c2ecf20Sopenharmony_ci RT286_CBJ_CTRL1, 0xf000, 0xb000); 12028c2ecf20Sopenharmony_ci } else { 12038c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12048c2ecf20Sopenharmony_ci RT286_CBJ_CTRL1, 0xf000, 0x5000); 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci mdelay(10); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (!rt286->pdata.gpio2_en) 12108c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000); 12118c2ecf20Sopenharmony_ci else 12128c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0); 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci mdelay(10); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); 12178c2ecf20Sopenharmony_ci /* Power down LDO, VREF */ 12188c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0xc, 0x0); 12198c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_POWER_CTRL1, 0x1001, 0x1001); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci /* Set depop parameter */ 12228c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); 12238c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); 12248c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) { 12278c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12288c2ecf20Sopenharmony_ci RT286_SET_GPIO_MASK, 0x40, 0x40); 12298c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12308c2ecf20Sopenharmony_ci RT286_SET_GPIO_DIRECTION, 0x40, 0x40); 12318c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12328c2ecf20Sopenharmony_ci RT286_SET_GPIO_DATA, 0x40, 0x40); 12338c2ecf20Sopenharmony_ci regmap_update_bits(rt286->regmap, 12348c2ecf20Sopenharmony_ci RT286_GPIO_CTRL, 0xc, 0x8); 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci if (rt286->i2c->irq) { 12388c2ecf20Sopenharmony_ci ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, 12398c2ecf20Sopenharmony_ci IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); 12408c2ecf20Sopenharmony_ci if (ret != 0) { 12418c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 12428c2ecf20Sopenharmony_ci "Failed to reguest IRQ: %d\n", ret); 12438c2ecf20Sopenharmony_ci return ret; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 12488c2ecf20Sopenharmony_ci &soc_component_dev_rt286, 12498c2ecf20Sopenharmony_ci rt286_dai, ARRAY_SIZE(rt286_dai)); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci return ret; 12528c2ecf20Sopenharmony_ci} 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_cistatic int rt286_i2c_remove(struct i2c_client *i2c) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci struct rt286_priv *rt286 = i2c_get_clientdata(i2c); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if (i2c->irq) 12598c2ecf20Sopenharmony_ci free_irq(i2c->irq, rt286); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci return 0; 12628c2ecf20Sopenharmony_ci} 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cistatic struct i2c_driver rt286_i2c_driver = { 12668c2ecf20Sopenharmony_ci .driver = { 12678c2ecf20Sopenharmony_ci .name = "rt286", 12688c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt286_acpi_match), 12698c2ecf20Sopenharmony_ci }, 12708c2ecf20Sopenharmony_ci .probe = rt286_i2c_probe, 12718c2ecf20Sopenharmony_ci .remove = rt286_i2c_remove, 12728c2ecf20Sopenharmony_ci .id_table = rt286_i2c_id, 12738c2ecf20Sopenharmony_ci}; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_cimodule_i2c_driver(rt286_i2c_driver); 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT286 driver"); 12788c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); 12798c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1280