162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * rt298.c -- RT298 ALSA SoC audio codec driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2015 Realtek Semiconductor Corp. 662306a36Sopenharmony_ci * Author: Bard Liao <bardliao@realtek.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/moduleparam.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/pm.h> 1462306a36Sopenharmony_ci#include <linux/i2c.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/spi/spi.h> 1762306a36Sopenharmony_ci#include <linux/dmi.h> 1862306a36Sopenharmony_ci#include <linux/acpi.h> 1962306a36Sopenharmony_ci#include <sound/core.h> 2062306a36Sopenharmony_ci#include <sound/pcm.h> 2162306a36Sopenharmony_ci#include <sound/pcm_params.h> 2262306a36Sopenharmony_ci#include <sound/soc.h> 2362306a36Sopenharmony_ci#include <sound/soc-dapm.h> 2462306a36Sopenharmony_ci#include <sound/initval.h> 2562306a36Sopenharmony_ci#include <sound/tlv.h> 2662306a36Sopenharmony_ci#include <sound/jack.h> 2762306a36Sopenharmony_ci#include <linux/workqueue.h> 2862306a36Sopenharmony_ci#include <sound/rt298.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include "rl6347a.h" 3162306a36Sopenharmony_ci#include "rt298.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define RT298_VENDOR_ID 0x10ec0298 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistruct rt298_priv { 3662306a36Sopenharmony_ci struct reg_default *index_cache; 3762306a36Sopenharmony_ci int index_cache_size; 3862306a36Sopenharmony_ci struct regmap *regmap; 3962306a36Sopenharmony_ci struct snd_soc_component *component; 4062306a36Sopenharmony_ci struct rt298_platform_data pdata; 4162306a36Sopenharmony_ci struct i2c_client *i2c; 4262306a36Sopenharmony_ci struct snd_soc_jack *jack; 4362306a36Sopenharmony_ci struct delayed_work jack_detect_work; 4462306a36Sopenharmony_ci int sys_clk; 4562306a36Sopenharmony_ci int clk_id; 4662306a36Sopenharmony_ci int is_hp_in; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct reg_default rt298_index_def[] = { 5062306a36Sopenharmony_ci { 0x01, 0xa5a8 }, 5162306a36Sopenharmony_ci { 0x02, 0x8e95 }, 5262306a36Sopenharmony_ci { 0x03, 0x0002 }, 5362306a36Sopenharmony_ci { 0x04, 0xaf67 }, 5462306a36Sopenharmony_ci { 0x08, 0x200f }, 5562306a36Sopenharmony_ci { 0x09, 0xd010 }, 5662306a36Sopenharmony_ci { 0x0a, 0x0100 }, 5762306a36Sopenharmony_ci { 0x0b, 0x0000 }, 5862306a36Sopenharmony_ci { 0x0d, 0x2800 }, 5962306a36Sopenharmony_ci { 0x0f, 0x0022 }, 6062306a36Sopenharmony_ci { 0x19, 0x0217 }, 6162306a36Sopenharmony_ci { 0x20, 0x0020 }, 6262306a36Sopenharmony_ci { 0x33, 0x0208 }, 6362306a36Sopenharmony_ci { 0x46, 0x0300 }, 6462306a36Sopenharmony_ci { 0x49, 0x4004 }, 6562306a36Sopenharmony_ci { 0x4f, 0x50c9 }, 6662306a36Sopenharmony_ci { 0x50, 0x3000 }, 6762306a36Sopenharmony_ci { 0x63, 0x1b02 }, 6862306a36Sopenharmony_ci { 0x67, 0x1111 }, 6962306a36Sopenharmony_ci { 0x68, 0x1016 }, 7062306a36Sopenharmony_ci { 0x69, 0x273f }, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci#define INDEX_CACHE_SIZE ARRAY_SIZE(rt298_index_def) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic const struct reg_default rt298_reg[] = { 7562306a36Sopenharmony_ci { 0x00170500, 0x00000400 }, 7662306a36Sopenharmony_ci { 0x00220000, 0x00000031 }, 7762306a36Sopenharmony_ci { 0x00239000, 0x0000007f }, 7862306a36Sopenharmony_ci { 0x0023a000, 0x0000007f }, 7962306a36Sopenharmony_ci { 0x00270500, 0x00000400 }, 8062306a36Sopenharmony_ci { 0x00370500, 0x00000400 }, 8162306a36Sopenharmony_ci { 0x00870500, 0x00000400 }, 8262306a36Sopenharmony_ci { 0x00920000, 0x00000031 }, 8362306a36Sopenharmony_ci { 0x00935000, 0x000000c3 }, 8462306a36Sopenharmony_ci { 0x00936000, 0x000000c3 }, 8562306a36Sopenharmony_ci { 0x00970500, 0x00000400 }, 8662306a36Sopenharmony_ci { 0x00b37000, 0x00000097 }, 8762306a36Sopenharmony_ci { 0x00b37200, 0x00000097 }, 8862306a36Sopenharmony_ci { 0x00b37300, 0x00000097 }, 8962306a36Sopenharmony_ci { 0x00c37000, 0x00000000 }, 9062306a36Sopenharmony_ci { 0x00c37100, 0x00000080 }, 9162306a36Sopenharmony_ci { 0x01270500, 0x00000400 }, 9262306a36Sopenharmony_ci { 0x01370500, 0x00000400 }, 9362306a36Sopenharmony_ci { 0x01371f00, 0x411111f0 }, 9462306a36Sopenharmony_ci { 0x01439000, 0x00000080 }, 9562306a36Sopenharmony_ci { 0x0143a000, 0x00000080 }, 9662306a36Sopenharmony_ci { 0x01470700, 0x00000000 }, 9762306a36Sopenharmony_ci { 0x01470500, 0x00000400 }, 9862306a36Sopenharmony_ci { 0x01470c00, 0x00000000 }, 9962306a36Sopenharmony_ci { 0x01470100, 0x00000000 }, 10062306a36Sopenharmony_ci { 0x01837000, 0x00000000 }, 10162306a36Sopenharmony_ci { 0x01870500, 0x00000400 }, 10262306a36Sopenharmony_ci { 0x02050000, 0x00000000 }, 10362306a36Sopenharmony_ci { 0x02139000, 0x00000080 }, 10462306a36Sopenharmony_ci { 0x0213a000, 0x00000080 }, 10562306a36Sopenharmony_ci { 0x02170100, 0x00000000 }, 10662306a36Sopenharmony_ci { 0x02170500, 0x00000400 }, 10762306a36Sopenharmony_ci { 0x02170700, 0x00000000 }, 10862306a36Sopenharmony_ci { 0x02270100, 0x00000000 }, 10962306a36Sopenharmony_ci { 0x02370100, 0x00000000 }, 11062306a36Sopenharmony_ci { 0x01870700, 0x00000020 }, 11162306a36Sopenharmony_ci { 0x00830000, 0x000000c3 }, 11262306a36Sopenharmony_ci { 0x00930000, 0x000000c3 }, 11362306a36Sopenharmony_ci { 0x01270700, 0x00000000 }, 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic bool rt298_volatile_register(struct device *dev, unsigned int reg) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci switch (reg) { 11962306a36Sopenharmony_ci case 0 ... 0xff: 12062306a36Sopenharmony_ci case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 12162306a36Sopenharmony_ci case RT298_GET_HP_SENSE: 12262306a36Sopenharmony_ci case RT298_GET_MIC1_SENSE: 12362306a36Sopenharmony_ci case RT298_PROC_COEF: 12462306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): 12562306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): 12662306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): 12762306a36Sopenharmony_ci return true; 12862306a36Sopenharmony_ci default: 12962306a36Sopenharmony_ci return false; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic bool rt298_readable_register(struct device *dev, unsigned int reg) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci switch (reg) { 13862306a36Sopenharmony_ci case 0 ... 0xff: 13962306a36Sopenharmony_ci case RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID): 14062306a36Sopenharmony_ci case RT298_GET_HP_SENSE: 14162306a36Sopenharmony_ci case RT298_GET_MIC1_SENSE: 14262306a36Sopenharmony_ci case RT298_SET_AUDIO_POWER: 14362306a36Sopenharmony_ci case RT298_SET_HPO_POWER: 14462306a36Sopenharmony_ci case RT298_SET_SPK_POWER: 14562306a36Sopenharmony_ci case RT298_SET_DMIC1_POWER: 14662306a36Sopenharmony_ci case RT298_SPK_MUX: 14762306a36Sopenharmony_ci case RT298_HPO_MUX: 14862306a36Sopenharmony_ci case RT298_ADC0_MUX: 14962306a36Sopenharmony_ci case RT298_ADC1_MUX: 15062306a36Sopenharmony_ci case RT298_SET_MIC1: 15162306a36Sopenharmony_ci case RT298_SET_PIN_HPO: 15262306a36Sopenharmony_ci case RT298_SET_PIN_SPK: 15362306a36Sopenharmony_ci case RT298_SET_PIN_DMIC1: 15462306a36Sopenharmony_ci case RT298_SPK_EAPD: 15562306a36Sopenharmony_ci case RT298_SET_AMP_GAIN_HPO: 15662306a36Sopenharmony_ci case RT298_SET_DMIC2_DEFAULT: 15762306a36Sopenharmony_ci case RT298_DACL_GAIN: 15862306a36Sopenharmony_ci case RT298_DACR_GAIN: 15962306a36Sopenharmony_ci case RT298_ADCL_GAIN: 16062306a36Sopenharmony_ci case RT298_ADCR_GAIN: 16162306a36Sopenharmony_ci case RT298_MIC_GAIN: 16262306a36Sopenharmony_ci case RT298_SPOL_GAIN: 16362306a36Sopenharmony_ci case RT298_SPOR_GAIN: 16462306a36Sopenharmony_ci case RT298_HPOL_GAIN: 16562306a36Sopenharmony_ci case RT298_HPOR_GAIN: 16662306a36Sopenharmony_ci case RT298_F_DAC_SWITCH: 16762306a36Sopenharmony_ci case RT298_F_RECMIX_SWITCH: 16862306a36Sopenharmony_ci case RT298_REC_MIC_SWITCH: 16962306a36Sopenharmony_ci case RT298_REC_I2S_SWITCH: 17062306a36Sopenharmony_ci case RT298_REC_LINE_SWITCH: 17162306a36Sopenharmony_ci case RT298_REC_BEEP_SWITCH: 17262306a36Sopenharmony_ci case RT298_DAC_FORMAT: 17362306a36Sopenharmony_ci case RT298_ADC_FORMAT: 17462306a36Sopenharmony_ci case RT298_COEF_INDEX: 17562306a36Sopenharmony_ci case RT298_PROC_COEF: 17662306a36Sopenharmony_ci case RT298_SET_AMP_GAIN_ADC_IN1: 17762306a36Sopenharmony_ci case RT298_SET_AMP_GAIN_ADC_IN2: 17862306a36Sopenharmony_ci case RT298_SET_POWER(RT298_DAC_OUT1): 17962306a36Sopenharmony_ci case RT298_SET_POWER(RT298_DAC_OUT2): 18062306a36Sopenharmony_ci case RT298_SET_POWER(RT298_ADC_IN1): 18162306a36Sopenharmony_ci case RT298_SET_POWER(RT298_ADC_IN2): 18262306a36Sopenharmony_ci case RT298_SET_POWER(RT298_DMIC2): 18362306a36Sopenharmony_ci case RT298_SET_POWER(RT298_MIC1): 18462306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_MIC1, 0): 18562306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_SPK_OUT, 0): 18662306a36Sopenharmony_ci case VERB_CMD(AC_VERB_GET_EAPD_BTLENABLE, RT298_HP_OUT, 0): 18762306a36Sopenharmony_ci return true; 18862306a36Sopenharmony_ci default: 18962306a36Sopenharmony_ci return false; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#ifdef CONFIG_PM 19462306a36Sopenharmony_cistatic void rt298_index_sync(struct snd_soc_component *component) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 19762306a36Sopenharmony_ci int i; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) { 20062306a36Sopenharmony_ci snd_soc_component_write(component, rt298->index_cache[i].reg, 20162306a36Sopenharmony_ci rt298->index_cache[i].def); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci#endif 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic int rt298_support_power_controls[] = { 20762306a36Sopenharmony_ci RT298_DAC_OUT1, 20862306a36Sopenharmony_ci RT298_DAC_OUT2, 20962306a36Sopenharmony_ci RT298_ADC_IN1, 21062306a36Sopenharmony_ci RT298_ADC_IN2, 21162306a36Sopenharmony_ci RT298_MIC1, 21262306a36Sopenharmony_ci RT298_DMIC1, 21362306a36Sopenharmony_ci RT298_DMIC2, 21462306a36Sopenharmony_ci RT298_SPK_OUT, 21562306a36Sopenharmony_ci RT298_HP_OUT, 21662306a36Sopenharmony_ci}; 21762306a36Sopenharmony_ci#define RT298_POWER_REG_LEN ARRAY_SIZE(rt298_support_power_controls) 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm; 22262306a36Sopenharmony_ci unsigned int val, buf; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci *hp = false; 22562306a36Sopenharmony_ci *mic = false; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (!rt298->component) 22862306a36Sopenharmony_ci return -EINVAL; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci dapm = snd_soc_component_get_dapm(rt298->component); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (rt298->pdata.cbj_en) { 23362306a36Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); 23462306a36Sopenharmony_ci *hp = buf & 0x80000000; 23562306a36Sopenharmony_ci if (*hp == rt298->is_hp_in) 23662306a36Sopenharmony_ci return -1; 23762306a36Sopenharmony_ci rt298->is_hp_in = *hp; 23862306a36Sopenharmony_ci if (*hp) { 23962306a36Sopenharmony_ci /* power on HV,VERF */ 24062306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 24162306a36Sopenharmony_ci RT298_DC_GAIN, 0x200, 0x200); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "HV"); 24462306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "VREF"); 24562306a36Sopenharmony_ci /* power LDO1 */ 24662306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "LDO1"); 24762306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 25062306a36Sopenharmony_ci RT298_POWER_CTRL1, 0x1001, 0); 25162306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 25262306a36Sopenharmony_ci RT298_POWER_CTRL2, 0x4, 0x4); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_MIC1, 0x24); 25562306a36Sopenharmony_ci msleep(50); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 25862306a36Sopenharmony_ci RT298_CBJ_CTRL1, 0xfcc0, 0xd400); 25962306a36Sopenharmony_ci msleep(300); 26062306a36Sopenharmony_ci regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (0x0070 == (val & 0x0070)) { 26362306a36Sopenharmony_ci *mic = true; 26462306a36Sopenharmony_ci } else { 26562306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 26662306a36Sopenharmony_ci RT298_CBJ_CTRL1, 0xfcc0, 0xe400); 26762306a36Sopenharmony_ci msleep(300); 26862306a36Sopenharmony_ci regmap_read(rt298->regmap, 26962306a36Sopenharmony_ci RT298_CBJ_CTRL2, &val); 27062306a36Sopenharmony_ci if (0x0070 == (val & 0x0070)) { 27162306a36Sopenharmony_ci *mic = true; 27262306a36Sopenharmony_ci } else { 27362306a36Sopenharmony_ci *mic = false; 27462306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 27562306a36Sopenharmony_ci RT298_CBJ_CTRL1, 27662306a36Sopenharmony_ci 0xfcc0, 0xc400); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 28162306a36Sopenharmony_ci RT298_DC_GAIN, 0x200, 0x0); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci } else { 28462306a36Sopenharmony_ci *mic = false; 28562306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_MIC1, 0x20); 28662306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 28762306a36Sopenharmony_ci RT298_CBJ_CTRL1, 0x0400, 0x0000); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci } else { 29062306a36Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_HP_SENSE, &buf); 29162306a36Sopenharmony_ci *hp = buf & 0x80000000; 29262306a36Sopenharmony_ci regmap_read(rt298->regmap, RT298_GET_MIC1_SENSE, &buf); 29362306a36Sopenharmony_ci *mic = buf & 0x80000000; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci if (!*mic) { 29662306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "HV"); 29762306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "VREF"); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci if (!*hp) 30062306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 30162306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci pr_debug("*hp = %d *mic = %d\n", *hp, *mic); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic void rt298_jack_detect_work(struct work_struct *work) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct rt298_priv *rt298 = 31162306a36Sopenharmony_ci container_of(work, struct rt298_priv, jack_detect_work.work); 31262306a36Sopenharmony_ci int status = 0; 31362306a36Sopenharmony_ci bool hp = false; 31462306a36Sopenharmony_ci bool mic = false; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (rt298_jack_detect(rt298, &hp, &mic) < 0) 31762306a36Sopenharmony_ci return; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (hp) 32062306a36Sopenharmony_ci status |= SND_JACK_HEADPHONE; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (mic) 32362306a36Sopenharmony_ci status |= SND_JACK_MICROPHONE; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci snd_soc_jack_report(rt298->jack, status, 32662306a36Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic int rt298_mic_detect(struct snd_soc_component *component, 33062306a36Sopenharmony_ci struct snd_soc_jack *jack, void *data) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 33362306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci rt298->jack = jack; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (jack) { 33862306a36Sopenharmony_ci /* Enable IRQ */ 33962306a36Sopenharmony_ci if (rt298->jack->status & SND_JACK_HEADPHONE) 34062306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "LDO1"); 34162306a36Sopenharmony_ci if (rt298->jack->status & SND_JACK_MICROPHONE) { 34262306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "HV"); 34362306a36Sopenharmony_ci snd_soc_dapm_force_enable_pin(dapm, "VREF"); 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2); 34662306a36Sopenharmony_ci /* Send an initial empty report */ 34762306a36Sopenharmony_ci snd_soc_jack_report(rt298->jack, rt298->jack->status, 34862306a36Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 34962306a36Sopenharmony_ci } else { 35062306a36Sopenharmony_ci /* Disable IRQ */ 35162306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x0); 35262306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "HV"); 35362306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "VREF"); 35462306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "LDO1"); 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci return 0; 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic int is_mclk_mode(struct snd_soc_dapm_widget *source, 36262306a36Sopenharmony_ci struct snd_soc_dapm_widget *sink) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 36562306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (rt298->clk_id == RT298_SCLK_S_MCLK) 36862306a36Sopenharmony_ci return 1; 36962306a36Sopenharmony_ci else 37062306a36Sopenharmony_ci return 0; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); 37462306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_snd_controls[] = { 37762306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT298_DACL_GAIN, 37862306a36Sopenharmony_ci RT298_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), 37962306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT298_ADCL_GAIN, 38062306a36Sopenharmony_ci RT298_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), 38162306a36Sopenharmony_ci SOC_SINGLE_TLV("AMIC Volume", RT298_MIC_GAIN, 38262306a36Sopenharmony_ci 0, 0x3, 0, mic_vol_tlv), 38362306a36Sopenharmony_ci SOC_DOUBLE_R("Speaker Playback Switch", RT298_SPOL_GAIN, 38462306a36Sopenharmony_ci RT298_SPOR_GAIN, RT298_MUTE_SFT, 1, 1), 38562306a36Sopenharmony_ci}; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/* Digital Mixer */ 38862306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_front_mix[] = { 38962306a36Sopenharmony_ci SOC_DAPM_SINGLE("DAC Switch", RT298_F_DAC_SWITCH, 39062306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 39162306a36Sopenharmony_ci SOC_DAPM_SINGLE("RECMIX Switch", RT298_F_RECMIX_SWITCH, 39262306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* Analog Input Mixer */ 39662306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_rec_mix[] = { 39762306a36Sopenharmony_ci SOC_DAPM_SINGLE("Mic1 Switch", RT298_REC_MIC_SWITCH, 39862306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 39962306a36Sopenharmony_ci SOC_DAPM_SINGLE("I2S Switch", RT298_REC_I2S_SWITCH, 40062306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 40162306a36Sopenharmony_ci SOC_DAPM_SINGLE("Line1 Switch", RT298_REC_LINE_SWITCH, 40262306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 40362306a36Sopenharmony_ci SOC_DAPM_SINGLE("Beep Switch", RT298_REC_BEEP_SWITCH, 40462306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1), 40562306a36Sopenharmony_ci}; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic const struct snd_kcontrol_new spo_enable_control = 40862306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", RT298_SET_PIN_SPK, 40962306a36Sopenharmony_ci RT298_SET_PIN_SFT, 1, 0); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic const struct snd_kcontrol_new hpol_enable_control = 41262306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOL_GAIN, 41362306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic const struct snd_kcontrol_new hpor_enable_control = 41662306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT298_HPOR_GAIN, 41762306a36Sopenharmony_ci RT298_MUTE_SFT, 1, 1); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* ADC0 source */ 42062306a36Sopenharmony_cistatic const char * const rt298_adc_src[] = { 42162306a36Sopenharmony_ci "Mic", "RECMIX", "Dmic" 42262306a36Sopenharmony_ci}; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic const int rt298_adc_values[] = { 42562306a36Sopenharmony_ci 0, 4, 5, 42662306a36Sopenharmony_ci}; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 42962306a36Sopenharmony_ci rt298_adc0_enum, RT298_ADC0_MUX, RT298_ADC_SEL_SFT, 43062306a36Sopenharmony_ci RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_adc0_mux = 43362306a36Sopenharmony_ci SOC_DAPM_ENUM("ADC 0 source", rt298_adc0_enum); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL( 43662306a36Sopenharmony_ci rt298_adc1_enum, RT298_ADC1_MUX, RT298_ADC_SEL_SFT, 43762306a36Sopenharmony_ci RT298_ADC_SEL_MASK, rt298_adc_src, rt298_adc_values); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_adc1_mux = 44062306a36Sopenharmony_ci SOC_DAPM_ENUM("ADC 1 source", rt298_adc1_enum); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic const char * const rt298_dac_src[] = { 44362306a36Sopenharmony_ci "Front", "Surround" 44462306a36Sopenharmony_ci}; 44562306a36Sopenharmony_ci/* HP-OUT source */ 44662306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt298_hpo_enum, RT298_HPO_MUX, 44762306a36Sopenharmony_ci 0, rt298_dac_src); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_hpo_mux = 45062306a36Sopenharmony_ciSOC_DAPM_ENUM("HPO source", rt298_hpo_enum); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/* SPK-OUT source */ 45362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt298_spo_enum, RT298_SPK_MUX, 45462306a36Sopenharmony_ci 0, rt298_dac_src); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt298_spo_mux = 45762306a36Sopenharmony_ciSOC_DAPM_ENUM("SPO source", rt298_spo_enum); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int rt298_spk_event(struct snd_soc_dapm_widget *w, 46062306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci switch (event) { 46562306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 46662306a36Sopenharmony_ci snd_soc_component_write(component, 46762306a36Sopenharmony_ci RT298_SPK_EAPD, RT298_SET_EAPD_HIGH); 46862306a36Sopenharmony_ci break; 46962306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 47062306a36Sopenharmony_ci snd_soc_component_write(component, 47162306a36Sopenharmony_ci RT298_SPK_EAPD, RT298_SET_EAPD_LOW); 47262306a36Sopenharmony_ci break; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci default: 47562306a36Sopenharmony_ci return 0; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return 0; 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic int rt298_set_dmic1_event(struct snd_soc_dapm_widget *w, 48262306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci switch (event) { 48762306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 48862306a36Sopenharmony_ci snd_soc_component_write(component, RT298_SET_PIN_DMIC1, 0x20); 48962306a36Sopenharmony_ci break; 49062306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 49162306a36Sopenharmony_ci snd_soc_component_write(component, RT298_SET_PIN_DMIC1, 0); 49262306a36Sopenharmony_ci break; 49362306a36Sopenharmony_ci default: 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci return 0; 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic int rt298_adc_event(struct snd_soc_dapm_widget *w, 50162306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 50462306a36Sopenharmony_ci unsigned int nid; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci nid = (w->reg >> 20) & 0xff; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci switch (event) { 50962306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 51062306a36Sopenharmony_ci snd_soc_component_update_bits(component, 51162306a36Sopenharmony_ci VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 51262306a36Sopenharmony_ci 0x7080, 0x7000); 51362306a36Sopenharmony_ci /* If MCLK doesn't exist, reset AD filter */ 51462306a36Sopenharmony_ci if (!(snd_soc_component_read(component, RT298_VAD_CTRL) & 0x200)) { 51562306a36Sopenharmony_ci pr_info("NO MCLK\n"); 51662306a36Sopenharmony_ci switch (nid) { 51762306a36Sopenharmony_ci case RT298_ADC_IN1: 51862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 51962306a36Sopenharmony_ci RT298_D_FILTER_CTRL, 0x2, 0x2); 52062306a36Sopenharmony_ci mdelay(10); 52162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 52262306a36Sopenharmony_ci RT298_D_FILTER_CTRL, 0x2, 0x0); 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case RT298_ADC_IN2: 52562306a36Sopenharmony_ci snd_soc_component_update_bits(component, 52662306a36Sopenharmony_ci RT298_D_FILTER_CTRL, 0x4, 0x4); 52762306a36Sopenharmony_ci mdelay(10); 52862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 52962306a36Sopenharmony_ci RT298_D_FILTER_CTRL, 0x4, 0x0); 53062306a36Sopenharmony_ci break; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci break; 53462306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 53562306a36Sopenharmony_ci snd_soc_component_update_bits(component, 53662306a36Sopenharmony_ci VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), 53762306a36Sopenharmony_ci 0x7080, 0x7080); 53862306a36Sopenharmony_ci break; 53962306a36Sopenharmony_ci default: 54062306a36Sopenharmony_ci return 0; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci return 0; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic int rt298_mic1_event(struct snd_soc_dapm_widget *w, 54762306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci switch (event) { 55262306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 55362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 55462306a36Sopenharmony_ci RT298_A_BIAS_CTRL3, 0xc000, 0x8000); 55562306a36Sopenharmony_ci snd_soc_component_update_bits(component, 55662306a36Sopenharmony_ci RT298_A_BIAS_CTRL2, 0xc000, 0x8000); 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 55962306a36Sopenharmony_ci snd_soc_component_update_bits(component, 56062306a36Sopenharmony_ci RT298_A_BIAS_CTRL3, 0xc000, 0x0000); 56162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 56262306a36Sopenharmony_ci RT298_A_BIAS_CTRL2, 0xc000, 0x0000); 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci default: 56562306a36Sopenharmony_ci return 0; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci return 0; 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget rt298_dapm_widgets[] = { 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("HV", 1, RT298_POWER_CTRL1, 57462306a36Sopenharmony_ci 12, 1, NULL, 0), 57562306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF", RT298_POWER_CTRL1, 57662306a36Sopenharmony_ci 0, 1, NULL, 0), 57762306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("BG_MBIAS", 1, RT298_POWER_CTRL2, 57862306a36Sopenharmony_ci 1, 0, NULL, 0), 57962306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT298_POWER_CTRL2, 58062306a36Sopenharmony_ci 2, 0, NULL, 0), 58162306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT298_POWER_CTRL2, 58262306a36Sopenharmony_ci 3, 0, NULL, 0), 58362306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("VREF1", 1, RT298_POWER_CTRL2, 58462306a36Sopenharmony_ci 4, 1, NULL, 0), 58562306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LV", 2, RT298_POWER_CTRL1, 58662306a36Sopenharmony_ci 13, 1, NULL, 0), 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MCLK MODE", RT298_PLL_CTRL1, 59062306a36Sopenharmony_ci 5, 0, NULL, 0), 59162306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, 59262306a36Sopenharmony_ci 0, 0, rt298_mic1_event, SND_SOC_DAPM_PRE_PMU | 59362306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMD), 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* Input Lines */ 59662306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1 Pin"), 59762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2 Pin"), 59862306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC1"), 59962306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("LINE1"), 60062306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("Beep"), 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* DMIC */ 60362306a36Sopenharmony_ci SND_SOC_DAPM_PGA_E("DMIC1", RT298_SET_POWER(RT298_DMIC1), 0, 1, 60462306a36Sopenharmony_ci NULL, 0, rt298_set_dmic1_event, 60562306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 60662306a36Sopenharmony_ci SND_SOC_DAPM_PGA("DMIC2", RT298_SET_POWER(RT298_DMIC2), 0, 1, 60762306a36Sopenharmony_ci NULL, 0), 60862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM, 60962306a36Sopenharmony_ci 0, 0, NULL, 0), 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* REC Mixer */ 61262306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0, 61362306a36Sopenharmony_ci rt298_rec_mix, ARRAY_SIZE(rt298_rec_mix)), 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* ADCs */ 61662306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0), 61762306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* ADC Mux */ 62062306a36Sopenharmony_ci SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT298_SET_POWER(RT298_ADC_IN1), 0, 1, 62162306a36Sopenharmony_ci &rt298_adc0_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | 62262306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU), 62362306a36Sopenharmony_ci SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT298_SET_POWER(RT298_ADC_IN2), 0, 1, 62462306a36Sopenharmony_ci &rt298_adc1_mux, rt298_adc_event, SND_SOC_DAPM_PRE_PMD | 62562306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU), 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* Audio Interface */ 62862306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 62962306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 63062306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), 63162306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* Output Side */ 63462306a36Sopenharmony_ci /* DACs */ 63562306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0), 63662306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0), 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci /* Output Mux */ 63962306a36Sopenharmony_ci SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt298_spo_mux), 64062306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt298_hpo_mux), 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("HP Power", RT298_SET_PIN_HPO, 64362306a36Sopenharmony_ci RT298_SET_PIN_SFT, 0, NULL, 0), 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci /* Output Mixer */ 64662306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("Front", RT298_SET_POWER(RT298_DAC_OUT1), 0, 1, 64762306a36Sopenharmony_ci rt298_front_mix, ARRAY_SIZE(rt298_front_mix)), 64862306a36Sopenharmony_ci SND_SOC_DAPM_PGA("Surround", RT298_SET_POWER(RT298_DAC_OUT2), 0, 1, 64962306a36Sopenharmony_ci NULL, 0), 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci /* Output Pga */ 65262306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0, 65362306a36Sopenharmony_ci &spo_enable_control, rt298_spk_event, 65462306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 65562306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0, 65662306a36Sopenharmony_ci &hpol_enable_control), 65762306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0, 65862306a36Sopenharmony_ci &hpor_enable_control), 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Output Lines */ 66162306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOL"), 66262306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOR"), 66362306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPO Pin"), 66462306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPDIF"), 66562306a36Sopenharmony_ci}; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic const struct snd_soc_dapm_route rt298_dapm_routes[] = { 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, 67062306a36Sopenharmony_ci {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, 67162306a36Sopenharmony_ci {"Front", NULL, "MCLK MODE", is_mclk_mode}, 67262306a36Sopenharmony_ci {"Surround", NULL, "MCLK MODE", is_mclk_mode}, 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci {"HP Power", NULL, "LDO1"}, 67562306a36Sopenharmony_ci {"HP Power", NULL, "LDO2"}, 67662306a36Sopenharmony_ci {"HP Power", NULL, "LV"}, 67762306a36Sopenharmony_ci {"HP Power", NULL, "VREF1"}, 67862306a36Sopenharmony_ci {"HP Power", NULL, "BG_MBIAS"}, 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci {"MIC1", NULL, "LDO1"}, 68162306a36Sopenharmony_ci {"MIC1", NULL, "LDO2"}, 68262306a36Sopenharmony_ci {"MIC1", NULL, "HV"}, 68362306a36Sopenharmony_ci {"MIC1", NULL, "LV"}, 68462306a36Sopenharmony_ci {"MIC1", NULL, "VREF"}, 68562306a36Sopenharmony_ci {"MIC1", NULL, "VREF1"}, 68662306a36Sopenharmony_ci {"MIC1", NULL, "BG_MBIAS"}, 68762306a36Sopenharmony_ci {"MIC1", NULL, "MIC1 Input Buffer"}, 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci {"SPO", NULL, "LDO1"}, 69062306a36Sopenharmony_ci {"SPO", NULL, "LDO2"}, 69162306a36Sopenharmony_ci {"SPO", NULL, "HV"}, 69262306a36Sopenharmony_ci {"SPO", NULL, "LV"}, 69362306a36Sopenharmony_ci {"SPO", NULL, "VREF"}, 69462306a36Sopenharmony_ci {"SPO", NULL, "VREF1"}, 69562306a36Sopenharmony_ci {"SPO", NULL, "BG_MBIAS"}, 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci {"DMIC1", NULL, "DMIC1 Pin"}, 69862306a36Sopenharmony_ci {"DMIC2", NULL, "DMIC2 Pin"}, 69962306a36Sopenharmony_ci {"DMIC1", NULL, "DMIC Receiver"}, 70062306a36Sopenharmony_ci {"DMIC2", NULL, "DMIC Receiver"}, 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci {"RECMIX", "Beep Switch", "Beep"}, 70362306a36Sopenharmony_ci {"RECMIX", "Line1 Switch", "LINE1"}, 70462306a36Sopenharmony_ci {"RECMIX", "Mic1 Switch", "MIC1"}, 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci {"ADC 0 Mux", "Dmic", "DMIC1"}, 70762306a36Sopenharmony_ci {"ADC 0 Mux", "RECMIX", "RECMIX"}, 70862306a36Sopenharmony_ci {"ADC 0 Mux", "Mic", "MIC1"}, 70962306a36Sopenharmony_ci {"ADC 1 Mux", "Dmic", "DMIC2"}, 71062306a36Sopenharmony_ci {"ADC 1 Mux", "RECMIX", "RECMIX"}, 71162306a36Sopenharmony_ci {"ADC 1 Mux", "Mic", "MIC1"}, 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci {"ADC 0", NULL, "ADC 0 Mux"}, 71462306a36Sopenharmony_ci {"ADC 1", NULL, "ADC 1 Mux"}, 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci {"AIF1TX", NULL, "ADC 0"}, 71762306a36Sopenharmony_ci {"AIF2TX", NULL, "ADC 1"}, 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci {"DAC 0", NULL, "AIF1RX"}, 72062306a36Sopenharmony_ci {"DAC 1", NULL, "AIF2RX"}, 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci {"Front", "DAC Switch", "DAC 0"}, 72362306a36Sopenharmony_ci {"Front", "RECMIX Switch", "RECMIX"}, 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci {"Surround", NULL, "DAC 1"}, 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci {"SPK Mux", "Front", "Front"}, 72862306a36Sopenharmony_ci {"SPK Mux", "Surround", "Surround"}, 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci {"HPO Mux", "Front", "Front"}, 73162306a36Sopenharmony_ci {"HPO Mux", "Surround", "Surround"}, 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci {"SPO", "Switch", "SPK Mux"}, 73462306a36Sopenharmony_ci {"HPO L", "Switch", "HPO Mux"}, 73562306a36Sopenharmony_ci {"HPO R", "Switch", "HPO Mux"}, 73662306a36Sopenharmony_ci {"HPO L", NULL, "HP Power"}, 73762306a36Sopenharmony_ci {"HPO R", NULL, "HP Power"}, 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci {"SPOL", NULL, "SPO"}, 74062306a36Sopenharmony_ci {"SPOR", NULL, "SPO"}, 74162306a36Sopenharmony_ci {"HPO Pin", NULL, "HPO L"}, 74262306a36Sopenharmony_ci {"HPO Pin", NULL, "HPO R"}, 74362306a36Sopenharmony_ci}; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic int rt298_hw_params(struct snd_pcm_substream *substream, 74662306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 74762306a36Sopenharmony_ci struct snd_soc_dai *dai) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 75062306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 75162306a36Sopenharmony_ci unsigned int val = 0; 75262306a36Sopenharmony_ci int d_len_code; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci switch (params_rate(params)) { 75562306a36Sopenharmony_ci /* bit 14 0:48K 1:44.1K */ 75662306a36Sopenharmony_ci case 44100: 75762306a36Sopenharmony_ci case 48000: 75862306a36Sopenharmony_ci break; 75962306a36Sopenharmony_ci default: 76062306a36Sopenharmony_ci dev_err(component->dev, "Unsupported sample rate %d\n", 76162306a36Sopenharmony_ci params_rate(params)); 76262306a36Sopenharmony_ci return -EINVAL; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci switch (rt298->sys_clk) { 76562306a36Sopenharmony_ci case 12288000: 76662306a36Sopenharmony_ci case 24576000: 76762306a36Sopenharmony_ci if (params_rate(params) != 48000) { 76862306a36Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 76962306a36Sopenharmony_ci params_rate(params), rt298->sys_clk); 77062306a36Sopenharmony_ci return -EINVAL; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci break; 77362306a36Sopenharmony_ci case 11289600: 77462306a36Sopenharmony_ci case 22579200: 77562306a36Sopenharmony_ci if (params_rate(params) != 44100) { 77662306a36Sopenharmony_ci dev_err(component->dev, "Sys_clk is not matched (%d %d)\n", 77762306a36Sopenharmony_ci params_rate(params), rt298->sys_clk); 77862306a36Sopenharmony_ci return -EINVAL; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (params_channels(params) <= 16) { 78462306a36Sopenharmony_ci /* bit 3:0 Number of Channel */ 78562306a36Sopenharmony_ci val |= (params_channels(params) - 1); 78662306a36Sopenharmony_ci } else { 78762306a36Sopenharmony_ci dev_err(component->dev, "Unsupported channels %d\n", 78862306a36Sopenharmony_ci params_channels(params)); 78962306a36Sopenharmony_ci return -EINVAL; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci d_len_code = 0; 79362306a36Sopenharmony_ci switch (params_width(params)) { 79462306a36Sopenharmony_ci /* bit 6:4 Bits per Sample */ 79562306a36Sopenharmony_ci case 16: 79662306a36Sopenharmony_ci d_len_code = 0; 79762306a36Sopenharmony_ci val |= (0x1 << 4); 79862306a36Sopenharmony_ci break; 79962306a36Sopenharmony_ci case 32: 80062306a36Sopenharmony_ci d_len_code = 2; 80162306a36Sopenharmony_ci val |= (0x4 << 4); 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci case 20: 80462306a36Sopenharmony_ci d_len_code = 1; 80562306a36Sopenharmony_ci val |= (0x2 << 4); 80662306a36Sopenharmony_ci break; 80762306a36Sopenharmony_ci case 24: 80862306a36Sopenharmony_ci d_len_code = 2; 80962306a36Sopenharmony_ci val |= (0x3 << 4); 81062306a36Sopenharmony_ci break; 81162306a36Sopenharmony_ci case 8: 81262306a36Sopenharmony_ci d_len_code = 3; 81362306a36Sopenharmony_ci break; 81462306a36Sopenharmony_ci default: 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 81962306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x0018, d_len_code << 3); 82062306a36Sopenharmony_ci dev_dbg(component->dev, "format val = 0x%x\n", val); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT298_DAC_FORMAT, 0x407f, val); 82362306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT298_ADC_FORMAT, 0x407f, val); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci return 0; 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistatic int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 82962306a36Sopenharmony_ci{ 83062306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 83362306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 83462306a36Sopenharmony_ci snd_soc_component_update_bits(component, 83562306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x800, 0x800); 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 83862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 83962306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x800, 0x0); 84062306a36Sopenharmony_ci break; 84162306a36Sopenharmony_ci default: 84262306a36Sopenharmony_ci return -EINVAL; 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 84662306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 84762306a36Sopenharmony_ci snd_soc_component_update_bits(component, 84862306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x0); 84962306a36Sopenharmony_ci break; 85062306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 85162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 85262306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x1 << 8); 85362306a36Sopenharmony_ci break; 85462306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 85562306a36Sopenharmony_ci snd_soc_component_update_bits(component, 85662306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x2 << 8); 85762306a36Sopenharmony_ci break; 85862306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 85962306a36Sopenharmony_ci snd_soc_component_update_bits(component, 86062306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x300, 0x3 << 8); 86162306a36Sopenharmony_ci break; 86262306a36Sopenharmony_ci default: 86362306a36Sopenharmony_ci return -EINVAL; 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci /* bit 15 Stream Type 0:PCM 1:Non-PCM */ 86662306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT298_DAC_FORMAT, 0x8000, 0); 86762306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT298_ADC_FORMAT, 0x8000, 0); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci return 0; 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int rt298_set_dai_sysclk(struct snd_soc_dai *dai, 87362306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 87662306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci dev_dbg(component->dev, "%s freq=%d\n", __func__, freq); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 88162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 88262306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x0100, 0x0); 88362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 88462306a36Sopenharmony_ci RT298_PLL_CTRL1, 0x20, 0x20); 88562306a36Sopenharmony_ci } else { 88662306a36Sopenharmony_ci snd_soc_component_update_bits(component, 88762306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x0100, 0x0100); 88862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 88962306a36Sopenharmony_ci RT298_PLL_CTRL1, 0x20, 0x0); 89062306a36Sopenharmony_ci } 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci switch (freq) { 89362306a36Sopenharmony_ci case 19200000: 89462306a36Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 89562306a36Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 89662306a36Sopenharmony_ci return -EINVAL; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 89962306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x40, 0x40); 90062306a36Sopenharmony_ci break; 90162306a36Sopenharmony_ci case 24000000: 90262306a36Sopenharmony_ci if (RT298_SCLK_S_MCLK == clk_id) { 90362306a36Sopenharmony_ci dev_err(component->dev, "Should not use MCLK\n"); 90462306a36Sopenharmony_ci return -EINVAL; 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci snd_soc_component_update_bits(component, 90762306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x40, 0x0); 90862306a36Sopenharmony_ci break; 90962306a36Sopenharmony_ci case 12288000: 91062306a36Sopenharmony_ci case 11289600: 91162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 91262306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x8, 0x0); 91362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 91462306a36Sopenharmony_ci RT298_CLK_DIV, 0xfc1e, 0x0004); 91562306a36Sopenharmony_ci break; 91662306a36Sopenharmony_ci case 24576000: 91762306a36Sopenharmony_ci case 22579200: 91862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 91962306a36Sopenharmony_ci RT298_I2S_CTRL2, 0x8, 0x8); 92062306a36Sopenharmony_ci snd_soc_component_update_bits(component, 92162306a36Sopenharmony_ci RT298_CLK_DIV, 0xfc1e, 0x5406); 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci default: 92462306a36Sopenharmony_ci dev_err(component->dev, "Unsupported system clock\n"); 92562306a36Sopenharmony_ci return -EINVAL; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci rt298->sys_clk = freq; 92962306a36Sopenharmony_ci rt298->clk_id = clk_id; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci return 0; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic int rt298_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); 93962306a36Sopenharmony_ci if (50 == ratio) 94062306a36Sopenharmony_ci snd_soc_component_update_bits(component, 94162306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x1000, 0x1000); 94262306a36Sopenharmony_ci else 94362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 94462306a36Sopenharmony_ci RT298_I2S_CTRL1, 0x1000, 0x0); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci return 0; 94862306a36Sopenharmony_ci} 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_cistatic int rt298_set_bias_level(struct snd_soc_component *component, 95162306a36Sopenharmony_ci enum snd_soc_bias_level level) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci switch (level) { 95462306a36Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 95562306a36Sopenharmony_ci if (SND_SOC_BIAS_STANDBY == 95662306a36Sopenharmony_ci snd_soc_component_get_bias_level(component)) { 95762306a36Sopenharmony_ci snd_soc_component_write(component, 95862306a36Sopenharmony_ci RT298_SET_AUDIO_POWER, AC_PWRST_D0); 95962306a36Sopenharmony_ci snd_soc_component_update_bits(component, 0x0d, 0x200, 0x200); 96062306a36Sopenharmony_ci snd_soc_component_update_bits(component, 0x52, 0x80, 0x0); 96162306a36Sopenharmony_ci mdelay(20); 96262306a36Sopenharmony_ci snd_soc_component_update_bits(component, 0x0d, 0x200, 0x0); 96362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 0x52, 0x80, 0x80); 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci break; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 96862306a36Sopenharmony_ci snd_soc_component_write(component, 96962306a36Sopenharmony_ci RT298_SET_AUDIO_POWER, AC_PWRST_D3); 97062306a36Sopenharmony_ci break; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci default: 97362306a36Sopenharmony_ci break; 97462306a36Sopenharmony_ci } 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci return 0; 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic irqreturn_t rt298_irq(int irq, void *data) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct rt298_priv *rt298 = data; 98262306a36Sopenharmony_ci bool hp = false; 98362306a36Sopenharmony_ci bool mic = false; 98462306a36Sopenharmony_ci int ret, status = 0; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci ret = rt298_jack_detect(rt298, &hp, &mic); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci /* Clear IRQ */ 98962306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (ret == 0) { 99262306a36Sopenharmony_ci if (hp) 99362306a36Sopenharmony_ci status |= SND_JACK_HEADPHONE; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci if (mic) 99662306a36Sopenharmony_ci status |= SND_JACK_MICROPHONE; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci snd_soc_jack_report(rt298->jack, status, 99962306a36Sopenharmony_ci SND_JACK_MICROPHONE | SND_JACK_HEADPHONE); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci pm_wakeup_event(&rt298->i2c->dev, 300); 100262306a36Sopenharmony_ci } 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci return IRQ_HANDLED; 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic int rt298_probe(struct snd_soc_component *component) 100862306a36Sopenharmony_ci{ 100962306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci rt298->component = component; 101262306a36Sopenharmony_ci INIT_DELAYED_WORK(&rt298->jack_detect_work, rt298_jack_detect_work); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci if (rt298->i2c->irq) 101562306a36Sopenharmony_ci schedule_delayed_work(&rt298->jack_detect_work, 101662306a36Sopenharmony_ci msecs_to_jiffies(1250)); 101762306a36Sopenharmony_ci return 0; 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_cistatic void rt298_remove(struct snd_soc_component *component) 102162306a36Sopenharmony_ci{ 102262306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci cancel_delayed_work_sync(&rt298->jack_detect_work); 102562306a36Sopenharmony_ci rt298->component = NULL; 102662306a36Sopenharmony_ci} 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci#ifdef CONFIG_PM 102962306a36Sopenharmony_cistatic int rt298_suspend(struct snd_soc_component *component) 103062306a36Sopenharmony_ci{ 103162306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci rt298->is_hp_in = -1; 103462306a36Sopenharmony_ci regcache_cache_only(rt298->regmap, true); 103562306a36Sopenharmony_ci regcache_mark_dirty(rt298->regmap); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci return 0; 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_cistatic int rt298_resume(struct snd_soc_component *component) 104162306a36Sopenharmony_ci{ 104262306a36Sopenharmony_ci struct rt298_priv *rt298 = snd_soc_component_get_drvdata(component); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci regcache_cache_only(rt298->regmap, false); 104562306a36Sopenharmony_ci rt298_index_sync(component); 104662306a36Sopenharmony_ci regcache_sync(rt298->regmap); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci return 0; 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci#else 105162306a36Sopenharmony_ci#define rt298_suspend NULL 105262306a36Sopenharmony_ci#define rt298_resume NULL 105362306a36Sopenharmony_ci#endif 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci#define RT298_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 105662306a36Sopenharmony_ci#define RT298_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 105762306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rt298_aif_dai_ops = { 106062306a36Sopenharmony_ci .hw_params = rt298_hw_params, 106162306a36Sopenharmony_ci .set_fmt = rt298_set_dai_fmt, 106262306a36Sopenharmony_ci .set_sysclk = rt298_set_dai_sysclk, 106362306a36Sopenharmony_ci .set_bclk_ratio = rt298_set_bclk_ratio, 106462306a36Sopenharmony_ci}; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_cistatic struct snd_soc_dai_driver rt298_dai[] = { 106762306a36Sopenharmony_ci { 106862306a36Sopenharmony_ci .name = "rt298-aif1", 106962306a36Sopenharmony_ci .id = RT298_AIF1, 107062306a36Sopenharmony_ci .playback = { 107162306a36Sopenharmony_ci .stream_name = "AIF1 Playback", 107262306a36Sopenharmony_ci .channels_min = 1, 107362306a36Sopenharmony_ci .channels_max = 2, 107462306a36Sopenharmony_ci .rates = RT298_STEREO_RATES, 107562306a36Sopenharmony_ci .formats = RT298_FORMATS, 107662306a36Sopenharmony_ci }, 107762306a36Sopenharmony_ci .capture = { 107862306a36Sopenharmony_ci .stream_name = "AIF1 Capture", 107962306a36Sopenharmony_ci .channels_min = 1, 108062306a36Sopenharmony_ci .channels_max = 2, 108162306a36Sopenharmony_ci .rates = RT298_STEREO_RATES, 108262306a36Sopenharmony_ci .formats = RT298_FORMATS, 108362306a36Sopenharmony_ci }, 108462306a36Sopenharmony_ci .ops = &rt298_aif_dai_ops, 108562306a36Sopenharmony_ci .symmetric_rate = 1, 108662306a36Sopenharmony_ci }, 108762306a36Sopenharmony_ci { 108862306a36Sopenharmony_ci .name = "rt298-aif2", 108962306a36Sopenharmony_ci .id = RT298_AIF2, 109062306a36Sopenharmony_ci .playback = { 109162306a36Sopenharmony_ci .stream_name = "AIF2 Playback", 109262306a36Sopenharmony_ci .channels_min = 1, 109362306a36Sopenharmony_ci .channels_max = 2, 109462306a36Sopenharmony_ci .rates = RT298_STEREO_RATES, 109562306a36Sopenharmony_ci .formats = RT298_FORMATS, 109662306a36Sopenharmony_ci }, 109762306a36Sopenharmony_ci .capture = { 109862306a36Sopenharmony_ci .stream_name = "AIF2 Capture", 109962306a36Sopenharmony_ci .channels_min = 1, 110062306a36Sopenharmony_ci .channels_max = 2, 110162306a36Sopenharmony_ci .rates = RT298_STEREO_RATES, 110262306a36Sopenharmony_ci .formats = RT298_FORMATS, 110362306a36Sopenharmony_ci }, 110462306a36Sopenharmony_ci .ops = &rt298_aif_dai_ops, 110562306a36Sopenharmony_ci .symmetric_rate = 1, 110662306a36Sopenharmony_ci }, 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci}; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt298 = { 111162306a36Sopenharmony_ci .probe = rt298_probe, 111262306a36Sopenharmony_ci .remove = rt298_remove, 111362306a36Sopenharmony_ci .suspend = rt298_suspend, 111462306a36Sopenharmony_ci .resume = rt298_resume, 111562306a36Sopenharmony_ci .set_bias_level = rt298_set_bias_level, 111662306a36Sopenharmony_ci .set_jack = rt298_mic_detect, 111762306a36Sopenharmony_ci .controls = rt298_snd_controls, 111862306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(rt298_snd_controls), 111962306a36Sopenharmony_ci .dapm_widgets = rt298_dapm_widgets, 112062306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), 112162306a36Sopenharmony_ci .dapm_routes = rt298_dapm_routes, 112262306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), 112362306a36Sopenharmony_ci .use_pmdown_time = 1, 112462306a36Sopenharmony_ci .endianness = 1, 112562306a36Sopenharmony_ci}; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_cistatic const struct regmap_config rt298_regmap = { 112862306a36Sopenharmony_ci .reg_bits = 32, 112962306a36Sopenharmony_ci .val_bits = 32, 113062306a36Sopenharmony_ci .max_register = 0x02370100, 113162306a36Sopenharmony_ci .volatile_reg = rt298_volatile_register, 113262306a36Sopenharmony_ci .readable_reg = rt298_readable_register, 113362306a36Sopenharmony_ci .reg_write = rl6347a_hw_write, 113462306a36Sopenharmony_ci .reg_read = rl6347a_hw_read, 113562306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 113662306a36Sopenharmony_ci .reg_defaults = rt298_reg, 113762306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt298_reg), 113862306a36Sopenharmony_ci}; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_cistatic const struct i2c_device_id rt298_i2c_id[] = { 114162306a36Sopenharmony_ci {"rt298", 0}, 114262306a36Sopenharmony_ci {} 114362306a36Sopenharmony_ci}; 114462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt298_i2c_id); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci#ifdef CONFIG_ACPI 114762306a36Sopenharmony_cistatic const struct acpi_device_id rt298_acpi_match[] = { 114862306a36Sopenharmony_ci { "INT343A", 0 }, 114962306a36Sopenharmony_ci {}, 115062306a36Sopenharmony_ci}; 115162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt298_acpi_match); 115262306a36Sopenharmony_ci#endif 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_cistatic const struct dmi_system_id force_combo_jack_table[] = { 115562306a36Sopenharmony_ci { 115662306a36Sopenharmony_ci .ident = "Intel Broxton P", 115762306a36Sopenharmony_ci .matches = { 115862306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"), 115962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Broxton P") 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci }, 116262306a36Sopenharmony_ci { 116362306a36Sopenharmony_ci .ident = "Intel Gemini Lake", 116462306a36Sopenharmony_ci .matches = { 116562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp"), 116662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Geminilake") 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci }, 116962306a36Sopenharmony_ci { 117062306a36Sopenharmony_ci .ident = "Intel Kabylake R RVP", 117162306a36Sopenharmony_ci .matches = { 117262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 117362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") 117462306a36Sopenharmony_ci } 117562306a36Sopenharmony_ci }, 117662306a36Sopenharmony_ci { } 117762306a36Sopenharmony_ci}; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_cistatic int rt298_i2c_probe(struct i2c_client *i2c) 118062306a36Sopenharmony_ci{ 118162306a36Sopenharmony_ci struct rt298_platform_data *pdata = dev_get_platdata(&i2c->dev); 118262306a36Sopenharmony_ci struct rt298_priv *rt298; 118362306a36Sopenharmony_ci struct device *dev = &i2c->dev; 118462306a36Sopenharmony_ci const struct acpi_device_id *acpiid; 118562306a36Sopenharmony_ci int i, ret; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci rt298 = devm_kzalloc(&i2c->dev, sizeof(*rt298), 118862306a36Sopenharmony_ci GFP_KERNEL); 118962306a36Sopenharmony_ci if (NULL == rt298) 119062306a36Sopenharmony_ci return -ENOMEM; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci rt298->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt298_regmap); 119362306a36Sopenharmony_ci if (IS_ERR(rt298->regmap)) { 119462306a36Sopenharmony_ci ret = PTR_ERR(rt298->regmap); 119562306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 119662306a36Sopenharmony_ci ret); 119762306a36Sopenharmony_ci return ret; 119862306a36Sopenharmony_ci } 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci regmap_read(rt298->regmap, 120162306a36Sopenharmony_ci RT298_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); 120262306a36Sopenharmony_ci if (ret != RT298_VENDOR_ID) { 120362306a36Sopenharmony_ci dev_err(&i2c->dev, 120462306a36Sopenharmony_ci "Device with ID register %#x is not rt298\n", ret); 120562306a36Sopenharmony_ci return -ENODEV; 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci rt298->index_cache = devm_kmemdup(&i2c->dev, rt298_index_def, 120962306a36Sopenharmony_ci sizeof(rt298_index_def), GFP_KERNEL); 121062306a36Sopenharmony_ci if (!rt298->index_cache) 121162306a36Sopenharmony_ci return -ENOMEM; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci rt298->index_cache_size = INDEX_CACHE_SIZE; 121462306a36Sopenharmony_ci rt298->i2c = i2c; 121562306a36Sopenharmony_ci i2c_set_clientdata(i2c, rt298); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* restore codec default */ 121862306a36Sopenharmony_ci for (i = 0; i < INDEX_CACHE_SIZE; i++) 121962306a36Sopenharmony_ci regmap_write(rt298->regmap, rt298->index_cache[i].reg, 122062306a36Sopenharmony_ci rt298->index_cache[i].def); 122162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rt298_reg); i++) 122262306a36Sopenharmony_ci regmap_write(rt298->regmap, rt298_reg[i].reg, 122362306a36Sopenharmony_ci rt298_reg[i].def); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (pdata) 122662306a36Sopenharmony_ci rt298->pdata = *pdata; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci /* enable jack combo mode on supported devices */ 122962306a36Sopenharmony_ci acpiid = acpi_match_device(dev->driver->acpi_match_table, dev); 123062306a36Sopenharmony_ci if (acpiid && acpiid->driver_data) { 123162306a36Sopenharmony_ci rt298->pdata = *(struct rt298_platform_data *) 123262306a36Sopenharmony_ci acpiid->driver_data; 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci if (dmi_check_system(force_combo_jack_table)) { 123662306a36Sopenharmony_ci rt298->pdata.cbj_en = true; 123762306a36Sopenharmony_ci rt298->pdata.gpio2_en = false; 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci /* VREF Charging */ 124162306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x04, 0x80, 0x80); 124262306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x1b, 0x860, 0x860); 124362306a36Sopenharmony_ci /* Vref2 */ 124462306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 0x08, 0x20, 0x20); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_AUDIO_POWER, AC_PWRST_D3); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci for (i = 0; i < RT298_POWER_REG_LEN; i++) 124962306a36Sopenharmony_ci regmap_write(rt298->regmap, 125062306a36Sopenharmony_ci RT298_SET_POWER(rt298_support_power_controls[i]), 125162306a36Sopenharmony_ci AC_PWRST_D1); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci if (!rt298->pdata.cbj_en) { 125462306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_CBJ_CTRL2, 0x0000); 125562306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_MIC1_DET_CTRL, 0x0816); 125662306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 125762306a36Sopenharmony_ci RT298_CBJ_CTRL1, 0xf000, 0xb000); 125862306a36Sopenharmony_ci } else { 125962306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 126062306a36Sopenharmony_ci RT298_CBJ_CTRL1, 0xf000, 0x5000); 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci mdelay(10); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci if (!rt298->pdata.gpio2_en) 126662306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40); 126762306a36Sopenharmony_ci else 126862306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0); 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci mdelay(10); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_MISC_CTRL1, 0x0000); 127362306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, 127462306a36Sopenharmony_ci RT298_WIND_FILTER_CTRL, 0x0082, 0x0082); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_INLINE_CMD, 0x81); 127762306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_HP_OUT, 0x82); 127862306a36Sopenharmony_ci regmap_write(rt298->regmap, RT298_UNSOLICITED_MIC1, 0x84); 127962306a36Sopenharmony_ci regmap_update_bits(rt298->regmap, RT298_IRQ_FLAG_CTRL, 0x2, 0x2); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci rt298->is_hp_in = -1; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (rt298->i2c->irq) { 128462306a36Sopenharmony_ci ret = request_threaded_irq(rt298->i2c->irq, NULL, rt298_irq, 128562306a36Sopenharmony_ci IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt298", rt298); 128662306a36Sopenharmony_ci if (ret != 0) { 128762306a36Sopenharmony_ci dev_err(&i2c->dev, 128862306a36Sopenharmony_ci "Failed to reguest IRQ: %d\n", ret); 128962306a36Sopenharmony_ci return ret; 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci } 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 129462306a36Sopenharmony_ci &soc_component_dev_rt298, 129562306a36Sopenharmony_ci rt298_dai, ARRAY_SIZE(rt298_dai)); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci return ret; 129862306a36Sopenharmony_ci} 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_cistatic void rt298_i2c_remove(struct i2c_client *i2c) 130162306a36Sopenharmony_ci{ 130262306a36Sopenharmony_ci struct rt298_priv *rt298 = i2c_get_clientdata(i2c); 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (i2c->irq) 130562306a36Sopenharmony_ci free_irq(i2c->irq, rt298); 130662306a36Sopenharmony_ci} 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_cistatic struct i2c_driver rt298_i2c_driver = { 131062306a36Sopenharmony_ci .driver = { 131162306a36Sopenharmony_ci .name = "rt298", 131262306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt298_acpi_match), 131362306a36Sopenharmony_ci }, 131462306a36Sopenharmony_ci .probe = rt298_i2c_probe, 131562306a36Sopenharmony_ci .remove = rt298_i2c_remove, 131662306a36Sopenharmony_ci .id_table = rt298_i2c_id, 131762306a36Sopenharmony_ci}; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_cimodule_i2c_driver(rt298_i2c_driver); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT298 driver"); 132262306a36Sopenharmony_ciMODULE_AUTHOR("Bard Liao <bardliao@realtek.com>"); 132362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1324