162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// rt1308.c -- RT1308 ALSA SoC amplifier component driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright 2019 Realtek Semiconductor Corp. 662306a36Sopenharmony_ci// Author: Derek Fang <derek.fang@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/regmap.h> 1662306a36Sopenharmony_ci#include <linux/acpi.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/firmware.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 2762306a36Sopenharmony_ci#include "rl6231.h" 2862306a36Sopenharmony_ci#include "rt1308.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const struct reg_sequence init_list[] = { 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci { RT1308_I2C_I2S_SDW_SET, 0x01014005 }, 3362306a36Sopenharmony_ci { RT1308_CLASS_D_SET_2, 0x227f5501 }, 3462306a36Sopenharmony_ci { RT1308_PADS_1, 0x50150505 }, 3562306a36Sopenharmony_ci { RT1308_VREF, 0x18100000 }, 3662306a36Sopenharmony_ci { RT1308_IV_SENSE, 0x87010000 }, 3762306a36Sopenharmony_ci { RT1308_DUMMY_REG, 0x00000200 }, 3862306a36Sopenharmony_ci { RT1308_SIL_DET, 0xe1c30000 }, 3962306a36Sopenharmony_ci { RT1308_DC_CAL_2, 0x00ffff00 }, 4062306a36Sopenharmony_ci { RT1308_CLK_DET, 0x01000000 }, 4162306a36Sopenharmony_ci { RT1308_POWER_STATUS, 0x08800000 }, 4262306a36Sopenharmony_ci { RT1308_DAC_SET, 0xafaf0700 }, 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci#define RT1308_INIT_REG_LEN ARRAY_SIZE(init_list) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistruct rt1308_priv { 4862306a36Sopenharmony_ci struct snd_soc_component *component; 4962306a36Sopenharmony_ci struct regmap *regmap; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci int sysclk; 5262306a36Sopenharmony_ci int sysclk_src; 5362306a36Sopenharmony_ci int lrck; 5462306a36Sopenharmony_ci int bclk; 5562306a36Sopenharmony_ci int master; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci int pll_src; 5862306a36Sopenharmony_ci int pll_in; 5962306a36Sopenharmony_ci int pll_out; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct reg_default rt1308_reg[] = { 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci { 0x01, 0x1f3f5f00 }, 6562306a36Sopenharmony_ci { 0x02, 0x07000000 }, 6662306a36Sopenharmony_ci { 0x03, 0x80003e00 }, 6762306a36Sopenharmony_ci { 0x04, 0x80800600 }, 6862306a36Sopenharmony_ci { 0x05, 0x0aaa1a0a }, 6962306a36Sopenharmony_ci { 0x06, 0x52000000 }, 7062306a36Sopenharmony_ci { 0x07, 0x00000000 }, 7162306a36Sopenharmony_ci { 0x08, 0x00600000 }, 7262306a36Sopenharmony_ci { 0x09, 0xe1030000 }, 7362306a36Sopenharmony_ci { 0x0a, 0x00000000 }, 7462306a36Sopenharmony_ci { 0x0b, 0x30000000 }, 7562306a36Sopenharmony_ci { 0x0c, 0x7fff7000 }, 7662306a36Sopenharmony_ci { 0x10, 0xffff0700 }, 7762306a36Sopenharmony_ci { 0x11, 0x0a000000 }, 7862306a36Sopenharmony_ci { 0x12, 0x60040000 }, 7962306a36Sopenharmony_ci { 0x13, 0x00000000 }, 8062306a36Sopenharmony_ci { 0x14, 0x0f300000 }, 8162306a36Sopenharmony_ci { 0x15, 0x00000022 }, 8262306a36Sopenharmony_ci { 0x16, 0x02000000 }, 8362306a36Sopenharmony_ci { 0x17, 0x01004045 }, 8462306a36Sopenharmony_ci { 0x18, 0x00000000 }, 8562306a36Sopenharmony_ci { 0x19, 0x00000000 }, 8662306a36Sopenharmony_ci { 0x1a, 0x80000000 }, 8762306a36Sopenharmony_ci { 0x1b, 0x10325476 }, 8862306a36Sopenharmony_ci { 0x1c, 0x1d1d0000 }, 8962306a36Sopenharmony_ci { 0x20, 0xd2101300 }, 9062306a36Sopenharmony_ci { 0x21, 0xf3ffff00 }, 9162306a36Sopenharmony_ci { 0x22, 0x00000000 }, 9262306a36Sopenharmony_ci { 0x23, 0x00000000 }, 9362306a36Sopenharmony_ci { 0x24, 0x00000000 }, 9462306a36Sopenharmony_ci { 0x25, 0x00000000 }, 9562306a36Sopenharmony_ci { 0x26, 0x00000000 }, 9662306a36Sopenharmony_ci { 0x27, 0x00000000 }, 9762306a36Sopenharmony_ci { 0x28, 0x00000000 }, 9862306a36Sopenharmony_ci { 0x29, 0x00000000 }, 9962306a36Sopenharmony_ci { 0x2a, 0x00000000 }, 10062306a36Sopenharmony_ci { 0x2b, 0x00000000 }, 10162306a36Sopenharmony_ci { 0x2c, 0x00000000 }, 10262306a36Sopenharmony_ci { 0x2d, 0x00000000 }, 10362306a36Sopenharmony_ci { 0x2e, 0x00000000 }, 10462306a36Sopenharmony_ci { 0x2f, 0x00000000 }, 10562306a36Sopenharmony_ci { 0x30, 0x01000000 }, 10662306a36Sopenharmony_ci { 0x31, 0x20025501 }, 10762306a36Sopenharmony_ci { 0x32, 0x00000000 }, 10862306a36Sopenharmony_ci { 0x33, 0x105a0000 }, 10962306a36Sopenharmony_ci { 0x34, 0x10100000 }, 11062306a36Sopenharmony_ci { 0x35, 0x2aaa52aa }, 11162306a36Sopenharmony_ci { 0x36, 0x00c00000 }, 11262306a36Sopenharmony_ci { 0x37, 0x20046100 }, 11362306a36Sopenharmony_ci { 0x50, 0x10022f00 }, 11462306a36Sopenharmony_ci { 0x51, 0x003c0000 }, 11562306a36Sopenharmony_ci { 0x54, 0x04000000 }, 11662306a36Sopenharmony_ci { 0x55, 0x01000000 }, 11762306a36Sopenharmony_ci { 0x56, 0x02000000 }, 11862306a36Sopenharmony_ci { 0x57, 0x02000000 }, 11962306a36Sopenharmony_ci { 0x58, 0x02000000 }, 12062306a36Sopenharmony_ci { 0x59, 0x02000000 }, 12162306a36Sopenharmony_ci { 0x5b, 0x02000000 }, 12262306a36Sopenharmony_ci { 0x5c, 0x00000000 }, 12362306a36Sopenharmony_ci { 0x5d, 0x00000000 }, 12462306a36Sopenharmony_ci { 0x5e, 0x00000000 }, 12562306a36Sopenharmony_ci { 0x5f, 0x00000000 }, 12662306a36Sopenharmony_ci { 0x60, 0x02000000 }, 12762306a36Sopenharmony_ci { 0x61, 0x00000000 }, 12862306a36Sopenharmony_ci { 0x62, 0x00000000 }, 12962306a36Sopenharmony_ci { 0x63, 0x00000000 }, 13062306a36Sopenharmony_ci { 0x64, 0x00000000 }, 13162306a36Sopenharmony_ci { 0x65, 0x02000000 }, 13262306a36Sopenharmony_ci { 0x66, 0x00000000 }, 13362306a36Sopenharmony_ci { 0x67, 0x00000000 }, 13462306a36Sopenharmony_ci { 0x68, 0x00000000 }, 13562306a36Sopenharmony_ci { 0x69, 0x00000000 }, 13662306a36Sopenharmony_ci { 0x6a, 0x02000000 }, 13762306a36Sopenharmony_ci { 0x6c, 0x00000000 }, 13862306a36Sopenharmony_ci { 0x6d, 0x00000000 }, 13962306a36Sopenharmony_ci { 0x6e, 0x00000000 }, 14062306a36Sopenharmony_ci { 0x70, 0x10EC1308 }, 14162306a36Sopenharmony_ci { 0x71, 0x00000000 }, 14262306a36Sopenharmony_ci { 0x72, 0x00000000 }, 14362306a36Sopenharmony_ci { 0x73, 0x00000000 }, 14462306a36Sopenharmony_ci { 0x74, 0x00000000 }, 14562306a36Sopenharmony_ci { 0x75, 0x00000000 }, 14662306a36Sopenharmony_ci { 0x76, 0x00000000 }, 14762306a36Sopenharmony_ci { 0x77, 0x00000000 }, 14862306a36Sopenharmony_ci { 0x78, 0x00000000 }, 14962306a36Sopenharmony_ci { 0x79, 0x00000000 }, 15062306a36Sopenharmony_ci { 0x7a, 0x00000000 }, 15162306a36Sopenharmony_ci { 0x7b, 0x00000000 }, 15262306a36Sopenharmony_ci { 0x7c, 0x00000000 }, 15362306a36Sopenharmony_ci { 0x7d, 0x00000000 }, 15462306a36Sopenharmony_ci { 0x7e, 0x00000000 }, 15562306a36Sopenharmony_ci { 0x7f, 0x00020f00 }, 15662306a36Sopenharmony_ci { 0x80, 0x00000000 }, 15762306a36Sopenharmony_ci { 0x81, 0x00000000 }, 15862306a36Sopenharmony_ci { 0x82, 0x00000000 }, 15962306a36Sopenharmony_ci { 0x83, 0x00000000 }, 16062306a36Sopenharmony_ci { 0x84, 0x00000000 }, 16162306a36Sopenharmony_ci { 0x85, 0x00000000 }, 16262306a36Sopenharmony_ci { 0x86, 0x00000000 }, 16362306a36Sopenharmony_ci { 0x87, 0x00000000 }, 16462306a36Sopenharmony_ci { 0x88, 0x00000000 }, 16562306a36Sopenharmony_ci { 0x89, 0x00000000 }, 16662306a36Sopenharmony_ci { 0x8a, 0x00000000 }, 16762306a36Sopenharmony_ci { 0x8b, 0x00000000 }, 16862306a36Sopenharmony_ci { 0x8c, 0x00000000 }, 16962306a36Sopenharmony_ci { 0x8d, 0x00000000 }, 17062306a36Sopenharmony_ci { 0x8e, 0x00000000 }, 17162306a36Sopenharmony_ci { 0x90, 0x50250905 }, 17262306a36Sopenharmony_ci { 0x91, 0x15050000 }, 17362306a36Sopenharmony_ci { 0xa0, 0x00000000 }, 17462306a36Sopenharmony_ci { 0xa1, 0x00000000 }, 17562306a36Sopenharmony_ci { 0xa2, 0x00000000 }, 17662306a36Sopenharmony_ci { 0xa3, 0x00000000 }, 17762306a36Sopenharmony_ci { 0xa4, 0x00000000 }, 17862306a36Sopenharmony_ci { 0xb0, 0x00000000 }, 17962306a36Sopenharmony_ci { 0xb1, 0x00000000 }, 18062306a36Sopenharmony_ci { 0xb2, 0x00000000 }, 18162306a36Sopenharmony_ci { 0xb3, 0x00000000 }, 18262306a36Sopenharmony_ci { 0xb4, 0x00000000 }, 18362306a36Sopenharmony_ci { 0xb5, 0x00000000 }, 18462306a36Sopenharmony_ci { 0xb6, 0x00000000 }, 18562306a36Sopenharmony_ci { 0xb7, 0x00000000 }, 18662306a36Sopenharmony_ci { 0xb8, 0x00000000 }, 18762306a36Sopenharmony_ci { 0xb9, 0x00000000 }, 18862306a36Sopenharmony_ci { 0xba, 0x00000000 }, 18962306a36Sopenharmony_ci { 0xbb, 0x00000000 }, 19062306a36Sopenharmony_ci { 0xc0, 0x01000000 }, 19162306a36Sopenharmony_ci { 0xc1, 0x00000000 }, 19262306a36Sopenharmony_ci { 0xf0, 0x00000000 }, 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic int rt1308_reg_init(struct snd_soc_component *component) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return regmap_multi_reg_write(rt1308->regmap, init_list, 20062306a36Sopenharmony_ci RT1308_INIT_REG_LEN); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic bool rt1308_volatile_register(struct device *dev, unsigned int reg) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci switch (reg) { 20662306a36Sopenharmony_ci case RT1308_RESET: 20762306a36Sopenharmony_ci case RT1308_RESET_N: 20862306a36Sopenharmony_ci case RT1308_CLK_2: 20962306a36Sopenharmony_ci case RT1308_SIL_DET: 21062306a36Sopenharmony_ci case RT1308_CLK_DET: 21162306a36Sopenharmony_ci case RT1308_DC_DET: 21262306a36Sopenharmony_ci case RT1308_DAC_SET: 21362306a36Sopenharmony_ci case RT1308_DAC_BUF: 21462306a36Sopenharmony_ci case RT1308_SDW_REG_RDATA: 21562306a36Sopenharmony_ci case RT1308_DC_CAL_1: 21662306a36Sopenharmony_ci case RT1308_PVDD_OFFSET_CTL: 21762306a36Sopenharmony_ci case RT1308_CAL_OFFSET_DAC_PBTL: 21862306a36Sopenharmony_ci case RT1308_CAL_OFFSET_DAC_L: 21962306a36Sopenharmony_ci case RT1308_CAL_OFFSET_DAC_R: 22062306a36Sopenharmony_ci case RT1308_CAL_OFFSET_PWM_L: 22162306a36Sopenharmony_ci case RT1308_CAL_OFFSET_PWM_R: 22262306a36Sopenharmony_ci case RT1308_CAL_PWM_VOS_ADC_L: 22362306a36Sopenharmony_ci case RT1308_CAL_PWM_VOS_ADC_R: 22462306a36Sopenharmony_ci case RT1308_MBIAS: 22562306a36Sopenharmony_ci case RT1308_POWER_STATUS: 22662306a36Sopenharmony_ci case RT1308_POWER_INT: 22762306a36Sopenharmony_ci case RT1308_SINE_TONE_GEN_2: 22862306a36Sopenharmony_ci case RT1308_BQ_SET: 22962306a36Sopenharmony_ci case RT1308_BQ_PARA_UPDATE: 23062306a36Sopenharmony_ci case RT1308_VEN_DEV_ID: 23162306a36Sopenharmony_ci case RT1308_VERSION_ID: 23262306a36Sopenharmony_ci case RT1308_EFUSE_1: 23362306a36Sopenharmony_ci case RT1308_EFUSE_READ_PVDD_L: 23462306a36Sopenharmony_ci case RT1308_EFUSE_READ_PVDD_R: 23562306a36Sopenharmony_ci case RT1308_EFUSE_READ_PVDD_PTBL: 23662306a36Sopenharmony_ci case RT1308_EFUSE_READ_DEV: 23762306a36Sopenharmony_ci case RT1308_EFUSE_READ_R0: 23862306a36Sopenharmony_ci case RT1308_EFUSE_READ_ADC_L: 23962306a36Sopenharmony_ci case RT1308_EFUSE_READ_ADC_R: 24062306a36Sopenharmony_ci case RT1308_EFUSE_READ_ADC_PBTL: 24162306a36Sopenharmony_ci case RT1308_EFUSE_RESERVE: 24262306a36Sopenharmony_ci case RT1308_EFUSE_DATA_0_MSB: 24362306a36Sopenharmony_ci case RT1308_EFUSE_DATA_0_LSB: 24462306a36Sopenharmony_ci case RT1308_EFUSE_DATA_1_MSB: 24562306a36Sopenharmony_ci case RT1308_EFUSE_DATA_1_LSB: 24662306a36Sopenharmony_ci case RT1308_EFUSE_DATA_2_MSB: 24762306a36Sopenharmony_ci case RT1308_EFUSE_DATA_2_LSB: 24862306a36Sopenharmony_ci case RT1308_EFUSE_DATA_3_MSB: 24962306a36Sopenharmony_ci case RT1308_EFUSE_DATA_3_LSB: 25062306a36Sopenharmony_ci case RT1308_EFUSE_STATUS_1: 25162306a36Sopenharmony_ci case RT1308_EFUSE_STATUS_2: 25262306a36Sopenharmony_ci case RT1308_DUMMY_REG: 25362306a36Sopenharmony_ci return true; 25462306a36Sopenharmony_ci default: 25562306a36Sopenharmony_ci return false; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic bool rt1308_readable_register(struct device *dev, unsigned int reg) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci switch (reg) { 26262306a36Sopenharmony_ci case RT1308_RESET: 26362306a36Sopenharmony_ci case RT1308_RESET_N: 26462306a36Sopenharmony_ci case RT1308_CLK_GATING ... RT1308_DC_DET_THRES: 26562306a36Sopenharmony_ci case RT1308_DAC_SET ... RT1308_AD_FILTER_SET: 26662306a36Sopenharmony_ci case RT1308_DC_CAL_1 ... RT1308_POWER_INT: 26762306a36Sopenharmony_ci case RT1308_SINE_TONE_GEN_1: 26862306a36Sopenharmony_ci case RT1308_SINE_TONE_GEN_2: 26962306a36Sopenharmony_ci case RT1308_BQ_SET: 27062306a36Sopenharmony_ci case RT1308_BQ_PARA_UPDATE: 27162306a36Sopenharmony_ci case RT1308_BQ_PRE_VOL_L ... RT1308_BQ_POST_VOL_R: 27262306a36Sopenharmony_ci case RT1308_BQ1_L_H0 ... RT1308_BQ2_R_A2: 27362306a36Sopenharmony_ci case RT1308_VEN_DEV_ID: 27462306a36Sopenharmony_ci case RT1308_VERSION_ID: 27562306a36Sopenharmony_ci case RT1308_SPK_BOUND: 27662306a36Sopenharmony_ci case RT1308_BQ1_EQ_L_1 ... RT1308_BQ2_EQ_R_3: 27762306a36Sopenharmony_ci case RT1308_EFUSE_1 ... RT1308_EFUSE_RESERVE: 27862306a36Sopenharmony_ci case RT1308_PADS_1: 27962306a36Sopenharmony_ci case RT1308_PADS_2: 28062306a36Sopenharmony_ci case RT1308_TEST_MODE: 28162306a36Sopenharmony_ci case RT1308_TEST_1: 28262306a36Sopenharmony_ci case RT1308_TEST_2: 28362306a36Sopenharmony_ci case RT1308_TEST_3: 28462306a36Sopenharmony_ci case RT1308_TEST_4: 28562306a36Sopenharmony_ci case RT1308_EFUSE_DATA_0_MSB ... RT1308_EFUSE_STATUS_2: 28662306a36Sopenharmony_ci case RT1308_TCON_1: 28762306a36Sopenharmony_ci case RT1308_TCON_2: 28862306a36Sopenharmony_ci case RT1308_DUMMY_REG: 28962306a36Sopenharmony_ci case RT1308_MAX_REG: 29062306a36Sopenharmony_ci return true; 29162306a36Sopenharmony_ci default: 29262306a36Sopenharmony_ci return false; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic int rt1308_classd_event(struct snd_soc_dapm_widget *w, 29762306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct snd_soc_component *component = 30062306a36Sopenharmony_ci snd_soc_dapm_to_component(w->dapm); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci switch (event) { 30362306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 30462306a36Sopenharmony_ci msleep(30); 30562306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT1308_POWER_STATUS, 30662306a36Sopenharmony_ci RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 30762306a36Sopenharmony_ci RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT); 30862306a36Sopenharmony_ci msleep(40); 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 31162306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT1308_POWER_STATUS, 31262306a36Sopenharmony_ci RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0); 31362306a36Sopenharmony_ci usleep_range(150000, 200000); 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci default: 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci return 0; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic const char * const rt1308_rx_data_ch_select[] = { 32462306a36Sopenharmony_ci "LR", 32562306a36Sopenharmony_ci "LL", 32662306a36Sopenharmony_ci "RL", 32762306a36Sopenharmony_ci "RR", 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt1308_rx_data_ch_enum, RT1308_DATA_PATH, 24, 33162306a36Sopenharmony_ci rt1308_rx_data_ch_select); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt1308_snd_controls[] = { 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* I2S Data Channel Selection */ 33662306a36Sopenharmony_ci SOC_ENUM("RX Channel Select", rt1308_rx_data_ch_enum), 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt1308_sto_dac_l = 34062306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET, 34162306a36Sopenharmony_ci RT1308_DVOL_MUTE_L_EN_SFT, 1, 1); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt1308_sto_dac_r = 34462306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", RT1308_DAC_SET, 34562306a36Sopenharmony_ci RT1308_DVOL_MUTE_R_EN_SFT, 1, 1); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = { 34862306a36Sopenharmony_ci /* Audio Interface */ 34962306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* Supply Widgets */ 35262306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MBIAS20U", RT1308_POWER, 35362306a36Sopenharmony_ci RT1308_POW_MBIAS20U_BIT, 0, NULL, 0), 35462306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ALDO", RT1308_POWER, 35562306a36Sopenharmony_ci RT1308_POW_ALDO_BIT, 0, NULL, 0), 35662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DBG", RT1308_POWER, 35762306a36Sopenharmony_ci RT1308_POW_DBG_BIT, 0, NULL, 0), 35862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DACL", RT1308_POWER, 35962306a36Sopenharmony_ci RT1308_POW_DACL_BIT, 0, NULL, 0), 36062306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("CLK25M", RT1308_POWER, 36162306a36Sopenharmony_ci RT1308_POW_CLK25M_BIT, 0, NULL, 0), 36262306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC_R", RT1308_POWER, 36362306a36Sopenharmony_ci RT1308_POW_ADC_R_BIT, 0, NULL, 0), 36462306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC_L", RT1308_POWER, 36562306a36Sopenharmony_ci RT1308_POW_ADC_L_BIT, 0, NULL, 0), 36662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DLDO", RT1308_POWER, 36762306a36Sopenharmony_ci RT1308_POW_DLDO_BIT, 0, NULL, 0), 36862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF", RT1308_POWER, 36962306a36Sopenharmony_ci RT1308_POW_VREF_BIT, 0, NULL, 0), 37062306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MIXER_R", RT1308_POWER, 37162306a36Sopenharmony_ci RT1308_POW_MIXER_R_BIT, 0, NULL, 0), 37262306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MIXER_L", RT1308_POWER, 37362306a36Sopenharmony_ci RT1308_POW_MIXER_L_BIT, 0, NULL, 0), 37462306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MBIAS4U", RT1308_POWER, 37562306a36Sopenharmony_ci RT1308_POW_MBIAS4U_BIT, 0, NULL, 0), 37662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2_LDO", RT1308_POWER, 37762306a36Sopenharmony_ci RT1308_POW_PLL2_LDO_EN_BIT, 0, NULL, 0), 37862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2B", RT1308_POWER, 37962306a36Sopenharmony_ci RT1308_POW_PLL2B_EN_BIT, 0, NULL, 0), 38062306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2F", RT1308_POWER, 38162306a36Sopenharmony_ci RT1308_POW_PLL2F_EN_BIT, 0, NULL, 0), 38262306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2F2", RT1308_POWER, 38362306a36Sopenharmony_ci RT1308_POW_PLL2F2_EN_BIT, 0, NULL, 0), 38462306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2B2", RT1308_POWER, 38562306a36Sopenharmony_ci RT1308_POW_PLL2B2_EN_BIT, 0, NULL, 0), 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* Digital Interface */ 38862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DAC Power", RT1308_POWER, 38962306a36Sopenharmony_ci RT1308_POW_DAC1_BIT, 0, NULL, 0), 39062306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), 39162306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("DAC L", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_l), 39262306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("DAC R", SND_SOC_NOPM, 0, 0, &rt1308_sto_dac_r), 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Output Lines */ 39562306a36Sopenharmony_ci SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0, 39662306a36Sopenharmony_ci rt1308_classd_event, 39762306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 39862306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOL"), 39962306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPOR"), 40062306a36Sopenharmony_ci}; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic const struct snd_soc_dapm_route rt1308_dapm_routes[] = { 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci { "DAC", NULL, "AIF1RX" }, 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci { "DAC", NULL, "MBIAS20U" }, 40762306a36Sopenharmony_ci { "DAC", NULL, "ALDO" }, 40862306a36Sopenharmony_ci { "DAC", NULL, "DBG" }, 40962306a36Sopenharmony_ci { "DAC", NULL, "DACL" }, 41062306a36Sopenharmony_ci { "DAC", NULL, "CLK25M" }, 41162306a36Sopenharmony_ci { "DAC", NULL, "ADC_R" }, 41262306a36Sopenharmony_ci { "DAC", NULL, "ADC_L" }, 41362306a36Sopenharmony_ci { "DAC", NULL, "DLDO" }, 41462306a36Sopenharmony_ci { "DAC", NULL, "VREF" }, 41562306a36Sopenharmony_ci { "DAC", NULL, "MIXER_R" }, 41662306a36Sopenharmony_ci { "DAC", NULL, "MIXER_L" }, 41762306a36Sopenharmony_ci { "DAC", NULL, "MBIAS4U" }, 41862306a36Sopenharmony_ci { "DAC", NULL, "PLL2_LDO" }, 41962306a36Sopenharmony_ci { "DAC", NULL, "PLL2B" }, 42062306a36Sopenharmony_ci { "DAC", NULL, "PLL2F" }, 42162306a36Sopenharmony_ci { "DAC", NULL, "PLL2F2" }, 42262306a36Sopenharmony_ci { "DAC", NULL, "PLL2B2" }, 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci { "DAC L", "Switch", "DAC" }, 42562306a36Sopenharmony_ci { "DAC R", "Switch", "DAC" }, 42662306a36Sopenharmony_ci { "DAC L", NULL, "DAC Power" }, 42762306a36Sopenharmony_ci { "DAC R", NULL, "DAC Power" }, 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci { "CLASS D", NULL, "DAC L" }, 43062306a36Sopenharmony_ci { "CLASS D", NULL, "DAC R" }, 43162306a36Sopenharmony_ci { "SPOL", NULL, "CLASS D" }, 43262306a36Sopenharmony_ci { "SPOR", NULL, "CLASS D" }, 43362306a36Sopenharmony_ci}; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int rt1308_get_clk_info(int sclk, int rate) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci int i; 43862306a36Sopenharmony_ci static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (sclk <= 0 || rate <= 0) 44162306a36Sopenharmony_ci return -EINVAL; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci rate = rate << 8; 44462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pd); i++) 44562306a36Sopenharmony_ci if (sclk == rate * pd[i]) 44662306a36Sopenharmony_ci return i; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return -EINVAL; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic int rt1308_hw_params(struct snd_pcm_substream *substream, 45262306a36Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 45562306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 45662306a36Sopenharmony_ci unsigned int val_len = 0, val_clk, mask_clk; 45762306a36Sopenharmony_ci int pre_div, bclk_ms, frame_size; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci rt1308->lrck = params_rate(params); 46062306a36Sopenharmony_ci pre_div = rt1308_get_clk_info(rt1308->sysclk, rt1308->lrck); 46162306a36Sopenharmony_ci if (pre_div < 0) { 46262306a36Sopenharmony_ci dev_err(component->dev, 46362306a36Sopenharmony_ci "Unsupported clock setting %d\n", rt1308->lrck); 46462306a36Sopenharmony_ci return -EINVAL; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci frame_size = snd_soc_params_to_frame_size(params); 46862306a36Sopenharmony_ci if (frame_size < 0) { 46962306a36Sopenharmony_ci dev_err(component->dev, "Unsupported frame size: %d\n", 47062306a36Sopenharmony_ci frame_size); 47162306a36Sopenharmony_ci return -EINVAL; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci bclk_ms = frame_size > 32; 47562306a36Sopenharmony_ci rt1308->bclk = rt1308->lrck * (32 << bclk_ms); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 47862306a36Sopenharmony_ci bclk_ms, pre_div, dai->id); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", 48162306a36Sopenharmony_ci rt1308->lrck, pre_div, dai->id); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci switch (params_width(params)) { 48462306a36Sopenharmony_ci case 16: 48562306a36Sopenharmony_ci val_len |= RT1308_I2S_DL_SEL_16B; 48662306a36Sopenharmony_ci break; 48762306a36Sopenharmony_ci case 20: 48862306a36Sopenharmony_ci val_len |= RT1308_I2S_DL_SEL_20B; 48962306a36Sopenharmony_ci break; 49062306a36Sopenharmony_ci case 24: 49162306a36Sopenharmony_ci val_len |= RT1308_I2S_DL_SEL_24B; 49262306a36Sopenharmony_ci break; 49362306a36Sopenharmony_ci case 8: 49462306a36Sopenharmony_ci val_len |= RT1308_I2S_DL_SEL_8B; 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci default: 49762306a36Sopenharmony_ci return -EINVAL; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci switch (dai->id) { 50162306a36Sopenharmony_ci case RT1308_AIF1: 50262306a36Sopenharmony_ci mask_clk = RT1308_DIV_FS_SYS_MASK; 50362306a36Sopenharmony_ci val_clk = pre_div << RT1308_DIV_FS_SYS_SFT; 50462306a36Sopenharmony_ci snd_soc_component_update_bits(component, 50562306a36Sopenharmony_ci RT1308_I2S_SET_2, RT1308_I2S_DL_SEL_MASK, 50662306a36Sopenharmony_ci val_len); 50762306a36Sopenharmony_ci break; 50862306a36Sopenharmony_ci default: 50962306a36Sopenharmony_ci dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); 51062306a36Sopenharmony_ci return -EINVAL; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT1308_CLK_1, 51462306a36Sopenharmony_ci mask_clk, val_clk); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci return 0; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic int rt1308_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 52262306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 52362306a36Sopenharmony_ci unsigned int reg_val = 0, reg1_val = 0; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 52662306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 52762306a36Sopenharmony_ci rt1308->master = 0; 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci default: 53062306a36Sopenharmony_ci return -EINVAL; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 53462306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 53562306a36Sopenharmony_ci break; 53662306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 53762306a36Sopenharmony_ci reg_val |= RT1308_I2S_DF_SEL_LEFT; 53862306a36Sopenharmony_ci break; 53962306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 54062306a36Sopenharmony_ci reg_val |= RT1308_I2S_DF_SEL_PCM_A; 54162306a36Sopenharmony_ci break; 54262306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 54362306a36Sopenharmony_ci reg_val |= RT1308_I2S_DF_SEL_PCM_B; 54462306a36Sopenharmony_ci break; 54562306a36Sopenharmony_ci default: 54662306a36Sopenharmony_ci return -EINVAL; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 55062306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 55362306a36Sopenharmony_ci reg1_val |= RT1308_I2S_BCLK_INV; 55462306a36Sopenharmony_ci break; 55562306a36Sopenharmony_ci default: 55662306a36Sopenharmony_ci return -EINVAL; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci switch (dai->id) { 56062306a36Sopenharmony_ci case RT1308_AIF1: 56162306a36Sopenharmony_ci snd_soc_component_update_bits(component, 56262306a36Sopenharmony_ci RT1308_I2S_SET_1, RT1308_I2S_DF_SEL_MASK, 56362306a36Sopenharmony_ci reg_val); 56462306a36Sopenharmony_ci snd_soc_component_update_bits(component, 56562306a36Sopenharmony_ci RT1308_I2S_SET_2, RT1308_I2S_BCLK_MASK, 56662306a36Sopenharmony_ci reg1_val); 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci default: 56962306a36Sopenharmony_ci dev_err(component->dev, "Invalid dai->id: %d\n", dai->id); 57062306a36Sopenharmony_ci return -EINVAL; 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci return 0; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic int rt1308_set_component_sysclk(struct snd_soc_component *component, 57662306a36Sopenharmony_ci int clk_id, int source, unsigned int freq, int dir) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 57962306a36Sopenharmony_ci unsigned int reg_val = 0; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (freq == rt1308->sysclk && clk_id == rt1308->sysclk_src) 58262306a36Sopenharmony_ci return 0; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci switch (clk_id) { 58562306a36Sopenharmony_ci case RT1308_FS_SYS_S_MCLK: 58662306a36Sopenharmony_ci reg_val |= RT1308_SEL_FS_SYS_SRC_MCLK; 58762306a36Sopenharmony_ci snd_soc_component_update_bits(component, 58862306a36Sopenharmony_ci RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK, 58962306a36Sopenharmony_ci RT1308_MCLK_DET_EN); 59062306a36Sopenharmony_ci break; 59162306a36Sopenharmony_ci case RT1308_FS_SYS_S_BCLK: 59262306a36Sopenharmony_ci reg_val |= RT1308_SEL_FS_SYS_SRC_BCLK; 59362306a36Sopenharmony_ci break; 59462306a36Sopenharmony_ci case RT1308_FS_SYS_S_PLL: 59562306a36Sopenharmony_ci reg_val |= RT1308_SEL_FS_SYS_SRC_PLL; 59662306a36Sopenharmony_ci break; 59762306a36Sopenharmony_ci case RT1308_FS_SYS_S_RCCLK: 59862306a36Sopenharmony_ci reg_val |= RT1308_SEL_FS_SYS_SRC_RCCLK; 59962306a36Sopenharmony_ci break; 60062306a36Sopenharmony_ci default: 60162306a36Sopenharmony_ci dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 60262306a36Sopenharmony_ci return -EINVAL; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT1308_CLK_1, 60562306a36Sopenharmony_ci RT1308_SEL_FS_SYS_MASK, reg_val); 60662306a36Sopenharmony_ci rt1308->sysclk = freq; 60762306a36Sopenharmony_ci rt1308->sysclk_src = clk_id; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", 61062306a36Sopenharmony_ci freq, clk_id); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci return 0; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic int rt1308_set_component_pll(struct snd_soc_component *component, 61662306a36Sopenharmony_ci int pll_id, int source, unsigned int freq_in, 61762306a36Sopenharmony_ci unsigned int freq_out) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 62062306a36Sopenharmony_ci struct rl6231_pll_code pll_code; 62162306a36Sopenharmony_ci int ret; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (source == rt1308->pll_src && freq_in == rt1308->pll_in && 62462306a36Sopenharmony_ci freq_out == rt1308->pll_out) 62562306a36Sopenharmony_ci return 0; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci if (!freq_in || !freq_out) { 62862306a36Sopenharmony_ci dev_dbg(component->dev, "PLL disabled\n"); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci rt1308->pll_in = 0; 63162306a36Sopenharmony_ci rt1308->pll_out = 0; 63262306a36Sopenharmony_ci snd_soc_component_update_bits(component, 63362306a36Sopenharmony_ci RT1308_CLK_1, RT1308_SEL_FS_SYS_MASK, 63462306a36Sopenharmony_ci RT1308_SEL_FS_SYS_SRC_MCLK); 63562306a36Sopenharmony_ci return 0; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci switch (source) { 63962306a36Sopenharmony_ci case RT1308_PLL_S_MCLK: 64062306a36Sopenharmony_ci snd_soc_component_update_bits(component, 64162306a36Sopenharmony_ci RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, 64262306a36Sopenharmony_ci RT1308_SEL_PLL_SRC_MCLK); 64362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 64462306a36Sopenharmony_ci RT1308_CLK_DET, RT1308_MCLK_DET_EN_MASK, 64562306a36Sopenharmony_ci RT1308_MCLK_DET_EN); 64662306a36Sopenharmony_ci break; 64762306a36Sopenharmony_ci case RT1308_PLL_S_BCLK: 64862306a36Sopenharmony_ci snd_soc_component_update_bits(component, 64962306a36Sopenharmony_ci RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, 65062306a36Sopenharmony_ci RT1308_SEL_PLL_SRC_BCLK); 65162306a36Sopenharmony_ci break; 65262306a36Sopenharmony_ci case RT1308_PLL_S_RCCLK: 65362306a36Sopenharmony_ci snd_soc_component_update_bits(component, 65462306a36Sopenharmony_ci RT1308_CLK_2, RT1308_SEL_PLL_SRC_MASK, 65562306a36Sopenharmony_ci RT1308_SEL_PLL_SRC_RCCLK); 65662306a36Sopenharmony_ci freq_in = 25000000; 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci default: 65962306a36Sopenharmony_ci dev_err(component->dev, "Unknown PLL Source %d\n", source); 66062306a36Sopenharmony_ci return -EINVAL; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 66462306a36Sopenharmony_ci if (ret < 0) { 66562306a36Sopenharmony_ci dev_err(component->dev, "Unsupported input clock %d\n", freq_in); 66662306a36Sopenharmony_ci return ret; 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", 67062306a36Sopenharmony_ci pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 67162306a36Sopenharmony_ci pll_code.n_code, pll_code.k_code); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci snd_soc_component_write(component, RT1308_PLL_1, 67462306a36Sopenharmony_ci (pll_code.k_code << RT1308_PLL1_K_SFT) | 67562306a36Sopenharmony_ci (pll_code.m_bp << RT1308_PLL1_M_BYPASS_SFT) | 67662306a36Sopenharmony_ci ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1308_PLL1_M_SFT) | 67762306a36Sopenharmony_ci (pll_code.n_code << RT1308_PLL1_N_SFT)); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci rt1308->pll_in = freq_in; 68062306a36Sopenharmony_ci rt1308->pll_out = freq_out; 68162306a36Sopenharmony_ci rt1308->pll_src = source; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic int rt1308_probe(struct snd_soc_component *component) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci rt1308->component = component; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci return rt1308_reg_init(component); 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic void rt1308_remove(struct snd_soc_component *component) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_RESET, 0); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci#ifdef CONFIG_PM 70362306a36Sopenharmony_cistatic int rt1308_suspend(struct snd_soc_component *component) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci regcache_cache_only(rt1308->regmap, true); 70862306a36Sopenharmony_ci regcache_mark_dirty(rt1308->regmap); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci return 0; 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic int rt1308_resume(struct snd_soc_component *component) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct rt1308_priv *rt1308 = snd_soc_component_get_drvdata(component); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci regcache_cache_only(rt1308->regmap, false); 71862306a36Sopenharmony_ci regcache_sync(rt1308->regmap); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci return 0; 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_ci#else 72362306a36Sopenharmony_ci#define rt1308_suspend NULL 72462306a36Sopenharmony_ci#define rt1308_resume NULL 72562306a36Sopenharmony_ci#endif 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci#define RT1308_STEREO_RATES SNDRV_PCM_RATE_48000 72862306a36Sopenharmony_ci#define RT1308_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 72962306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \ 73062306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE) 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rt1308_aif_dai_ops = { 73362306a36Sopenharmony_ci .hw_params = rt1308_hw_params, 73462306a36Sopenharmony_ci .set_fmt = rt1308_set_dai_fmt, 73562306a36Sopenharmony_ci}; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_cistatic struct snd_soc_dai_driver rt1308_dai[] = { 73862306a36Sopenharmony_ci { 73962306a36Sopenharmony_ci .name = "rt1308-aif", 74062306a36Sopenharmony_ci .playback = { 74162306a36Sopenharmony_ci .stream_name = "AIF1 Playback", 74262306a36Sopenharmony_ci .channels_min = 1, 74362306a36Sopenharmony_ci .channels_max = 2, 74462306a36Sopenharmony_ci .rates = RT1308_STEREO_RATES, 74562306a36Sopenharmony_ci .formats = RT1308_FORMATS, 74662306a36Sopenharmony_ci }, 74762306a36Sopenharmony_ci .ops = &rt1308_aif_dai_ops, 74862306a36Sopenharmony_ci }, 74962306a36Sopenharmony_ci}; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt1308 = { 75262306a36Sopenharmony_ci .probe = rt1308_probe, 75362306a36Sopenharmony_ci .remove = rt1308_remove, 75462306a36Sopenharmony_ci .suspend = rt1308_suspend, 75562306a36Sopenharmony_ci .resume = rt1308_resume, 75662306a36Sopenharmony_ci .controls = rt1308_snd_controls, 75762306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(rt1308_snd_controls), 75862306a36Sopenharmony_ci .dapm_widgets = rt1308_dapm_widgets, 75962306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt1308_dapm_widgets), 76062306a36Sopenharmony_ci .dapm_routes = rt1308_dapm_routes, 76162306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt1308_dapm_routes), 76262306a36Sopenharmony_ci .set_sysclk = rt1308_set_component_sysclk, 76362306a36Sopenharmony_ci .set_pll = rt1308_set_component_pll, 76462306a36Sopenharmony_ci .use_pmdown_time = 1, 76562306a36Sopenharmony_ci .endianness = 1, 76662306a36Sopenharmony_ci}; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_cistatic const struct regmap_config rt1308_regmap = { 76962306a36Sopenharmony_ci .reg_bits = 8, 77062306a36Sopenharmony_ci .val_bits = 32, 77162306a36Sopenharmony_ci .max_register = RT1308_MAX_REG, 77262306a36Sopenharmony_ci .volatile_reg = rt1308_volatile_register, 77362306a36Sopenharmony_ci .readable_reg = rt1308_readable_register, 77462306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 77562306a36Sopenharmony_ci .reg_defaults = rt1308_reg, 77662306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt1308_reg), 77762306a36Sopenharmony_ci .use_single_read = true, 77862306a36Sopenharmony_ci .use_single_write = true, 77962306a36Sopenharmony_ci}; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci#ifdef CONFIG_OF 78262306a36Sopenharmony_cistatic const struct of_device_id rt1308_of_match[] = { 78362306a36Sopenharmony_ci { .compatible = "realtek,rt1308", }, 78462306a36Sopenharmony_ci { }, 78562306a36Sopenharmony_ci}; 78662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rt1308_of_match); 78762306a36Sopenharmony_ci#endif 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci#ifdef CONFIG_ACPI 79062306a36Sopenharmony_cistatic const struct acpi_device_id rt1308_acpi_match[] = { 79162306a36Sopenharmony_ci { "10EC1308", 0, }, 79262306a36Sopenharmony_ci { }, 79362306a36Sopenharmony_ci}; 79462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt1308_acpi_match); 79562306a36Sopenharmony_ci#endif 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic const struct i2c_device_id rt1308_i2c_id[] = { 79862306a36Sopenharmony_ci { "rt1308", 0 }, 79962306a36Sopenharmony_ci { } 80062306a36Sopenharmony_ci}; 80162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt1308_i2c_id); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic void rt1308_efuse(struct rt1308_priv *rt1308) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_RESET, 0); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); 80862306a36Sopenharmony_ci msleep(100); 80962306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); 81062306a36Sopenharmony_ci msleep(20); 81162306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic int rt1308_i2c_probe(struct i2c_client *i2c) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci struct rt1308_priv *rt1308; 81762306a36Sopenharmony_ci int ret; 81862306a36Sopenharmony_ci unsigned int val; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci rt1308 = devm_kzalloc(&i2c->dev, sizeof(struct rt1308_priv), 82162306a36Sopenharmony_ci GFP_KERNEL); 82262306a36Sopenharmony_ci if (rt1308 == NULL) 82362306a36Sopenharmony_ci return -ENOMEM; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci i2c_set_clientdata(i2c, rt1308); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci rt1308->regmap = devm_regmap_init_i2c(i2c, &rt1308_regmap); 82862306a36Sopenharmony_ci if (IS_ERR(rt1308->regmap)) { 82962306a36Sopenharmony_ci ret = PTR_ERR(rt1308->regmap); 83062306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 83162306a36Sopenharmony_ci ret); 83262306a36Sopenharmony_ci return ret; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci regmap_read(rt1308->regmap, RT1308_VEN_DEV_ID, &val); 83662306a36Sopenharmony_ci /* ignore last byte difference */ 83762306a36Sopenharmony_ci if ((val & 0xFFFFFF00) != RT1308_DEVICE_ID_NUM) { 83862306a36Sopenharmony_ci dev_err(&i2c->dev, 83962306a36Sopenharmony_ci "Device with ID register %x is not rt1308\n", val); 84062306a36Sopenharmony_ci return -ENODEV; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci rt1308_efuse(rt1308); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci return devm_snd_soc_register_component(&i2c->dev, 84662306a36Sopenharmony_ci &soc_component_dev_rt1308, 84762306a36Sopenharmony_ci rt1308_dai, ARRAY_SIZE(rt1308_dai)); 84862306a36Sopenharmony_ci} 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_cistatic void rt1308_i2c_shutdown(struct i2c_client *client) 85162306a36Sopenharmony_ci{ 85262306a36Sopenharmony_ci struct rt1308_priv *rt1308 = i2c_get_clientdata(client); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci regmap_write(rt1308->regmap, RT1308_RESET, 0); 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic struct i2c_driver rt1308_i2c_driver = { 85862306a36Sopenharmony_ci .driver = { 85962306a36Sopenharmony_ci .name = "rt1308", 86062306a36Sopenharmony_ci .of_match_table = of_match_ptr(rt1308_of_match), 86162306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt1308_acpi_match), 86262306a36Sopenharmony_ci }, 86362306a36Sopenharmony_ci .probe = rt1308_i2c_probe, 86462306a36Sopenharmony_ci .shutdown = rt1308_i2c_shutdown, 86562306a36Sopenharmony_ci .id_table = rt1308_i2c_id, 86662306a36Sopenharmony_ci}; 86762306a36Sopenharmony_cimodule_i2c_driver(rt1308_i2c_driver); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT1308 amplifier driver"); 87062306a36Sopenharmony_ciMODULE_AUTHOR("Derek Fang <derek.fang@realtek.com>"); 87162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 872