913 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * ak4619.c -- Asahi Kasei ALSA SoC Audio driver4 *5 * Copyright (C) 2023 Renesas Electronics Corporation6 * Khanh Le <khanh.le.xr@renesas.com>7 *8 * Based on ak4613.c by Kuninori Morimoto9 * Based on da7213.c by Adam Thomson10 * Based on ak4641.c by Harald Welte11 */12 13#include <linux/clk.h>14#include <linux/gpio/consumer.h>15#include <linux/i2c.h>16#include <linux/slab.h>17#include <linux/of_device.h>18#include <linux/module.h>19#include <linux/regmap.h>20#include <sound/soc.h>21#include <sound/pcm.h>22#include <sound/pcm_params.h>23#include <sound/tlv.h>24 25/*26 * Registers27 */28 29#define PWR_MGMT 0x00 /* Power Management */30#define AU_IFF1 0x01 /* Audio I/F Format */31#define AU_IFF2 0x02 /* Audio I/F Format (Extended) */32#define SYS_CLK 0x03 /* System Clock Setting */33#define MIC_AMP1 0x04 /* MIC AMP Gain 1 */34#define MIC_AMP2 0x05 /* MIC AMP Gain 2 */35#define LADC1 0x06 /* ADC1 Lch Digital Volume */36#define RADC1 0x07 /* ADC1 Rch Digital Volume */37#define LADC2 0x08 /* ADC2 Lch Digital Volume */38#define RADC2 0x09 /* ADC2 Rch Digital Volume */39#define ADC_DF 0x0a /* ADC Digital Filter Setting */40#define ADC_AI 0x0b /* ADC Analog Input Setting */41#define ADC_MHPF 0x0D /* ADC Mute & HPF Control */42#define LDAC1 0x0E /* DAC1 Lch Digital Volume */43#define RDAC1 0x0F /* DAC1 Rch Digital Volume */44#define LDAC2 0x10 /* DAC2 Lch Digital Volume */45#define RDAC2 0x11 /* DAC2 Rch Digital Volume */46#define DAC_IS 0x12 /* DAC Input Select Setting */47#define DAC_DEMP 0x13 /* DAC De-Emphasis Setting */48#define DAC_MF 0x14 /* DAC Mute & Filter Setting */49 50/*51 * Bit fields52 */53 54/* Power Management */55#define PMAD2 BIT(5)56#define PMAD1 BIT(4)57#define PMDA2 BIT(2)58#define PMDA1 BIT(1)59#define RSTN BIT(0)60 61/* Audio_I/F Format */62#define DCF_STEREO_I2S (0x0 << 4)63#define DCF_STEREO_MSB (0x5 << 4)64#define DCF_PCM_SF (0x6 << 4)65#define DCF_PCM_LF (0x7 << 4)66#define DSL_32 (0x3 << 2)67#define DCF_MASK (0x7 << 4)68#define DSL_MASK (0x3 << 2)69#define BCKP BIT(1)70 71/* Audio_I/F Format (Extended) */72#define DIDL_24 (0x0 << 2)73#define DIDL_20 (0x1 << 2)74#define DIDL_16 (0x2 << 2)75#define DIDL_32 (0x3 << 2)76#define DODL_24 (0x0 << 0)77#define DODL_20 (0x1 << 0)78#define DODL_16 (0x2 << 0)79#define DIDL_MASK (0x3 << 2)80#define DODL_MASK (0x3 << 0)81#define SLOT BIT(4)82 83/* System Clock Setting */84#define FS_MASK 0x785 86/* MIC AMP Gain */87#define MGNL_SHIFT 488#define MGNR_SHIFT 089#define MGN_MAX 0xB90 91/* ADC Digital Volume */92#define VOLAD_SHIFT 093#define VOLAD_MAX 0xFF94 95/* ADC Digital Filter Setting */96#define AD1SL_SHIFT 097#define AD2SL_SHIFT 498 99/* Analog Input Select */100#define AD1LSEL_SHIFT 6101#define AD1RSEL_SHIFT 4102#define AD2LSEL_SHIFT 2103#define AD2RSEL_SHIFT 0104 105/* ADC Mute & HPF Control */106#define ATSPAD_SHIFT 7107#define AD1MUTE_SHIFT 5108#define AD2MUTE_SHIFT 6109#define AD1MUTE_MAX 1110#define AD2MUTE_MAX 1111#define AD1MUTE_EN BIT(5)112#define AD2MUTE_EN BIT(6)113#define AD1HPFN_SHIFT 1114#define AD1HPFN_MAX 1115#define AD2HPFN_SHIFT 2116#define AD2HPFN_MAX 1117 118/* DAC Digital Volume */119#define VOLDA_SHIFT 0120#define VOLDA_MAX 0xFF121 122/* DAC Input Select Setting */123#define DAC1SEL_SHIFT 0124#define DAC2SEL_SHIFT 2125 126/* DAC De-Emphasis Setting */127#define DEM1_32000 (0x3 << 0)128#define DEM1_44100 (0x0 << 0)129#define DEM1_48000 (0x2 << 0)130#define DEM1_OFF (0x1 << 0)131#define DEM2_32000 (0x3 << 2)132#define DEM2_44100 (0x0 << 2)133#define DEM2_48000 (0x2 << 2)134#define DEM2_OFF (0x1 << 2)135#define DEM1_MASK (0x3 << 0)136#define DEM2_MASK (0x3 << 2)137#define DEM1_SHIFT 0138#define DEM2_SHIFT 2139 140/* DAC Mute & Filter Setting */141#define DA1MUTE_SHIFT 4142#define DA1MUTE_MAX 1143#define DA2MUTE_SHIFT 5144#define DA2MUTE_MAX 1145#define DA1MUTE_EN BIT(4)146#define DA2MUTE_EN BIT(5)147#define ATSPDA_SHIFT 7148#define DA1SL_SHIFT 0149#define DA2SL_SHIFT 2150 151/* Codec private data */152struct ak4619_priv {153 struct regmap *regmap;154 struct snd_pcm_hw_constraint_list constraint;155 int deemph_en;156 unsigned int playback_rate;157 unsigned int sysclk;158};159 160/*161 * DAC Volume162 *163 * max : 0x00 : +12.0 dB164 * ( 0.5 dB step )165 * min : 0xFE : -115.0 dB166 * mute: 0xFF167 */168static const DECLARE_TLV_DB_SCALE(dac_tlv, -11550, 50, 1);169 170/*171 * MIC Volume172 *173 * max : 0x0B : +27.0 dB174 * ( 3 dB step )175 * min: 0x00 : -6.0 dB176 */177static const DECLARE_TLV_DB_SCALE(mic_tlv, -600, 300, 0);178 179/*180 * ADC Volume181 *182 * max : 0x00 : +24.0 dB183 * ( 0.5 dB step )184 * min : 0xFE : -103.0 dB185 * mute: 0xFF186 */187static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);188 189/* ADC & DAC Volume Level Transition Time select */190static const char * const ak4619_vol_trans_txt[] = {191 "4/fs", "16/fs"192};193 194static SOC_ENUM_SINGLE_DECL(ak4619_adc_vol_trans, ADC_MHPF, ATSPAD_SHIFT, ak4619_vol_trans_txt);195static SOC_ENUM_SINGLE_DECL(ak4619_dac_vol_trans, DAC_MF, ATSPDA_SHIFT, ak4619_vol_trans_txt);196 197/* ADC Digital Filter select */198static const char * const ak4619_adc_digi_fil_txt[] = {199 "Sharp Roll-Off Filter",200 "Slow Roll-Off Filter",201 "Short Delay Sharp Roll-Off Filter",202 "Short Delay Slow Roll-Off Filter",203 "Voice Filter"204};205 206static SOC_ENUM_SINGLE_DECL(ak4619_adc_1_digi_fil, ADC_DF, AD1SL_SHIFT, ak4619_adc_digi_fil_txt);207static SOC_ENUM_SINGLE_DECL(ak4619_adc_2_digi_fil, ADC_DF, AD2SL_SHIFT, ak4619_adc_digi_fil_txt);208 209/* DAC De-Emphasis Filter select */210static const char * const ak4619_dac_de_emp_txt[] = {211 "44.1kHz", "OFF", "48kHz", "32kHz"212};213 214static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_de_emp, DAC_DEMP, DEM1_SHIFT, ak4619_dac_de_emp_txt);215static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_de_emp, DAC_DEMP, DEM2_SHIFT, ak4619_dac_de_emp_txt);216 217/* DAC Digital Filter select */218static const char * const ak4619_dac_digi_fil_txt[] = {219 "Sharp Roll-Off Filter",220 "Slow Roll-Off Filter",221 "Short Delay Sharp Roll-Off Filter",222 "Short Delay Slow Roll-Off Filter"223};224 225static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_digi_fil, DAC_MF, DA1SL_SHIFT, ak4619_dac_digi_fil_txt);226static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_digi_fil, DAC_MF, DA2SL_SHIFT, ak4619_dac_digi_fil_txt);227 228/*229 * Control functions230 */231 232static void ak4619_set_deemph(struct snd_soc_component *component)233{234 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);235 u8 dem = 0;236 237 if (!ak4619->deemph_en)238 return;239 240 switch (ak4619->playback_rate) {241 case 32000:242 dem |= DEM1_32000 | DEM2_32000;243 break;244 case 44100:245 dem |= DEM1_44100 | DEM2_44100;246 break;247 case 48000:248 dem |= DEM1_48000 | DEM2_48000;249 break;250 default:251 dem |= DEM1_OFF | DEM2_OFF;252 break;253 }254 snd_soc_component_update_bits(component, DAC_DEMP, DEM1_MASK | DEM2_MASK, dem);255}256 257static int ak4619_put_deemph(struct snd_kcontrol *kcontrol,258 struct snd_ctl_elem_value *ucontrol)259{260 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);261 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);262 int deemph_en = ucontrol->value.integer.value[0];263 int ret = 0;264 265 switch (deemph_en) {266 case 0:267 case 1:268 break;269 default:270 return -EINVAL;271 }272 273 if (ak4619->deemph_en != deemph_en)274 ret = 1; /* The value changed */275 276 ak4619->deemph_en = deemph_en;277 ak4619_set_deemph(component);278 279 return ret;280}281 282static int ak4619_get_deemph(struct snd_kcontrol *kcontrol,283 struct snd_ctl_elem_value *ucontrol)284{285 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);286 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);287 288 ucontrol->value.integer.value[0] = ak4619->deemph_en;289 290 return 0;291};292 293/*294 * KControls295 */296static const struct snd_kcontrol_new ak4619_snd_controls[] = {297 298 /* Volume controls */299 SOC_DOUBLE_R_TLV("DAC 1 Volume", LDAC1, RDAC1, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv),300 SOC_DOUBLE_R_TLV("DAC 2 Volume", LDAC2, RDAC2, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv),301 SOC_DOUBLE_R_TLV("ADC 1 Volume", LADC1, RADC1, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv),302 SOC_DOUBLE_R_TLV("ADC 2 Volume", LADC2, RADC2, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv),303 304 SOC_DOUBLE_TLV("Mic 1 Volume", MIC_AMP1, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv),305 SOC_DOUBLE_TLV("Mic 2 Volume", MIC_AMP2, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv),306 307 /* Volume Level Transition Time controls */308 SOC_ENUM("ADC Volume Level Transition Time", ak4619_adc_vol_trans),309 SOC_ENUM("DAC Volume Level Transition Time", ak4619_dac_vol_trans),310 311 /* Mute controls */312 SOC_SINGLE("DAC 1 Switch", DAC_MF, DA1MUTE_SHIFT, DA1MUTE_MAX, 1),313 SOC_SINGLE("DAC 2 Switch", DAC_MF, DA2MUTE_SHIFT, DA2MUTE_MAX, 1),314 315 SOC_SINGLE("ADC 1 Switch", ADC_MHPF, AD1MUTE_SHIFT, AD1MUTE_MAX, 1),316 SOC_SINGLE("ADC 2 Switch", ADC_MHPF, AD2MUTE_SHIFT, AD2MUTE_MAX, 1),317 318 /* Filter controls */319 SOC_ENUM("ADC 1 Digital Filter", ak4619_adc_1_digi_fil),320 SOC_ENUM("ADC 2 Digital Filter", ak4619_adc_2_digi_fil),321 322 SOC_SINGLE("ADC 1 HPF", ADC_MHPF, AD1HPFN_SHIFT, AD1HPFN_MAX, 1),323 SOC_SINGLE("ADC 2 HPF", ADC_MHPF, AD2HPFN_SHIFT, AD2HPFN_MAX, 1),324 325 SOC_ENUM("DAC 1 De-Emphasis Filter", ak4619_dac_1_de_emp),326 SOC_ENUM("DAC 2 De-Emphasis Filter", ak4619_dac_2_de_emp),327 328 SOC_ENUM("DAC 1 Digital Filter", ak4619_dac_1_digi_fil),329 SOC_ENUM("DAC 2 Digital Filter", ak4619_dac_2_digi_fil),330 331 SOC_SINGLE_BOOL_EXT("Playback De-Emphasis Switch", 0, ak4619_get_deemph, ak4619_put_deemph),332};333 334/*335 * DAPM336 */337 338/* Analog input mode */339static const char * const ak4619_analog_in_txt[] = {340 "Differential", "Single-Ended1", "Single-Ended2", "Pseudo Differential"341};342 343static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_left_in, ADC_AI, AD1LSEL_SHIFT, ak4619_analog_in_txt);344static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_right_in, ADC_AI, AD1RSEL_SHIFT, ak4619_analog_in_txt);345static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_left_in, ADC_AI, AD2LSEL_SHIFT, ak4619_analog_in_txt);346static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_right_in, ADC_AI, AD2RSEL_SHIFT, ak4619_analog_in_txt);347 348static const struct snd_kcontrol_new ak4619_ad_1_left_in_mux =349 SOC_DAPM_ENUM("Analog Input 1 Left MUX", ak4619_ad_1_left_in);350static const struct snd_kcontrol_new ak4619_ad_1_right_in_mux =351 SOC_DAPM_ENUM("Analog Input 1 Right MUX", ak4619_ad_1_right_in);352static const struct snd_kcontrol_new ak4619_ad_2_left_in_mux =353 SOC_DAPM_ENUM("Analog Input 2 Left MUX", ak4619_ad_2_left_in);354static const struct snd_kcontrol_new ak4619_ad_2_right_in_mux =355 SOC_DAPM_ENUM("Analog Input 2 Right MUX", ak4619_ad_2_right_in);356 357/* DAC source mux */358static const char * const ak4619_dac_in_txt[] = {359 "SDIN1", "SDIN2", "SDOUT1", "SDOUT2"360};361 362static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_in, DAC_IS, DAC1SEL_SHIFT, ak4619_dac_in_txt);363static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_in, DAC_IS, DAC2SEL_SHIFT, ak4619_dac_in_txt);364 365static const struct snd_kcontrol_new ak4619_dac_1_in_mux =366 SOC_DAPM_ENUM("DAC 1 Source MUX", ak4619_dac_1_in);367static const struct snd_kcontrol_new ak4619_dac_2_in_mux =368 SOC_DAPM_ENUM("DAC 2 Source MUX", ak4619_dac_2_in);369 370static const struct snd_soc_dapm_widget ak4619_dapm_widgets[] = {371 372 /* DACs */373 SND_SOC_DAPM_DAC("DAC1", NULL, PWR_MGMT, 1, 0),374 SND_SOC_DAPM_DAC("DAC2", NULL, PWR_MGMT, 2, 0),375 376 /* ADCs */377 SND_SOC_DAPM_ADC("ADC1", NULL, PWR_MGMT, 4, 0),378 SND_SOC_DAPM_ADC("ADC2", NULL, PWR_MGMT, 5, 0),379 380 /* Outputs */381 SND_SOC_DAPM_OUTPUT("AOUT1L"),382 SND_SOC_DAPM_OUTPUT("AOUT2L"),383 384 SND_SOC_DAPM_OUTPUT("AOUT1R"),385 SND_SOC_DAPM_OUTPUT("AOUT2R"),386 387 /* Inputs */388 SND_SOC_DAPM_INPUT("AIN1L"),389 SND_SOC_DAPM_INPUT("AIN2L"),390 SND_SOC_DAPM_INPUT("AIN4L"),391 SND_SOC_DAPM_INPUT("AIN5L"),392 393 SND_SOC_DAPM_INPUT("AIN1R"),394 SND_SOC_DAPM_INPUT("AIN2R"),395 SND_SOC_DAPM_INPUT("AIN4R"),396 SND_SOC_DAPM_INPUT("AIN5R"),397 398 SND_SOC_DAPM_INPUT("MIC1L"),399 SND_SOC_DAPM_INPUT("MIC1R"),400 SND_SOC_DAPM_INPUT("MIC2L"),401 SND_SOC_DAPM_INPUT("MIC2R"),402 403 /* DAI */404 SND_SOC_DAPM_AIF_IN("SDIN1", "Playback", 0, SND_SOC_NOPM, 0, 0),405 SND_SOC_DAPM_AIF_IN("SDIN2", "Playback", 0, SND_SOC_NOPM, 0, 0),406 SND_SOC_DAPM_AIF_OUT("SDOUT1", "Capture", 0, SND_SOC_NOPM, 0, 0),407 SND_SOC_DAPM_AIF_OUT("SDOUT2", "Capture", 0, SND_SOC_NOPM, 0, 0),408 409 /* MUXs for Mic PGA source selection */410 SND_SOC_DAPM_MUX("Analog Input 1 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_left_in_mux),411 SND_SOC_DAPM_MUX("Analog Input 1 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_right_in_mux),412 SND_SOC_DAPM_MUX("Analog Input 2 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_left_in_mux),413 SND_SOC_DAPM_MUX("Analog Input 2 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_right_in_mux),414 415 /* MUXs for DAC source selection */416 SND_SOC_DAPM_MUX("DAC 1 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_1_in_mux),417 SND_SOC_DAPM_MUX("DAC 2 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_2_in_mux),418};419 420static const struct snd_soc_dapm_route ak4619_intercon[] = {421 /* Dest Connecting Widget Source */422 423 /* Output path */424 {"AOUT1L", NULL, "DAC1"},425 {"AOUT2L", NULL, "DAC2"},426 427 {"AOUT1R", NULL, "DAC1"},428 {"AOUT2R", NULL, "DAC2"},429 430 {"DAC1", NULL, "DAC 1 Source MUX"},431 {"DAC2", NULL, "DAC 2 Source MUX"},432 433 {"DAC 1 Source MUX", "SDIN1", "SDIN1"},434 {"DAC 1 Source MUX", "SDIN2", "SDIN2"},435 {"DAC 1 Source MUX", "SDOUT1", "SDOUT1"},436 {"DAC 1 Source MUX", "SDOUT2", "SDOUT2"},437 438 {"DAC 2 Source MUX", "SDIN1", "SDIN1"},439 {"DAC 2 Source MUX", "SDIN2", "SDIN2"},440 {"DAC 2 Source MUX", "SDOUT1", "SDOUT1"},441 {"DAC 2 Source MUX", "SDOUT2", "SDOUT2"},442 443 /* Input path */444 {"SDOUT1", NULL, "ADC1"},445 {"SDOUT2", NULL, "ADC2"},446 447 {"ADC1", NULL, "Analog Input 1 Left MUX"},448 {"ADC1", NULL, "Analog Input 1 Right MUX"},449 450 {"ADC2", NULL, "Analog Input 2 Left MUX"},451 {"ADC2", NULL, "Analog Input 2 Right MUX"},452 453 {"Analog Input 1 Left MUX", "Differential", "MIC1L"},454 {"Analog Input 1 Left MUX", "Single-Ended1", "MIC1L"},455 {"Analog Input 1 Left MUX", "Single-Ended2", "MIC1L"},456 {"Analog Input 1 Left MUX", "Pseudo Differential", "MIC1L"},457 458 {"Analog Input 1 Right MUX", "Differential", "MIC1R"},459 {"Analog Input 1 Right MUX", "Single-Ended1", "MIC1R"},460 {"Analog Input 1 Right MUX", "Single-Ended2", "MIC1R"},461 {"Analog Input 1 Right MUX", "Pseudo Differential", "MIC1R"},462 463 {"Analog Input 2 Left MUX", "Differential", "MIC2L"},464 {"Analog Input 2 Left MUX", "Single-Ended1", "MIC2L"},465 {"Analog Input 2 Left MUX", "Single-Ended2", "MIC2L"},466 {"Analog Input 2 Left MUX", "Pseudo Differential", "MIC2L"},467 468 {"Analog Input 2 Right MUX", "Differential", "MIC2R"},469 {"Analog Input 2 Right MUX", "Single-Ended1", "MIC2R"},470 {"Analog Input 2 Right MUX", "Single-Ended2", "MIC2R"},471 {"Analog Input 2 Right MUX", "Pseudo Differential", "MIC2R"},472 473 {"MIC1L", NULL, "AIN1L"},474 {"MIC1L", NULL, "AIN2L"},475 476 {"MIC1R", NULL, "AIN1R"},477 {"MIC1R", NULL, "AIN2R"},478 479 {"MIC2L", NULL, "AIN4L"},480 {"MIC2L", NULL, "AIN5L"},481 482 {"MIC2R", NULL, "AIN4R"},483 {"MIC2R", NULL, "AIN5R"},484};485 486static const struct reg_default ak4619_reg_defaults[] = {487 { PWR_MGMT, 0x00 },488 { AU_IFF1, 0x0C },489 { AU_IFF2, 0x0C },490 { SYS_CLK, 0x00 },491 { MIC_AMP1, 0x22 },492 { MIC_AMP2, 0x22 },493 { LADC1, 0x30 },494 { RADC1, 0x30 },495 { LADC2, 0x30 },496 { RADC2, 0x30 },497 { ADC_DF, 0x00 },498 { ADC_AI, 0x00 },499 { ADC_MHPF, 0x00 },500 { LDAC1, 0x18 },501 { RDAC1, 0x18 },502 { LDAC2, 0x18 },503 { RDAC2, 0x18 },504 { DAC_IS, 0x04 },505 { DAC_DEMP, 0x05 },506 { DAC_MF, 0x0A },507};508 509static int ak4619_set_bias_level(struct snd_soc_component *component,510 enum snd_soc_bias_level level)511{512 u8 pwr_ctrl = 0;513 514 switch (level) {515 case SND_SOC_BIAS_ON:516 pwr_ctrl |= RSTN;517 fallthrough;518 case SND_SOC_BIAS_PREPARE:519 pwr_ctrl |= PMAD1 | PMAD2 | PMDA1 | PMDA2;520 fallthrough;521 case SND_SOC_BIAS_STANDBY:522 case SND_SOC_BIAS_OFF:523 default:524 break;525 }526 527 snd_soc_component_write(component, PWR_MGMT, pwr_ctrl);528 529 return 0;530}531 532static int ak4619_dai_hw_params(struct snd_pcm_substream *substream,533 struct snd_pcm_hw_params *params,534 struct snd_soc_dai *dai)535{536 struct snd_soc_component *component = dai->component;537 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);538 unsigned int width;539 unsigned int rate;540 unsigned int fs;541 bool is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;542 u8 dai_ctrl = 0;543 u8 clk_mode = 0;544 545 width = params_width(params);546 switch (width) {547 case 16:548 dai_ctrl |= is_play ? DIDL_16 : DODL_16;549 break;550 case 20:551 dai_ctrl |= is_play ? DIDL_20 : DODL_20;552 break;553 case 24:554 dai_ctrl |= is_play ? DIDL_24 : DODL_24;555 break;556 case 32:557 if (is_play)558 dai_ctrl |= DIDL_32;559 else560 return -EINVAL;561 break;562 default:563 return -EINVAL;564 }565 566 rate = params_rate(params);567 if (rate)568 fs = ak4619->sysclk / rate;569 else570 return -EINVAL;571 572 switch (rate) {573 case 8000:574 case 11025:575 case 12000:576 case 16000:577 case 22050:578 case 24000:579 case 32000:580 case 44100:581 case 48000:582 switch (fs) {583 case 256:584 clk_mode |= (0x0 << 0);585 break;586 case 384:587 clk_mode |= (0x2 << 0);588 break;589 case 512:590 clk_mode |= (0x3 << 0);591 break;592 default:593 return -EINVAL;594 }595 break;596 case 64000:597 case 88200:598 case 96000:599 if (fs == 256)600 clk_mode |= (0x1 << 0);601 else602 return -EINVAL;603 break;604 case 176400:605 case 192000:606 if (fs == 128)607 clk_mode |= (0x4 << 0);608 else609 return -EINVAL;610 break;611 default:612 return -EINVAL;613 }614 615 snd_soc_component_update_bits(component, SYS_CLK, FS_MASK, clk_mode);616 snd_soc_component_update_bits(component, AU_IFF2,617 is_play ? DIDL_MASK : DODL_MASK, dai_ctrl);618 619 if (is_play) {620 ak4619->playback_rate = rate;621 ak4619_set_deemph(component);622 }623 624 return 0;625}626 627static int ak4619_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)628{629 struct snd_soc_component *component = dai->component;630 u8 dai_fmt1 = 0;631 u8 dai_fmt2 = 0;632 633 /* Set clock normal/inverted */634 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {635 case SND_SOC_DAIFMT_NB_NF:636 break;637 case SND_SOC_DAIFMT_IB_NF:638 dai_fmt1 |= BCKP;639 break;640 case SND_SOC_DAIFMT_NB_IF:641 case SND_SOC_DAIFMT_IB_IF:642 default:643 return -EINVAL;644 }645 646 /* Only Stereo modes are supported */647 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {648 case SND_SOC_DAIFMT_I2S:649 dai_fmt1 |= DCF_STEREO_I2S;650 break;651 case SND_SOC_DAIFMT_LEFT_J:652 dai_fmt1 |= DCF_STEREO_MSB;653 break;654 case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */655 dai_fmt1 |= DCF_PCM_SF;656 dai_fmt2 |= SLOT;657 break;658 case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */659 dai_fmt1 |= DCF_PCM_LF;660 dai_fmt2 |= SLOT;661 break;662 default:663 return -EINVAL;664 }665 666 /* Only slave mode is support */667 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {668 case SND_SOC_DAIFMT_CBC_CFC:669 break;670 default:671 return -EINVAL;672 }673 674 /* By default only 64 BICK per LRCLK is supported */675 dai_fmt1 |= DSL_32;676 677 snd_soc_component_update_bits(component, AU_IFF1, DCF_MASK |678 DSL_MASK | BCKP, dai_fmt1);679 snd_soc_component_update_bits(component, AU_IFF2, SLOT, dai_fmt2);680 681 return 0;682}683 684static int ak4619_dai_set_sysclk(struct snd_soc_dai *codec_dai,685 int clk_id, unsigned int freq, int dir)686{687 struct snd_soc_component *component = codec_dai->component;688 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);689 690 ak4619->sysclk = freq;691 692 return 0;693}694 695static int ak4619_dai_mute(struct snd_soc_dai *dai, int mute, int direction)696{697 struct snd_soc_component *component = dai->component;698 699 snd_soc_component_update_bits(component, DAC_MF, DA1MUTE_EN, mute ? DA1MUTE_EN : 0);700 snd_soc_component_update_bits(component, DAC_MF, DA2MUTE_EN, mute ? DA2MUTE_EN : 0);701 702 return 0;703}704 705static void ak4619_hw_constraints(struct ak4619_priv *ak4619,706 struct snd_pcm_runtime *runtime)707{708 struct snd_pcm_hw_constraint_list *constraint = &ak4619->constraint;709 int ak4619_rate_mask = 0;710 unsigned int fs;711 int i;712 static const unsigned int ak4619_sr[] = {713 8000,714 11025,715 12000,716 16000,717 22050,718 24000,719 32000,720 44100,721 48000,722 64000,723 88200,724 96000,725 176400,726 192000,727 };728 729 /*730 * [8kHz - 48kHz] : 256fs, 384fs or 512fs731 * [64kHz - 96kHz] : 256fs732 * [176.4kHz, 192kHz] : 128fs733 */734 735 for (i = 0; i < ARRAY_SIZE(ak4619_sr); i++) {736 fs = ak4619->sysclk / ak4619_sr[i];737 738 switch (fs) {739 case 512:740 case 384:741 case 256:742 ak4619_rate_mask |= (1 << i);743 break;744 case 128:745 switch (i) {746 case (ARRAY_SIZE(ak4619_sr) - 1):747 case (ARRAY_SIZE(ak4619_sr) - 2):748 ak4619_rate_mask |= (1 << i);749 break;750 default:751 break;752 }753 break;754 default:755 break;756 }757 }758 759 constraint->list = ak4619_sr;760 constraint->mask = ak4619_rate_mask;761 constraint->count = ARRAY_SIZE(ak4619_sr);762 763 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, constraint);764};765 766#define PLAYBACK_MODE 0767#define CAPTURE_MODE 1768 769static int ak4619_dai_startup(struct snd_pcm_substream *substream,770 struct snd_soc_dai *dai)771{772 struct snd_soc_component *component = dai->component;773 struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component);774 775 ak4619_hw_constraints(ak4619, substream->runtime);776 777 return 0;778}779 780static u64 ak4619_dai_formats[] = {781 /*782 * Select below from Sound Card, not here783 * SND_SOC_DAIFMT_CBC_CFC784 * SND_SOC_DAIFMT_CBP_CFP785 */786 787 /* First Priority */788 SND_SOC_POSSIBLE_DAIFMT_I2S |789 SND_SOC_POSSIBLE_DAIFMT_LEFT_J,790 791 /* Second Priority */792 SND_SOC_POSSIBLE_DAIFMT_DSP_A |793 SND_SOC_POSSIBLE_DAIFMT_DSP_B,794};795 796static const struct snd_soc_dai_ops ak4619_dai_ops = {797 .startup = ak4619_dai_startup,798 .set_sysclk = ak4619_dai_set_sysclk,799 .set_fmt = ak4619_dai_set_fmt,800 .hw_params = ak4619_dai_hw_params,801 .mute_stream = ak4619_dai_mute,802 .auto_selectable_formats = ak4619_dai_formats,803 .num_auto_selectable_formats = ARRAY_SIZE(ak4619_dai_formats),804};805 806static const struct snd_soc_component_driver soc_component_dev_ak4619 = {807 .set_bias_level = ak4619_set_bias_level,808 .controls = ak4619_snd_controls,809 .num_controls = ARRAY_SIZE(ak4619_snd_controls),810 .dapm_widgets = ak4619_dapm_widgets,811 .num_dapm_widgets = ARRAY_SIZE(ak4619_dapm_widgets),812 .dapm_routes = ak4619_intercon,813 .num_dapm_routes = ARRAY_SIZE(ak4619_intercon),814 .idle_bias_on = 1,815 .endianness = 1,816};817 818static const struct regmap_config ak4619_regmap_cfg = {819 .reg_bits = 8,820 .val_bits = 8,821 .max_register = 0x14,822 .reg_defaults = ak4619_reg_defaults,823 .num_reg_defaults = ARRAY_SIZE(ak4619_reg_defaults),824 .cache_type = REGCACHE_MAPLE,825};826 827static const struct of_device_id ak4619_of_match[] = {828 { .compatible = "asahi-kasei,ak4619", .data = &ak4619_regmap_cfg },829 {},830};831MODULE_DEVICE_TABLE(of, ak4619_of_match);832 833static const struct i2c_device_id ak4619_i2c_id[] = {834 { "ak4619", (kernel_ulong_t)&ak4619_regmap_cfg },835 { }836};837MODULE_DEVICE_TABLE(i2c, ak4619_i2c_id);838 839#define AK4619_RATES SNDRV_PCM_RATE_8000_192000840 841#define AK4619_DAC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\842 SNDRV_PCM_FMTBIT_S20_LE |\843 SNDRV_PCM_FMTBIT_S24_LE |\844 SNDRV_PCM_FMTBIT_S32_LE)845 846#define AK4619_ADC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\847 SNDRV_PCM_FMTBIT_S20_LE |\848 SNDRV_PCM_FMTBIT_S24_LE)849 850static struct snd_soc_dai_driver ak4619_dai = {851 .name = "ak4619-hifi",852 .playback = {853 .stream_name = "Playback",854 .channels_min = 1,855 .channels_max = 2,856 .rates = AK4619_RATES,857 .formats = AK4619_DAC_FORMATS,858 },859 .capture = {860 .stream_name = "Capture",861 .channels_min = 1,862 .channels_max = 2,863 .rates = AK4619_RATES,864 .formats = AK4619_ADC_FORMATS,865 },866 .ops = &ak4619_dai_ops,867 .symmetric_rate = 1,868};869 870static int ak4619_i2c_probe(struct i2c_client *i2c)871{872 struct device *dev = &i2c->dev;873 struct ak4619_priv *ak4619;874 int ret;875 876 ak4619 = devm_kzalloc(dev, sizeof(*ak4619), GFP_KERNEL);877 if (!ak4619)878 return -ENOMEM;879 880 i2c_set_clientdata(i2c, ak4619);881 882 ak4619->regmap = devm_regmap_init_i2c(i2c, &ak4619_regmap_cfg);883 if (IS_ERR(ak4619->regmap)) {884 ret = PTR_ERR(ak4619->regmap);885 dev_err(dev, "regmap_init() failed: %d\n", ret);886 return ret;887 }888 889 ret = devm_snd_soc_register_component(dev, &soc_component_dev_ak4619,890 &ak4619_dai, 1);891 if (ret < 0) {892 dev_err(dev, "Failed to register ak4619 component: %d\n",893 ret);894 return ret;895 }896 897 return 0;898}899 900static struct i2c_driver ak4619_i2c_driver = {901 .driver = {902 .name = "ak4619-codec",903 .of_match_table = ak4619_of_match,904 },905 .probe = ak4619_i2c_probe,906 .id_table = ak4619_i2c_id,907};908module_i2c_driver(ak4619_i2c_driver);909 910MODULE_DESCRIPTION("SoC AK4619 driver");911MODULE_AUTHOR("Khanh Le <khanh.le.xr@renesas.com>");912MODULE_LICENSE("GPL v2");913