diff options
Diffstat (limited to 'sound/soc/codecs')
65 files changed, 6275 insertions, 455 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b5e6d0a986c8..7092842480ef 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -157,6 +157,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MC13783 imply SND_SOC_ML26124 imply SND_SOC_MT6351 + imply SND_SOC_MT6357 imply SND_SOC_MT6358 imply SND_SOC_MT6359 imply SND_SOC_MT6660 @@ -2501,6 +2502,12 @@ config SND_SOC_ML26124 config SND_SOC_MT6351 tristate "MediaTek MT6351 Codec" +config SND_SOC_MT6357 + tristate "MediaTek MT6357 Codec" + help + Enable support for the platform which uses MT6357 as + external codec device. + config SND_SOC_MT6358 tristate "MediaTek MT6358 Codec" help diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 622e360f0086..54cbc3feae32 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -177,6 +177,7 @@ snd-soc-ml26124-y := ml26124.o snd-soc-msm8916-analog-y := msm8916-wcd-analog.o snd-soc-msm8916-digital-y := msm8916-wcd-digital.o snd-soc-mt6351-y := mt6351.o +snd-soc-mt6357-y := mt6357.o snd-soc-mt6358-y := mt6358.o snd-soc-mt6359-y := mt6359.o snd-soc-mt6359-accdet-y := mt6359-accdet.o @@ -578,6 +579,7 @@ obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o +obj-$(CONFIG_SND_SOC_MT6357) += snd-soc-mt6357.o obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o obj-$(CONFIG_SND_SOC_MT6359) += snd-soc-mt6359.o obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 551738abd1a5..de9e43185555 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -840,14 +840,14 @@ static void ak4613_parse_of(struct ak4613_priv *priv, /* Input 1 - 2 */ for (i = 0; i < 2; i++) { snprintf(prop, sizeof(prop), "asahi-kasei,in%d-single-end", i + 1); - if (!of_get_property(np, prop, NULL)) + if (!of_property_read_bool(np, prop)) priv->ic |= 1 << i; } /* Output 1 - 6 */ for (i = 0; i < 6; i++) { snprintf(prop, sizeof(prop), "asahi-kasei,out%d-single-end", i + 1); - if (!of_get_property(np, prop, NULL)) + if (!of_property_read_bool(np, prop)) priv->oc |= 1 << i; } diff --git a/sound/soc/codecs/chv3-codec.c b/sound/soc/codecs/chv3-codec.c index ab99effa6874..40020500b1fe 100644 --- a/sound/soc/codecs/chv3-codec.c +++ b/sound/soc/codecs/chv3-codec.c @@ -26,6 +26,7 @@ static const struct of_device_id chv3_codec_of_match[] = { { .compatible = "google,chv3-codec", }, { } }; +MODULE_DEVICE_TABLE(of, chv3_codec_of_match); static struct platform_driver chv3_codec_platform_driver = { .driver = { diff --git a/sound/soc/codecs/cs-amp-lib-test.c b/sound/soc/codecs/cs-amp-lib-test.c index 8169ec88a8ba..a6e8348a1bd5 100644 --- a/sound/soc/codecs/cs-amp-lib-test.c +++ b/sound/soc/codecs/cs-amp-lib-test.c @@ -515,6 +515,49 @@ static void cs_amp_lib_test_get_efi_cal_zero_not_matched_test(struct kunit *test kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); } +/* + * If an entry has a timestamp of 0 it should be ignored even if it has + * a matching target UID. + */ +static void cs_amp_lib_test_get_efi_cal_empty_entry_test(struct kunit *test) +{ + struct cs_amp_lib_test_priv *priv = test->priv; + struct cirrus_amp_cal_data result_data; + u64 uid; + + cs_amp_lib_test_init_dummy_cal_blob(test, 8); + + /* Mark the 3rd entry invalid by zeroing calTime */ + priv->cal_blob->data[2].calTime[0] = 0; + priv->cal_blob->data[2].calTime[1] = 0; + + /* Get the UID value of the 3rd entry */ + uid = priv->cal_blob->data[2].calTarget[1]; + uid <<= 32; + uid |= priv->cal_blob->data[2].calTarget[0]; + + /* Redirect calls to get EFI data */ + kunit_activate_static_stub(test, + cs_amp_test_hooks->get_efi_variable, + cs_amp_lib_test_get_efi_variable); + + /* Lookup by UID should not find it */ + KUNIT_EXPECT_EQ(test, + cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, + uid, -1, + &result_data), + -ENOENT); + + /* Get by index should ignore it */ + KUNIT_EXPECT_EQ(test, + cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, + 0, 2, + &result_data), + -ENOENT); + + kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); +} + static const struct cirrus_amp_cal_controls cs_amp_lib_test_calibration_controls = { .alg_id = 0x9f210, .mem_region = WMFW_ADSP2_YM, @@ -696,6 +739,7 @@ static struct kunit_case cs_amp_lib_test_cases[] = { cs_amp_lib_test_get_cal_gen_params), KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_fallback_test, cs_amp_lib_test_get_cal_gen_params), + KUNIT_CASE(cs_amp_lib_test_get_efi_cal_empty_entry_test), /* Tests for writing calibration data */ KUNIT_CASE(cs_amp_lib_test_write_cal_data_test), diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index e63a518e3b8e..287b27476a10 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -562,26 +562,6 @@ static int cs35l34_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } -static const unsigned int cs35l34_src_rates[] = { - 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 -}; - - -static const struct snd_pcm_hw_constraint_list cs35l34_constraints = { - .count = ARRAY_SIZE(cs35l34_src_rates), - .list = cs35l34_src_rates, -}; - -static int cs35l34_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &cs35l34_constraints); - return 0; -} - - static int cs35l34_set_tristate(struct snd_soc_dai *dai, int tristate) { @@ -639,7 +619,6 @@ static int cs35l34_dai_set_sysclk(struct snd_soc_dai *dai, } static const struct snd_soc_dai_ops cs35l34_ops = { - .startup = cs35l34_pcm_startup, .set_tristate = cs35l34_set_tristate, .set_fmt = cs35l34_set_dai_fmt, .hw_params = cs35l34_pcm_hw_params, diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index cbea79bd8980..b49c6905e872 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -949,32 +949,22 @@ static const struct cs35l36_pll_config *cs35l36_get_clk_config( return NULL; } -static const unsigned int cs35l36_src_rates[] = { - 8000, 12000, 11025, 16000, 22050, 24000, 32000, - 44100, 48000, 88200, 96000, 176400, 192000, 384000 -}; - -static const struct snd_pcm_hw_constraint_list cs35l36_constraints = { - .count = ARRAY_SIZE(cs35l36_src_rates), - .list = cs35l36_src_rates, -}; - -static int cs35l36_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &cs35l36_constraints); - - return 0; -} - static const struct snd_soc_dai_ops cs35l36_ops = { - .startup = cs35l36_pcm_startup, .set_fmt = cs35l36_set_dai_fmt, .hw_params = cs35l36_pcm_hw_params, .set_sysclk = cs35l36_dai_set_sysclk, }; +#define CS35L36_RATES ( \ + SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_12000 | \ + SNDRV_PCM_RATE_24000 | \ + SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | \ + SNDRV_PCM_RATE_192000 | \ + SNDRV_PCM_RATE_384000) + static struct snd_soc_dai_driver cs35l36_dai[] = { { .name = "cs35l36-pcm", @@ -983,14 +973,14 @@ static struct snd_soc_dai_driver cs35l36_dai[] = { .stream_name = "AMP Playback", .channels_min = 1, .channels_max = 8, - .rates = SNDRV_PCM_RATE_KNOT, + .rates = CS35L36_RATES, .formats = CS35L36_RX_FORMATS, }, .capture = { .stream_name = "AMP Capture", .channels_min = 1, .channels_max = 8, - .rates = SNDRV_PCM_RATE_KNOT, + .rates = CS35L36_RATES, .formats = CS35L36_TX_FORMATS, }, .ops = &cs35l36_ops, diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 1688c2c688f0..07a5cab35fe1 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -808,26 +808,6 @@ static int cs35l41_get_clk_config(int freq) return -EINVAL; } -static const unsigned int cs35l41_src_rates[] = { - 8000, 12000, 11025, 16000, 22050, 24000, 32000, - 44100, 48000, 88200, 96000, 176400, 192000 -}; - -static const struct snd_pcm_hw_constraint_list cs35l41_constraints = { - .count = ARRAY_SIZE(cs35l41_src_rates), - .list = cs35l41_src_rates, -}; - -static int cs35l41_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - if (substream->runtime) - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &cs35l41_constraints); - return 0; -} - static int cs35l41_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) @@ -974,13 +954,21 @@ static void cs35l41_component_remove(struct snd_soc_component *component) } static const struct snd_soc_dai_ops cs35l41_ops = { - .startup = cs35l41_pcm_startup, .set_fmt = cs35l41_set_dai_fmt, .hw_params = cs35l41_pcm_hw_params, .set_sysclk = cs35l41_dai_set_sysclk, .set_channel_map = cs35l41_set_channel_map, }; +#define CS35L41_RATES ( \ + SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_12000 | \ + SNDRV_PCM_RATE_24000 | \ + SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | \ + SNDRV_PCM_RATE_192000) + static struct snd_soc_dai_driver cs35l41_dai[] = { { .name = "cs35l41-pcm", @@ -989,14 +977,14 @@ static struct snd_soc_dai_driver cs35l41_dai[] = { .stream_name = "AMP Playback", .channels_min = 1, .channels_max = 2, - .rates = SNDRV_PCM_RATE_KNOT, + .rates = CS35L41_RATES, .formats = CS35L41_RX_FORMATS, }, .capture = { .stream_name = "AMP Capture", .channels_min = 1, .channels_max = 4, - .rates = SNDRV_PCM_RATE_KNOT, + .rates = CS35L41_RATES, .formats = CS35L41_TX_FORMATS, }, .ops = &cs35l41_ops, diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 1e9d73bee3b4..fa1d9d9151f9 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -177,7 +177,7 @@ static int cs35l45_activate_ctl(struct snd_soc_component *component, struct snd_kcontrol_volatile *vd; unsigned int index_offset; - kcontrol = snd_soc_component_get_kcontrol_locked(component, ctl_name); + kcontrol = snd_soc_component_get_kcontrol(component, ctl_name); if (!kcontrol) { dev_err(component->dev, "Can't find kcontrol %s\n", ctl_name); return -EINVAL; diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index bd74fef33d49..e45e9ae01bc6 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -451,32 +451,23 @@ static const struct reg_sequence cs35l56_hibernate_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE), }; -static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { - REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), -}; - static void cs35l56_issue_wake_event(struct cs35l56_base *cs35l56_base) { + unsigned int val; + /* * Dummy transactions to trigger I2C/SPI auto-wake. Issue two * transactions to meet the minimum required time from the rising edge * to the last falling edge of wake. * - * It uses bypassed write because we must wake the chip before + * It uses bypassed read because we must wake the chip before * disabling regmap cache-only. - * - * This can NAK on I2C which will terminate the write sequence so the - * single-write sequence is issued twice. */ - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_hibernate_wake_seq, - ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); usleep_range(CS35L56_WAKE_HOLD_TIME_US, 2 * CS35L56_WAKE_HOLD_TIME_US); - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_hibernate_wake_seq, - ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); cs35l56_wait_control_port_ready(); } @@ -925,7 +916,7 @@ const unsigned int cs35l56_tx_input_values[] = { }; EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED); -struct regmap_config cs35l56_regmap_i2c = { +const struct regmap_config cs35l56_regmap_i2c = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, @@ -941,7 +932,7 @@ struct regmap_config cs35l56_regmap_i2c = { }; EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED); -struct regmap_config cs35l56_regmap_spi = { +const struct regmap_config cs35l56_regmap_spi = { .reg_bits = 32, .val_bits = 32, .pad_bits = 16, @@ -958,7 +949,7 @@ struct regmap_config cs35l56_regmap_spi = { }; EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED); -struct regmap_config cs35l56_regmap_sdw = { +const struct regmap_config cs35l56_regmap_sdw = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index 94a66a325303..29891c1f6bec 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -323,15 +323,15 @@ static int cs42l42_sdw_read_prop(struct sdw_slave *peripheral) prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; /* DP1 - capture */ - ports[0].num = CS42L42_SDW_CAPTURE_PORT, - ports[0].type = SDW_DPN_FULL, - ports[0].ch_prep_timeout = 10, + ports[0].num = CS42L42_SDW_CAPTURE_PORT; + ports[0].type = SDW_DPN_FULL; + ports[0].ch_prep_timeout = 10; prop->src_dpn_prop = &ports[0]; /* DP2 - playback */ - ports[1].num = CS42L42_SDW_PLAYBACK_PORT, - ports[1].type = SDW_DPN_FULL, - ports[1].ch_prep_timeout = 10, + ports[1].num = CS42L42_SDW_PLAYBACK_PORT; + ports[1].type = SDW_DPN_FULL; + ports[1].ch_prep_timeout = 10; prop->sink_dpn_prop = &ports[1]; return 0; diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index 5183b4586424..d0098b4558b5 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2461,7 +2461,7 @@ static struct platform_driver cs42l43_codec_driver = { }, .probe = cs42l43_codec_probe, - .remove_new = cs42l43_codec_remove, + .remove = cs42l43_codec_remove, .id_table = cs42l43_codec_id_table, }; module_platform_driver(cs42l43_codec_driver); diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index be4037890fdb..f8e2fb69ada2 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -1415,7 +1415,7 @@ static const char * const bypass_mux_text[] = { static SOC_ENUM_SINGLE_DECL(bypass_enum, SND_SOC_NOPM, 0, bypass_mux_text); static const struct snd_kcontrol_new bypass_ctrl = SOC_DAPM_ENUM("Switch", bypass_enum); -static const struct snd_soc_dapm_widget digital_hp_widgets[] = { +static const struct snd_soc_dapm_widget hp_widgets[] = { SND_SOC_DAPM_MUX("Bypass Switch", SND_SOC_NOPM, 0, 0, &bypass_ctrl), SND_SOC_DAPM_OUTPUT("HPOUTA"), SND_SOC_DAPM_OUTPUT("HPOUTB"), @@ -1447,19 +1447,16 @@ static const struct snd_soc_dapm_widget digital_hp_widgets[] = { CS43130_PDN_HP_SHIFT, 1, cs43130_dac_event, (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD)), -}; -static const struct snd_soc_dapm_widget analog_hp_widgets[] = { +/* Some devices have some extra analog widgets */ +#define NUM_ANALOG_WIDGETS 1 + SND_SOC_DAPM_DAC_E("Analog Playback", NULL, CS43130_HP_OUT_CTL_1, CS43130_HP_IN_EN_SHIFT, 0, cs43130_hpin_event, (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)), }; -static struct snd_soc_dapm_widget all_hp_widgets[ - ARRAY_SIZE(digital_hp_widgets) + - ARRAY_SIZE(analog_hp_widgets)]; - -static const struct snd_soc_dapm_route digital_hp_routes[] = { +static const struct snd_soc_dapm_route hp_routes[] = { {"ASPIN PCM", NULL, "ASP PCM Playback"}, {"ASPIN DoP", NULL, "ASP DoP Playback"}, {"XSPIN DoP", NULL, "XSP DoP Playback"}, @@ -1472,15 +1469,12 @@ static const struct snd_soc_dapm_route digital_hp_routes[] = { {"Bypass Switch", "Internal", "HiFi DAC"}, {"HPOUTA", NULL, "Bypass Switch"}, {"HPOUTB", NULL, "Bypass Switch"}, -}; -static const struct snd_soc_dapm_route analog_hp_routes[] = { +/* Some devices have some extra analog routes */ +#define NUM_ANALOG_ROUTES 1 {"Bypass Switch", "Alternative", "Analog Playback"}, }; -static struct snd_soc_dapm_route all_hp_routes[ - ARRAY_SIZE(digital_hp_routes) + - ARRAY_SIZE(analog_hp_routes)]; static const unsigned int cs43130_asp_src_rates[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 @@ -1811,7 +1805,7 @@ static struct attribute *hpload_attrs[] = { }; ATTRIBUTE_GROUPS(hpload); -static struct reg_sequence hp_en_cal_seq[] = { +static const struct reg_sequence hp_en_cal_seq[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, @@ -1826,7 +1820,7 @@ static struct reg_sequence hp_en_cal_seq[] = { {CS43130_HP_LOAD_1, 0x80}, }; -static struct reg_sequence hp_en_cal_seq2[] = { +static const struct reg_sequence hp_en_cal_seq2[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, @@ -1834,7 +1828,7 @@ static struct reg_sequence hp_en_cal_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, }; -static struct reg_sequence hp_dis_cal_seq[] = { +static const struct reg_sequence hp_dis_cal_seq[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_DXD1, 0x99}, {CS43130_DXD12, 0}, @@ -1842,12 +1836,12 @@ static struct reg_sequence hp_dis_cal_seq[] = { {CS43130_HP_LOAD_1, 0}, }; -static struct reg_sequence hp_dis_cal_seq2[] = { +static const struct reg_sequence hp_dis_cal_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0}, }; -static struct reg_sequence hp_dc_ch_l_seq[] = { +static const struct reg_sequence hp_dc_ch_l_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x0A}, {CS43130_DXD17, 0x93}, @@ -1857,12 +1851,12 @@ static struct reg_sequence hp_dc_ch_l_seq[] = { {CS43130_HP_LOAD_1, 0x81}, }; -static struct reg_sequence hp_dc_ch_l_seq2[] = { +static const struct reg_sequence hp_dc_ch_l_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0x81}, }; -static struct reg_sequence hp_dc_ch_r_seq[] = { +static const struct reg_sequence hp_dc_ch_r_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x8A}, {CS43130_DXD17, 0x15}, @@ -1872,12 +1866,12 @@ static struct reg_sequence hp_dc_ch_r_seq[] = { {CS43130_HP_LOAD_1, 0x91}, }; -static struct reg_sequence hp_dc_ch_r_seq2[] = { +static const struct reg_sequence hp_dc_ch_r_seq2[] = { {CS43130_HP_LOAD_1, 0x90}, {CS43130_HP_LOAD_1, 0x91}, }; -static struct reg_sequence hp_ac_ch_l_seq[] = { +static const struct reg_sequence hp_ac_ch_l_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x0A}, {CS43130_DXD17, 0x93}, @@ -1887,12 +1881,12 @@ static struct reg_sequence hp_ac_ch_l_seq[] = { {CS43130_HP_LOAD_1, 0x82}, }; -static struct reg_sequence hp_ac_ch_l_seq2[] = { +static const struct reg_sequence hp_ac_ch_l_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0x82}, }; -static struct reg_sequence hp_ac_ch_r_seq[] = { +static const struct reg_sequence hp_ac_ch_r_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x8A}, {CS43130_DXD17, 0x15}, @@ -1902,24 +1896,24 @@ static struct reg_sequence hp_ac_ch_r_seq[] = { {CS43130_HP_LOAD_1, 0x92}, }; -static struct reg_sequence hp_ac_ch_r_seq2[] = { +static const struct reg_sequence hp_ac_ch_r_seq2[] = { {CS43130_HP_LOAD_1, 0x90}, {CS43130_HP_LOAD_1, 0x92}, }; -static struct reg_sequence hp_cln_seq[] = { +static const struct reg_sequence hp_cln_seq[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, }; struct reg_sequences { - struct reg_sequence *seq; - int size; - unsigned int msk; + const struct reg_sequence *seq; + int size; + unsigned int msk; }; -static struct reg_sequences hpload_seq1[] = { +static const struct reg_sequences hpload_seq1[] = { { .seq = hp_en_cal_seq, .size = ARRAY_SIZE(hp_en_cal_seq), @@ -1957,7 +1951,7 @@ static struct reg_sequences hpload_seq1[] = { }, }; -static struct reg_sequences hpload_seq2[] = { +static const struct reg_sequences hpload_seq2[] = { { .seq = hp_en_cal_seq2, .size = ARRAY_SIZE(hp_en_cal_seq2), @@ -2047,7 +2041,7 @@ static int cs43130_update_hpload(unsigned int msk, int ac_idx, } static int cs43130_hpload_proc(struct cs43130_private *cs43130, - struct reg_sequence *seq, int seq_size, + const struct reg_sequence *seq, int seq_size, unsigned int rslt_msk, int ac_idx) { int ret; @@ -2128,7 +2122,7 @@ static void cs43130_imp_meas(struct work_struct *wk) int i, ret, ac_idx; struct cs43130_private *cs43130; struct snd_soc_component *component; - struct reg_sequences *hpload_seq; + const struct reg_sequences *hpload_seq; cs43130 = container_of(wk, struct cs43130_private, work); component = cs43130->component; @@ -2398,7 +2392,23 @@ static int cs43130_probe(struct snd_soc_component *component) return 0; } -static struct snd_soc_component_driver soc_component_dev_cs43130 = { +static const struct snd_soc_component_driver soc_component_dev_cs43130_digital = { + .probe = cs43130_probe, + .controls = cs43130_snd_controls, + .num_controls = ARRAY_SIZE(cs43130_snd_controls), + .set_sysclk = cs43130_component_set_sysclk, + .set_pll = cs43130_set_pll, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + /* Don't take into account the ending analog widgets and routes */ + .dapm_widgets = hp_widgets, + .num_dapm_widgets = ARRAY_SIZE(hp_widgets) - NUM_ANALOG_WIDGETS, + .dapm_routes = hp_routes, + .num_dapm_routes = ARRAY_SIZE(hp_routes) - NUM_ANALOG_ROUTES, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs43130_analog = { .probe = cs43130_probe, .controls = cs43130_snd_controls, .num_controls = ARRAY_SIZE(cs43130_snd_controls), @@ -2407,6 +2417,10 @@ static struct snd_soc_component_driver soc_component_dev_cs43130 = { .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, + .dapm_widgets = hp_widgets, + .num_dapm_widgets = ARRAY_SIZE(hp_widgets), + .dapm_routes = hp_routes, + .num_dapm_routes = ARRAY_SIZE(hp_routes), }; static const struct regmap_config cs43130_regmap = { @@ -2479,6 +2493,7 @@ static int cs43130_handle_device_data(struct cs43130_private *cs43130) static int cs43130_i2c_probe(struct i2c_client *client) { + const struct snd_soc_component_driver *component_driver; struct cs43130_private *cs43130; int ret; unsigned int reg; @@ -2596,39 +2611,15 @@ static int cs43130_i2c_probe(struct i2c_client *client) switch (cs43130->dev_id) { case CS43130_CHIP_ID: case CS43131_CHIP_ID: - memcpy(all_hp_widgets, digital_hp_widgets, - sizeof(digital_hp_widgets)); - memcpy(all_hp_widgets + ARRAY_SIZE(digital_hp_widgets), - analog_hp_widgets, sizeof(analog_hp_widgets)); - memcpy(all_hp_routes, digital_hp_routes, - sizeof(digital_hp_routes)); - memcpy(all_hp_routes + ARRAY_SIZE(digital_hp_routes), - analog_hp_routes, sizeof(analog_hp_routes)); - - soc_component_dev_cs43130.dapm_widgets = - all_hp_widgets; - soc_component_dev_cs43130.num_dapm_widgets = - ARRAY_SIZE(all_hp_widgets); - soc_component_dev_cs43130.dapm_routes = - all_hp_routes; - soc_component_dev_cs43130.num_dapm_routes = - ARRAY_SIZE(all_hp_routes); + component_driver = &soc_component_dev_cs43130_analog; break; case CS43198_CHIP_ID: case CS4399_CHIP_ID: - soc_component_dev_cs43130.dapm_widgets = - digital_hp_widgets; - soc_component_dev_cs43130.num_dapm_widgets = - ARRAY_SIZE(digital_hp_widgets); - soc_component_dev_cs43130.dapm_routes = - digital_hp_routes; - soc_component_dev_cs43130.num_dapm_routes = - ARRAY_SIZE(digital_hp_routes); + component_driver = &soc_component_dev_cs43130_digital; break; } - ret = devm_snd_soc_register_component(cs43130->dev, - &soc_component_dev_cs43130, + ret = devm_snd_soc_register_component(cs43130->dev, component_driver, cs43130_dai, ARRAY_SIZE(cs43130_dai)); if (ret < 0) { dev_err(cs43130->dev, diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index ab6e7cd99733..29a2bcfb3048 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -1493,7 +1493,7 @@ static struct platform_driver cs47l15_codec_driver = { .name = "cs47l15-codec", }, .probe = &cs47l15_probe, - .remove_new = cs47l15_remove, + .remove = cs47l15_remove, }; module_platform_driver(cs47l15_codec_driver); diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index ec405ef66a8e..e2a839fae4fc 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1344,7 +1344,7 @@ static struct platform_driver cs47l24_codec_driver = { .name = "cs47l24-codec", }, .probe = cs47l24_probe, - .remove_new = cs47l24_remove, + .remove = cs47l24_remove, }; module_platform_driver(cs47l24_codec_driver); diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index 0d7ee7ea6257..85555c7a2e4b 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -1769,7 +1769,7 @@ static struct platform_driver cs47l35_codec_driver = { .name = "cs47l35-codec", }, .probe = &cs47l35_probe, - .remove_new = cs47l35_remove, + .remove = cs47l35_remove, }; module_platform_driver(cs47l35_codec_driver); diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 2dfb867e6edd..d34f4e8c26d3 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -2720,7 +2720,7 @@ static struct platform_driver cs47l85_codec_driver = { .name = "cs47l85-codec", }, .probe = &cs47l85_probe, - .remove_new = cs47l85_remove, + .remove = cs47l85_remove, }; module_platform_driver(cs47l85_codec_driver); diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 2549cb1fc121..a9e703981f37 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -2644,7 +2644,7 @@ static struct platform_driver cs47l90_codec_driver = { .name = "cs47l90-codec", }, .probe = &cs47l90_probe, - .remove_new = cs47l90_remove, + .remove = cs47l90_remove, }; module_platform_driver(cs47l90_codec_driver); diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 0c05ae0b09fb..2c355c61acd8 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -2092,7 +2092,7 @@ static struct platform_driver cs47l92_codec_driver = { .name = "cs47l92-codec", }, .probe = &cs47l92_probe, - .remove_new = cs47l92_remove, + .remove = cs47l92_remove, }; module_platform_driver(cs47l92_codec_driver); diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index bcbaf28a0b2d..28f4be37dec1 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -739,24 +739,6 @@ static int cs53l30_set_tristate(struct snd_soc_dai *dai, int tristate) CS53L30_ASP_3ST_MASK, val); } -static unsigned int const cs53l30_src_rates[] = { - 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 -}; - -static const struct snd_pcm_hw_constraint_list src_constraints = { - .count = ARRAY_SIZE(cs53l30_src_rates), - .list = cs53l30_src_rates, -}; - -static int cs53l30_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &src_constraints); - - return 0; -} - /* * Note: CS53L30 counts the slot number per byte while ASoC counts the slot * number per slot_width. So there is a difference between the slots of ASoC @@ -843,14 +825,14 @@ static int cs53l30_mute_stream(struct snd_soc_dai *dai, int mute, int stream) return 0; } -/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ -#define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) +#define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_12000 | \ + SNDRV_PCM_RATE_24000) #define CS53L30_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) static const struct snd_soc_dai_ops cs53l30_ops = { - .startup = cs53l30_pcm_startup, .hw_params = cs53l30_pcm_hw_params, .set_fmt = cs53l30_set_dai_fmt, .set_sysclk = cs53l30_set_sysclk, diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index be3c79232a31..d5362b3be484 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -805,6 +805,7 @@ static void es8326_jack_button_handler(struct work_struct *work) SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); button_to_report = 0; } + es8326_disable_micbias(es8326->component); } mutex_unlock(&es8326->lock); } @@ -880,7 +881,6 @@ static void es8326_jack_detect_handler(struct work_struct *work) regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00); - es8326_enable_micbias(es8326->component); usleep_range(50000, 70000); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10); @@ -899,6 +899,7 @@ static void es8326_jack_detect_handler(struct work_struct *work) dev_dbg(comp->dev, "button pressed\n"); regmap_write(es8326->regmap, ES8326_INT_SOURCE, (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); + es8326_enable_micbias(es8326->component); queue_delayed_work(system_wq, &es8326->button_press_work, 10); goto exit; } @@ -1069,6 +1070,9 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); regmap_write(es8326->regmap, ES8326_CLK_DIV_LRCK, 0xff); + regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44); + regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); + es8326_disable_micbias(es8326->component); msleep(200); regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 11320423c69c..fdd19f8e8864 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -476,7 +476,7 @@ static struct platform_driver rk3036_codec_platform_driver = { .of_match_table = of_match_ptr(rk3036_codec_of_match), }, .probe = rk3036_codec_platform_probe, - .remove_new = rk3036_codec_platform_remove, + .remove = rk3036_codec_platform_remove, }; module_platform_driver(rk3036_codec_platform_driver); diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index ce42749660c8..71e0d3bffd3f 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -4024,7 +4024,7 @@ static struct platform_driver rx_macro_driver = { .pm = &rx_macro_pm_ops, }, .probe = rx_macro_probe, - .remove_new = rx_macro_remove, + .remove = rx_macro_remove, }; module_platform_driver(rx_macro_driver); diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 209c12ec16dd..a134584acf90 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2534,7 +2534,7 @@ static struct platform_driver tx_macro_driver = { .pm = &tx_macro_pm_ops, }, .probe = tx_macro_probe, - .remove_new = tx_macro_remove, + .remove = tx_macro_remove, }; module_platform_driver(tx_macro_driver); diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 8454193ed22a..c781da476240 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -228,11 +228,13 @@ struct va_macro { struct va_macro_data { bool has_swr_master; bool has_npl_clk; + int version; }; static const struct va_macro_data sm8250_va_data = { .has_swr_master = false, .has_npl_clk = false, + .version = LPASS_CODEC_VERSION_1_0, }; static const struct va_macro_data sm8450_va_data = { @@ -1587,7 +1589,14 @@ static int va_macro_probe(struct platform_device *pdev) goto err_npl; } - va_macro_set_lpass_codec_version(va); + /** + * old version of codecs do not have a reliable way to determine the + * version from registers, get them from soc specific data + */ + if (data->version) + lpass_macro_set_codec_version(data->version); + else /* read version from register */ + va_macro_set_lpass_codec_version(va); if (va->has_swr_master) { /* Set default CLK div to 1 */ @@ -1729,7 +1738,7 @@ static struct platform_driver va_macro_driver = { .pm = &va_macro_pm_ops, }, .probe = va_macro_probe, - .remove_new = va_macro_remove, + .remove = va_macro_remove, }; module_platform_driver(va_macro_driver); diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 73a588289408..c989d82d1d3c 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2297,36 +2297,37 @@ static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol, struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); u32 enable = ucontrol->value.integer.value[0]; u32 spk_tx_id = mixer->shift; + u32 dai_id = widget->shift; if (enable) { if (spk_tx_id == WSA_MACRO_TX0 && !test_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { set_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]++; } if (spk_tx_id == WSA_MACRO_TX1 && !test_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { set_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]++; } } else { if (spk_tx_id == WSA_MACRO_TX0 && test_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { clear_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]--; } if (spk_tx_id == WSA_MACRO_TX1 && test_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { clear_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]--; } } snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL); @@ -2979,7 +2980,7 @@ static struct platform_driver wsa_macro_driver = { .pm = &wsa_macro_pm_ops, }, .probe = wsa_macro_probe, - .remove_new = wsa_macro_remove, + .remove = wsa_macro_remove, }; module_platform_driver(wsa_macro_driver); diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 978c4d056e81..ebb6f2e84818 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -1241,7 +1241,7 @@ static struct platform_driver msm8916_wcd_digital_driver = { .of_match_table = msm8916_wcd_digital_match_table, }, .probe = msm8916_wcd_digital_probe, - .remove_new = msm8916_wcd_digital_remove, + .remove = msm8916_wcd_digital_remove, }; module_platform_driver(msm8916_wcd_digital_driver); diff --git a/sound/soc/codecs/mt6357.c b/sound/soc/codecs/mt6357.c new file mode 100644 index 000000000000..988728df15e4 --- /dev/null +++ b/sound/soc/codecs/mt6357.c @@ -0,0 +1,1855 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MT6357 ALSA SoC audio codec driver + * + * Copyright (c) 2024 Baylibre + * Author: Nicolas Belin <nbelin@baylibre.com> + */ + +#include <linux/dma-mapping.h> +#include <sound/soc.h> +#include <sound/tlv.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/regulator/consumer.h> + +#include "mt6357.h" + +static void set_playback_gpio(struct mt6357_priv *priv, bool enable) +{ + regmap_write(priv->regmap, MT6357_GPIO_MODE2_CLR, MT6357_GPIO_MODE2_CLEAR_ALL); + if (enable) { + /* set gpio mosi mode */ + regmap_write(priv->regmap, MT6357_GPIO_MODE2_SET, + MT6357_GPIO8_MODE_SET_AUD_CLK_MOSI | + MT6357_GPIO9_MODE_SET_AUD_DAT_MOSI0 | + MT6357_GPIO10_MODE_SET_AUD_DAT_MOSI1 | + MT6357_GPIO11_MODE_SET_AUD_SYNC_MOSI); + } else { + /* pad_aud_*_mosi are GPIO mode after clear and set them to dir input + * reason: + * pad_aud_dat_mosi*, because the pin is used as boot strap + */ + regmap_update_bits(priv->regmap, MT6357_GPIO_DIR0, + MT6357_GPIO8_DIR_MASK | + MT6357_GPIO9_DIR_MASK | + MT6357_GPIO10_DIR_MASK | + MT6357_GPIO11_DIR_MASK, + MT6357_GPIO8_DIR_INPUT | + MT6357_GPIO9_DIR_INPUT | + MT6357_GPIO10_DIR_INPUT | + MT6357_GPIO11_DIR_INPUT); + } +} + +static void set_capture_gpio(struct mt6357_priv *priv, bool enable) +{ + regmap_write(priv->regmap, MT6357_GPIO_MODE3_CLR, MT6357_GPIO_MODE3_CLEAR_ALL); + if (enable) { + /* set gpio miso mode */ + regmap_write(priv->regmap, MT6357_GPIO_MODE3_SET, + MT6357_GPIO12_MODE_SET_AUD_CLK_MISO | + MT6357_GPIO13_MODE_SET_AUD_DAT_MISO0 | + MT6357_GPIO14_MODE_SET_AUD_DAT_MISO1 | + MT6357_GPIO15_MODE_SET_AUD_SYNC_MISO); + } else { + /* pad_aud_*_mosi are GPIO mode after clear and set them to dir input + * reason: + * pad_aud_clk_miso, because when playback only the miso_clk + * will also have 26m, so will have power leak + * pad_aud_dat_miso*, because the pin is used as boot strap + */ + regmap_update_bits(priv->regmap, MT6357_GPIO_DIR0, + MT6357_GPIO12_DIR_MASK | + MT6357_GPIO13_DIR_MASK | + MT6357_GPIO14_DIR_MASK | + MT6357_GPIO15_DIR_MASK, + MT6357_GPIO12_DIR_INPUT | + MT6357_GPIO13_DIR_INPUT | + MT6357_GPIO14_DIR_INPUT | + MT6357_GPIO15_DIR_INPUT); + } +} + +static void hp_main_output_ramp(struct mt6357_priv *priv, bool up) +{ + int i, stage; + + /* Enable/Reduce HPL/R main output stage step by step */ + for (i = 0; i <= MT6357_HPLOUT_STG_CTRL_VAUDP15_MAX; i++) { + stage = up ? i : MT6357_HPLOUT_STG_CTRL_VAUDP15_MAX - i; + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPLOUT_STG_CTRL_VAUDP15_MASK, + stage << MT6357_HPLOUT_STG_CTRL_VAUDP15_SFT); + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_STG_CTRL_VAUDP15_MASK, + stage << MT6357_HPROUT_STG_CTRL_VAUDP15_SFT); + usleep_range(600, 700); + } +} + +static void hp_aux_feedback_loop_gain_ramp(struct mt6357_priv *priv, bool up) +{ + int i, stage; + + /* Reduce HP aux feedback loop gain step by step */ + for (i = 0; i <= MT6357_HP_AUX_LOOP_GAIN_MAX; i++) { + stage = up ? i : MT6357_HP_AUX_LOOP_GAIN_MAX - i; + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HP_AUX_LOOP_GAIN_MASK, + stage << MT6357_HP_AUX_LOOP_GAIN_SFT); + usleep_range(600, 700); + } +} + +static void hp_pull_down(struct mt6357_priv *priv, bool enable) +{ + if (enable) + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON2, + MT6357_HPP_SHORT_2VCM_VAUDP15_MASK, + MT6357_HPP_SHORT_2VCM_VAUDP15_ENABLE); + else + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON2, + MT6357_HPP_SHORT_2VCM_VAUDP15_MASK, + MT6357_HPP_SHORT_2VCM_VAUDP15_DISABLE); +} + +static bool is_valid_hp_pga_idx(int reg_idx) +{ + return (reg_idx >= DL_GAIN_8DB && reg_idx <= DL_GAIN_N_12DB) || reg_idx == DL_GAIN_N_40DB; +} + +static void volume_ramp(struct mt6357_priv *priv, int lfrom, int lto, + int rfrom, int rto, unsigned int reg_addr) +{ + int lcount, rcount, sleep = 0; + + if (!is_valid_hp_pga_idx(lfrom) || !is_valid_hp_pga_idx(lto)) + pr_debug("%s(), invalid left volume index, from %d, to %d\n", + __func__, lfrom, lto); + + if (!is_valid_hp_pga_idx(rfrom) || !is_valid_hp_pga_idx(rto)) + pr_debug("%s(), invalid right volume index, from %d, to %d\n", + __func__, rfrom, rto); + + if (lto > lfrom) + lcount = 1; + else + lcount = -1; + + if (rto > rfrom) + rcount = 1; + else + rcount = -1; + + while ((lto != lfrom) || (rto != rfrom)) { + if (lto != lfrom) { + lfrom += lcount; + if (is_valid_hp_pga_idx(lfrom)) { + regmap_update_bits(priv->regmap, reg_addr, + MT6357_DL_GAIN_REG_LEFT_MASK, + lfrom << MT6357_DL_GAIN_REG_LEFT_SHIFT); + sleep = 1; + } + } + if (rto != rfrom) { + rfrom += rcount; + if (is_valid_hp_pga_idx(rfrom)) { + regmap_update_bits(priv->regmap, reg_addr, + MT6357_DL_GAIN_REG_RIGHT_MASK, + rfrom << MT6357_DL_GAIN_REG_RIGHT_SHIFT); + sleep = 1; + } + } + if (sleep) + usleep_range(200, 300); + } +} + +static void lo_volume_ramp(struct mt6357_priv *priv, int lfrom, int lto, int rfrom, int rto) +{ + volume_ramp(priv, lfrom, lto, rfrom, rto, MT6357_ZCD_CON1); +} + +static void hp_volume_ramp(struct mt6357_priv *priv, int lfrom, int lto, int rfrom, int rto) +{ + volume_ramp(priv, lfrom, lto, rfrom, rto, MT6357_ZCD_CON2); +} + +static void hs_volume_ramp(struct mt6357_priv *priv, int from, int to) +{ + volume_ramp(priv, from, to, 0, 0, MT6357_ZCD_CON3); +} + +/* Volume and channel swap controls */ +static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0); +static const DECLARE_TLV_DB_SCALE(capture_tlv, 0, 600, 0); +static const DECLARE_TLV_DB_SCALE(hp_degain_tlv, -1200, 1200, 0); + +static const struct snd_kcontrol_new mt6357_controls[] = { + /* dl pga gain */ + SOC_DOUBLE_TLV("Headphone Volume", + MT6357_ZCD_CON2, MT6357_AUD_HPL_GAIN_SFT, + MT6357_AUD_HPR_GAIN_SFT, MT6357_AUD_HP_GAIN_MAX, + 1, playback_tlv), + SOC_SINGLE_TLV("Headphone Vin Volume", + MT6357_AUDDEC_ANA_CON7, MT6357_HP_IVBUF_DEGAIN_SFT, + MT6357_HP_IVBUF_DEGAIN_MAX, 1, hp_degain_tlv), + SOC_DOUBLE_TLV("Lineout Volume", + MT6357_ZCD_CON1, MT6357_AUD_LOL_GAIN_SFT, + MT6357_AUD_LOR_GAIN_SFT, MT6357_AUD_LO_GAIN_MAX, + 1, playback_tlv), + SOC_SINGLE_TLV("Handset Volume", + MT6357_ZCD_CON3, MT6357_AUD_HS_GAIN_SFT, + MT6357_AUD_HS_GAIN_MAX, 1, playback_tlv), + /* ul pga gain */ + SOC_DOUBLE_R_TLV("Mic Volume", + MT6357_AUDENC_ANA_CON0, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPLGAIN_SFT, MT6357_AUDPREAMPLGAIN_MAX, + 0, capture_tlv), +}; + +/* Uplink controls */ + +enum { + MIC_TYPE_MUX_IDLE, + MIC_TYPE_MUX_ACC, + MIC_TYPE_MUX_DMIC, + MIC_TYPE_MUX_DCC, + MIC_TYPE_MUX_DCC_ECM_DIFF, + MIC_TYPE_MUX_DCC_ECM_SINGLE, + MIC_TYPE_MUX_LPBK, + MIC_TYPE_MUX_SGEN, +}; + +#define IS_DCC_BASE(type) ((type) == MIC_TYPE_MUX_DCC || \ + (type) == MIC_TYPE_MUX_DCC_ECM_DIFF || \ + (type) == MIC_TYPE_MUX_DCC_ECM_SINGLE) + +static const char * const mic_type_mux_map[] = { + "Idle", + "ACC", + "DMIC", + "DCC", + "DCC_ECM_DIFF", + "DCC_ECM_SINGLE", + "Loopback", + "Sine Generator", +}; + +static SOC_ENUM_SINGLE_DECL(mic_type_mux_map_enum, SND_SOC_NOPM, + 0, mic_type_mux_map); + +static const struct snd_kcontrol_new mic_type_mux_control = + SOC_DAPM_ENUM("Mic Type Select", mic_type_mux_map_enum); + +static const char * const pga_mux_map[] = { + "None", "AIN0", "AIN1", "AIN2" +}; + +static SOC_ENUM_SINGLE_DECL(pga_left_mux_map_enum, + MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLINPUTSEL_SFT, + pga_mux_map); + +static const struct snd_kcontrol_new pga_left_mux_control = + SOC_DAPM_ENUM("PGA L Select", pga_left_mux_map_enum); + +static SOC_ENUM_SINGLE_DECL(pga_right_mux_map_enum, + MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRINPUTSEL_SFT, + pga_mux_map); + +static const struct snd_kcontrol_new pga_right_mux_control = + SOC_DAPM_ENUM("PGA R Select", pga_right_mux_map_enum); + +/* Downlink controls */ +static const char * const hslo_mux_map[] = { + "Open", "DACR", "Playback", "Test mode" +}; + +static SOC_ENUM_SINGLE_DECL(lo_mux_map_enum, + MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_MUX_INPUT_VAUDP15_SFT, + hslo_mux_map); + +static const struct snd_kcontrol_new lo_mux_control = + SOC_DAPM_ENUM("Line out source", lo_mux_map_enum); + +static SOC_ENUM_SINGLE_DECL(hs_mux_map_enum, + MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_MUX_INPUT_VAUDP15_SFT, + hslo_mux_map); + +static const struct snd_kcontrol_new hs_mux_control = + SOC_DAPM_ENUM("Handset source", hs_mux_map_enum); + +static const char * const hplr_mux_map[] = { + "Open", "Line Out", "DAC", "Handset" +}; + +static SOC_ENUM_SINGLE_DECL(hpr_mux_map_enum, + MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_MUX_INPUT_VAUDP15_SFT, + hplr_mux_map); + +static const struct snd_kcontrol_new hpr_mux_control = + SOC_DAPM_ENUM("Headphone Right source", hpr_mux_map_enum); + +static SOC_ENUM_SINGLE_DECL(hpl_mux_map_enum, + MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPL_MUX_INPUT_VAUDP15_SFT, + hplr_mux_map); + +static const struct snd_kcontrol_new hpl_mux_control = + SOC_DAPM_ENUM("Headphone Left source", hpl_mux_map_enum); + +static const char * const dac_mux_map[] = { + "Normal Path", "Sine Generator" +}; + +static SOC_ENUM_SINGLE_DECL(dac_mux_map_enum, + MT6357_AFE_TOP_CON0, + MT6357_DL_SINE_ON_SFT, + dac_mux_map); + +static const struct snd_kcontrol_new dac_mux_control = + SOC_DAPM_ENUM("DAC Select", dac_mux_map_enum); + +static int mt6357_set_dmic(struct mt6357_priv *priv, bool enable) +{ + if (enable) { + /* DMIC enable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON7, + MT6357_AUDDIGMICBIAS_MASK | MT6357_AUDDIGMICEN_MASK, + MT6357_AUDDIGMICBIAS_DEFAULT_VALUE | MT6357_AUDDIGMICEN_ENABLE); + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_ENABLE); + /* UL dmic setting: dual mode */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_H, + MT6357_C_TWO_DIGITAL_MIC_CTL_MASK, + MT6357_C_TWO_DIGITAL_MIC_ENABLE); + /* UL turn on SDM 3 level mode */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SDM_3_LEVEL_CTL_MASK, + MT6357_UL_SDM_3_LEVEL_SELECT); + /* UL turn on */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_ENABLE); + /* Wait to avoid any pop noises */ + msleep(100); + } else { + /* UL turn off */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_DISABLE); + /* UL turn on SDM 3 level mode */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SDM_3_LEVEL_CTL_MASK, + MT6357_UL_SDM_3_LEVEL_DESELECT); + /* disable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_DISABLE); + /* UL dmic setting: dual mode */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_H, + MT6357_C_TWO_DIGITAL_MIC_CTL_MASK, + MT6357_C_TWO_DIGITAL_MIC_DISABLE); + /* DMIC disable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON7, + MT6357_AUDDIGMICBIAS_MASK | MT6357_AUDDIGMICEN_MASK, + MT6357_AUDDIGMICBIAS_OFF | MT6357_AUDDIGMICEN_DISABLE); + } + return 0; +} + +static int mt6357_set_amic(struct mt6357_priv *priv, bool enable, unsigned int mic_type) +{ + if (enable) { + if (IS_DCC_BASE(mic_type)) { + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_DIV_MASK, MT6357_DCCLK_DIV_RUN_VALUE); + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_PDN_MASK, MT6357_DCCLK_OUTPUT); + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_GEN_ON_MASK, MT6357_DCCLK_GEN_ON); + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG1, + MT6357_DCCLK_RESYNC_BYPASS_MASK, + MT6357_DCCLK_RESYNC_BYPASS); + + /* mic bias 0: set the correct DC couple*/ + switch (mic_type) { + case MIC_TYPE_MUX_DCC_ECM_DIFF: + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_DC_MASK, + MT6357_AUD_MICBIAS0_DC_ENABLE_ALL); + break; + case MIC_TYPE_MUX_DCC_ECM_SINGLE: + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_DC_MASK, + MT6357_AUD_MICBIAS0_DC_ENABLE_P1); + break; + default: + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_DC_MASK, + MT6357_AUD_MICBIAS0_DC_DISABLE_ALL); + break; + } + + /* mic bias 1: set the correct DC couple */ + if (mic_type == MIC_TYPE_MUX_DCC_ECM_SINGLE) + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON9, + MT6357_AUD_MICBIAS1_DCSW1P_EN_MASK, + MT6357_AUD_MICBIAS1_DCSW1P_ENABLE); + + /* Audio L/R preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCPRECHARGE_MASK, + MT6357_AUDPREAMPLDCPRECHARGE_ENABLE); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCPRECHARGE_MASK, + MT6357_AUDPREAMPRDCPRECHARGE_ENABLE); + /* L preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCCEN_MASK, + MT6357_AUDPREAMPLDCCEN_DC); + /* R preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCCEN_MASK, + MT6357_AUDPREAMPRDCCEN_DC); + } else { + /* Audio L preamplifier DCC precharge disable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCPRECHARGE_MASK, + MT6357_AUDPREAMPLDCPRECHARGE_DISABLE); + /* L preamplifier ACC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCCEN_MASK, + MT6357_AUDPREAMPLDCCEN_AC); + /* Audio R preamplifier DCC precharge disable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCPRECHARGE_MASK, + MT6357_AUDPREAMPRDCPRECHARGE_DISABLE); + /* R preamplifier ACC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCCEN_MASK, + MT6357_AUDPREAMPRDCCEN_AC); + } + } else { + /* disable any Mic Bias 0 DC couple */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_DC_MASK, + MT6357_AUD_MICBIAS0_DC_DISABLE_ALL); + /* disable any Mic Bias 1 DC couple */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON9, + MT6357_AUD_MICBIAS1_DCSW1P_EN_MASK, + MT6357_AUD_MICBIAS1_DCSW1P_DISABLE); + if (IS_DCC_BASE(mic_type)) { + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_GEN_ON_MASK, MT6357_DCCLK_GEN_OFF); + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_PDN_MASK, MT6357_DCCLK_PDN); + regmap_update_bits(priv->regmap, MT6357_AFE_DCCLK_CFG0, + MT6357_DCCLK_DIV_MASK, MT6357_DCCLK_DIV_STOP_VALUE); + } + } + + return 0; +} + +static int mt6357_set_loopback(struct mt6357_priv *priv, bool enable) +{ + if (enable) { + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_ENABLE); + /* enable aud_pad lpk TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_LPBK_MASK, + MT6357_AUD_PAD_TX_FIFO_LPBK_ENABLE); + /* Set UL Part: enable new lpbk 2 */ + regmap_update_bits(priv->regmap, MT6357_AFE_ADDA_MTKAIF_CFG0, + MT6357_ADDA_MTKAIF_LPBK_CTL_MASK, + MT6357_ADDA_MTKAIF_LPBK_ENABLE); + /* UL turn on */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_ENABLE); + } else { + /* UL turn off */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_DISABLE); + /* disable new lpbk 2 */ + regmap_update_bits(priv->regmap, MT6357_AFE_ADDA_MTKAIF_CFG0, + MT6357_ADDA_MTKAIF_LPBK_CTL_MASK, + MT6357_ADDA_MTKAIF_LPBK_DISABLE); + /* disable aud_pad lpbk TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_LPBK_MASK, + MT6357_AUD_PAD_TX_FIFO_LPBK_DISABLE); + /* disable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_DISABLE); + } + + return 0; +} + +static int mt6357_set_ul_sine_gen(struct mt6357_priv *priv, bool enable) +{ + if (enable) { + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_ENABLE); + /* UL turn on */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_ENABLE); + } else { + /* UL turn off */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, + MT6357_UL_SRC_DISABLE); + /* disable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_DISABLE); + } + + return 0; +} + +static int mt_aif_out_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + set_capture_gpio(priv, true); + break; + case SND_SOC_DAPM_POST_PMD: + set_capture_gpio(priv, false); + break; + default: + break; + } + + return 0; +} + +static int mt_adc_supply_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable audio ADC CLKGEN */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON11, + MT6357_RSTB_ENCODER_VA28_MASK, MT6357_RSTB_ENCODER_VA28_ENABLE); + /* Enable LCLDO_ENC 2P8V */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_LCLDO_ENC_EN_VA28_MASK, MT6357_LCLDO_ENC_EN_VA28_ENABLE); + /* LCLDO_ENC remote sense */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_VA28REFGEN_EN_VA28_MASK | + MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_MASK, + MT6357_VA28REFGEN_EN_VA28_ENABLE | + MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_ENABLE); + break; + case SND_SOC_DAPM_POST_PMD: + /* LCLDO_ENC remote sense off */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_VA28REFGEN_EN_VA28_MASK | + MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_MASK, + MT6357_VA28REFGEN_EN_VA28_DISABLE | + MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_DISABLE); + /* disable LCLDO_ENC 2P8V */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_LCLDO_ENC_EN_VA28_MASK, + MT6357_LCLDO_ENC_EN_VA28_DISABLE); + /* disable audio ADC CLKGEN */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON11, + MT6357_RSTB_ENCODER_VA28_MASK, + MT6357_RSTB_ENCODER_VA28_DISABLE); + break; + default: + break; + } + + return 0; +} + +static int mt_mic_type_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mic_type = dapm_kcontrol_get_value(w->kcontrols[0]); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (mic_type) { + case MIC_TYPE_MUX_DMIC: + mt6357_set_dmic(priv, true); + break; + case MIC_TYPE_MUX_LPBK: + mt6357_set_loopback(priv, true); + break; + case MIC_TYPE_MUX_SGEN: + mt6357_set_ul_sine_gen(priv, true); + break; + default: + mt6357_set_amic(priv, true, mic_type); + break; + } + break; + case SND_SOC_DAPM_POST_PMD: + switch (mic_type) { + case MIC_TYPE_MUX_DMIC: + mt6357_set_dmic(priv, false); + break; + case MIC_TYPE_MUX_LPBK: + mt6357_set_loopback(priv, false); + break; + case MIC_TYPE_MUX_SGEN: + mt6357_set_ul_sine_gen(priv, false); + break; + default: + mt6357_set_amic(priv, false, mic_type); + break; + } + break; + default: + break; + } + + return 0; +} + +static int mt_pga_left_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* L preamplifier enable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLON_MASK, + MT6357_AUDPREAMPLON_ENABLE); + /* L ADC input sel : L PGA. Enable audio L ADC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDADCLINPUTSEL_MASK, + MT6357_AUDADCLINPUTSEL_PREAMPLIFIER); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDADCLPWRUP_MASK, + MT6357_AUDADCLPWRUP); + /* Audio L preamplifier DCC precharge off */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCPRECHARGE_MASK, + MT6357_AUDPREAMPLDCPRECHARGE_DISABLE); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Audio L ADC input sel : off, disable audio L ADC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDADCLPWRUP_MASK, + MT6357_AUDADCLPWRDOWN); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDADCLINPUTSEL_MASK, + MT6357_AUDADCLINPUTSEL_IDLE); + /* L preamplifier ACC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCCEN_MASK, + MT6357_AUDPREAMPLDCCEN_AC); + /* L preamplifier disable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLON_MASK, + MT6357_AUDPREAMPLON_DISABLE); + /* disable Audio L preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLDCPRECHARGE_MASK, + MT6357_AUDPREAMPLDCPRECHARGE_DISABLE); + break; + default: + break; + } + + return 0; +} + +static int mt_pga_right_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* R preamplifier enable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRON_MASK, MT6357_AUDPREAMPRON_ENABLE); + /* R ADC input sel : R PGA. Enable audio R ADC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDADCRINPUTSEL_MASK, + MT6357_AUDADCRINPUTSEL_PREAMPLIFIER); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDADCRPWRUP_MASK, MT6357_AUDADCRPWRUP); + /* Audio R preamplifier DCC precharge off */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCPRECHARGE_MASK, + MT6357_AUDPREAMPRDCPRECHARGE_DISABLE); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Audio R ADC input sel : off, disable audio R ADC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDADCRPWRUP_MASK, MT6357_AUDADCRPWRDOWN); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDADCRINPUTSEL_MASK, MT6357_AUDADCRINPUTSEL_IDLE); + /* R preamplifier ACC */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCCEN_MASK, MT6357_AUDPREAMPRDCCEN_AC); + /* R preamplifier disable */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRON_MASK, MT6357_AUDPREAMPRON_DISABLE); + /* disable Audio R preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRDCPRECHARGE_MASK, + MT6357_AUDPREAMPRDCPRECHARGE_DISABLE); + break; + default: + break; + } + + return 0; +} + +static int adc_enable_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int lgain, rgain; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_read(priv->regmap, MT6357_AUDENC_ANA_CON0, &lgain); + regmap_read(priv->regmap, MT6357_AUDENC_ANA_CON1, &rgain); + /* L PGA 0 dB gain */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLGAIN_MASK, + UL_GAIN_0DB << MT6357_AUDPREAMPLGAIN_SFT); + /* R PGA 0 dB gain */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRGAIN_MASK, + UL_GAIN_0DB << MT6357_AUDPREAMPRGAIN_SFT); + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_ENABLE); + /* UL turn on */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, MT6357_UL_SRC_ENABLE); + /* Wait to avoid any pop noises */ + msleep(100); + /* set the mic gains to the stored values */ + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON0, + MT6357_AUDPREAMPLGAIN_MASK, lgain); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON1, + MT6357_AUDPREAMPRGAIN_MASK, rgain); + break; + case SND_SOC_DAPM_POST_PMD: + /* UL turn off */ + regmap_update_bits(priv->regmap, MT6357_AFE_UL_SRC_CON0_L, + MT6357_UL_SRC_ON_TMP_CTL_MASK, MT6357_UL_SRC_DISABLE); + /* disable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6357_AFE_AUD_PAD_TOP, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK, + MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_DISABLE); + break; + default: + break; + } + + return 0; +} + +static void configure_downlinks(struct mt6357_priv *priv, bool enable) +{ + if (enable) { + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ELR_0, + MT6357_AUD_HP_TRIM_EN_VAUDP15_MASK, + MT6357_AUD_HP_TRIM_EN_VAUDP15_ENABLE); + /* Disable headphone short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_SC_VAUDP15_MASK | MT6357_AUD_HPL_SC_VAUDP15_MASK, + MT6357_AUD_HPR_SC_VAUDP15_DISABLE | + MT6357_AUD_HPL_SC_VAUDP15_DISABLE); + /* Disable handset short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_SC_VAUDP15_MASK, + MT6357_AUD_HS_SC_VAUDP15_DISABLE); + /* Disable lineout short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_SC_VAUDP15_MASK, + MT6357_AUD_LOL_SC_VAUDP15_DISABLE); + /* Reduce ESD resistance of AU_REFN */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON2, + MT6357_AUD_REFN_DERES_VAUDP15_MASK, + MT6357_AUD_REFN_DERES_VAUDP15_ENABLE); + /* Turn on DA_600K_NCP_VA18 */ + regmap_write(priv->regmap, MT6357_AUDNCP_CLKDIV_CON1, MT6357_DIVCKS_ON); + /* Set NCP clock as 604kHz // 26MHz/43 = 604KHz */ + regmap_write(priv->regmap, MT6357_AUDNCP_CLKDIV_CON2, 0x002c); + /* Toggle DIVCKS_CHG */ + regmap_write(priv->regmap, MT6357_AUDNCP_CLKDIV_CON0, MT6357_DIVCKS_CHG); + /* Set NCP soft start mode as default mode: 150us */ + regmap_write(priv->regmap, MT6357_AUDNCP_CLKDIV_CON4, + MT6357_DIVCKS_PWD_NCP_ST_150US); + /* Enable NCP */ + regmap_write(priv->regmap, MT6357_AUDNCP_CLKDIV_CON3, + MT6357_DIVCKS_PWD_NCP_ENABLE); + usleep_range(250, 270); + /* Enable cap-less LDOs (1.5V) */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_VA33REFGEN_EN_VA18_MASK | + MT6357_LCLDO_REMOTE_SENSE_VA18_MASK | + MT6357_LCLDO_EN_VA18_MASK | + MT6357_HCLDO_REMOTE_SENSE_VA18_MASK | + MT6357_HCLDO_EN_VA18_MASK, + MT6357_VA33REFGEN_EN_VA18_ENABLE | + MT6357_LCLDO_REMOTE_SENSE_VA18_ENABLE | + MT6357_LCLDO_EN_VA18_ENABLE | + MT6357_HCLDO_REMOTE_SENSE_VA18_ENABLE | + MT6357_HCLDO_EN_VA18_ENABLE); + /* Enable NV regulator (-1.2V) */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON13, + MT6357_NVREG_EN_VAUDP15_MASK, MT6357_NVREG_EN_VAUDP15_ENABLE); + usleep_range(100, 120); + /* Enable IBIST */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON10, + MT6357_AUD_IBIAS_PWRDN_VAUDP15_MASK, + MT6357_AUD_IBIAS_PWRDN_VAUDP15_ENABLE); + /* Enable AUD_CLK */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON11, + MT6357_RSTB_DECODER_VA28_MASK, + MT6357_RSTB_DECODER_VA28_ENABLE); + /* Enable low-noise mode of DAC */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_DAC_LOW_NOISE_MODE_MASK, + MT6357_DAC_LOW_NOISE_MODE_ENABLE); + usleep_range(100, 120); + } else { + /* Disable low-noise mode of DAC */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_DAC_LOW_NOISE_MODE_MASK, + MT6357_DAC_LOW_NOISE_MODE_DISABLE); + /* Disable AUD_CLK */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON11, + MT6357_RSTB_DECODER_VA28_MASK, + MT6357_RSTB_DECODER_VA28_DISABLE); + /* Enable linout short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_SC_VAUDP15_MASK, + MT6357_AUD_LOL_SC_VAUDP15_ENABLE); + /* Enable handset short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_SC_VAUDP15_MASK, + MT6357_AUD_HS_SC_VAUDP15_ENABLE); + /* Enable headphone short-circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_SC_VAUDP15_MASK | + MT6357_AUD_HPL_SC_VAUDP15_MASK, + MT6357_AUD_HPR_SC_VAUDP15_ENABLE | + MT6357_AUD_HPL_SC_VAUDP15_ENABLE); + /* Disable IBIST */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON10, + MT6357_AUD_IBIAS_PWRDN_VAUDP15_MASK, + MT6357_AUD_IBIAS_PWRDN_VAUDP15_DISABLE); + /* Disable NV regulator (-1.2V) */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON13, + MT6357_NVREG_EN_VAUDP15_MASK, + MT6357_NVREG_EN_VAUDP15_DISABLE); + /* Disable cap-less LDOs (1.5V) */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON12, + MT6357_VA33REFGEN_EN_VA18_MASK | + MT6357_LCLDO_REMOTE_SENSE_VA18_MASK | + MT6357_LCLDO_EN_VA18_MASK | + MT6357_HCLDO_REMOTE_SENSE_VA18_MASK | + MT6357_HCLDO_EN_VA18_MASK, + MT6357_VA33REFGEN_EN_VA18_DISABLE | + MT6357_LCLDO_REMOTE_SENSE_VA18_DISABLE | + MT6357_LCLDO_EN_VA18_DISABLE | + MT6357_HCLDO_REMOTE_SENSE_VA18_DISABLE | + MT6357_HCLDO_EN_VA18_DISABLE); + /* Disable NCP */ + regmap_update_bits(priv->regmap, MT6357_AUDNCP_CLKDIV_CON3, + MT6357_DIVCKS_PWD_NCP_MASK, MT6357_DIVCKS_PWD_NCP_DISABLE); + } +} + +static int mt_audio_in_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + set_playback_gpio(priv, true); + + /* Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, true); + + /* Disable HP main CMFB Switch */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HPRL_MAIN_CMFB_LOOP_MASK, + MT6357_HPRL_MAIN_CMFB_LOOP_DISABLE); + /* Audio system digital clock power down release */ + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON2, + MT6357_CCI_AUDIO_FIFO_DISABLE | + MT6357_CCI_ACD_MODE_NORMAL_PATH | + MT6357_CCI_AFIFO_CLK_PWDB_ON | + MT6357_CCI_ACD_FUNC_RSTB_RESET); + /* sdm audio fifo clock power on */ + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON0, + MT6357_CCI_AUD_ANACK_INVERT | + (4 << MT6357_CCI_AUDIO_FIFO_WPTR_SFT) | + MT6357_CCI_SCRAMBLER_CG_ENABLE | + MT6357_CCI_RAND_ENABLE | + MT6357_CCI_SPLT_SCRMB_CLK_ON | + MT6357_CCI_SPLT_SCRMB_ON | + MT6357_CCI_ZERO_PADDING_DISABLE | + MT6357_CCI_SCRAMBLER_ENABLE); + /* scrambler clock on enable */ + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON2, + MT6357_CCI_AUDIO_FIFO_DISABLE | + MT6357_CCI_ACD_MODE_TEST_PATH | + MT6357_CCI_AFIFO_CLK_PWDB_ON | + MT6357_CCI_ACD_FUNC_RSTB_RELEASE); + /* sdm power on */ + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON2, + MT6357_CCI_AUDIO_FIFO_ENABLE | + MT6357_CCI_ACD_MODE_TEST_PATH | + MT6357_CCI_AFIFO_CLK_PWDB_ON | + MT6357_CCI_ACD_FUNC_RSTB_RELEASE); + + configure_downlinks(priv, true); + break; + case SND_SOC_DAPM_POST_PMD: + configure_downlinks(priv, false); + /* DL scrambler disabling sequence */ + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON2, + MT6357_CCI_AUDIO_FIFO_DISABLE | + MT6357_CCI_ACD_MODE_TEST_PATH | + MT6357_CCI_AFIFO_CLK_PWDB_DOWN | + MT6357_CCI_ACD_FUNC_RSTB_RESET); + regmap_write(priv->regmap, MT6357_AFUNC_AUD_CON0, + MT6357_CCI_AUD_ANACK_INVERT | + (4 << MT6357_CCI_AUDIO_FIFO_WPTR_SFT) | + MT6357_CCI_SCRAMBLER_CG_ENABLE | + MT6357_CCI_RAND_ENABLE | + MT6357_CCI_SPLT_SCRMB_CLK_ON | + MT6357_CCI_SPLT_SCRMB_ON | + MT6357_CCI_ZERO_PADDING_DISABLE | + MT6357_CCI_SCRAMBLER_DISABLE); + + set_playback_gpio(priv, false); + + /* disable Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, false); + break; + default: + break; + } + + return 0; +} + +static int mt_delay_250_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(250, 270); + break; + case SND_SOC_DAPM_PRE_PMD: + usleep_range(250, 270); + break; + default: + break; + } + + return 0; +} + +static int lo_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int lgain, rgain; + + /* Get current gain value */ + regmap_read(priv->regmap, MT6357_ZCD_CON1, &lgain); + rgain = (lgain & MT6357_AUD_LOR_GAIN_MASK) >> MT6357_AUD_LOR_GAIN_SFT; + lgain = lgain & MT6357_AUD_LOL_GAIN_MASK; + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Set -40dB before enable HS to avoid POP noise */ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON1, + MT6357_AUD_LOL_GAIN_MASK | + MT6357_AUD_LOR_GAIN_MASK, + MT6357_DL_GAIN_N_40DB_REG); + /* Set LO STB enhance circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_MASK, + MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_ENABLE); + /* Enable LO driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_MASK, + MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_ENABLE); + /* Enable LO driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_PWRUP_VAUDP15_MASK, + MT6357_AUD_LOL_PWRUP_VAUDP15_ENABLE); + /* Set LOL gain to normal gain step by step */ + lo_volume_ramp(priv, DL_GAIN_N_40DB, lgain, + DL_GAIN_N_40DB, rgain); + break; + case SND_SOC_DAPM_PRE_PMD: + /* decrease LOL gain to minimum gain step by step */ + + lo_volume_ramp(priv, lgain, DL_GAIN_N_40DB, + rgain, DL_GAIN_N_40DB); + /* Disable LO driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_PWRUP_VAUDP15_MASK, + MT6357_AUD_LOL_PWRUP_VAUDP15_DISABLE); + /* Disable LO driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_MASK, + MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_DISABLE); + /* Clear LO STB enhance circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_MASK, + MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_DISABLE); + /* Save the gain value into the register*/ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON1, + MT6357_AUD_LOL_GAIN_MASK | + MT6357_AUD_LOR_GAIN_MASK, + lgain << MT6357_AUD_LOL_GAIN_SFT | + rgain << MT6357_AUD_LOR_GAIN_SFT); + + break; + default: + break; + } + + return 0; +} + +static int hs_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int gain; /* HS register has only one gain slot */ + + /* Get current gain value */ + regmap_read(priv->regmap, MT6357_ZCD_CON3, &gain); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Set -40dB before enable HS to avoid POP noise */ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON3, + MT6357_AUD_HS_GAIN_MASK, + DL_GAIN_N_40DB); + + /* Set HS STB enhance circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HSOUT_STB_ENH_VAUDP15_MASK, + MT6357_AUD_HSOUT_STB_ENH_VAUDP15_ENABLE); + /* Enable HS driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_MASK, + MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_ENABLE); + /* Enable HS driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_PWRUP_VAUDP15_MASK, + MT6357_AUD_HS_PWRUP_VAUDP15_ENABLE); + /* Set HS gain to normal gain step by step */ + hs_volume_ramp(priv, DL_GAIN_N_40DB, gain); + break; + case SND_SOC_DAPM_PRE_PMD: + /* decrease HS gain to minimum gain step by step */ + hs_volume_ramp(priv, gain, DL_GAIN_N_40DB); + /* Disable HS driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_PWRUP_VAUDP15_MASK, + MT6357_AUD_HS_PWRUP_VAUDP15_DISABLE); + /* Disable HS driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_MASK, + MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_ENABLE); + /* Clear HS STB enhance circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HSOUT_STB_ENH_VAUDP15_MASK, + MT6357_AUD_HSOUT_STB_ENH_VAUDP15_DISABLE); + /* Save the gain value into the register*/ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON3, + MT6357_AUD_HS_GAIN_MASK, gain); + break; + default: + break; + } + + return 0; +} + +static int hp_main_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int lgain, rgain; + + /* Get current gain value */ + regmap_read(priv->regmap, MT6357_ZCD_CON2, &lgain); + rgain = (lgain & MT6357_AUD_HPR_GAIN_MASK) >> MT6357_AUD_HPR_GAIN_SFT; + lgain = lgain & MT6357_AUD_HPL_GAIN_MASK; + switch (event) { + case SND_SOC_DAPM_POST_PMU: + priv->hp_channel_number++; + if (priv->hp_channel_number > 1) + break; + /* Set -40dB before enable HS to avoid POP noise */ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON2, + MT6357_AUD_HPL_GAIN_MASK | + MT6357_AUD_HPR_GAIN_MASK, + MT6357_DL_GAIN_N_40DB_REG); + /* Set HPP/N STB enhance circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON2, + MT6357_HPROUT_STB_ENH_VAUDP15_MASK | + MT6357_HPLOUT_STB_ENH_VAUDP15_MASK, + MT6357_HPROUT_STB_ENH_VAUDP15_N470_P250 | + MT6357_HPLOUT_STB_ENH_VAUDP15_N470_P250); + /* Enable HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_ENABLE | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_ENABLE); + /* Enable HP aux feedback loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_AUX_FBRSW_VAUDP15_MASK | + MT6357_HPL_AUX_FBRSW_VAUDP15_MASK, + MT6357_HPR_AUX_FBRSW_VAUDP15_ENABLE | + MT6357_HPL_AUX_FBRSW_VAUDP15_ENABLE); + /* Enable HP aux CMFB loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HP_CMFB_RST_MASK | + MT6357_HPL_AUX_CMFB_LOOP_MASK | + MT6357_HPR_AUX_CMFB_LOOP_MASK, + MT6357_HP_CMFB_RST_NORMAL | + MT6357_HPL_AUX_CMFB_LOOP_ENABLE | + MT6357_HPR_AUX_CMFB_LOOP_ENABLE); + /* Enable HP driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_BIAS_VAUDP15_MASK | + MT6357_AUD_HPL_BIAS_VAUDP15_MASK, + MT6357_AUD_HPR_BIAS_VAUDP15_ENABLE | + MT6357_AUD_HPL_BIAS_VAUDP15_ENABLE); + /* Enable HP driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_PWRUP_VAUDP15_MASK | + MT6357_AUD_HPL_PWRUP_VAUDP15_MASK, + MT6357_AUD_HPR_PWRUP_VAUDP15_ENABLE | + MT6357_AUD_HPL_PWRUP_VAUDP15_ENABLE); + /* Short HP main output to HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_MASK | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_MASK, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_ENABLE | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_ENABLE); + /* Enable HP main CMFB loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HPRL_MAIN_CMFB_LOOP_MASK, + MT6357_HPRL_MAIN_CMFB_LOOP_ENABLE); + /* Disable HP aux CMFB loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HPR_AUX_CMFB_LOOP_MASK | + MT6357_HPL_AUX_CMFB_LOOP_MASK, + MT6357_HPR_AUX_CMFB_LOOP_DISABLE | + MT6357_HPL_AUX_CMFB_LOOP_DISABLE); + /* Enable HP main output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_PWRUP_VAUDP15_ENABLE | + MT6357_HPLOUT_PWRUP_VAUDP15_ENABLE); + /* Enable HPR/L main output stage step by step */ + hp_main_output_ramp(priv, true); + usleep_range(1000, 1200); + /* Reduce HP aux feedback loop gain */ + hp_aux_feedback_loop_gain_ramp(priv, true); + /* Disable HP aux feedback loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_AUX_FBRSW_VAUDP15_MASK | + MT6357_HPL_AUX_FBRSW_VAUDP15_MASK, + MT6357_HPR_AUX_FBRSW_VAUDP15_DISABLE | + MT6357_HPL_AUX_FBRSW_VAUDP15_DISABLE); + /* apply volume setting */ + hp_volume_ramp(priv, DL_GAIN_N_40DB, lgain, + DL_GAIN_N_40DB, rgain); + /* Disable HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_DISABLE | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_DISABLE); + /* Unshort HP main output to HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_MASK | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_MASK, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_DISABLE | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_DISABLE); + usleep_range(100, 120); + break; + case SND_SOC_DAPM_PRE_PMD: + priv->hp_channel_number--; + if (priv->hp_channel_number > 0) + break; + /* Short HP main output to HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_MASK | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_MASK, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_ENABLE | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_ENABLE); + /* Enable HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_ENABLE | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_ENABLE); + /* decrease HPL/R gain to normal gain step by step */ + hp_volume_ramp(priv, lgain, DL_GAIN_N_40DB, + rgain, DL_GAIN_N_40DB); + /* Enable HP aux feedback loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_AUX_FBRSW_VAUDP15_MASK | + MT6357_HPL_AUX_FBRSW_VAUDP15_MASK, + MT6357_HPR_AUX_FBRSW_VAUDP15_ENABLE | + MT6357_HPL_AUX_FBRSW_VAUDP15_ENABLE); + /* Reduce HP aux feedback loop gain */ + hp_aux_feedback_loop_gain_ramp(priv, false); + /* decrease HPR/L main output stage step by step */ + hp_main_output_ramp(priv, false); + /* Disable HP main output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_PWRUP_VAUDP15_DISABLE | + MT6357_HPLOUT_PWRUP_VAUDP15_DISABLE); + /* Enable HP aux CMFB loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HP_CMFB_RST_MASK | + MT6357_HPL_AUX_CMFB_LOOP_MASK | + MT6357_HPR_AUX_CMFB_LOOP_MASK, + MT6357_HP_CMFB_RST_RESET | + MT6357_HPL_AUX_CMFB_LOOP_ENABLE | + MT6357_HPR_AUX_CMFB_LOOP_ENABLE); + /* Disable HP main CMFB loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HPRL_MAIN_CMFB_LOOP_MASK, + MT6357_HPRL_MAIN_CMFB_LOOP_DISABLE); + /* Unshort HP main output to HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_MASK | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_MASK, + MT6357_HPR_SHORT2HPR_AUX_VAUDP15_DISABLE | + MT6357_HPL_SHORT2HPR_AUX_VAUDP15_DISABLE); + /* Disable HP driver core circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_PWRUP_VAUDP15_MASK | + MT6357_AUD_HPL_PWRUP_VAUDP15_MASK, + MT6357_AUD_HPR_PWRUP_VAUDP15_DISABLE | + MT6357_AUD_HPL_PWRUP_VAUDP15_DISABLE); + /* Disable HP driver bias circuits */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_BIAS_VAUDP15_MASK | + MT6357_AUD_HPL_BIAS_VAUDP15_MASK, + MT6357_AUD_HPR_BIAS_VAUDP15_DISABLE | + MT6357_AUD_HPL_BIAS_VAUDP15_DISABLE); + /* Disable HP aux CMFB loop, + * Enable HP main CMFB for HP off state + */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON6, + MT6357_HPRL_MAIN_CMFB_LOOP_MASK | + MT6357_HPR_AUX_CMFB_LOOP_MASK | + MT6357_HPL_AUX_CMFB_LOOP_MASK, + MT6357_HPRL_MAIN_CMFB_LOOP_ENABLE | + MT6357_HPR_AUX_CMFB_LOOP_DISABLE | + MT6357_HPL_AUX_CMFB_LOOP_DISABLE); + /* Disable HP aux feedback loop */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPR_AUX_FBRSW_VAUDP15_MASK | + MT6357_HPL_AUX_FBRSW_VAUDP15_MASK, + MT6357_HPR_AUX_FBRSW_VAUDP15_DISABLE | + MT6357_HPL_AUX_FBRSW_VAUDP15_DISABLE); + /* Disable HP aux output stage */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON1, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_MASK | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_MASK, + MT6357_HPROUT_AUX_PWRUP_VAUDP15_DISABLE | + MT6357_HPLOUT_AUX_PWRUP_VAUDP15_DISABLE); + /* Save the gain value into the register*/ + regmap_update_bits(priv->regmap, MT6357_ZCD_CON2, + MT6357_AUD_HPL_GAIN_MASK | + MT6357_AUD_HPR_GAIN_MASK, + lgain << MT6357_AUD_HPL_GAIN_SFT | + rgain << MT6357_AUD_HPR_GAIN_SFT); + break; + default: + break; + } + + return 0; +} + +static int right_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable Audio DAC and control audio bias gen */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_DACR_PWRUP_VA28_MASK | + MT6357_AUD_DACR_PWRUP_VAUDP15_MASK, + MT6357_AUD_DACR_PWRUP_VA28_ENABLE | + MT6357_AUD_DACR_PWRUP_VAUDP15_ENABLE); + break; + case SND_SOC_DAPM_POST_PMU: + /* disable Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, false); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, true); + /* Disable Audio DAC and control audio bias gen */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_DACR_PWRUP_VA28_MASK | + MT6357_AUD_DACR_PWRUP_VAUDP15_MASK, + MT6357_AUD_DACR_PWRUP_VA28_DISABLE | + MT6357_AUD_DACR_PWRUP_VAUDP15_DISABLE); + break; + default: + break; + } + + return 0; +} + +static int left_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6357_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Enable Audio DAC and control audio bias gen */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_DACL_PWRUP_VA28_MASK | + MT6357_AUD_DACL_PWRUP_VAUDP15_MASK, + MT6357_AUD_DACL_PWRUP_VA28_ENABLE | + MT6357_AUD_DACL_PWRUP_VAUDP15_ENABLE); + break; + case SND_SOC_DAPM_POST_PMU: + /* disable Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, false); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Pull-down HPL/R to AVSS28_AUD */ + if (priv->pull_down_needed) + hp_pull_down(priv, true); + /* Disable Audio DAC and control audio bias gen */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_DACL_PWRUP_VA28_MASK | + MT6357_AUD_DACL_PWRUP_VAUDP15_MASK, + MT6357_AUD_DACL_PWRUP_VA28_DISABLE | + MT6357_AUD_DACL_PWRUP_VAUDP15_DISABLE); + break; + default: + break; + } + + return 0; +} + +/* Supply widgets subsequence */ +enum { + /* common */ + SUPPLY_SEQ_CLK_BUF, + SUPPLY_SEQ_AUD_GLB, + SUPPLY_SEQ_CLKSQ, + SUPPLY_SEQ_VOW_AUD_LPW, + SUPPLY_SEQ_AUD_VOW, + SUPPLY_SEQ_VOW_CLK, + SUPPLY_SEQ_VOW_LDO, + SUPPLY_SEQ_TOP_CK, + SUPPLY_SEQ_TOP_CK_LAST, + SUPPLY_SEQ_AUD_TOP, + SUPPLY_SEQ_AUD_TOP_LAST, + SUPPLY_SEQ_AFE, + /* capture */ + SUPPLY_SEQ_ADC_SUPPLY, +}; + +/* DAPM Widgets */ +static const struct snd_soc_dapm_widget mt6357_dapm_widgets[] = { + /* Analog Clocks */ + SND_SOC_DAPM_SUPPLY_S("CLK_BUF", SUPPLY_SEQ_CLK_BUF, + MT6357_DCXO_CW14, + MT6357_XO_AUDIO_EN_M_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDGLB", SUPPLY_SEQ_AUD_GLB, + MT6357_AUDDEC_ANA_CON11, + MT6357_AUDGLB_PWRDN_VA28_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("CLKSQ Audio", SUPPLY_SEQ_CLKSQ, + MT6357_AUDENC_ANA_CON6, + MT6357_CLKSQ_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDNCP_CK", SUPPLY_SEQ_TOP_CK, + MT6357_AUD_TOP_CKPDN_CON0, + MT6357_AUDNCP_CK_PDN_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ZCD13M_CK", SUPPLY_SEQ_TOP_CK, + MT6357_AUD_TOP_CKPDN_CON0, + MT6357_ZCD13M_CK_PDN_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUD_CK", SUPPLY_SEQ_TOP_CK_LAST, + MT6357_AUD_TOP_CKPDN_CON0, + MT6357_AUD_CK_PDN_SFT, 1, + mt_delay_250_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY_S("AUDIF_CK", SUPPLY_SEQ_TOP_CK, + MT6357_AUD_TOP_CKPDN_CON0, + MT6357_AUDIF_CK_PDN_SFT, 1, NULL, 0), + + /* Digital Clocks */ + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_AFE_CTL", SUPPLY_SEQ_AUD_TOP_LAST, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_AFE_CTL_SFT, 1, + mt_delay_250_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_DAC_CTL", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_DAC_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_ADC_CTL", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_ADC_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_I2S_DL", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_I2S_DL_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PWR_CLK", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PWR_CLK_DIS_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_AFE_TESTMODEL", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_AFE_TESTMODEL_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_RESERVED", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_RESERVED_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_LPBK", SUPPLY_SEQ_AUD_TOP, + MT6357_AUDIO_TOP_CON0, + MT6357_PDN_LPBK_CTL_SFT, 1, NULL, 0), + + /* General */ + SND_SOC_DAPM_SUPPLY_S("AFE_ON", SUPPLY_SEQ_AFE, + MT6357_AFE_UL_DL_CON0, + MT6357_AFE_ON_SFT, 0, NULL, 0), + + /* Uplinks */ + SND_SOC_DAPM_AIF_OUT_E("AIF1TX", "MT6357 Capture", 0, + SND_SOC_NOPM, 0, 0, + mt_aif_out_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("ADC Supply", SUPPLY_SEQ_ADC_SUPPLY, + SND_SOC_NOPM, 0, 0, + mt_adc_supply_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADC", NULL, SND_SOC_NOPM, 0, 0, adc_enable_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("PGA L Mux", SND_SOC_NOPM, 0, 0, + &pga_left_mux_control, + mt_pga_left_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MUX_E("PGA R Mux", SND_SOC_NOPM, 0, 0, + &pga_right_mux_control, + mt_pga_right_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA("PGA L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("PGA R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX_E("Mic Type Mux", SND_SOC_NOPM, 0, 0, + &mic_type_mux_control, + mt_mic_type_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("MICBIAS0", MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_PWD_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS1", MT6357_AUDENC_ANA_CON9, + MT6357_AUD_MICBIAS1_PWD_SFT, 0, NULL, 0), + + /* UL inputs */ + SND_SOC_DAPM_INPUT("AIN0"), + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("LPBK"), + SND_SOC_DAPM_INPUT("SGEN UL"), + + /* Downlinks */ + SND_SOC_DAPM_AIF_IN_E("AIF_RX", "MT6357 Playback", 0, + SND_SOC_NOPM, 0, 0, + mt_audio_in_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_INPUT("SGEN DL"), + SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0, &dac_mux_control), + + SND_SOC_DAPM_DAC_E("DACR", NULL, SND_SOC_NOPM, 0, 0, right_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("DACL", NULL, SND_SOC_NOPM, 0, 0, left_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY("DL Digital Supply", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DL Analog Supply", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DL SRC", MT6357_AFE_DL_SRC2_CON0_L, + MT6357_DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0, NULL, 0), + + SND_SOC_DAPM_MUX_E("Line Out Source", SND_SOC_NOPM, 0, 0, &lo_mux_control, + lo_mux_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_MUX_E("Handset Source", SND_SOC_NOPM, 0, 0, &hs_mux_control, + hs_mux_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_MUX_E("Headphone Right Source", SND_SOC_NOPM, 0, 0, &hpr_mux_control, + hp_main_mux_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_MUX_E("Headphone Left Source", SND_SOC_NOPM, 0, 0, &hpl_mux_control, + hp_main_mux_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + /* DL outputs */ + SND_SOC_DAPM_OUTPUT("Headphones"), + SND_SOC_DAPM_OUTPUT("Hansdet"), + SND_SOC_DAPM_OUTPUT("Line out"), + + /* Sine generator */ + SND_SOC_DAPM_SUPPLY("SGEN UL Enable", + MT6357_AFE_TOP_CON0, MT6357_UL_SINE_ON_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SGEN Enable", + MT6357_AFE_SGEN_CFG0, + MT6357_SGEN_DAC_EN_CTL_SFT, 0, mt_audio_in_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("SGEN MUTE", + MT6357_AFE_SGEN_CFG0, + MT6357_SGEN_MUTE_SW_CTL_SFT, 1, NULL, 0) +}; + +static const struct snd_soc_dapm_route mt6357_dapm_routes[] = { + /* Capture */ + {"AIF1TX", NULL, "Mic Type Mux"}, + {"AIF1TX", NULL, "CLK_BUF"}, + {"AIF1TX", NULL, "AUDGLB"}, + {"AIF1TX", NULL, "CLKSQ Audio"}, + {"AIF1TX", NULL, "AUD_CK"}, + {"AIF1TX", NULL, "AUDIF_CK"}, + + {"AIF1TX", NULL, "AUDIO_TOP_AFE_CTL"}, + {"AIF1TX", NULL, "AUDIO_TOP_ADC_CTL"}, + {"AIF1TX", NULL, "AUDIO_TOP_PWR_CLK"}, + {"AIF1TX", NULL, "AUDIO_TOP_PDN_RESERVED"}, + {"AIF1TX", NULL, "AUDIO_TOP_I2S_DL"}, + {"AIF1TX", NULL, "AFE_ON"}, + + {"Mic Type Mux", "ACC", "ADC"}, + {"Mic Type Mux", "DCC", "ADC"}, + {"Mic Type Mux", "DCC_ECM_DIFF", "ADC"}, + {"Mic Type Mux", "DCC_ECM_SINGLE", "ADC"}, + {"Mic Type Mux", "DMIC", "AIN0"}, + {"Mic Type Mux", "DMIC", "AIN2"}, + {"Mic Type Mux", "Loopback", "LPBK"}, + {"Mic Type Mux", "Sine Generator", "SGEN UL"}, + + {"SGEN UL", NULL, "AUDIO_TOP_PDN_AFE_TESTMODEL"}, + {"SGEN UL", NULL, "SGEN UL Enable"}, + {"SGEN UL", NULL, "SGEN MUTE"}, + {"SGEN UL", NULL, "SGEN Enable"}, + + {"ADC", NULL, "PGA L Mux"}, + {"ADC", NULL, "PGA R Mux"}, + {"ADC", NULL, "ADC Supply"}, + + {"PGA L Mux", "AIN0", "AIN0"}, + {"PGA L Mux", "AIN1", "AIN1"}, + {"PGA L Mux", "AIN2", "AIN2"}, + + {"PGA R Mux", "AIN0", "AIN0"}, + {"PGA R Mux", "AIN1", "AIN1"}, + {"PGA R Mux", "AIN2", "AIN2"}, + + {"AIN0", NULL, "MICBIAS0"}, + {"AIN1", NULL, "MICBIAS1"}, + {"AIN2", NULL, "MICBIAS0"}, + {"LPBK", NULL, "AUDIO_TOP_LPBK"}, + + /* Playback */ + {"DAC Mux", "Normal Path", "AIF_RX"}, + {"DAC Mux", "Sine Generator", "SGEN DL"}, + + {"AIF_RX", NULL, "DL SRC"}, + + {"SGEN DL", NULL, "DL SRC"}, + {"SGEN DL", NULL, "SGEN MUTE"}, + {"SGEN DL", NULL, "SGEN Enable"}, + {"SGEN DL", NULL, "DL Digital Supply"}, + {"SGEN DL", NULL, "AUDIO_TOP_PDN_AFE_TESTMODEL"}, + + {"DACL", NULL, "DAC Mux"}, + {"DACR", NULL, "DAC Mux"}, + + {"DL Analog Supply", NULL, "CLK_BUF"}, + {"DL Analog Supply", NULL, "AUDGLB"}, + {"DL Analog Supply", NULL, "CLKSQ Audio"}, + {"DL Analog Supply", NULL, "AUDNCP_CK"}, + {"DL Analog Supply", NULL, "ZCD13M_CK"}, + {"DL Analog Supply", NULL, "AUD_CK"}, + {"DL Analog Supply", NULL, "AUDIF_CK"}, + + {"DL Digital Supply", NULL, "AUDIO_TOP_AFE_CTL"}, + {"DL Digital Supply", NULL, "AUDIO_TOP_DAC_CTL"}, + {"DL Digital Supply", NULL, "AUDIO_TOP_PWR_CLK"}, + {"DL Digital Supply", NULL, "AFE_ON"}, + + {"DACR", NULL, "DL Digital Supply"}, + {"DACR", NULL, "DL Analog Supply"}, + {"DACL", NULL, "DL Digital Supply"}, + {"DACL", NULL, "DL Analog Supply"}, + + {"Line Out Source", "DACR", "DACR"}, + {"Line Out Source", "Playback", "DACL"}, + {"Line Out Source", "Test mode", "DACL"}, + + {"Handset Source", "DACR", "DACR"}, + {"Handset Source", "Playback", "DACL"}, + {"Handset Source", "Test mode", "DACL"}, + + {"Headphone Right Source", "DAC", "DACR"}, + {"Headphone Right Source", "Line Out", "Line Out Source"}, + {"Headphone Right Source", "Handset", "Handset Source"}, + + {"Headphone Left Source", "DAC", "DACL"}, + {"Headphone Left Source", "Line Out", "Line Out Source"}, + {"Headphone Left Source", "Handset", "Handset Source"}, + + {"Line out", NULL, "Line Out Source"}, + {"Hansdet", NULL, "Handset Source"}, + + {"Headphones", NULL, "Headphone Right Source"}, + {"Headphones", NULL, "Headphone Left Source"}, +}; + +static struct snd_soc_dai_driver mtk_6357_dai_codecs[] = { + { + .name = "mt6357-snd-codec-aif1", + .playback = { + .stream_name = "MT6357 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = MT6357_SND_SOC_ADV_MT_FMTS, + }, + .capture = { + .stream_name = "MT6357 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MT6357_SOC_HIGH_USE_RATE, + .formats = MT6357_SND_SOC_ADV_MT_FMTS, + }, + }, +}; + +static int mt6357_codec_probe(struct snd_soc_component *codec) +{ + struct mt6357_priv *priv = snd_soc_component_get_drvdata(codec); + + snd_soc_component_init_regmap(codec, priv->regmap); + + /* Enable audio part */ + regmap_update_bits(priv->regmap, MT6357_DCXO_CW14, + MT6357_XO_AUDIO_EN_M_MASK, MT6357_XO_AUDIO_EN_M_ENABLE); + /* Disable HeadphoneL/HeadphoneR short circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON0, + MT6357_AUD_HPR_SC_VAUDP15_MASK | + MT6357_AUD_HPL_SC_VAUDP15_MASK, + MT6357_AUD_HPR_SC_VAUDP15_DISABLE | + MT6357_AUD_HPL_SC_VAUDP15_DISABLE); + /* Disable voice short circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON3, + MT6357_AUD_HS_SC_VAUDP15_MASK, + MT6357_AUD_HS_SC_VAUDP15_DISABLE); + /* disable LO buffer left short circuit protection */ + regmap_update_bits(priv->regmap, MT6357_AUDDEC_ANA_CON4, + MT6357_AUD_LOL_SC_VAUDP15_MASK, + MT6357_AUD_LOL_SC_VAUDP15_DISABLE); + /* set gpio */ + set_playback_gpio(priv, false); + set_capture_gpio(priv, false); + /* Disable audio part */ + regmap_update_bits(priv->regmap, MT6357_DCXO_CW14, + MT6357_XO_AUDIO_EN_M_MASK, + MT6357_XO_AUDIO_EN_M_DISABLE); + + return 0; +} + +static const struct snd_soc_component_driver mt6357_soc_component_driver = { + .probe = mt6357_codec_probe, + .read = snd_soc_component_read, + .write = snd_soc_component_write, + .controls = mt6357_controls, + .num_controls = ARRAY_SIZE(mt6357_controls), + .dapm_widgets = mt6357_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt6357_dapm_widgets), + .dapm_routes = mt6357_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt6357_dapm_routes), +}; + +static const u32 micbias_values[] = { + 1700000, 1800000, 1900000, 2000000, + 2100000, 2500000, 2600000, 2700000 +}; + +static u32 mt6357_get_micbias_idx(struct device_node *np, const char *micbias) +{ + int err; + u32 idx, val; + + err = of_property_read_u32(np, micbias, &val); + if (err) + return 0; + + for (idx = 0; idx < ARRAY_SIZE(micbias_values); idx++) { + if (val == micbias_values[idx]) + return idx; + } + return 0; +} + +static int mt6357_parse_dt(struct mt6357_priv *priv) +{ + u32 micbias_voltage_index = 0; + struct device_node *np = priv->dev->parent->of_node; + + if (!np) + return -EINVAL; + + priv->pull_down_needed = false; + if (of_property_read_bool(np, "mediatek,hp-pull-down")) + priv->pull_down_needed = true; + + micbias_voltage_index = mt6357_get_micbias_idx(np, "mediatek,micbias0-microvolt"); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON8, + MT6357_AUD_MICBIAS0_VREF_MASK, + micbias_voltage_index << MT6357_AUD_MICBIAS0_VREF_SFT); + + micbias_voltage_index = mt6357_get_micbias_idx(np, "mediatek,micbias1-microvolt"); + regmap_update_bits(priv->regmap, MT6357_AUDENC_ANA_CON9, + MT6357_AUD_MICBIAS1_VREF_MASK, + micbias_voltage_index << MT6357_AUD_MICBIAS1_VREF_SFT); + + return 0; +} + +static int mt6357_platform_driver_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); + struct mt6357_priv *priv; + int ret; + + ret = devm_regulator_get_enable(&pdev->dev, "vaud28"); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to enable vaud28 regulator\n"); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, priv); + priv->dev = &pdev->dev; + + priv->regmap = mt6397->regmap; + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + ret = mt6357_parse_dt(priv); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to parse dts\n"); + + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64); + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + + return devm_snd_soc_register_component(&pdev->dev, + &mt6357_soc_component_driver, + mtk_6357_dai_codecs, + ARRAY_SIZE(mtk_6357_dai_codecs)); +} + +static const struct platform_device_id mt6357_platform_ids[] = { + {"mt6357-sound", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6357_platform_ids); + +static struct platform_driver mt6357_platform_driver = { + .driver = { + .name = "mt6357-sound", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .probe = mt6357_platform_driver_probe, + .id_table = mt6357_platform_ids, +}; + +module_platform_driver(mt6357_platform_driver) + +MODULE_DESCRIPTION("MT6357 ALSA SoC codec driver"); +MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/mt6357.h b/sound/soc/codecs/mt6357.h new file mode 100644 index 000000000000..7f6fccada6a2 --- /dev/null +++ b/sound/soc/codecs/mt6357.h @@ -0,0 +1,660 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt6357.h -- mt6357 ALSA SoC audio codec driver + * + * Copyright (c) 2024 Baylibre + * Author: Nicolas Belin <nbelin@baylibre.com> + */ + +#ifndef __MT6357_H__ +#define __MT6357_H__ + +#include <linux/types.h> + +/* Reg bit defines */ +/* MT6357_GPIO_DIR0 */ +#define MT6357_GPIO8_DIR_MASK BIT(8) +#define MT6357_GPIO8_DIR_INPUT 0 +#define MT6357_GPIO8_DIR_OUTPUT BIT(8) +#define MT6357_GPIO9_DIR_MASK BIT(9) +#define MT6357_GPIO9_DIR_INPUT 0 +#define MT6357_GPIO9_DIR_OUTPUT BIT(9) +#define MT6357_GPIO10_DIR_MASK BIT(10) +#define MT6357_GPIO10_DIR_INPUT 0 +#define MT6357_GPIO10_DIR_OUTPUT BIT(10) +#define MT6357_GPIO11_DIR_MASK BIT(11) +#define MT6357_GPIO11_DIR_INPUT 0 +#define MT6357_GPIO11_DIR_OUTPUT BIT(11) +#define MT6357_GPIO12_DIR_MASK BIT(12) +#define MT6357_GPIO12_DIR_INPUT 0 +#define MT6357_GPIO12_DIR_OUTPUT BIT(12) +#define MT6357_GPIO13_DIR_MASK BIT(13) +#define MT6357_GPIO13_DIR_INPUT 0 +#define MT6357_GPIO13_DIR_OUTPUT BIT(13) +#define MT6357_GPIO14_DIR_MASK BIT(14) +#define MT6357_GPIO14_DIR_INPUT 0 +#define MT6357_GPIO14_DIR_OUTPUT BIT(14) +#define MT6357_GPIO15_DIR_MASK BIT(15) +#define MT6357_GPIO15_DIR_INPUT 0 +#define MT6357_GPIO15_DIR_OUTPUT BIT(15) + +/* MT6357_GPIO_MODE2 */ +#define MT6357_GPIO8_MODE_MASK GENMASK(2, 0) +#define MT6357_GPIO8_MODE_AUD_CLK_MOSI BIT(0) +#define MT6357_GPIO8_MODE_GPIO 0 +#define MT6357_GPIO9_MODE_MASK GENMASK(5, 3) +#define MT6357_GPIO9_MODE_AUD_DAT_MOSI0 BIT(3) +#define MT6357_GPIO9_MODE_GPIO 0 +#define MT6357_GPIO10_MODE_MASK GENMASK(8, 6) +#define MT6357_GPIO10_MODE_AUD_DAT_MOSI1 BIT(6) +#define MT6357_GPIO10_MODE_GPIO 0 +#define MT6357_GPIO11_MODE_MASK GENMASK(11, 9) +#define MT6357_GPIO11_MODE_AUD_SYNC_MOSI BIT(9) +#define MT6357_GPIO11_MODE_GPIO 0 + +/* MT6357_GPIO_MODE2_SET */ +#define MT6357_GPIO8_MODE_SET_MASK GENMASK(2, 0) +#define MT6357_GPIO8_MODE_SET_AUD_CLK_MOSI BIT(0) +#define MT6357_GPIO9_MODE_SET_MASK GENMASK(5, 3) +#define MT6357_GPIO9_MODE_SET_AUD_DAT_MOSI0 BIT(3) +#define MT6357_GPIO10_MODE_SET_MASK GENMASK(8, 6) +#define MT6357_GPIO10_MODE_SET_AUD_DAT_MOSI1 BIT(6) +#define MT6357_GPIO11_MODE_SET_MASK GENMASK(11, 9) +#define MT6357_GPIO11_MODE_SET_AUD_SYNC_MOSI BIT(9) + +/* MT6357_GPIO_MODE2_CLR */ +#define MT6357_GPIO_MODE2_CLEAR_ALL GENMASK(15, 0) + +/* MT6357_GPIO_MODE3 */ +#define MT6357_GPIO12_MODE_MASK GENMASK(2, 0) +#define MT6357_GPIO12_MODE_AUD_CLK_MISO BIT(0) +#define MT6357_GPIO12_MODE_GPIO 0 +#define MT6357_GPIO13_MODE_MASK GENMASK(5, 3) +#define MT6357_GPIO13_MODE_AUD_DAT_MISO0 BIT(3) +#define MT6357_GPIO13_MODE_GPIO 0 +#define MT6357_GPIO14_MODE_MASK GENMASK(8, 6) +#define MT6357_GPIO14_MODE_AUD_DAT_MISO1 BIT(6) +#define MT6357_GPIO14_MODE_GPIO 0 +#define MT6357_GPIO15_MODE_MASK GENMASK(11, 9) +#define MT6357_GPIO15_MODE_AUD_SYNC_MISO BIT(9) +#define MT6357_GPIO15_MODE_GPIO 0 + +/* MT6357_GPIO_MODE3_SET */ +#define MT6357_GPIO12_MODE_SET_MASK GENMASK(2, 0) +#define MT6357_GPIO12_MODE_SET_AUD_CLK_MISO BIT(0) +#define MT6357_GPIO13_MODE_SET_MASK GENMASK(5, 3) +#define MT6357_GPIO13_MODE_SET_AUD_DAT_MISO0 BIT(3) +#define MT6357_GPIO14_MODE_SET_MASK GENMASK(8, 6) +#define MT6357_GPIO14_MODE_SET_AUD_DAT_MISO1 BIT(6) +#define MT6357_GPIO15_MODE_SET_MASK GENMASK(11, 9) +#define MT6357_GPIO15_MODE_SET_AUD_SYNC_MISO BIT(9) + +/* MT6357_GPIO_MODE3_CLR */ +#define MT6357_GPIO_MODE3_CLEAR_ALL GENMASK(15, 0) + +/* MT6357_DCXO_CW14 */ +#define MT6357_XO_AUDIO_EN_M_SFT 13 +#define MT6357_XO_AUDIO_EN_M_MASK BIT(13) +#define MT6357_XO_AUDIO_EN_M_ENABLE BIT(13) +#define MT6357_XO_AUDIO_EN_M_DISABLE 0 + +/* MT6357_AUD_TOP_CKPDN_CON0 */ +#define MT6357_AUDNCP_CK_PDN_SFT 6 +#define MT6357_ZCD13M_CK_PDN_SFT 5 +#define MT6357_AUDIF_CK_PDN_SFT 2 +#define MT6357_AUD_CK_PDN_SFT 1 + +/* MT6357_AUDNCP_CLKDIV_CON0 */ +#define MT6357_DIVCKS_CHG BIT(0) + +/* MT6357_AUDNCP_CLKDIV_CON1 */ +#define MT6357_DIVCKS_ON BIT(0) + +/* MT6357_AUDNCP_CLKDIV_CON3 */ +#define MT6357_DIVCKS_PWD_NCP_MASK BIT(0) +#define MT6357_DIVCKS_PWD_NCP_DISABLE BIT(0) +#define MT6357_DIVCKS_PWD_NCP_ENABLE 0 + +/* MT6357_AUDNCP_CLKDIV_CON4 */ +#define MT6357_DIVCKS_PWD_NCP_ST_SEL_MASK GENMASK(1, 0) +#define MT6357_DIVCKS_PWD_NCP_ST_50US 0 +#define MT6357_DIVCKS_PWD_NCP_ST_100US 1 +#define MT6357_DIVCKS_PWD_NCP_ST_150US 2 +#define MT6357_DIVCKS_PWD_NCP_ST_200US 3 + +/* MT6357_AFE_UL_DL_CON0 */ +#define MT6357_AFE_UL_LR_SWAP_SFT 15 +#define MT6357_AFE_ON_SFT 0 + +/* MT6357_AFE_DL_SRC2_CON0_L */ +#define MT6357_DL_2_SRC_ON_TMP_CTL_PRE_SFT 0 + +/* MT6357_AFE_UL_SRC_CON0_H */ +#define MT6357_C_TWO_DIGITAL_MIC_CTL_MASK BIT(7) +#define MT6357_C_TWO_DIGITAL_MIC_ENABLE BIT(7) +#define MT6357_C_TWO_DIGITAL_MIC_DISABLE 0 + +/* MT6357_AFE_UL_SRC_CON0_L */ +#define MT6357_UL_SDM_3_LEVEL_CTL_MASK BIT(1) +#define MT6357_UL_SDM_3_LEVEL_SELECT BIT(1) +#define MT6357_UL_SDM_3_LEVEL_DESELECT 0 +#define MT6357_UL_SRC_ON_TMP_CTL_MASK BIT(0) +#define MT6357_UL_SRC_ENABLE BIT(0) +#define MT6357_UL_SRC_DISABLE 0 + +/* MT6357_AFE_TOP_CON0 */ +#define MT6357_UL_SINE_ON_SFT 1 +#define MT6357_UL_SINE_ON_MASK BIT(1) +#define MT6357_DL_SINE_ON_SFT 0 +#define MT6357_DL_SINE_ON_MASK BIT(0) + +/* MT6357_AUDIO_TOP_CON0 */ +#define MT6357_PDN_LPBK_CTL_SFT 15 +#define MT6357_PDN_AFE_CTL_SFT 7 +#define MT6357_PDN_DAC_CTL_SFT 6 +#define MT6357_PDN_ADC_CTL_SFT 5 +#define MT6357_PDN_I2S_DL_CTL_SFT 3 +#define MT6357_PWR_CLK_DIS_CTL_SFT 2 +#define MT6357_PDN_AFE_TESTMODEL_CTL_SFT 1 +#define MT6357_PDN_RESERVED_SFT 0 + +/* MT6357_AFUNC_AUD_CON0 */ +#define MT6357_CCI_AUD_ANACK_INVERT BIT(15) +#define MT6357_CCI_AUD_ANACK_NORMAL 0 +#define MT6357_CCI_AUDIO_FIFO_WPTR_SFT 12 +#define MT6357_CCI_SCRAMBLER_CG_ENABLE BIT(11) +#define MT6357_CCI_SCRAMBLER_CG_DISABLE 0 +#define MT6357_CCI_LCK_INV_OUT_OF_PHASE BIT(10) +#define MT6357_CCI_LCK_INV_IN_PHASE 0 +#define MT6357_CCI_RAND_ENABLE BIT(9) +#define MT6357_CCI_RAND_DISABLE 0 +#define MT6357_CCI_SPLT_SCRMB_CLK_ON BIT(8) +#define MT6357_CCI_SPLT_SCRMB_CLK_OFF 0 +#define MT6357_CCI_SPLT_SCRMB_ON BIT(7) +#define MT6357_CCI_SPLT_SCRMB_OFF 0 +#define MT6357_CCI_AUD_IDAC_TEST_EN_FROM_TEST_IN BIT(6) +#define MT6357_CCI_AUD_IDAC_TEST_EN_NORMAL_PATH 0 +#define MT6357_CCI_ZERO_PADDING_DISABLE BIT(5) +#define MT6357_CCI_ZERO_PADDING_ENABLE 0 +#define MT6357_CCI_AUD_SPLIT_TEST_EN_FROM_TEST_IN BIT(4) +#define MT6357_CCI_AUD_SPLIT_TEST_EN_NORMAL_PATH 0 +#define MT6357_CCI_AUD_SDM_MUTE_L_REG_CTL BIT(3) +#define MT6357_CCI_AUD_SDM_MUTE_L_NO_CTL 0 +#define MT6357_CCI_AUD_SDM_MUTE_R_REG_CTL BIT(2) +#define MT6357_CCI_AUD_SDM_MUTE_R_NO_CTL 0 +#define MT6357_CCI_AUD_SDM_7BIT_FROM_SPLITTER3 BIT(1) +#define MT6357_CCI_AUD_SDM_7BIT_FROM_SPLITTER1 0 +#define MT6357_CCI_SCRAMBLER_ENABLE BIT(0) +#define MT6357_CCI_SCRAMBLER_DISABLE 0 + +/* MT6357_AFUNC_AUD_CON2 */ +#define MT6357_CCI_AUDIO_FIFO_ENABLE BIT(3) +#define MT6357_CCI_AUDIO_FIFO_DISABLE 0 +#define MT6357_CCI_ACD_MODE_NORMAL_PATH BIT(2) +#define MT6357_CCI_ACD_MODE_TEST_PATH 0 +#define MT6357_CCI_AFIFO_CLK_PWDB_ON BIT(1) +#define MT6357_CCI_AFIFO_CLK_PWDB_DOWN 0 +#define MT6357_CCI_ACD_FUNC_RSTB_RELEASE BIT(0) +#define MT6357_CCI_ACD_FUNC_RSTB_RESET 0 + +/* MT6357_AFE_ADDA_MTKAIF_CFG0 */ +#define MT6357_ADDA_MTKAIF_LPBK_CTL_MASK BIT(1) +#define MT6357_ADDA_MTKAIF_LPBK_ENABLE BIT(1) +#define MT6357_ADDA_MTKAIF_LPBK_DISABLE 0 + +/* MT6357_AFE_SGEN_CFG0 */ +#define MT6357_SGEN_DAC_EN_CTL_SFT 7 +#define MT6357_SGEN_DAC_ENABLE BIT(7) +#define MT6357_SGEN_MUTE_SW_CTL_SFT 6 +#define MT6357_SGEN_MUTE_SW_DISABLE 0 + +/* MT6357_AFE_DCCLK_CFG0 */ +#define MT6357_DCCLK_DIV_MASK GENMASK(15, 5) +#define MT6357_DCCLK_DIV_SFT 5 +#define MT6357_DCCLK_DIV_RUN_VALUE (32 << MT6357_DCCLK_DIV_SFT) +#define MT6357_DCCLK_DIV_STOP_VALUE (259 << MT6357_DCCLK_DIV_SFT) +#define MT6357_DCCLK_PDN_MASK BIT(1) +#define MT6357_DCCLK_PDN BIT(1) +#define MT6357_DCCLK_OUTPUT 0 +#define MT6357_DCCLK_GEN_ON_MASK BIT(0) +#define MT6357_DCCLK_GEN_ON BIT(0) +#define MT6357_DCCLK_GEN_OFF 0 + +/* MT6357_AFE_DCCLK_CFG1 */ +#define MT6357_DCCLK_RESYNC_BYPASS_MASK BIT(8) +#define MT6357_DCCLK_RESYNC_BYPASS BIT(8) + +/* MT6357_AFE_AUD_PAD_TOP */ +#define MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_MASK GENMASK(15, 8) +#define MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_ENABLE (BIT(13) | BIT(12) | BIT(8)) +#define MT6357_AUD_PAD_TX_FIFO_NORMAL_PATH_DISABLE (BIT(13) | BIT(12)) +#define MT6357_AUD_PAD_TX_FIFO_LPBK_MASK GENMASK(7, 0) +#define MT6357_AUD_PAD_TX_FIFO_LPBK_ENABLE (BIT(5) | BIT(4) | BIT(0)) +#define MT6357_AUD_PAD_TX_FIFO_LPBK_DISABLE 0 + +/* MT6357_AUDENC_ANA_CON0 */ +#define MT6357_AUDADCLINPUTSEL_MASK GENMASK(14, 13) +#define MT6357_AUDADCLINPUTSEL_PREAMPLIFIER BIT(14) +#define MT6357_AUDADCLINPUTSEL_IDLE 0 +#define MT6357_AUDADCLPWRUP_SFT 12 +#define MT6357_AUDADCLPWRUP_MASK BIT(12) +#define MT6357_AUDADCLPWRUP BIT(12) +#define MT6357_AUDADCLPWRDOWN 0 +#define MT6357_AUDPREAMPLGAIN_SFT 8 +#define MT6357_AUDPREAMPLGAIN_MASK GENMASK(10, 8) +#define MT6357_AUDPREAMPLGAIN_MAX 4 +#define MT6357_AUDPREAMPLINPUTSEL_SFT 6 +#define MT6357_AUDPREAMPLINPUTSEL_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUDPREAMPLDCPRECHARGE_MASK BIT(2) +#define MT6357_AUDPREAMPLDCPRECHARGE_ENABLE BIT(2) +#define MT6357_AUDPREAMPLDCPRECHARGE_DISABLE 0 +#define MT6357_AUDPREAMPLDCCEN_MASK BIT(1) +#define MT6357_AUDPREAMPLDCCEN_DC BIT(1) +#define MT6357_AUDPREAMPLDCCEN_AC 0 +#define MT6357_AUDPREAMPLON_MASK BIT(0) +#define MT6357_AUDPREAMPLON_ENABLE BIT(0) +#define MT6357_AUDPREAMPLON_DISABLE 0 + +/* MT6357_AUDENC_ANA_CON1 */ +#define MT6357_AUDADCRINPUTSEL_MASK GENMASK(14, 13) +#define MT6357_AUDADCRINPUTSEL_PREAMPLIFIER BIT(14) +#define MT6357_AUDADCRINPUTSEL_IDLE 0 +#define MT6357_AUDADCRPWRUP_SFT 12 +#define MT6357_AUDADCRPWRUP_MASK BIT(12) +#define MT6357_AUDADCRPWRUP BIT(12) +#define MT6357_AUDADCRPWRDOWN 0 +#define MT6357_AUDPREAMPRGAIN_SFT 8 +#define MT6357_AUDPREAMPRGAIN_MASK GENMASK(10, 8) +#define MT6357_AUDPREAMPRGAIN_MAX 4 +#define MT6357_AUDPREAMPRINPUTSEL_SFT 6 +#define MT6357_AUDPREAMPRINPUTSEL_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUDPREAMPRDCPRECHARGE_MASK BIT(2) +#define MT6357_AUDPREAMPRDCPRECHARGE_ENABLE BIT(2) +#define MT6357_AUDPREAMPRDCPRECHARGE_DISABLE 0 +#define MT6357_AUDPREAMPRDCCEN_MASK BIT(1) +#define MT6357_AUDPREAMPRDCCEN_DC BIT(1) +#define MT6357_AUDPREAMPRDCCEN_AC 0 +#define MT6357_AUDPREAMPRON_MASK BIT(0) +#define MT6357_AUDPREAMPRON_ENABLE BIT(0) +#define MT6357_AUDPREAMPRON_DISABLE 0 + +/* MT6357_AUDENC_ANA_CON6 */ +#define MT6357_CLKSQ_EN_SFT 0 + +/* MT6357_AUDENC_ANA_CON7 */ +#define MT6357_AUDDIGMICBIAS_MASK GENMASK(2, 1) +#define MT6357_AUDDIGMICBIAS_DEFAULT_VALUE BIT(2) +#define MT6357_AUDDIGMICBIAS_OFF 0 +#define MT6357_AUDDIGMICEN_MASK BIT(0) +#define MT6357_AUDDIGMICEN_ENABLE BIT(0) +#define MT6357_AUDDIGMICEN_DISABLE 0 + +/* MT6357_AUDENC_ANA_CON8 */ +#define MT6357_AUD_MICBIAS0_DCSW2N_EN_MASK BIT(14) +#define MT6357_AUD_MICBIAS0_DCSW2N_ENABLE BIT(14) +#define MT6357_AUD_MICBIAS0_DCSW2N_DISABLE 0 +#define MT6357_AUD_MICBIAS0_DCSW2P2_EN_MASK BIT(13) +#define MT6357_AUD_MICBIAS0_DCSW2P2_ENABLE BIT(13) +#define MT6357_AUD_MICBIAS0_DCSW2P2_DISABLE 0 +#define MT6357_AUD_MICBIAS0_DCSW2P1_EN_MASK BIT(12) +#define MT6357_AUD_MICBIAS0_DCSW2P1_ENABLE BIT(12) +#define MT6357_AUD_MICBIAS0_DCSW2P1_DISABLE 0 +#define MT6357_AUD_MICBIAS0_DCSW0N_EN_MASK BIT(10) +#define MT6357_AUD_MICBIAS0_DCSW0N_ENABLE BIT(10) +#define MT6357_AUD_MICBIAS0_DCSWN_DISABLE 0 +#define MT6357_AUD_MICBIAS0_DCSW0P2_EN_MASK BIT(9) +#define MT6357_AUD_MICBIAS0_DCSW0P2_ENABLE BIT(9) +#define MT6357_AUD_MICBIAS0_DCSW0P2_DISABLE 0 +#define MT6357_AUD_MICBIAS0_DCSW0P1_EN_MASK BIT(8) +#define MT6357_AUD_MICBIAS0_DCSW0P1_ENABLE BIT(8) +#define MT6357_AUD_MICBIAS0_DCSW0P1_DISABLE 0 +#define MT6357_AUD_MICBIAS0_VREF_MASK GENMASK(6, 4) +#define MT6357_AUD_MICBIAS0_VREF_SFT 4 +#define MT6357_AUD_MICBIAS0_PWD_SFT 0 + +#define MT6357_AUD_MICBIAS0_DC_MASK (MT6357_AUD_MICBIAS0_DCSW2N_EN_MASK | \ + MT6357_AUD_MICBIAS0_DCSW2P2_EN_MASK | \ + MT6357_AUD_MICBIAS0_DCSW2P1_EN_MASK | \ + MT6357_AUD_MICBIAS0_DCSW0N_EN_MASK | \ + MT6357_AUD_MICBIAS0_DCSW0P2_EN_MASK | \ + MT6357_AUD_MICBIAS0_DCSW0P1_EN_MASK) + +#define MT6357_AUD_MICBIAS0_DC_ENABLE_ALL (MT6357_AUD_MICBIAS0_DCSW2N_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW2P2_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW2P1_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW0N_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW0P2_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW0P1_ENABLE) + +#define MT6357_AUD_MICBIAS0_DC_ENABLE_P1 (MT6357_AUD_MICBIAS0_DCSW2P1_ENABLE | \ + MT6357_AUD_MICBIAS0_DCSW0P1_ENABLE) + +#define MT6357_AUD_MICBIAS0_DC_DISABLE_ALL 0 + +/* MT6357_AUDENC_ANA_CON9 */ +#define MT6357_AUD_MICBIAS1_DCSW1P_EN_MASK BIT(8) +#define MT6357_AUD_MICBIAS1_DCSW1P_ENABLE BIT(8) +#define MT6357_AUD_MICBIAS1_DCSW1P_DISABLE 0 +#define MT6357_AUD_MICBIAS1_VREF_MASK GENMASK(6, 4) +#define MT6357_AUD_MICBIAS1_VREF_SFT 4 +#define MT6357_AUD_MICBIAS1_PWD_SFT 0 + +/* MT6357_AUDDEC_ANA_CON0 */ +#define MT6357_AUD_HPR_SC_VAUDP15_MASK BIT(13) +#define MT6357_AUD_HPR_SC_VAUDP15_DISABLE BIT(13) +#define MT6357_AUD_HPR_SC_VAUDP15_ENABLE 0 +#define MT6357_AUD_HPL_SC_VAUDP15_MASK BIT(12) +#define MT6357_AUD_HPL_SC_VAUDP15_DISABLE BIT(12) +#define MT6357_AUD_HPL_SC_VAUDP15_ENABLE 0 +#define MT6357_AUD_HPR_MUX_INPUT_VAUDP15_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUD_HPR_MUX_INPUT_VAUDP15_SFT 10 +#define MT6357_AUD_HPL_MUX_INPUT_VAUDP15_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUD_HPL_MUX_INPUT_VAUDP15_SFT 8 +#define MT6357_AUD_HPR_BIAS_VAUDP15_MASK BIT(7) +#define MT6357_AUD_HPR_BIAS_VAUDP15_ENABLE BIT(7) +#define MT6357_AUD_HPR_BIAS_VAUDP15_DISABLE 0 +#define MT6357_AUD_HPL_BIAS_VAUDP15_MASK BIT(6) +#define MT6357_AUD_HPL_BIAS_VAUDP15_ENABLE BIT(6) +#define MT6357_AUD_HPL_BIAS_VAUDP15_DISABLE 0 +#define MT6357_AUD_HPR_PWRUP_VAUDP15_MASK BIT(5) +#define MT6357_AUD_HPR_PWRUP_VAUDP15_ENABLE BIT(5) +#define MT6357_AUD_HPR_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_AUD_HPL_PWRUP_VAUDP15_MASK BIT(4) +#define MT6357_AUD_HPL_PWRUP_VAUDP15_ENABLE BIT(4) +#define MT6357_AUD_HPL_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_AUD_DACL_PWRUP_VA28_MASK BIT(3) +#define MT6357_AUD_DACL_PWRUP_VA28_ENABLE BIT(3) +#define MT6357_AUD_DACL_PWRUP_VA28_DISABLE 0 +#define MT6357_AUD_DACR_PWRUP_VA28_MASK BIT(2) +#define MT6357_AUD_DACR_PWRUP_VA28_ENABLE BIT(2) +#define MT6357_AUD_DACR_PWRUP_VA28_DISABLE 0 +#define MT6357_AUD_DACR_PWRUP_VAUDP15_MASK BIT(1) +#define MT6357_AUD_DACR_PWRUP_VAUDP15_ENABLE BIT(1) +#define MT6357_AUD_DACR_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_AUD_DACL_PWRUP_VAUDP15_MASK BIT(0) +#define MT6357_AUD_DACL_PWRUP_VAUDP15_ENABLE BIT(0) +#define MT6357_AUD_DACL_PWRUP_VAUDP15_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON1 */ +#define MT6357_HPROUT_STG_CTRL_VAUDP15_MASK GENMASK(14, 12) +#define MT6357_HPROUT_STG_CTRL_VAUDP15_SFT 12 +#define MT6357_HPLOUT_STG_CTRL_VAUDP15_MASK GENMASK(10, 8) +#define MT6357_HPLOUT_STG_CTRL_VAUDP15_SFT 8 +#define MT6357_HPLOUT_STG_CTRL_VAUDP15_MAX 7 +#define MT6357_HPR_SHORT2HPR_AUX_VAUDP15_MASK BIT(7) +#define MT6357_HPR_SHORT2HPR_AUX_VAUDP15_ENABLE BIT(7) +#define MT6357_HPR_SHORT2HPR_AUX_VAUDP15_DISABLE 0 +#define MT6357_HPL_SHORT2HPR_AUX_VAUDP15_MASK BIT(6) +#define MT6357_HPL_SHORT2HPR_AUX_VAUDP15_ENABLE BIT(6) +#define MT6357_HPL_SHORT2HPR_AUX_VAUDP15_DISABLE 0 +#define MT6357_HPR_AUX_FBRSW_VAUDP15_MASK BIT(5) +#define MT6357_HPR_AUX_FBRSW_VAUDP15_ENABLE BIT(5) +#define MT6357_HPR_AUX_FBRSW_VAUDP15_DISABLE 0 +#define MT6357_HPL_AUX_FBRSW_VAUDP15_MASK BIT(4) +#define MT6357_HPL_AUX_FBRSW_VAUDP15_ENABLE BIT(4) +#define MT6357_HPL_AUX_FBRSW_VAUDP15_DISABLE 0 +#define MT6357_HPROUT_AUX_PWRUP_VAUDP15_MASK BIT(3) +#define MT6357_HPROUT_AUX_PWRUP_VAUDP15_ENABLE BIT(3) +#define MT6357_HPROUT_AUX_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_HPLOUT_AUX_PWRUP_VAUDP15_MASK BIT(2) +#define MT6357_HPLOUT_AUX_PWRUP_VAUDP15_ENABLE BIT(2) +#define MT6357_HPLOUT_AUX_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_HPROUT_PWRUP_VAUDP15_MASK BIT(1) +#define MT6357_HPROUT_PWRUP_VAUDP15_ENABLE BIT(1) +#define MT6357_HPROUT_PWRUP_VAUDP15_DISABLE 0 +#define MT6357_HPLOUT_PWRUP_VAUDP15_MASK BIT(0) +#define MT6357_HPLOUT_PWRUP_VAUDP15_ENABLE BIT(0) +#define MT6357_HPLOUT_PWRUP_VAUDP15_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON2 */ +#define MT6357_HPP_SHORT_2VCM_VAUDP15_MASK BIT(10) +#define MT6357_HPP_SHORT_2VCM_VAUDP15_ENABLE BIT(10) +#define MT6357_HPP_SHORT_2VCM_VAUDP15_DISABLE 0 +#define MT6357_AUD_REFN_DERES_VAUDP15_MASK BIT(9) +#define MT6357_AUD_REFN_DERES_VAUDP15_ENABLE BIT(9) +#define MT6357_AUD_REFN_DERES_VAUDP15_DISABLE 0 +#define MT6357_HPROUT_STB_ENH_VAUDP15_MASK GENMASK(6, 4) +#define MT6357_HPROUT_STB_ENH_VAUDP15_OPEN 0 +#define MT6357_HPROUT_STB_ENH_VAUDP15_NOPEN_P250 BIT(4) +#define MT6357_HPROUT_STB_ENH_VAUDP15_N470_POPEN BIT(5) +#define MT6357_HPROUT_STB_ENH_VAUDP15_N470_P250 (BIT(4) | BIT(5)) +#define MT6357_HPROUT_STB_ENH_VAUDP15_NOPEN_P470 (BIT(4) | BIT(6)) +#define MT6357_HPROUT_STB_ENH_VAUDP15_N470_P470 (BIT(4) | BIT(5) | BIT(6)) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_MASK GENMASK(2, 0) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_OPEN 0 +#define MT6357_HPLOUT_STB_ENH_VAUDP15_NOPEN_P250 BIT(0) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_N470_POPEN BIT(1) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_N470_P250 (BIT(0) | BIT(1)) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_NOPEN_P470 (BIT(0) | BIT(2)) +#define MT6357_HPLOUT_STB_ENH_VAUDP15_N470_P470 (BIT(0) | BIT(1) | BIT(2)) + +/* MT6357_AUDDEC_ANA_CON3 */ +#define MT6357_AUD_HSOUT_STB_ENH_VAUDP15_MASK BIT(7) +#define MT6357_AUD_HSOUT_STB_ENH_VAUDP15_ENABLE BIT(7) +#define MT6357_AUD_HSOUT_STB_ENH_VAUDP15_DISABLE 0 +#define MT6357_AUD_HS_SC_VAUDP15_MASK BIT(4) +#define MT6357_AUD_HS_SC_VAUDP15_DISABLE BIT(4) +#define MT6357_AUD_HS_SC_VAUDP15_ENABLE 0 +#define MT6357_AUD_HS_MUX_INPUT_VAUDP15_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUD_HS_MUX_INPUT_VAUDP15_SFT 2 +#define MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_MASK BIT(1) +#define MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_ENABLE BIT(1) +#define MT6357_AUD_HS_PWRUP_BIAS_VAUDP15_DISABLE 0 +#define MT6357_AUD_HS_PWRUP_VAUDP15_MASK BIT(0) +#define MT6357_AUD_HS_PWRUP_VAUDP15_ENABLE BIT(0) +#define MT6357_AUD_HS_PWRUP_VAUDP15_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON4 */ +#define MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_MASK BIT(8) +#define MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_ENABLE BIT(8) +#define MT6357_AUD_LOLOUT_STB_ENH_VAUDP15_DISABLE 0 +#define MT6357_AUD_LOL_SC_VAUDP15_MASK BIT(4) +#define MT6357_AUD_LOL_SC_VAUDP15_DISABLE BIT(4) +#define MT6357_AUD_LOL_SC_VAUDP15_ENABLE 0 +#define MT6357_AUD_LOL_MUX_INPUT_VAUDP15_MASK_NOSFT GENMASK(1, 0) +#define MT6357_AUD_LOL_MUX_INPUT_VAUDP15_SFT 2 +#define MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_MASK BIT(1) +#define MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_ENABLE BIT(1) +#define MT6357_AUD_LOL_PWRUP_BIAS_VAUDP15_DISABLE 0 +#define MT6357_AUD_LOL_PWRUP_VAUDP15_MASK BIT(0) +#define MT6357_AUD_LOL_PWRUP_VAUDP15_ENABLE BIT(0) +#define MT6357_AUD_LOL_PWRUP_VAUDP15_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON6 */ +#define MT6357_HP_AUX_LOOP_GAIN_MASK GENMASK(15, 12) +#define MT6357_HP_AUX_LOOP_GAIN_SFT 12 +#define MT6357_HP_AUX_LOOP_GAIN_MAX 0x0f +#define MT6357_HPR_AUX_CMFB_LOOP_MASK BIT(11) +#define MT6357_HPR_AUX_CMFB_LOOP_ENABLE BIT(11) +#define MT6357_HPR_AUX_CMFB_LOOP_DISABLE 0 +#define MT6357_HPL_AUX_CMFB_LOOP_MASK BIT(10) +#define MT6357_HPL_AUX_CMFB_LOOP_ENABLE BIT(10) +#define MT6357_HPL_AUX_CMFB_LOOP_DISABLE 0 +#define MT6357_HPRL_MAIN_CMFB_LOOP_MASK BIT(9) +#define MT6357_HPRL_MAIN_CMFB_LOOP_ENABLE BIT(9) +#define MT6357_HPRL_MAIN_CMFB_LOOP_DISABLE 0 +#define MT6357_HP_CMFB_RST_MASK BIT(7) +#define MT6357_HP_CMFB_RST_NORMAL BIT(7) +#define MT6357_HP_CMFB_RST_RESET 0 +#define MT6357_DAC_LOW_NOISE_MODE_MASK BIT(0) +#define MT6357_DAC_LOW_NOISE_MODE_ENABLE BIT(0) +#define MT6357_DAC_LOW_NOISE_MODE_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON7 */ +#define MT6357_HP_IVBUF_DEGAIN_SFT 2 +#define MT6357_HP_IVBUF_DEGAIN_MAX 1 + +/* MT6357_AUDDEC_ANA_CON10 */ +#define MT6357_AUD_IBIAS_PWRDN_VAUDP15_MASK BIT(8) +#define MT6357_AUD_IBIAS_PWRDN_VAUDP15_DISABLE BIT(8) +#define MT6357_AUD_IBIAS_PWRDN_VAUDP15_ENABLE 0 + +/* MT6357_AUDDEC_ANA_CON11 */ +#define MT6357_RSTB_ENCODER_VA28_MASK BIT(5) +#define MT6357_RSTB_ENCODER_VA28_ENABLE BIT(5) +#define MT6357_RSTB_ENCODER_VA28_DISABLE 0 +#define MT6357_AUDGLB_PWRDN_VA28_SFT 4 +#define MT6357_RSTB_DECODER_VA28_MASK BIT(0) +#define MT6357_RSTB_DECODER_VA28_ENABLE BIT(0) +#define MT6357_RSTB_DECODER_VA28_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON12 */ +#define MT6357_VA28REFGEN_EN_VA28_MASK BIT(13) +#define MT6357_VA28REFGEN_EN_VA28_ENABLE BIT(13) +#define MT6357_VA28REFGEN_EN_VA28_DISABLE 0 +#define MT6357_VA33REFGEN_EN_VA18_MASK BIT(12) +#define MT6357_VA33REFGEN_EN_VA18_ENABLE BIT(12) +#define MT6357_VA33REFGEN_EN_VA18_DISABLE 0 +#define MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_MASK BIT(10) +#define MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_ENABLE BIT(10) +#define MT6357_LCLDO_ENC_REMOTE_SENSE_VA28_DISABLE 0 +#define MT6357_LCLDO_ENC_EN_VA28_MASK BIT(8) +#define MT6357_LCLDO_ENC_EN_VA28_ENABLE BIT(8) +#define MT6357_LCLDO_ENC_EN_VA28_DISABLE 0 +#define MT6357_LCLDO_REMOTE_SENSE_VA18_MASK BIT(6) +#define MT6357_LCLDO_REMOTE_SENSE_VA18_ENABLE BIT(6) +#define MT6357_LCLDO_REMOTE_SENSE_VA18_DISABLE 0 +#define MT6357_LCLDO_EN_VA18_MASK BIT(4) +#define MT6357_LCLDO_EN_VA18_ENABLE BIT(4) +#define MT6357_LCLDO_EN_VA18_DISABLE 0 +#define MT6357_HCLDO_REMOTE_SENSE_VA18_MASK BIT(2) +#define MT6357_HCLDO_REMOTE_SENSE_VA18_ENABLE BIT(2) +#define MT6357_HCLDO_REMOTE_SENSE_VA18_DISABLE 0 +#define MT6357_HCLDO_EN_VA18_MASK BIT(0) +#define MT6357_HCLDO_EN_VA18_ENABLE BIT(0) +#define MT6357_HCLDO_EN_VA18_DISABLE 0 + +/* MT6357_AUDDEC_ANA_CON13 */ +#define MT6357_NVREG_EN_VAUDP15_MASK BIT(0) +#define MT6357_NVREG_EN_VAUDP15_ENABLE BIT(0) +#define MT6357_NVREG_EN_VAUDP15_DISABLE 0 + +/* MT6357_AUDDEC_ELR_0 */ +#define MT6357_AUD_HP_TRIM_EN_VAUDP15_MASK BIT(12) +#define MT6357_AUD_HP_TRIM_EN_VAUDP15_ENABLE BIT(12) +#define MT6357_AUD_HP_TRIM_EN_VAUDP15_DISABLE 0 + +/* MT6357_ZCD_CON1 */ +#define MT6357_AUD_LOL_GAIN_MASK GENMASK(4, 0) +#define MT6357_AUD_LOL_GAIN_SFT 0 +#define MT6357_AUD_LOR_GAIN_MASK GENMASK(11, 7) +#define MT6357_AUD_LOR_GAIN_SFT 7 +#define MT6357_AUD_LO_GAIN_MAX 0x12 + +/* MT6357_ZCD_CON2 */ +#define MT6357_AUD_HPL_GAIN_MASK GENMASK(4, 0) +#define MT6357_AUD_HPL_GAIN_SFT 0 +#define MT6357_AUD_HPR_GAIN_MASK GENMASK(11, 7) +#define MT6357_AUD_HPR_GAIN_SFT 7 +#define MT6357_AUD_HP_GAIN_MAX 0x12 + +/* MT6357_ZCD_CON3 */ +#define MT6357_AUD_HS_GAIN_MASK GENMASK(4, 0) +#define MT6357_AUD_HS_GAIN_SFT 0 +#define MT6357_AUD_HS_GAIN_MAX 0x12 + +/* Registers list */ +/* gpio direction */ +#define MT6357_GPIO_DIR0 0x0088 +/* mosi */ +#define MT6357_GPIO_MODE2 0x00B6 +#define MT6357_GPIO_MODE2_SET 0x00B8 +#define MT6357_GPIO_MODE2_CLR 0x00BA +/* miso */ +#define MT6357_GPIO_MODE3 0x00BC +#define MT6357_GPIO_MODE3_SET 0x00BE +#define MT6357_GPIO_MODE3_CLR 0x00C0 + +#define MT6357_DCXO_CW14 0x07AC + +#define MT6357_AUD_TOP_CKPDN_CON0 0x208C +#define MT6357_AUDNCP_CLKDIV_CON0 0x20B4 +#define MT6357_AUDNCP_CLKDIV_CON1 0x20B6 +#define MT6357_AUDNCP_CLKDIV_CON2 0x20B8 +#define MT6357_AUDNCP_CLKDIV_CON3 0x20BA +#define MT6357_AUDNCP_CLKDIV_CON4 0x20BC +#define MT6357_AFE_UL_DL_CON0 0x2108 +#define MT6357_AFE_DL_SRC2_CON0_L 0x210A +#define MT6357_AFE_UL_SRC_CON0_H 0x210C +#define MT6357_AFE_UL_SRC_CON0_L 0x210E +#define MT6357_AFE_TOP_CON0 0x2110 +#define MT6357_AUDIO_TOP_CON0 0x2112 +#define MT6357_AFUNC_AUD_CON0 0x2116 +#define MT6357_AFUNC_AUD_CON2 0x211A +#define MT6357_AFE_ADDA_MTKAIF_CFG0 0x2134 +#define MT6357_AFE_SGEN_CFG0 0x2140 +#define MT6357_AFE_DCCLK_CFG0 0x2146 +#define MT6357_AFE_DCCLK_CFG1 0x2148 +#define MT6357_AFE_AUD_PAD_TOP 0x214C +#define MT6357_AUDENC_ANA_CON0 0x2188 +#define MT6357_AUDENC_ANA_CON1 0x218A +#define MT6357_AUDENC_ANA_CON6 0x2194 +#define MT6357_AUDENC_ANA_CON7 0x2196 +#define MT6357_AUDENC_ANA_CON8 0x2198 +#define MT6357_AUDENC_ANA_CON9 0x219A +#define MT6357_AUDDEC_ANA_CON0 0x2208 +#define MT6357_AUDDEC_ANA_CON1 0x220A +#define MT6357_AUDDEC_ANA_CON2 0x220C +#define MT6357_AUDDEC_ANA_CON3 0x220E +#define MT6357_AUDDEC_ANA_CON4 0x2210 +#define MT6357_AUDDEC_ANA_CON6 0x2214 +#define MT6357_AUDDEC_ANA_CON7 0x2216 +#define MT6357_AUDDEC_ANA_CON10 0x221C +#define MT6357_AUDDEC_ANA_CON11 0x221E +#define MT6357_AUDDEC_ANA_CON12 0x2220 +#define MT6357_AUDDEC_ANA_CON13 0x2222 +#define MT6357_AUDDEC_ELR_0 0x2226 +#define MT6357_ZCD_CON1 0x228A +#define MT6357_ZCD_CON2 0x228C +#define MT6357_ZCD_CON3 0x228E + +enum { + DL_GAIN_8DB = 0, + DL_GAIN_0DB = 8, + DL_GAIN_N_1DB = 9, + DL_GAIN_N_10DB = 18, + DL_GAIN_N_12DB = 20, + DL_GAIN_N_40DB = 0x1f, +}; + +enum { + UL_GAIN_0DB = 0, + UL_GAIN_6DB, + UL_GAIN_12DB, + UL_GAIN_18DB, + UL_GAIN_24DB, +}; + +#define MT6357_DL_GAIN_N_40DB_REG (DL_GAIN_N_40DB << 7 | DL_GAIN_N_40DB) +#define MT6357_DL_GAIN_REG_LEFT_MASK 0x001f +#define MT6357_DL_GAIN_REG_LEFT_SHIFT 0 +#define MT6357_DL_GAIN_REG_RIGHT_MASK 0x0f80 +#define MT6357_DL_GAIN_REG_RIGHT_SHIFT 7 +#define MT6357_DL_GAIN_REG_MASK 0x0f9f + +#define MT6357_SND_SOC_ADV_MT_FMTS (\ + SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_U16_LE |\ + SNDRV_PCM_FMTBIT_U16_BE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_U24_LE |\ + SNDRV_PCM_FMTBIT_U24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE |\ + SNDRV_PCM_FMTBIT_S32_BE |\ + SNDRV_PCM_FMTBIT_U32_LE |\ + SNDRV_PCM_FMTBIT_U32_BE) + +#define MT6357_SOC_HIGH_USE_RATE (\ + SNDRV_PCM_RATE_CONTINUOUS |\ + SNDRV_PCM_RATE_8000_192000) + +/* codec private structure */ +struct mt6357_priv { + struct device *dev; + struct regmap *regmap; + bool pull_down_needed; + int hp_channel_number; +}; +#endif diff --git a/sound/soc/codecs/peb2466.c b/sound/soc/codecs/peb2466.c index 76ee7e3f4d9b..74b628ae1964 100644 --- a/sound/soc/codecs/peb2466.c +++ b/sound/soc/codecs/peb2466.c @@ -229,7 +229,8 @@ static int peb2466_reg_read(void *context, unsigned int reg, unsigned int *val) case PEB2466_CMD_XOP: case PEB2466_CMD_SOP: ret = peb2466_read_byte(peb2466, reg, &tmp); - *val = tmp; + if (!ret) + *val = tmp; break; default: dev_err(&peb2466->spi->dev, "Not a XOP or SOP command\n"); @@ -1975,12 +1976,9 @@ static int peb2466_spi_probe(struct spi_device *spi) if (IS_ERR(peb2466->reset_gpio)) return PTR_ERR(peb2466->reset_gpio); - peb2466->mclk = devm_clk_get(&peb2466->spi->dev, "mclk"); + peb2466->mclk = devm_clk_get_enabled(&peb2466->spi->dev, "mclk"); if (IS_ERR(peb2466->mclk)) return PTR_ERR(peb2466->mclk); - ret = clk_prepare_enable(peb2466->mclk); - if (ret) - return ret; if (peb2466->reset_gpio) { gpiod_set_value_cansleep(peb2466->reset_gpio, 1); @@ -2031,17 +2029,9 @@ static int peb2466_spi_probe(struct spi_device *spi) return 0; failed: - clk_disable_unprepare(peb2466->mclk); return ret; } -static void peb2466_spi_remove(struct spi_device *spi) -{ - struct peb2466 *peb2466 = spi_get_drvdata(spi); - - clk_disable_unprepare(peb2466->mclk); -} - static const struct of_device_id peb2466_of_match[] = { { .compatible = "infineon,peb2466", }, { } @@ -2061,7 +2051,6 @@ static struct spi_driver peb2466_spi_driver = { }, .id_table = peb2466_id_table, .probe = peb2466_spi_probe, - .remove = peb2466_spi_remove, }; module_spi_driver(peb2466_spi_driver); diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 5fea600bc3a4..3c5b66357661 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -529,7 +529,7 @@ static struct platform_driver rk817_codec_driver = { .name = "rk817-codec", }, .probe = rk817_platform_probe, - .remove_new = rk817_platform_remove, + .remove = rk817_platform_remove, }; module_platform_driver(rk817_codec_driver); diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c index 83b29b441be9..e12b1e96a53a 100644 --- a/sound/soc/codecs/rt1318.c +++ b/sound/soc/codecs/rt1318.c @@ -30,7 +30,7 @@ #include "rt1318.h" -static struct reg_sequence init_list[] = { +static const struct reg_sequence init_list[] = { { 0x0000C000, 0x01}, { 0x0000F20D, 0x00}, { 0x0000F212, 0x3E}, @@ -254,7 +254,6 @@ static struct reg_sequence init_list[] = { { 0x0000C320, 0x20}, { 0x0000C203, 0x9C}, }; -#define rt1318_INIT_REG_LEN ARRAY_SIZE(init_list) static const struct reg_default rt1318_reg[] = { { 0xc000, 0x00 }, diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index 2916fa77b791..f4e1ea29c265 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -91,6 +91,2027 @@ static const struct reg_sequence rt1320_blind_write[] = { { 0xd486, 0xc3 }, }; +static const struct reg_sequence rt1320_vc_blind_write[] = { + { 0xc003, 0xe0 }, + { 0xe80a, 0x01 }, + { 0xc5c3, 0xf3 }, + { 0xc057, 0x51 }, + { 0xc054, 0x35 }, + { 0xca05, 0xd6 }, + { 0xca07, 0x07 }, + { 0xca25, 0xd6 }, + { 0xca27, 0x07 }, + { 0xc604, 0x40 }, + { 0xc609, 0x40 }, + { 0xc046, 0xff }, + { 0xc045, 0xff }, + { 0xda81, 0x14 }, + { 0xda8d, 0x14 }, + { 0xc044, 0xff }, + { 0xc043, 0xff }, + { 0xc042, 0xff }, + { 0xc041, 0x7f }, + { 0xc040, 0xff }, + { 0xcc10, 0x01 }, + { 0xc700, 0xf0 }, + { 0xc701, 0x13 }, + { 0xc901, 0x09 }, + { 0xc900, 0xd0 }, + { 0xde03, 0x05 }, + { 0xdd0b, 0x0d }, + { 0xdd0a, 0xff }, + { 0xdd09, 0x0d }, + { 0xdd08, 0xff }, + { 0xc570, 0x08 }, + { 0xc086, 0x02 }, + { 0xc085, 0x7f }, + { 0xc084, 0x00 }, + { 0xc081, 0xfe }, + { 0xf084, 0x0f }, + { 0xf083, 0xff }, + { 0xf082, 0xff }, + { 0xf081, 0xff }, + { 0xf080, 0xff }, + { 0xe802, 0xf8 }, + { 0xe803, 0xbe }, + { 0xc003, 0xc0 }, + { 0xd470, 0xec }, + { 0xd471, 0x3a }, + { 0xd474, 0x11 }, + { 0xd475, 0x32 }, + { 0xd478, 0x64 }, + { 0xd479, 0x20 }, + { 0xd47a, 0x10 }, + { 0xd47c, 0xff }, + { 0xc019, 0x10 }, + { 0xd487, 0x0b }, + { 0xd487, 0x3b }, + { 0xd486, 0xc3 }, + { 0xc598, 0x04 }, + { 0xd500, 0x00 }, + { 0xd500, 0x17 }, + { 0xd600, 0x01 }, + { 0xd601, 0x02 }, + { 0xd602, 0x03 }, + { 0xd603, 0x04 }, + { 0xd64c, 0x03 }, + { 0xd64d, 0x03 }, + { 0xd64e, 0x03 }, + { 0xd64f, 0x03 }, + { 0xd650, 0x03 }, + { 0xd651, 0x03 }, + { 0xd652, 0x03 }, + { 0xd610, 0x01 }, + { 0xd608, 0x03 }, + { 0xd609, 0x00 }, +}; + +static const struct reg_sequence rt1320_vc_patch_code_write[] = { + { 0x10007000, 0x37 }, + { 0x10007001, 0x77 }, + { 0x10007002, 0x00 }, + { 0x10007003, 0x10 }, + { 0x10007004, 0xb7 }, + { 0x10007005, 0xe7 }, + { 0x10007006, 0x00 }, + { 0x10007007, 0x10 }, + { 0x10007008, 0x13 }, + { 0x10007009, 0x07 }, + { 0x1000700a, 0x87 }, + { 0x1000700b, 0x48 }, + { 0x1000700c, 0x23 }, + { 0x1000700d, 0xa6 }, + { 0x1000700e, 0xe7 }, + { 0x1000700f, 0xee }, + { 0x10007010, 0x37 }, + { 0x10007011, 0x77 }, + { 0x10007012, 0x00 }, + { 0x10007013, 0x10 }, + { 0x10007014, 0x13 }, + { 0x10007015, 0x07 }, + { 0x10007016, 0x87 }, + { 0x10007017, 0x56 }, + { 0x10007018, 0x23 }, + { 0x10007019, 0xac }, + { 0x1000701a, 0xe7 }, + { 0x1000701b, 0xde }, + { 0x1000701c, 0x37 }, + { 0x1000701d, 0x77 }, + { 0x1000701e, 0x00 }, + { 0x1000701f, 0x10 }, + { 0x10007020, 0x13 }, + { 0x10007021, 0x07 }, + { 0x10007022, 0xc7 }, + { 0x10007023, 0x5f }, + { 0x10007024, 0x23 }, + { 0x10007025, 0xae }, + { 0x10007026, 0xe7 }, + { 0x10007027, 0xdc }, + { 0x10007028, 0x37 }, + { 0x10007029, 0x87 }, + { 0x1000702a, 0x00 }, + { 0x1000702b, 0x10 }, + { 0x1000702c, 0x13 }, + { 0x1000702d, 0x07 }, + { 0x1000702e, 0xc7 }, + { 0x1000702f, 0x86 }, + { 0x10007030, 0x23 }, + { 0x10007031, 0xae }, + { 0x10007032, 0xe7 }, + { 0x10007033, 0xe6 }, + { 0x10007034, 0x37 }, + { 0x10007035, 0x77 }, + { 0x10007036, 0x00 }, + { 0x10007037, 0x10 }, + { 0x10007038, 0x13 }, + { 0x10007039, 0x07 }, + { 0x1000703a, 0x07 }, + { 0x1000703b, 0x40 }, + { 0x1000703c, 0x23 }, + { 0x1000703d, 0xa6 }, + { 0x1000703e, 0xe7 }, + { 0x1000703f, 0xe8 }, + { 0x10007040, 0x37 }, + { 0x10007041, 0x77 }, + { 0x10007042, 0x00 }, + { 0x10007043, 0x10 }, + { 0x10007044, 0x13 }, + { 0x10007045, 0x07 }, + { 0x10007046, 0xc7 }, + { 0x10007047, 0x63 }, + { 0x10007048, 0x23 }, + { 0x10007049, 0xa2 }, + { 0x1000704a, 0xe7 }, + { 0x1000704b, 0xec }, + { 0x1000704c, 0x37 }, + { 0x1000704d, 0x77 }, + { 0x1000704e, 0x00 }, + { 0x1000704f, 0x10 }, + { 0x10007050, 0x13 }, + { 0x10007051, 0x07 }, + { 0x10007052, 0x47 }, + { 0x10007053, 0x6f }, + { 0x10007054, 0x23 }, + { 0x10007055, 0xa6 }, + { 0x10007056, 0xe7 }, + { 0x10007057, 0xec }, + { 0x10007058, 0x37 }, + { 0x10007059, 0x77 }, + { 0x1000705a, 0x00 }, + { 0x1000705b, 0x10 }, + { 0x1000705c, 0x13 }, + { 0x1000705d, 0x07 }, + { 0x1000705e, 0x07 }, + { 0x1000705f, 0x44 }, + { 0x10007060, 0x23 }, + { 0x10007061, 0xa8 }, + { 0x10007062, 0xe7 }, + { 0x10007063, 0xec }, + { 0x10007064, 0x37 }, + { 0x10007065, 0x87 }, + { 0x10007066, 0x00 }, + { 0x10007067, 0x10 }, + { 0x10007068, 0x13 }, + { 0x10007069, 0x07 }, + { 0x1000706a, 0x87 }, + { 0x1000706b, 0x84 }, + { 0x1000706c, 0x23 }, + { 0x1000706d, 0xa8 }, + { 0x1000706e, 0xe7 }, + { 0x1000706f, 0xee }, + { 0x10007070, 0x37 }, + { 0x10007071, 0x87 }, + { 0x10007072, 0x00 }, + { 0x10007073, 0x10 }, + { 0x10007074, 0x13 }, + { 0x10007075, 0x07 }, + { 0x10007076, 0x47 }, + { 0x10007077, 0x97 }, + { 0x10007078, 0x23 }, + { 0x10007079, 0xaa }, + { 0x1000707a, 0xe7 }, + { 0x1000707b, 0xee }, + { 0x1000707c, 0x67 }, + { 0x1000707d, 0x80 }, + { 0x1000707e, 0x00 }, + { 0x1000707f, 0x00 }, + { 0x10007400, 0xb7 }, + { 0x10007401, 0xd6 }, + { 0x10007402, 0x00 }, + { 0x10007403, 0x00 }, + { 0x10007404, 0x83 }, + { 0x10007405, 0xc7 }, + { 0x10007406, 0x06 }, + { 0x10007407, 0x47 }, + { 0x10007408, 0x93 }, + { 0x10007409, 0xf7 }, + { 0x1000740a, 0x87 }, + { 0x1000740b, 0x00 }, + { 0x1000740c, 0x63 }, + { 0x1000740d, 0x88 }, + { 0x1000740e, 0x07 }, + { 0x1000740f, 0x02 }, + { 0x10007410, 0x03 }, + { 0x10007411, 0xc7 }, + { 0x10007412, 0x31 }, + { 0x10007413, 0x43 }, + { 0x10007414, 0x63 }, + { 0x10007415, 0x14 }, + { 0x10007416, 0x07 }, + { 0x10007417, 0x02 }, + { 0x10007418, 0x13 }, + { 0x10007419, 0x07 }, + { 0x1000741a, 0x10 }, + { 0x1000741b, 0x00 }, + { 0x1000741c, 0xa3 }, + { 0x1000741d, 0x89 }, + { 0x1000741e, 0xe1 }, + { 0x1000741f, 0x42 }, + { 0x10007420, 0x37 }, + { 0x10007421, 0xc7 }, + { 0x10007422, 0x00 }, + { 0x10007423, 0x00 }, + { 0x10007424, 0x03 }, + { 0x10007425, 0x46 }, + { 0x10007426, 0x07 }, + { 0x10007427, 0x06 }, + { 0x10007428, 0x23 }, + { 0x10007429, 0x8a }, + { 0x1000742a, 0xc1 }, + { 0x1000742b, 0x42 }, + { 0x1000742c, 0x83 }, + { 0x1000742d, 0xc7 }, + { 0x1000742e, 0x46 }, + { 0x1000742f, 0x47 }, + { 0x10007430, 0x93 }, + { 0x10007431, 0xf7 }, + { 0x10007432, 0xf7 }, + { 0x10007433, 0x0f }, + { 0x10007434, 0x23 }, + { 0x10007435, 0x00 }, + { 0x10007436, 0xf7 }, + { 0x10007437, 0x06 }, + { 0x10007438, 0x23 }, + { 0x10007439, 0x89 }, + { 0x1000743a, 0x01 }, + { 0x1000743b, 0x42 }, + { 0x1000743c, 0x67 }, + { 0x1000743d, 0x80 }, + { 0x1000743e, 0x00 }, + { 0x1000743f, 0x00 }, + { 0x10007440, 0x37 }, + { 0x10007441, 0xc7 }, + { 0x10007442, 0x00 }, + { 0x10007443, 0x00 }, + { 0x10007444, 0x83 }, + { 0x10007445, 0x27 }, + { 0x10007446, 0xc7 }, + { 0x10007447, 0x5f }, + { 0x10007448, 0x13 }, + { 0x10007449, 0x05 }, + { 0x1000744a, 0x00 }, + { 0x1000744b, 0x00 }, + { 0x1000744c, 0x23 }, + { 0x1000744d, 0xa2 }, + { 0x1000744e, 0xf1 }, + { 0x1000744f, 0x42 }, + { 0x10007450, 0xb7 }, + { 0x10007451, 0x06 }, + { 0x10007452, 0x00 }, + { 0x10007453, 0x10 }, + { 0x10007454, 0xb3 }, + { 0x10007455, 0xf7 }, + { 0x10007456, 0xd7 }, + { 0x10007457, 0x00 }, + { 0x10007458, 0x63 }, + { 0x10007459, 0x86 }, + { 0x1000745a, 0x07 }, + { 0x1000745b, 0x02 }, + { 0x1000745c, 0x83 }, + { 0x1000745d, 0x47 }, + { 0x1000745e, 0x07 }, + { 0x1000745f, 0x56 }, + { 0x10007460, 0x93 }, + { 0x10007461, 0xf7 }, + { 0x10007462, 0x87 }, + { 0x10007463, 0x01 }, + { 0x10007464, 0x63 }, + { 0x10007465, 0x80 }, + { 0x10007466, 0x07 }, + { 0x10007467, 0x02 }, + { 0x10007468, 0x83 }, + { 0x10007469, 0x47 }, + { 0x1000746a, 0x17 }, + { 0x1000746b, 0x08 }, + { 0x1000746c, 0x93 }, + { 0x1000746d, 0xf7 }, + { 0x1000746e, 0x47 }, + { 0x1000746f, 0x00 }, + { 0x10007470, 0x63 }, + { 0x10007471, 0x8a }, + { 0x10007472, 0x07 }, + { 0x10007473, 0x00 }, + { 0x10007474, 0xb7 }, + { 0x10007475, 0xc7 }, + { 0x10007476, 0xc2 }, + { 0x10007477, 0x3f }, + { 0x10007478, 0x03 }, + { 0x10007479, 0xa5 }, + { 0x1000747a, 0x47 }, + { 0x1000747b, 0xfc }, + { 0x1000747c, 0x13 }, + { 0x1000747d, 0x55 }, + { 0x1000747e, 0x25 }, + { 0x1000747f, 0x00 }, + { 0x10007480, 0x13 }, + { 0x10007481, 0x75 }, + { 0x10007482, 0x15 }, + { 0x10007483, 0x00 }, + { 0x10007484, 0x67 }, + { 0x10007485, 0x80 }, + { 0x10007486, 0x00 }, + { 0x10007487, 0x00 }, + { 0x10007488, 0x03 }, + { 0x10007489, 0xa7 }, + { 0x1000748a, 0x81 }, + { 0x1000748b, 0x57 }, + { 0x1000748c, 0x13 }, + { 0x1000748d, 0x01 }, + { 0x1000748e, 0x01 }, + { 0x1000748f, 0xff }, + { 0x10007490, 0x23 }, + { 0x10007491, 0x26 }, + { 0x10007492, 0x11 }, + { 0x10007493, 0x00 }, + { 0x10007494, 0x23 }, + { 0x10007495, 0x24 }, + { 0x10007496, 0x81 }, + { 0x10007497, 0x00 }, + { 0x10007498, 0x23 }, + { 0x10007499, 0x22 }, + { 0x1000749a, 0x91 }, + { 0x1000749b, 0x00 }, + { 0x1000749c, 0x93 }, + { 0x1000749d, 0x07 }, + { 0x1000749e, 0xa0 }, + { 0x1000749f, 0x05 }, + { 0x100074a0, 0x63 }, + { 0x100074a1, 0x14 }, + { 0x100074a2, 0xf7 }, + { 0x100074a3, 0x04 }, + { 0x100074a4, 0x37 }, + { 0x100074a5, 0x07 }, + { 0x100074a6, 0x00 }, + { 0x100074a7, 0x11 }, + { 0x100074a8, 0x83 }, + { 0x100074a9, 0x47 }, + { 0x100074aa, 0x07 }, + { 0x100074ab, 0x01 }, + { 0x100074ac, 0x13 }, + { 0x100074ad, 0x06 }, + { 0x100074ae, 0x30 }, + { 0x100074af, 0x00 }, + { 0x100074b0, 0x93 }, + { 0x100074b1, 0xf7 }, + { 0x100074b2, 0xf7 }, + { 0x100074b3, 0x0f }, + { 0x100074b4, 0x63 }, + { 0x100074b5, 0x9a }, + { 0x100074b6, 0xc7 }, + { 0x100074b7, 0x02 }, + { 0x100074b8, 0x03 }, + { 0x100074b9, 0x47 }, + { 0x100074ba, 0x87 }, + { 0x100074bb, 0x01 }, + { 0x100074bc, 0x13 }, + { 0x100074bd, 0x77 }, + { 0x100074be, 0xf7 }, + { 0x100074bf, 0x0f }, + { 0x100074c0, 0x63 }, + { 0x100074c1, 0x14 }, + { 0x100074c2, 0xf7 }, + { 0x100074c3, 0x02 }, + { 0x100074c4, 0x37 }, + { 0x100074c5, 0xd7 }, + { 0x100074c6, 0x00 }, + { 0x100074c7, 0x00 }, + { 0x100074c8, 0x83 }, + { 0x100074c9, 0x47 }, + { 0x100074ca, 0x37 }, + { 0x100074cb, 0x54 }, + { 0x100074cc, 0x93 }, + { 0x100074cd, 0xf7 }, + { 0x100074ce, 0xf7 }, + { 0x100074cf, 0x0f }, + { 0x100074d0, 0x93 }, + { 0x100074d1, 0xe7 }, + { 0x100074d2, 0x07 }, + { 0x100074d3, 0x02 }, + { 0x100074d4, 0xa3 }, + { 0x100074d5, 0x01 }, + { 0x100074d6, 0xf7 }, + { 0x100074d7, 0x54 }, + { 0x100074d8, 0x83 }, + { 0x100074d9, 0x47 }, + { 0x100074da, 0x37 }, + { 0x100074db, 0x54 }, + { 0x100074dc, 0x93 }, + { 0x100074dd, 0xf7 }, + { 0x100074de, 0xf7 }, + { 0x100074df, 0x0d }, + { 0x100074e0, 0xa3 }, + { 0x100074e1, 0x01 }, + { 0x100074e2, 0xf7 }, + { 0x100074e3, 0x54 }, + { 0x100074e4, 0x23 }, + { 0x100074e5, 0xac }, + { 0x100074e6, 0x01 }, + { 0x100074e7, 0x56 }, + { 0x100074e8, 0x37 }, + { 0x100074e9, 0xd4 }, + { 0x100074ea, 0x00 }, + { 0x100074eb, 0x00 }, + { 0x100074ec, 0x83 }, + { 0x100074ed, 0x47 }, + { 0x100074ee, 0xd4 }, + { 0x100074ef, 0x47 }, + { 0x100074f0, 0x93 }, + { 0x100074f1, 0xf7 }, + { 0x100074f2, 0x17 }, + { 0x100074f3, 0x00 }, + { 0x100074f4, 0x63 }, + { 0x100074f5, 0x80 }, + { 0x100074f6, 0x07 }, + { 0x100074f7, 0x06 }, + { 0x100074f8, 0x37 }, + { 0x100074f9, 0xd7 }, + { 0x100074fa, 0x00 }, + { 0x100074fb, 0x10 }, + { 0x100074fc, 0x83 }, + { 0x100074fd, 0x47 }, + { 0x100074fe, 0x77 }, + { 0x100074ff, 0xd9 }, + { 0x10007500, 0x93 }, + { 0x10007501, 0x87 }, + { 0x10007502, 0x17 }, + { 0x10007503, 0x00 }, + { 0x10007504, 0x93 }, + { 0x10007505, 0xf7 }, + { 0x10007506, 0xf7 }, + { 0x10007507, 0x0f }, + { 0x10007508, 0xa3 }, + { 0x10007509, 0x0b }, + { 0x1000750a, 0xf7 }, + { 0x1000750b, 0xd8 }, + { 0x1000750c, 0x03 }, + { 0x1000750d, 0x47 }, + { 0x1000750e, 0x77 }, + { 0x1000750f, 0xd9 }, + { 0x10007510, 0x83 }, + { 0x10007511, 0x47 }, + { 0x10007512, 0xc4 }, + { 0x10007513, 0x47 }, + { 0x10007514, 0x13 }, + { 0x10007515, 0x77 }, + { 0x10007516, 0xf7 }, + { 0x10007517, 0x0f }, + { 0x10007518, 0x93 }, + { 0x10007519, 0xf7 }, + { 0x1000751a, 0xf7 }, + { 0x1000751b, 0x0f }, + { 0x1000751c, 0x63 }, + { 0x1000751d, 0x6c }, + { 0x1000751e, 0xf7 }, + { 0x1000751f, 0x02 }, + { 0x10007520, 0xb7 }, + { 0x10007521, 0xf4 }, + { 0x10007522, 0x00 }, + { 0x10007523, 0x00 }, + { 0x10007524, 0x93 }, + { 0x10007525, 0x05 }, + { 0x10007526, 0x00 }, + { 0x10007527, 0x01 }, + { 0x10007528, 0x13 }, + { 0x10007529, 0x85 }, + { 0x1000752a, 0x34 }, + { 0x1000752b, 0x52 }, + { 0x1000752c, 0xef }, + { 0x1000752d, 0xa0 }, + { 0x1000752e, 0x8f }, + { 0x1000752f, 0xc6 }, + { 0x10007530, 0x93 }, + { 0x10007531, 0x05 }, + { 0x10007532, 0x00 }, + { 0x10007533, 0x00 }, + { 0x10007534, 0x13 }, + { 0x10007535, 0x85 }, + { 0x10007536, 0x54 }, + { 0x10007537, 0x10 }, + { 0x10007538, 0xef }, + { 0x10007539, 0xa0 }, + { 0x1000753a, 0xcf }, + { 0x1000753b, 0xc5 }, + { 0x1000753c, 0x93 }, + { 0x1000753d, 0x05 }, + { 0x1000753e, 0x00 }, + { 0x1000753f, 0x00 }, + { 0x10007540, 0x13 }, + { 0x10007541, 0x85 }, + { 0x10007542, 0x74 }, + { 0x10007543, 0x10 }, + { 0x10007544, 0xef }, + { 0x10007545, 0xa0 }, + { 0x10007546, 0x0f }, + { 0x10007547, 0xc5 }, + { 0x10007548, 0x83 }, + { 0x10007549, 0x47 }, + { 0x1000754a, 0xd4 }, + { 0x1000754b, 0x47 }, + { 0x1000754c, 0x93 }, + { 0x1000754d, 0xf7 }, + { 0x1000754e, 0xe7 }, + { 0x1000754f, 0x0f }, + { 0x10007550, 0xa3 }, + { 0x10007551, 0x0e }, + { 0x10007552, 0xf4 }, + { 0x10007553, 0x46 }, + { 0x10007554, 0x83 }, + { 0x10007555, 0x20 }, + { 0x10007556, 0xc1 }, + { 0x10007557, 0x00 }, + { 0x10007558, 0x03 }, + { 0x10007559, 0x24 }, + { 0x1000755a, 0x81 }, + { 0x1000755b, 0x00 }, + { 0x1000755c, 0x83 }, + { 0x1000755d, 0x24 }, + { 0x1000755e, 0x41 }, + { 0x1000755f, 0x00 }, + { 0x10007560, 0x13 }, + { 0x10007561, 0x01 }, + { 0x10007562, 0x01 }, + { 0x10007563, 0x01 }, + { 0x10007564, 0x67 }, + { 0x10007565, 0x80 }, + { 0x10007566, 0x00 }, + { 0x10007567, 0x00 }, + { 0x10007568, 0x13 }, + { 0x10007569, 0x01 }, + { 0x1000756a, 0x01 }, + { 0x1000756b, 0xff }, + { 0x1000756c, 0x23 }, + { 0x1000756d, 0x24 }, + { 0x1000756e, 0x81 }, + { 0x1000756f, 0x00 }, + { 0x10007570, 0x23 }, + { 0x10007571, 0x26 }, + { 0x10007572, 0x11 }, + { 0x10007573, 0x00 }, + { 0x10007574, 0x23 }, + { 0x10007575, 0x22 }, + { 0x10007576, 0x91 }, + { 0x10007577, 0x00 }, + { 0x10007578, 0x37 }, + { 0x10007579, 0xd4 }, + { 0x1000757a, 0x00 }, + { 0x1000757b, 0x00 }, + { 0x1000757c, 0x83 }, + { 0x1000757d, 0x47 }, + { 0x1000757e, 0x04 }, + { 0x1000757f, 0x54 }, + { 0x10007580, 0x93 }, + { 0x10007581, 0x97 }, + { 0x10007582, 0x87 }, + { 0x10007583, 0x01 }, + { 0x10007584, 0x93 }, + { 0x10007585, 0xd7 }, + { 0x10007586, 0x87 }, + { 0x10007587, 0x41 }, + { 0x10007588, 0x63 }, + { 0x10007589, 0xd0 }, + { 0x1000758a, 0x07 }, + { 0x1000758b, 0x06 }, + { 0x1000758c, 0xb7 }, + { 0x1000758d, 0xf4 }, + { 0x1000758e, 0x00 }, + { 0x1000758f, 0x00 }, + { 0x10007590, 0x93 }, + { 0x10007591, 0x05 }, + { 0x10007592, 0x60 }, + { 0x10007593, 0x01 }, + { 0x10007594, 0x13 }, + { 0x10007595, 0x85 }, + { 0x10007596, 0x34 }, + { 0x10007597, 0x52 }, + { 0x10007598, 0xef }, + { 0x10007599, 0xa0 }, + { 0x1000759a, 0xcf }, + { 0x1000759b, 0xbf }, + { 0x1000759c, 0x93 }, + { 0x1000759d, 0x05 }, + { 0x1000759e, 0x00 }, + { 0x1000759f, 0x04 }, + { 0x100075a0, 0x13 }, + { 0x100075a1, 0x85 }, + { 0x100075a2, 0x54 }, + { 0x100075a3, 0x10 }, + { 0x100075a4, 0xef }, + { 0x100075a5, 0xa0 }, + { 0x100075a6, 0x0f }, + { 0x100075a7, 0xbf }, + { 0x100075a8, 0x93 }, + { 0x100075a9, 0x05 }, + { 0x100075aa, 0x00 }, + { 0x100075ab, 0x04 }, + { 0x100075ac, 0x13 }, + { 0x100075ad, 0x85 }, + { 0x100075ae, 0x74 }, + { 0x100075af, 0x10 }, + { 0x100075b0, 0xef }, + { 0x100075b1, 0xa0 }, + { 0x100075b2, 0x4f }, + { 0x100075b3, 0xbe }, + { 0x100075b4, 0x83 }, + { 0x100075b5, 0x47 }, + { 0x100075b6, 0xd4 }, + { 0x100075b7, 0x47 }, + { 0x100075b8, 0x37 }, + { 0x100075b9, 0xd7 }, + { 0x100075ba, 0x00 }, + { 0x100075bb, 0x10 }, + { 0x100075bc, 0x93 }, + { 0x100075bd, 0xf7 }, + { 0x100075be, 0xf7 }, + { 0x100075bf, 0x0f }, + { 0x100075c0, 0x93 }, + { 0x100075c1, 0xe7 }, + { 0x100075c2, 0x17 }, + { 0x100075c3, 0x00 }, + { 0x100075c4, 0xa3 }, + { 0x100075c5, 0x0e }, + { 0x100075c6, 0xf4 }, + { 0x100075c7, 0x46 }, + { 0x100075c8, 0xa3 }, + { 0x100075c9, 0x0b }, + { 0x100075ca, 0x07 }, + { 0x100075cb, 0xd8 }, + { 0x100075cc, 0x83 }, + { 0x100075cd, 0x47 }, + { 0x100075ce, 0x87 }, + { 0x100075cf, 0xd9 }, + { 0x100075d0, 0x93 }, + { 0x100075d1, 0x87 }, + { 0x100075d2, 0x17 }, + { 0x100075d3, 0x00 }, + { 0x100075d4, 0x93 }, + { 0x100075d5, 0xf7 }, + { 0x100075d6, 0xf7 }, + { 0x100075d7, 0x0f }, + { 0x100075d8, 0x23 }, + { 0x100075d9, 0x0c }, + { 0x100075da, 0xf7 }, + { 0x100075db, 0xd8 }, + { 0x100075dc, 0x83 }, + { 0x100075dd, 0x47 }, + { 0x100075de, 0x04 }, + { 0x100075df, 0x54 }, + { 0x100075e0, 0x93 }, + { 0x100075e1, 0xf7 }, + { 0x100075e2, 0xf7 }, + { 0x100075e3, 0x07 }, + { 0x100075e4, 0x23 }, + { 0x100075e5, 0x00 }, + { 0x100075e6, 0xf4 }, + { 0x100075e7, 0x54 }, + { 0x100075e8, 0x83 }, + { 0x100075e9, 0x20 }, + { 0x100075ea, 0xc1 }, + { 0x100075eb, 0x00 }, + { 0x100075ec, 0x03 }, + { 0x100075ed, 0x24 }, + { 0x100075ee, 0x81 }, + { 0x100075ef, 0x00 }, + { 0x100075f0, 0x83 }, + { 0x100075f1, 0x24 }, + { 0x100075f2, 0x41 }, + { 0x100075f3, 0x00 }, + { 0x100075f4, 0x13 }, + { 0x100075f5, 0x01 }, + { 0x100075f6, 0x01 }, + { 0x100075f7, 0x01 }, + { 0x100075f8, 0x67 }, + { 0x100075f9, 0x80 }, + { 0x100075fa, 0x00 }, + { 0x100075fb, 0x00 }, + { 0x100075fc, 0x13 }, + { 0x100075fd, 0x01 }, + { 0x100075fe, 0x01 }, + { 0x100075ff, 0xff }, + { 0x10007600, 0x23 }, + { 0x10007601, 0x24 }, + { 0x10007602, 0x81 }, + { 0x10007603, 0x00 }, + { 0x10007604, 0x37 }, + { 0x10007605, 0xd4 }, + { 0x10007606, 0x00 }, + { 0x10007607, 0x00 }, + { 0x10007608, 0x83 }, + { 0x10007609, 0x27 }, + { 0x1000760a, 0x04 }, + { 0x1000760b, 0x53 }, + { 0x1000760c, 0x23 }, + { 0x1000760d, 0x22 }, + { 0x1000760e, 0x91 }, + { 0x1000760f, 0x00 }, + { 0x10007610, 0xb7 }, + { 0x10007611, 0x04 }, + { 0x10007612, 0x00 }, + { 0x10007613, 0x40 }, + { 0x10007614, 0x23 }, + { 0x10007615, 0x26 }, + { 0x10007616, 0x11 }, + { 0x10007617, 0x00 }, + { 0x10007618, 0xb3 }, + { 0x10007619, 0xf7 }, + { 0x1000761a, 0x97 }, + { 0x1000761b, 0x00 }, + { 0x1000761c, 0x63 }, + { 0x1000761d, 0x86 }, + { 0x1000761e, 0x07 }, + { 0x1000761f, 0x00 }, + { 0x10007620, 0xef }, + { 0x10007621, 0xd0 }, + { 0x10007622, 0x5f }, + { 0x10007623, 0xc2 }, + { 0x10007624, 0x23 }, + { 0x10007625, 0x28 }, + { 0x10007626, 0x94 }, + { 0x10007627, 0x52 }, + { 0x10007628, 0x83 }, + { 0x10007629, 0x20 }, + { 0x1000762a, 0xc1 }, + { 0x1000762b, 0x00 }, + { 0x1000762c, 0x03 }, + { 0x1000762d, 0x24 }, + { 0x1000762e, 0x81 }, + { 0x1000762f, 0x00 }, + { 0x10007630, 0x83 }, + { 0x10007631, 0x24 }, + { 0x10007632, 0x41 }, + { 0x10007633, 0x00 }, + { 0x10007634, 0x13 }, + { 0x10007635, 0x01 }, + { 0x10007636, 0x01 }, + { 0x10007637, 0x01 }, + { 0x10007638, 0x67 }, + { 0x10007639, 0x80 }, + { 0x1000763a, 0x00 }, + { 0x1000763b, 0x00 }, + { 0x1000763c, 0x37 }, + { 0x1000763d, 0xc7 }, + { 0x1000763e, 0x00 }, + { 0x1000763f, 0x00 }, + { 0x10007640, 0x83 }, + { 0x10007641, 0x27 }, + { 0x10007642, 0xc7 }, + { 0x10007643, 0x5f }, + { 0x10007644, 0x23 }, + { 0x10007645, 0xa2 }, + { 0x10007646, 0xf1 }, + { 0x10007647, 0x42 }, + { 0x10007648, 0xb7 }, + { 0x10007649, 0x06 }, + { 0x1000764a, 0x00 }, + { 0x1000764b, 0x10 }, + { 0x1000764c, 0xb3 }, + { 0x1000764d, 0xf7 }, + { 0x1000764e, 0xd7 }, + { 0x1000764f, 0x00 }, + { 0x10007650, 0x63 }, + { 0x10007651, 0x80 }, + { 0x10007652, 0x07 }, + { 0x10007653, 0x0a }, + { 0x10007654, 0x83 }, + { 0x10007655, 0x47 }, + { 0x10007656, 0x07 }, + { 0x10007657, 0x56 }, + { 0x10007658, 0x93 }, + { 0x10007659, 0xf7 }, + { 0x1000765a, 0x87 }, + { 0x1000765b, 0x01 }, + { 0x1000765c, 0x63 }, + { 0x1000765d, 0x8a }, + { 0x1000765e, 0x07 }, + { 0x1000765f, 0x08 }, + { 0x10007660, 0x83 }, + { 0x10007661, 0x47 }, + { 0x10007662, 0x17 }, + { 0x10007663, 0x08 }, + { 0x10007664, 0x93 }, + { 0x10007665, 0xf7 }, + { 0x10007666, 0x47 }, + { 0x10007667, 0x00 }, + { 0x10007668, 0x63 }, + { 0x10007669, 0x84 }, + { 0x1000766a, 0x07 }, + { 0x1000766b, 0x08 }, + { 0x1000766c, 0x13 }, + { 0x1000766d, 0x01 }, + { 0x1000766e, 0x01 }, + { 0x1000766f, 0xff }, + { 0x10007670, 0x23 }, + { 0x10007671, 0x26 }, + { 0x10007672, 0x11 }, + { 0x10007673, 0x00 }, + { 0x10007674, 0xb7 }, + { 0x10007675, 0xc7 }, + { 0x10007676, 0xc2 }, + { 0x10007677, 0x3f }, + { 0x10007678, 0x03 }, + { 0x10007679, 0xa7 }, + { 0x1000767a, 0x07 }, + { 0x1000767b, 0xfc }, + { 0x1000767c, 0x63 }, + { 0x1000767d, 0x10 }, + { 0x1000767e, 0x05 }, + { 0x1000767f, 0x06 }, + { 0x10007680, 0x13 }, + { 0x10007681, 0x67 }, + { 0x10007682, 0x07 }, + { 0x10007683, 0x20 }, + { 0x10007684, 0x23 }, + { 0x10007685, 0xa0 }, + { 0x10007686, 0xe7 }, + { 0x10007687, 0xfc }, + { 0x10007688, 0x03 }, + { 0x10007689, 0xa7 }, + { 0x1000768a, 0x07 }, + { 0x1000768b, 0xfc }, + { 0x1000768c, 0x13 }, + { 0x1000768d, 0x67 }, + { 0x1000768e, 0x07 }, + { 0x1000768f, 0x40 }, + { 0x10007690, 0x23 }, + { 0x10007691, 0xa0 }, + { 0x10007692, 0xe7 }, + { 0x10007693, 0xfc }, + { 0x10007694, 0x37 }, + { 0x10007695, 0xc7 }, + { 0x10007696, 0xc2 }, + { 0x10007697, 0x3f }, + { 0x10007698, 0x83 }, + { 0x10007699, 0x27 }, + { 0x1000769a, 0x07 }, + { 0x1000769b, 0xfc }, + { 0x1000769c, 0x13 }, + { 0x1000769d, 0x75 }, + { 0x1000769e, 0x15 }, + { 0x1000769f, 0x00 }, + { 0x100076a0, 0x13 }, + { 0x100076a1, 0x15 }, + { 0x100076a2, 0x85 }, + { 0x100076a3, 0x00 }, + { 0x100076a4, 0x93 }, + { 0x100076a5, 0xf7 }, + { 0x100076a6, 0xf7 }, + { 0x100076a7, 0xef }, + { 0x100076a8, 0x33 }, + { 0x100076a9, 0xe5 }, + { 0x100076aa, 0xa7 }, + { 0x100076ab, 0x00 }, + { 0x100076ac, 0x23 }, + { 0x100076ad, 0x20 }, + { 0x100076ae, 0xa7 }, + { 0x100076af, 0xfc }, + { 0x100076b0, 0x93 }, + { 0x100076b1, 0x05 }, + { 0x100076b2, 0x00 }, + { 0x100076b3, 0x00 }, + { 0x100076b4, 0x13 }, + { 0x100076b5, 0x05 }, + { 0x100076b6, 0xa0 }, + { 0x100076b7, 0x00 }, + { 0x100076b8, 0xef }, + { 0x100076b9, 0xe0 }, + { 0x100076ba, 0xcf }, + { 0x100076bb, 0xb6 }, + { 0x100076bc, 0x37 }, + { 0x100076bd, 0xf7 }, + { 0x100076be, 0x00 }, + { 0x100076bf, 0x00 }, + { 0x100076c0, 0x83 }, + { 0x100076c1, 0x47 }, + { 0x100076c2, 0x57 }, + { 0x100076c3, 0x01 }, + { 0x100076c4, 0x93 }, + { 0x100076c5, 0xf7 }, + { 0x100076c6, 0xf7 }, + { 0x100076c7, 0x0f }, + { 0x100076c8, 0x93 }, + { 0x100076c9, 0xe7 }, + { 0x100076ca, 0x47 }, + { 0x100076cb, 0x00 }, + { 0x100076cc, 0xa3 }, + { 0x100076cd, 0x0a }, + { 0x100076ce, 0xf7 }, + { 0x100076cf, 0x00 }, + { 0x100076d0, 0x83 }, + { 0x100076d1, 0x20 }, + { 0x100076d2, 0xc1 }, + { 0x100076d3, 0x00 }, + { 0x100076d4, 0x13 }, + { 0x100076d5, 0x01 }, + { 0x100076d6, 0x01 }, + { 0x100076d7, 0x01 }, + { 0x100076d8, 0x67 }, + { 0x100076d9, 0x80 }, + { 0x100076da, 0x00 }, + { 0x100076db, 0x00 }, + { 0x100076dc, 0x13 }, + { 0x100076dd, 0x77 }, + { 0x100076de, 0xf7 }, + { 0x100076df, 0xdf }, + { 0x100076e0, 0x23 }, + { 0x100076e1, 0xa0 }, + { 0x100076e2, 0xe7 }, + { 0x100076e3, 0xfc }, + { 0x100076e4, 0x03 }, + { 0x100076e5, 0xa7 }, + { 0x100076e6, 0x07 }, + { 0x100076e7, 0xfc }, + { 0x100076e8, 0x13 }, + { 0x100076e9, 0x77 }, + { 0x100076ea, 0xf7 }, + { 0x100076eb, 0xbf }, + { 0x100076ec, 0x6f }, + { 0x100076ed, 0xf0 }, + { 0x100076ee, 0x5f }, + { 0x100076ef, 0xfa }, + { 0x100076f0, 0x67 }, + { 0x100076f1, 0x80 }, + { 0x100076f2, 0x00 }, + { 0x100076f3, 0x00 }, + { 0x100076f4, 0xb7 }, + { 0x100076f5, 0xc7 }, + { 0x100076f6, 0x00 }, + { 0x100076f7, 0x00 }, + { 0x100076f8, 0x03 }, + { 0x100076f9, 0xc7 }, + { 0x100076fa, 0x87 }, + { 0x100076fb, 0x59 }, + { 0x100076fc, 0x13 }, + { 0x100076fd, 0x77 }, + { 0x100076fe, 0xf7 }, + { 0x100076ff, 0x0f }, + { 0x10007700, 0x13 }, + { 0x10007701, 0x67 }, + { 0x10007702, 0x17 }, + { 0x10007703, 0x00 }, + { 0x10007704, 0x23 }, + { 0x10007705, 0x8c }, + { 0x10007706, 0xe7 }, + { 0x10007707, 0x58 }, + { 0x10007708, 0x03 }, + { 0x10007709, 0xc7 }, + { 0x1000770a, 0x77 }, + { 0x1000770b, 0x04 }, + { 0x1000770c, 0x13 }, + { 0x1000770d, 0x17 }, + { 0x1000770e, 0x87 }, + { 0x1000770f, 0x01 }, + { 0x10007710, 0x13 }, + { 0x10007711, 0x57 }, + { 0x10007712, 0x87 }, + { 0x10007713, 0x41 }, + { 0x10007714, 0x63 }, + { 0x10007715, 0x58 }, + { 0x10007716, 0x07 }, + { 0x10007717, 0x12 }, + { 0x10007718, 0x37 }, + { 0x10007719, 0xd7 }, + { 0x1000771a, 0x00 }, + { 0x1000771b, 0x00 }, + { 0x1000771c, 0x83 }, + { 0x1000771d, 0x26 }, + { 0x1000771e, 0x87 }, + { 0x1000771f, 0x53 }, + { 0x10007720, 0x37 }, + { 0x10007721, 0x06 }, + { 0x10007722, 0x00 }, + { 0x10007723, 0x40 }, + { 0x10007724, 0x93 }, + { 0x10007725, 0x05 }, + { 0x10007726, 0x80 }, + { 0x10007727, 0x01 }, + { 0x10007728, 0xb3 }, + { 0x10007729, 0xe6 }, + { 0x1000772a, 0xc6 }, + { 0x1000772b, 0x00 }, + { 0x1000772c, 0x23 }, + { 0x1000772d, 0x2c }, + { 0x1000772e, 0xd7 }, + { 0x1000772f, 0x52 }, + { 0x10007730, 0x83 }, + { 0x10007731, 0xc6 }, + { 0x10007732, 0x07 }, + { 0x10007733, 0x56 }, + { 0x10007734, 0x93 }, + { 0x10007735, 0xf6 }, + { 0x10007736, 0xf6 }, + { 0x10007737, 0x0f }, + { 0x10007738, 0x63 }, + { 0x10007739, 0x9c }, + { 0x1000773a, 0xb6 }, + { 0x1000773b, 0x0e }, + { 0x1000773c, 0x83 }, + { 0x1000773d, 0x27 }, + { 0x1000773e, 0x87 }, + { 0x1000773f, 0x53 }, + { 0x10007740, 0xb3 }, + { 0x10007741, 0xf7 }, + { 0x10007742, 0xc7 }, + { 0x10007743, 0x00 }, + { 0x10007744, 0x63 }, + { 0x10007745, 0x80 }, + { 0x10007746, 0x07 }, + { 0x10007747, 0x10 }, + { 0x10007748, 0x13 }, + { 0x10007749, 0x01 }, + { 0x1000774a, 0x01 }, + { 0x1000774b, 0xff }, + { 0x1000774c, 0x23 }, + { 0x1000774d, 0x24 }, + { 0x1000774e, 0x81 }, + { 0x1000774f, 0x00 }, + { 0x10007750, 0x83 }, + { 0x10007751, 0xa7 }, + { 0x10007752, 0x41 }, + { 0x10007753, 0x58 }, + { 0x10007754, 0x23 }, + { 0x10007755, 0x26 }, + { 0x10007756, 0x11 }, + { 0x10007757, 0x00 }, + { 0x10007758, 0x63 }, + { 0x10007759, 0x94 }, + { 0x1000775a, 0x07 }, + { 0x1000775b, 0x0c }, + { 0x1000775c, 0x83 }, + { 0x1000775d, 0x27 }, + { 0x1000775e, 0x07 }, + { 0x1000775f, 0x53 }, + { 0x10007760, 0x03 }, + { 0x10007761, 0xc6 }, + { 0x10007762, 0xb1 }, + { 0x10007763, 0x42 }, + { 0x10007764, 0x93 }, + { 0x10007765, 0xd7 }, + { 0x10007766, 0xe7 }, + { 0x10007767, 0x01 }, + { 0x10007768, 0x93 }, + { 0x10007769, 0xf7 }, + { 0x1000776a, 0x17 }, + { 0x1000776b, 0x00 }, + { 0x1000776c, 0x93 }, + { 0x1000776d, 0x06 }, + { 0x1000776e, 0x10 }, + { 0x1000776f, 0x00 }, + { 0x10007770, 0x63 }, + { 0x10007771, 0x14 }, + { 0x10007772, 0x06 }, + { 0x10007773, 0x00 }, + { 0x10007774, 0xb3 }, + { 0x10007775, 0x86 }, + { 0x10007776, 0xf6 }, + { 0x10007777, 0x40 }, + { 0x10007778, 0xa3 }, + { 0x10007779, 0x85 }, + { 0x1000777a, 0xd1 }, + { 0x1000777b, 0x42 }, + { 0x1000777c, 0x03 }, + { 0x1000777d, 0xc6 }, + { 0x1000777e, 0xa1 }, + { 0x1000777f, 0x42 }, + { 0x10007780, 0x93 }, + { 0x10007781, 0x06 }, + { 0x10007782, 0x10 }, + { 0x10007783, 0x00 }, + { 0x10007784, 0x63 }, + { 0x10007785, 0x14 }, + { 0x10007786, 0x06 }, + { 0x10007787, 0x00 }, + { 0x10007788, 0xb3 }, + { 0x10007789, 0x86 }, + { 0x1000778a, 0xf6 }, + { 0x1000778b, 0x40 }, + { 0x1000778c, 0x23 }, + { 0x1000778d, 0x85 }, + { 0x1000778e, 0xd1 }, + { 0x1000778f, 0x42 }, + { 0x10007790, 0x03 }, + { 0x10007791, 0xc6 }, + { 0x10007792, 0x91 }, + { 0x10007793, 0x42 }, + { 0x10007794, 0x93 }, + { 0x10007795, 0x06 }, + { 0x10007796, 0x10 }, + { 0x10007797, 0x00 }, + { 0x10007798, 0x63 }, + { 0x10007799, 0x14 }, + { 0x1000779a, 0x06 }, + { 0x1000779b, 0x00 }, + { 0x1000779c, 0xb3 }, + { 0x1000779d, 0x86 }, + { 0x1000779e, 0xf6 }, + { 0x1000779f, 0x40 }, + { 0x100077a0, 0xa3 }, + { 0x100077a1, 0x84 }, + { 0x100077a2, 0xd1 }, + { 0x100077a3, 0x42 }, + { 0x100077a4, 0x03 }, + { 0x100077a5, 0xc6 }, + { 0x100077a6, 0x81 }, + { 0x100077a7, 0x42 }, + { 0x100077a8, 0x93 }, + { 0x100077a9, 0x06 }, + { 0x100077aa, 0x10 }, + { 0x100077ab, 0x00 }, + { 0x100077ac, 0x63 }, + { 0x100077ad, 0x14 }, + { 0x100077ae, 0x06 }, + { 0x100077af, 0x00 }, + { 0x100077b0, 0xb3 }, + { 0x100077b1, 0x86 }, + { 0x100077b2, 0xf6 }, + { 0x100077b3, 0x40 }, + { 0x100077b4, 0x23 }, + { 0x100077b5, 0x84 }, + { 0x100077b6, 0xd1 }, + { 0x100077b7, 0x42 }, + { 0x100077b8, 0xb7 }, + { 0x100077b9, 0xd7 }, + { 0x100077ba, 0x00 }, + { 0x100077bb, 0x00 }, + { 0x100077bc, 0x83 }, + { 0x100077bd, 0xa7 }, + { 0x100077be, 0x07 }, + { 0x100077bf, 0x53 }, + { 0x100077c0, 0x37 }, + { 0x100077c1, 0x07 }, + { 0x100077c2, 0x00 }, + { 0x100077c3, 0x40 }, + { 0x100077c4, 0xb3 }, + { 0x100077c5, 0xf7 }, + { 0x100077c6, 0xe7 }, + { 0x100077c7, 0x00 }, + { 0x100077c8, 0x63 }, + { 0x100077c9, 0x8c }, + { 0x100077ca, 0x07 }, + { 0x100077cb, 0x04 }, + { 0x100077cc, 0xb7 }, + { 0x100077cd, 0x47 }, + { 0x100077ce, 0x0f }, + { 0x100077cf, 0x00 }, + { 0x100077d0, 0x93 }, + { 0x100077d1, 0x87 }, + { 0x100077d2, 0x17 }, + { 0x100077d3, 0x24 }, + { 0x100077d4, 0xb7 }, + { 0x100077d5, 0xf6 }, + { 0x100077d6, 0x00 }, + { 0x100077d7, 0x00 }, + { 0x100077d8, 0x03 }, + { 0x100077d9, 0xc7 }, + { 0x100077da, 0xf6 }, + { 0x100077db, 0x83 }, + { 0x100077dc, 0x13 }, + { 0x100077dd, 0x77 }, + { 0x100077de, 0x07 }, + { 0x100077df, 0x04 }, + { 0x100077e0, 0x63 }, + { 0x100077e1, 0x16 }, + { 0x100077e2, 0x07 }, + { 0x100077e3, 0x00 }, + { 0x100077e4, 0x93 }, + { 0x100077e5, 0x87 }, + { 0x100077e6, 0xf7 }, + { 0x100077e7, 0xff }, + { 0x100077e8, 0xe3 }, + { 0x100077e9, 0x98 }, + { 0x100077ea, 0x07 }, + { 0x100077eb, 0xfe }, + { 0x100077ec, 0x13 }, + { 0x100077ed, 0x05 }, + { 0x100077ee, 0x80 }, + { 0x100077ef, 0x3e }, + { 0x100077f0, 0x93 }, + { 0x100077f1, 0x05 }, + { 0x100077f2, 0x00 }, + { 0x100077f3, 0x00 }, + { 0x100077f4, 0xef }, + { 0x100077f5, 0xe0 }, + { 0x100077f6, 0x0f }, + { 0x100077f7, 0xa3 }, + { 0x100077f8, 0x37 }, + { 0x100077f9, 0xf7 }, + { 0x100077fa, 0x00 }, + { 0x100077fb, 0x00 }, + { 0x100077fc, 0x83 }, + { 0x100077fd, 0x47 }, + { 0x100077fe, 0xb7 }, + { 0x100077ff, 0x80 }, + { 0x10007800, 0x93 }, + { 0x10007801, 0xe7 }, + { 0x10007802, 0x07 }, + { 0x10007803, 0xf8 }, + { 0x10007804, 0x93 }, + { 0x10007805, 0xf7 }, + { 0x10007806, 0xf7 }, + { 0x10007807, 0x0f }, + { 0x10007808, 0xa3 }, + { 0x10007809, 0x05 }, + { 0x1000780a, 0xf7 }, + { 0x1000780b, 0x80 }, + { 0x1000780c, 0xb7 }, + { 0x1000780d, 0xd7 }, + { 0x1000780e, 0x00 }, + { 0x1000780f, 0x00 }, + { 0x10007810, 0x37 }, + { 0x10007811, 0x07 }, + { 0x10007812, 0x00 }, + { 0x10007813, 0x40 }, + { 0x10007814, 0x23 }, + { 0x10007815, 0xa8 }, + { 0x10007816, 0xe7 }, + { 0x10007817, 0x52 }, + { 0x10007818, 0x93 }, + { 0x10007819, 0x07 }, + { 0x1000781a, 0x10 }, + { 0x1000781b, 0x00 }, + { 0x1000781c, 0x23 }, + { 0x1000781d, 0xa2 }, + { 0x1000781e, 0xf1 }, + { 0x1000781f, 0x58 }, + { 0x10007820, 0x83 }, + { 0x10007821, 0x20 }, + { 0x10007822, 0xc1 }, + { 0x10007823, 0x00 }, + { 0x10007824, 0x03 }, + { 0x10007825, 0x24 }, + { 0x10007826, 0x81 }, + { 0x10007827, 0x00 }, + { 0x10007828, 0x13 }, + { 0x10007829, 0x01 }, + { 0x1000782a, 0x01 }, + { 0x1000782b, 0x01 }, + { 0x1000782c, 0x67 }, + { 0x1000782d, 0x80 }, + { 0x1000782e, 0x00 }, + { 0x1000782f, 0x00 }, + { 0x10007830, 0x83 }, + { 0x10007831, 0xc7 }, + { 0x10007832, 0x07 }, + { 0x10007833, 0x56 }, + { 0x10007834, 0x93 }, + { 0x10007835, 0xf7 }, + { 0x10007836, 0xf7 }, + { 0x10007837, 0x0f }, + { 0x10007838, 0x63 }, + { 0x10007839, 0x96 }, + { 0x1000783a, 0x07 }, + { 0x1000783b, 0x00 }, + { 0x1000783c, 0x23 }, + { 0x1000783d, 0xa2 }, + { 0x1000783e, 0x01 }, + { 0x1000783f, 0x58 }, + { 0x10007840, 0x67 }, + { 0x10007841, 0x80 }, + { 0x10007842, 0x00 }, + { 0x10007843, 0x00 }, + { 0x10007844, 0x67 }, + { 0x10007845, 0x80 }, + { 0x10007846, 0x00 }, + { 0x10007847, 0x00 }, + { 0x10007848, 0xb7 }, + { 0x10007849, 0xc7 }, + { 0x1000784a, 0x00 }, + { 0x1000784b, 0x00 }, + { 0x1000784c, 0x83 }, + { 0x1000784d, 0xc7 }, + { 0x1000784e, 0x07 }, + { 0x1000784f, 0x56 }, + { 0x10007850, 0x13 }, + { 0x10007851, 0x07 }, + { 0x10007852, 0x80 }, + { 0x10007853, 0x01 }, + { 0x10007854, 0x93 }, + { 0x10007855, 0xf7 }, + { 0x10007856, 0xf7 }, + { 0x10007857, 0x0f }, + { 0x10007858, 0x63 }, + { 0x10007859, 0x98 }, + { 0x1000785a, 0xe7 }, + { 0x1000785b, 0x00 }, + { 0x1000785c, 0x13 }, + { 0x1000785d, 0x05 }, + { 0x1000785e, 0x00 }, + { 0x1000785f, 0x7d }, + { 0x10007860, 0x93 }, + { 0x10007861, 0x05 }, + { 0x10007862, 0x00 }, + { 0x10007863, 0x00 }, + { 0x10007864, 0x6f }, + { 0x10007865, 0xe0 }, + { 0x10007866, 0x0f }, + { 0x10007867, 0x9c }, + { 0x10007868, 0x67 }, + { 0x10007869, 0x80 }, + { 0x1000786a, 0x00 }, + { 0x1000786b, 0x00 }, + { 0x1000786c, 0x13 }, + { 0x1000786d, 0x01 }, + { 0x1000786e, 0x01 }, + { 0x1000786f, 0xff }, + { 0x10007870, 0x23 }, + { 0x10007871, 0x26 }, + { 0x10007872, 0x11 }, + { 0x10007873, 0x00 }, + { 0x10007874, 0x23 }, + { 0x10007875, 0x24 }, + { 0x10007876, 0x81 }, + { 0x10007877, 0x00 }, + { 0x10007878, 0xef }, + { 0x10007879, 0xd0 }, + { 0x1000787a, 0x4f }, + { 0x1000787b, 0x91 }, + { 0x1000787c, 0x83 }, + { 0x1000787d, 0xc7 }, + { 0x1000787e, 0x81 }, + { 0x1000787f, 0x41 }, + { 0x10007880, 0x63 }, + { 0x10007881, 0x84 }, + { 0x10007882, 0x07 }, + { 0x10007883, 0x08 }, + { 0x10007884, 0xb7 }, + { 0x10007885, 0xd7 }, + { 0x10007886, 0x00 }, + { 0x10007887, 0x00 }, + { 0x10007888, 0x83 }, + { 0x10007889, 0xc7 }, + { 0x1000788a, 0x07 }, + { 0x1000788b, 0x47 }, + { 0x1000788c, 0x93 }, + { 0x1000788d, 0xf7 }, + { 0x1000788e, 0x07 }, + { 0x1000788f, 0x02 }, + { 0x10007890, 0x63 }, + { 0x10007891, 0x8a }, + { 0x10007892, 0x07 }, + { 0x10007893, 0x04 }, + { 0x10007894, 0x83 }, + { 0x10007895, 0xc7 }, + { 0x10007896, 0x11 }, + { 0x10007897, 0x44 }, + { 0x10007898, 0x93 }, + { 0x10007899, 0xf7 }, + { 0x1000789a, 0xd7 }, + { 0x1000789b, 0x0f }, + { 0x1000789c, 0x63 }, + { 0x1000789d, 0x90 }, + { 0x1000789e, 0x07 }, + { 0x1000789f, 0x02 }, + { 0x100078a0, 0x03 }, + { 0x100078a1, 0xc7 }, + { 0x100078a2, 0xd1 }, + { 0x100078a3, 0x58 }, + { 0x100078a4, 0xb7 }, + { 0x100078a5, 0x07 }, + { 0x100078a6, 0x00 }, + { 0x100078a7, 0x11 }, + { 0x100078a8, 0x23 }, + { 0x100078a9, 0x88 }, + { 0x100078aa, 0xe7 }, + { 0x100078ab, 0x00 }, + { 0x100078ac, 0x23 }, + { 0x100078ad, 0x88 }, + { 0x100078ae, 0xe7 }, + { 0x100078af, 0x20 }, + { 0x100078b0, 0x03 }, + { 0x100078b1, 0xc7 }, + { 0x100078b2, 0xc1 }, + { 0x100078b3, 0x58 }, + { 0x100078b4, 0x23 }, + { 0x100078b5, 0x8c }, + { 0x100078b6, 0xe7 }, + { 0x100078b7, 0x00 }, + { 0x100078b8, 0x6f }, + { 0x100078b9, 0x00 }, + { 0x100078ba, 0x80 }, + { 0x100078bb, 0x04 }, + { 0x100078bc, 0xb7 }, + { 0x100078bd, 0x07 }, + { 0x100078be, 0x00 }, + { 0x100078bf, 0x11 }, + { 0x100078c0, 0x23 }, + { 0x100078c1, 0x88 }, + { 0x100078c2, 0x07 }, + { 0x100078c3, 0x00 }, + { 0x100078c4, 0x23 }, + { 0x100078c5, 0x88 }, + { 0x100078c6, 0x07 }, + { 0x100078c7, 0x20 }, + { 0x100078c8, 0x23 }, + { 0x100078c9, 0x8c }, + { 0x100078ca, 0x07 }, + { 0x100078cb, 0x00 }, + { 0x100078cc, 0x23 }, + { 0x100078cd, 0x8c }, + { 0x100078ce, 0x07 }, + { 0x100078cf, 0x20 }, + { 0x100078d0, 0xef }, + { 0x100078d1, 0xb0 }, + { 0x100078d2, 0xcf }, + { 0x100078d3, 0xc4 }, + { 0x100078d4, 0x03 }, + { 0x100078d5, 0x24 }, + { 0x100078d6, 0x81 }, + { 0x100078d7, 0x00 }, + { 0x100078d8, 0x83 }, + { 0x100078d9, 0x20 }, + { 0x100078da, 0xc1 }, + { 0x100078db, 0x00 }, + { 0x100078dc, 0x13 }, + { 0x100078dd, 0x01 }, + { 0x100078de, 0x01 }, + { 0x100078df, 0x01 }, + { 0x100078e0, 0x6f }, + { 0x100078e1, 0xb0 }, + { 0x100078e2, 0xcf }, + { 0x100078e3, 0xcd }, + { 0x100078e4, 0x03 }, + { 0x100078e5, 0xc7 }, + { 0x100078e6, 0xd1 }, + { 0x100078e7, 0x58 }, + { 0x100078e8, 0xb7 }, + { 0x100078e9, 0x07 }, + { 0x100078ea, 0x00 }, + { 0x100078eb, 0x11 }, + { 0x100078ec, 0x23 }, + { 0x100078ed, 0x88 }, + { 0x100078ee, 0xe7 }, + { 0x100078ef, 0x00 }, + { 0x100078f0, 0x83 }, + { 0x100078f1, 0xc6 }, + { 0x100078f2, 0xc1 }, + { 0x100078f3, 0x58 }, + { 0x100078f4, 0x23 }, + { 0x100078f5, 0x88 }, + { 0x100078f6, 0xd7 }, + { 0x100078f7, 0x20 }, + { 0x100078f8, 0x23 }, + { 0x100078f9, 0x8c }, + { 0x100078fa, 0xd7 }, + { 0x100078fb, 0x00 }, + { 0x100078fc, 0x03 }, + { 0x100078fd, 0xc7 }, + { 0x100078fe, 0xc1 }, + { 0x100078ff, 0x58 }, + { 0x10007900, 0x23 }, + { 0x10007901, 0x8c }, + { 0x10007902, 0xe7 }, + { 0x10007903, 0x20 }, + { 0x10007904, 0x6f }, + { 0x10007905, 0xf0 }, + { 0x10007906, 0xdf }, + { 0x10007907, 0xfc }, + { 0x10007908, 0xb7 }, + { 0x10007909, 0x06 }, + { 0x1000790a, 0x00 }, + { 0x1000790b, 0x11 }, + { 0x1000790c, 0x03 }, + { 0x1000790d, 0xc7 }, + { 0x1000790e, 0x06 }, + { 0x1000790f, 0x21 }, + { 0x10007910, 0x03 }, + { 0x10007911, 0xc6 }, + { 0x10007912, 0xd1 }, + { 0x10007913, 0x58 }, + { 0x10007914, 0x13 }, + { 0x10007915, 0x84 }, + { 0x10007916, 0x07 }, + { 0x10007917, 0x00 }, + { 0x10007918, 0x13 }, + { 0x10007919, 0x77 }, + { 0x1000791a, 0xf7 }, + { 0x1000791b, 0x0f }, + { 0x1000791c, 0x63 }, + { 0x1000791d, 0x1a }, + { 0x1000791e, 0xe6 }, + { 0x1000791f, 0x00 }, + { 0x10007920, 0x83 }, + { 0x10007921, 0xc7 }, + { 0x10007922, 0x86 }, + { 0x10007923, 0x21 }, + { 0x10007924, 0x03 }, + { 0x10007925, 0xc7 }, + { 0x10007926, 0xc1 }, + { 0x10007927, 0x58 }, + { 0x10007928, 0x93 }, + { 0x10007929, 0xf7 }, + { 0x1000792a, 0xf7 }, + { 0x1000792b, 0x0f }, + { 0x1000792c, 0xe3 }, + { 0x1000792d, 0x02 }, + { 0x1000792e, 0xf7 }, + { 0x1000792f, 0xfa }, + { 0x10007930, 0xb7 }, + { 0x10007931, 0xc7 }, + { 0x10007932, 0x00 }, + { 0x10007933, 0x00 }, + { 0x10007934, 0x83 }, + { 0x10007935, 0xc7 }, + { 0x10007936, 0x07 }, + { 0x10007937, 0x56 }, + { 0x10007938, 0x13 }, + { 0x10007939, 0x07 }, + { 0x1000793a, 0xf0 }, + { 0x1000793b, 0x00 }, + { 0x1000793c, 0x93 }, + { 0x1000793d, 0xf7 }, + { 0x1000793e, 0xf7 }, + { 0x1000793f, 0x0f }, + { 0x10007940, 0xe3 }, + { 0x10007941, 0x78 }, + { 0x10007942, 0xf7 }, + { 0x10007943, 0xf8 }, + { 0x10007944, 0xb7 }, + { 0x10007945, 0xd7 }, + { 0x10007946, 0x00 }, + { 0x10007947, 0x00 }, + { 0x10007948, 0x83 }, + { 0x10007949, 0xc5 }, + { 0x1000794a, 0xa7 }, + { 0x1000794b, 0x47 }, + { 0x1000794c, 0x93 }, + { 0x1000794d, 0xf7 }, + { 0x1000794e, 0xf5 }, + { 0x1000794f, 0x0f }, + { 0x10007950, 0x93 }, + { 0x10007951, 0x95 }, + { 0x10007952, 0x57 }, + { 0x10007953, 0x00 }, + { 0x10007954, 0xb3 }, + { 0x10007955, 0x85 }, + { 0x10007956, 0xf5 }, + { 0x10007957, 0x40 }, + { 0x10007958, 0x93 }, + { 0x10007959, 0x95 }, + { 0x1000795a, 0x25 }, + { 0x1000795b, 0x00 }, + { 0x1000795c, 0xb3 }, + { 0x1000795d, 0x85 }, + { 0x1000795e, 0xf5 }, + { 0x1000795f, 0x00 }, + { 0x10007960, 0x13 }, + { 0x10007961, 0x95 }, + { 0x10007962, 0x35 }, + { 0x10007963, 0x00 }, + { 0x10007964, 0x93 }, + { 0x10007965, 0xd5 }, + { 0x10007966, 0xf5 }, + { 0x10007967, 0x41 }, + { 0x10007968, 0xef }, + { 0x10007969, 0xe0 }, + { 0x1000796a, 0xcf }, + { 0x1000796b, 0x8b }, + { 0x1000796c, 0x03 }, + { 0x1000796d, 0xc7 }, + { 0x1000796e, 0xd1 }, + { 0x1000796f, 0x58 }, + { 0x10007970, 0x6f }, + { 0x10007971, 0xf0 }, + { 0x10007972, 0x5f }, + { 0x10007973, 0xf3 }, + { 0x10007974, 0x13 }, + { 0x10007975, 0x01 }, + { 0x10007976, 0x01 }, + { 0x10007977, 0xfe }, + { 0x10007978, 0x23 }, + { 0x10007979, 0x2c }, + { 0x1000797a, 0x81 }, + { 0x1000797b, 0x00 }, + { 0x1000797c, 0x83 }, + { 0x1000797d, 0xc7 }, + { 0x1000797e, 0x21 }, + { 0x1000797f, 0x41 }, + { 0x10007980, 0x23 }, + { 0x10007981, 0x2e }, + { 0x10007982, 0x11 }, + { 0x10007983, 0x00 }, + { 0x10007984, 0x23 }, + { 0x10007985, 0x2a }, + { 0x10007986, 0x91 }, + { 0x10007987, 0x00 }, + { 0x10007988, 0x23 }, + { 0x10007989, 0x28 }, + { 0x1000798a, 0x21 }, + { 0x1000798b, 0x01 }, + { 0x1000798c, 0x23 }, + { 0x1000798d, 0x26 }, + { 0x1000798e, 0x31 }, + { 0x1000798f, 0x01 }, + { 0x10007990, 0x13 }, + { 0x10007991, 0x07 }, + { 0x10007992, 0x10 }, + { 0x10007993, 0x00 }, + { 0x10007994, 0x63 }, + { 0x10007995, 0x92 }, + { 0x10007996, 0xe7 }, + { 0x10007997, 0x02 }, + { 0x10007998, 0xa3 }, + { 0x10007999, 0x81 }, + { 0x1000799a, 0xf1 }, + { 0x1000799b, 0x40 }, + { 0x1000799c, 0x83 }, + { 0x1000799d, 0x20 }, + { 0x1000799e, 0xc1 }, + { 0x1000799f, 0x01 }, + { 0x100079a0, 0x03 }, + { 0x100079a1, 0x24 }, + { 0x100079a2, 0x81 }, + { 0x100079a3, 0x01 }, + { 0x100079a4, 0x83 }, + { 0x100079a5, 0x24 }, + { 0x100079a6, 0x41 }, + { 0x100079a7, 0x01 }, + { 0x100079a8, 0x03 }, + { 0x100079a9, 0x29 }, + { 0x100079aa, 0x01 }, + { 0x100079ab, 0x01 }, + { 0x100079ac, 0x83 }, + { 0x100079ad, 0x29 }, + { 0x100079ae, 0xc1 }, + { 0x100079af, 0x00 }, + { 0x100079b0, 0x13 }, + { 0x100079b1, 0x01 }, + { 0x100079b2, 0x01 }, + { 0x100079b3, 0x02 }, + { 0x100079b4, 0x67 }, + { 0x100079b5, 0x80 }, + { 0x100079b6, 0x00 }, + { 0x100079b7, 0x00 }, + { 0x100079b8, 0xe3 }, + { 0x100079b9, 0x92 }, + { 0x100079ba, 0x07 }, + { 0x100079bb, 0xfe }, + { 0x100079bc, 0x37 }, + { 0x100079bd, 0xc9 }, + { 0x100079be, 0x00 }, + { 0x100079bf, 0x00 }, + { 0x100079c0, 0x83 }, + { 0x100079c1, 0x47 }, + { 0x100079c2, 0x09 }, + { 0x100079c3, 0x56 }, + { 0x100079c4, 0x13 }, + { 0x100079c5, 0x07 }, + { 0x100079c6, 0x80 }, + { 0x100079c7, 0x01 }, + { 0x100079c8, 0x93 }, + { 0x100079c9, 0xf7 }, + { 0x100079ca, 0xf7 }, + { 0x100079cb, 0x0f }, + { 0x100079cc, 0xe3 }, + { 0x100079cd, 0x78 }, + { 0x100079ce, 0xf7 }, + { 0x100079cf, 0xfc }, + { 0x100079d0, 0x83 }, + { 0x100079d1, 0xc7 }, + { 0x100079d2, 0x31 }, + { 0x100079d3, 0x40 }, + { 0x100079d4, 0xe3 }, + { 0x100079d5, 0x84 }, + { 0x100079d6, 0x07 }, + { 0x100079d7, 0xfc }, + { 0x100079d8, 0xb7 }, + { 0x100079d9, 0xd4 }, + { 0x100079da, 0x00 }, + { 0x100079db, 0x00 }, + { 0x100079dc, 0x03 }, + { 0x100079dd, 0xc5 }, + { 0x100079de, 0x94 }, + { 0x100079df, 0x47 }, + { 0x100079e0, 0xb7 }, + { 0x100079e1, 0x15 }, + { 0x100079e2, 0x00 }, + { 0x100079e3, 0x00 }, + { 0x100079e4, 0x93 }, + { 0x100079e5, 0x85 }, + { 0x100079e6, 0x85 }, + { 0x100079e7, 0x38 }, + { 0x100079e8, 0x13 }, + { 0x100079e9, 0x75 }, + { 0x100079ea, 0xf5 }, + { 0x100079eb, 0x0f }, + { 0x100079ec, 0xef }, + { 0x100079ed, 0xe0 }, + { 0x100079ee, 0x5f }, + { 0x100079ef, 0xe0 }, + { 0x100079f0, 0x93 }, + { 0x100079f1, 0x55 }, + { 0x100079f2, 0xf5 }, + { 0x100079f3, 0x41 }, + { 0x100079f4, 0xef }, + { 0x100079f5, 0xe0 }, + { 0x100079f6, 0x0f }, + { 0x100079f7, 0x83 }, + { 0x100079f8, 0xa3 }, + { 0x100079f9, 0x81 }, + { 0x100079fa, 0x01 }, + { 0x100079fb, 0x40 }, + { 0x100079fc, 0x83 }, + { 0x100079fd, 0x27 }, + { 0x100079fe, 0xc9 }, + { 0x100079ff, 0x5f }, + { 0x10007a00, 0x37 }, + { 0x10007a01, 0x07 }, + { 0x10007a02, 0x00 }, + { 0x10007a03, 0x02 }, + { 0x10007a04, 0xb3 }, + { 0x10007a05, 0xf7 }, + { 0x10007a06, 0xe7 }, + { 0x10007a07, 0x00 }, + { 0x10007a08, 0xe3 }, + { 0x10007a09, 0x8a }, + { 0x10007a0a, 0x07 }, + { 0x10007a0b, 0xf8 }, + { 0x10007a0c, 0x03 }, + { 0x10007a0d, 0xc7 }, + { 0x10007a0e, 0x04 }, + { 0x10007a0f, 0x90 }, + { 0x10007a10, 0x93 }, + { 0x10007a11, 0x07 }, + { 0x10007a12, 0x10 }, + { 0x10007a13, 0x00 }, + { 0x10007a14, 0x13 }, + { 0x10007a15, 0x77 }, + { 0x10007a16, 0x17 }, + { 0x10007a17, 0x00 }, + { 0x10007a18, 0x63 }, + { 0x10007a19, 0x1c }, + { 0x10007a1a, 0x07 }, + { 0x10007a1b, 0x00 }, + { 0x10007a1c, 0x83 }, + { 0x10007a1d, 0xc7 }, + { 0x10007a1e, 0x34 }, + { 0x10007a1f, 0x54 }, + { 0x10007a20, 0x93 }, + { 0x10007a21, 0xf7 }, + { 0x10007a22, 0xf7 }, + { 0x10007a23, 0x0f }, + { 0x10007a24, 0x93 }, + { 0x10007a25, 0xd7 }, + { 0x10007a26, 0x17 }, + { 0x10007a27, 0x00 }, + { 0x10007a28, 0x93 }, + { 0x10007a29, 0xc7 }, + { 0x10007a2a, 0x17 }, + { 0x10007a2b, 0x00 }, + { 0x10007a2c, 0x93 }, + { 0x10007a2d, 0xf7 }, + { 0x10007a2e, 0x17 }, + { 0x10007a2f, 0x00 }, + { 0x10007a30, 0xa3 }, + { 0x10007a31, 0x85 }, + { 0x10007a32, 0xf1 }, + { 0x10007a33, 0x42 }, + { 0x10007a34, 0x37 }, + { 0x10007a35, 0xd6 }, + { 0x10007a36, 0x00 }, + { 0x10007a37, 0x00 }, + { 0x10007a38, 0x03 }, + { 0x10007a39, 0x47 }, + { 0x10007a3a, 0x06 }, + { 0x10007a3b, 0x90 }, + { 0x10007a3c, 0x93 }, + { 0x10007a3d, 0x06 }, + { 0x10007a3e, 0x10 }, + { 0x10007a3f, 0x00 }, + { 0x10007a40, 0x13 }, + { 0x10007a41, 0x77 }, + { 0x10007a42, 0x27 }, + { 0x10007a43, 0x00 }, + { 0x10007a44, 0x63 }, + { 0x10007a45, 0x18 }, + { 0x10007a46, 0x07 }, + { 0x10007a47, 0x00 }, + { 0x10007a48, 0x03 }, + { 0x10007a49, 0x47 }, + { 0x10007a4a, 0x36 }, + { 0x10007a4b, 0x54 }, + { 0x10007a4c, 0x13 }, + { 0x10007a4d, 0x77 }, + { 0x10007a4e, 0x17 }, + { 0x10007a4f, 0x00 }, + { 0x10007a50, 0xb3 }, + { 0x10007a51, 0x86 }, + { 0x10007a52, 0xe6 }, + { 0x10007a53, 0x40 }, + { 0x10007a54, 0x23 }, + { 0x10007a55, 0x85 }, + { 0x10007a56, 0xd1 }, + { 0x10007a57, 0x42 }, + { 0x10007a58, 0xb7 }, + { 0x10007a59, 0xd5 }, + { 0x10007a5a, 0x00 }, + { 0x10007a5b, 0x00 }, + { 0x10007a5c, 0x03 }, + { 0x10007a5d, 0xc6 }, + { 0x10007a5e, 0x05 }, + { 0x10007a5f, 0x92 }, + { 0x10007a60, 0x13 }, + { 0x10007a61, 0x07 }, + { 0x10007a62, 0x10 }, + { 0x10007a63, 0x00 }, + { 0x10007a64, 0x13 }, + { 0x10007a65, 0x76 }, + { 0x10007a66, 0x16 }, + { 0x10007a67, 0x00 }, + { 0x10007a68, 0x63 }, + { 0x10007a69, 0x1c }, + { 0x10007a6a, 0x06 }, + { 0x10007a6b, 0x00 }, + { 0x10007a6c, 0x03 }, + { 0x10007a6d, 0xc7 }, + { 0x10007a6e, 0x35 }, + { 0x10007a6f, 0x54 }, + { 0x10007a70, 0x13 }, + { 0x10007a71, 0x77 }, + { 0x10007a72, 0xf7 }, + { 0x10007a73, 0x0f }, + { 0x10007a74, 0x13 }, + { 0x10007a75, 0x57 }, + { 0x10007a76, 0x37 }, + { 0x10007a77, 0x00 }, + { 0x10007a78, 0x13 }, + { 0x10007a79, 0x47 }, + { 0x10007a7a, 0x17 }, + { 0x10007a7b, 0x00 }, + { 0x10007a7c, 0x13 }, + { 0x10007a7d, 0x77 }, + { 0x10007a7e, 0x17 }, + { 0x10007a7f, 0x00 }, + { 0x10007a80, 0xa3 }, + { 0x10007a81, 0x84 }, + { 0x10007a82, 0xe1 }, + { 0x10007a83, 0x42 }, + { 0x10007a84, 0xb7 }, + { 0x10007a85, 0xd5 }, + { 0x10007a86, 0x00 }, + { 0x10007a87, 0x00 }, + { 0x10007a88, 0x03 }, + { 0x10007a89, 0xc6 }, + { 0x10007a8a, 0x05 }, + { 0x10007a8b, 0x92 }, + { 0x10007a8c, 0x13 }, + { 0x10007a8d, 0x07 }, + { 0x10007a8e, 0x10 }, + { 0x10007a8f, 0x00 }, + { 0x10007a90, 0x13 }, + { 0x10007a91, 0x76 }, + { 0x10007a92, 0x26 }, + { 0x10007a93, 0x00 }, + { 0x10007a94, 0x63 }, + { 0x10007a95, 0x1c }, + { 0x10007a96, 0x06 }, + { 0x10007a97, 0x00 }, + { 0x10007a98, 0x03 }, + { 0x10007a99, 0xc7 }, + { 0x10007a9a, 0x35 }, + { 0x10007a9b, 0x54 }, + { 0x10007a9c, 0x13 }, + { 0x10007a9d, 0x77 }, + { 0x10007a9e, 0xf7 }, + { 0x10007a9f, 0x0f }, + { 0x10007aa0, 0x13 }, + { 0x10007aa1, 0x57 }, + { 0x10007aa2, 0x27 }, + { 0x10007aa3, 0x00 }, + { 0x10007aa4, 0x13 }, + { 0x10007aa5, 0x47 }, + { 0x10007aa6, 0x17 }, + { 0x10007aa7, 0x00 }, + { 0x10007aa8, 0x13 }, + { 0x10007aa9, 0x77 }, + { 0x10007aaa, 0x17 }, + { 0x10007aab, 0x00 }, + { 0x10007aac, 0x23 }, + { 0x10007aad, 0x84 }, + { 0x10007aae, 0xe1 }, + { 0x10007aaf, 0x42 }, + { 0x10007ab0, 0x63 }, + { 0x10007ab1, 0x84 }, + { 0x10007ab2, 0x07 }, + { 0x10007ab3, 0x00 }, + { 0x10007ab4, 0xe3 }, + { 0x10007ab5, 0x94 }, + { 0x10007ab6, 0x06 }, + { 0x10007ab7, 0xee }, + { 0x10007ab8, 0xef }, + { 0x10007ab9, 0x90 }, + { 0x10007aba, 0x0f }, + { 0x10007abb, 0x86 }, + { 0x10007abc, 0xef }, + { 0x10007abd, 0xd0 }, + { 0x10007abe, 0x0f }, + { 0x10007abf, 0x97 }, + { 0x10007ac0, 0x37 }, + { 0x10007ac1, 0x15 }, + { 0x10007ac2, 0x00 }, + { 0x10007ac3, 0x00 }, + { 0x10007ac4, 0x13 }, + { 0x10007ac5, 0x05 }, + { 0x10007ac6, 0x85 }, + { 0x10007ac7, 0xbb }, + { 0x10007ac8, 0x93 }, + { 0x10007ac9, 0x05 }, + { 0x10007aca, 0x00 }, + { 0x10007acb, 0x00 }, + { 0x10007acc, 0xef }, + { 0x10007acd, 0xd0 }, + { 0x10007ace, 0x9f }, + { 0x10007acf, 0xf5 }, + { 0x10007ad0, 0xb7 }, + { 0x10007ad1, 0xd7 }, + { 0x10007ad2, 0x00 }, + { 0x10007ad3, 0x00 }, + { 0x10007ad4, 0x83 }, + { 0x10007ad5, 0xc7 }, + { 0x10007ad6, 0x07 }, + { 0x10007ad7, 0x47 }, + { 0x10007ad8, 0x93 }, + { 0x10007ad9, 0xf7 }, + { 0x10007ada, 0x47 }, + { 0x10007adb, 0x00 }, + { 0x10007adc, 0xe3 }, + { 0x10007add, 0x80 }, + { 0x10007ade, 0x07 }, + { 0x10007adf, 0xec }, + { 0x10007ae0, 0xef }, + { 0x10007ae1, 0x80 }, + { 0x10007ae2, 0xdf }, + { 0x10007ae3, 0xf4 }, + { 0x10007ae4, 0x23 }, + { 0x10007ae5, 0x89 }, + { 0x10007ae6, 0xa1 }, + { 0x10007ae7, 0x40 }, + { 0x10007ae8, 0x6f }, + { 0x10007ae9, 0xf0 }, + { 0x10007aea, 0x5f }, + { 0x10007aeb, 0xeb }, + { 0x10007aec, 0x00 }, + { 0x10007aed, 0x00 }, + { 0x10007aee, 0x00 }, + { 0x10007aef, 0x00 }, + { 0x3fc2bf83, 0x00 }, + { 0x3fc2bf82, 0x00 }, + { 0x3fc2bf81, 0x00 }, + { 0x3fc2bf80, 0x00 }, + { 0x3fc2bfc7, 0x00 }, + { 0x3fc2bfc6, 0x00 }, + { 0x3fc2bfc5, 0x00 }, + { 0x3fc2bfc4, 0x00 }, + { 0x3fc2bfc3, 0x00 }, + { 0x3fc2bfc2, 0x00 }, + { 0x3fc2bfc1, 0x00 }, + { 0x3fc2bfc0, 0x03 }, + { 0x0000d486, 0x43 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x00 }, + { 0x1000db00, 0x04 }, + { 0x1000db01, 0x00 }, + { 0x1000db02, 0x11 }, + { 0x1000db03, 0x00 }, + { 0x1000db04, 0x00 }, + { 0x1000db05, 0x82 }, + { 0x1000db06, 0x04 }, + { 0x1000db07, 0xf1 }, + { 0x1000db08, 0x00 }, + { 0x1000db09, 0x00 }, + { 0x1000db0a, 0x40 }, + { 0x1000db0b, 0x02 }, + { 0x1000db0c, 0xf2 }, + { 0x1000db0d, 0x00 }, + { 0x1000db0e, 0x00 }, + { 0x1000db0f, 0xe0 }, + { 0x1000db10, 0x00 }, + { 0x1000db11, 0x10 }, + { 0x1000db12, 0x00 }, + { 0x1000db13, 0x00 }, + { 0x1000db14, 0x45 }, + { 0x0000d540, 0x01 }, + { 0x0000c081, 0xfc }, + { 0x0000f01e, 0x80 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, +}; + /* * The 'patch code' is written to the patch code area. * The patch code area is used for SDCA register expansion flexibility. @@ -1418,12 +3439,13 @@ static const struct reg_sequence rt1320_patch_code_write[] = { static const struct reg_default rt1320_reg_defaults[] = { { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0), 0x00 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), 0x03 }, }; static const struct reg_default rt1320_mbq_defaults[] = { @@ -1484,21 +3506,36 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg) case 0xde00 ... 0xde09: case 0xdf00 ... 0xdf1b: case 0xe000 ... 0xe847: + case 0xf01e: case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: + case 0x1000cd91 ... 0x1000cd96: case 0x1000f008: + case 0x1000f021: case 0x3fe2e000 ... 0x3fe2e003: - case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): + case 0x3fc2ab80 ... 0x3fc2abd4: + /* 0x41000189/0x4100018a */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02): - case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0): - case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): + /* 0x41001388 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): + /* 0x41001988 */ + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): + /* 0x41080000 */ + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): + /* 0x41080200 */ + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0): + /* 0x41080900 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + /* 0x41080980 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + /* 0x41081080 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + /* 0x41081480/0x41081488 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): + /* 0x41081980 */ + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): return true; default: return false; @@ -1508,6 +3545,9 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg) static bool rt1320_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case 0xc000: + case 0xc003: + case 0xc081: case 0xc402 ... 0xc406: case 0xc48c ... 0xc48f: case 0xc560: @@ -1545,16 +3585,21 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg) case 0xde02: case 0xdf14 ... 0xdf1b: case 0xe83c ... 0xe847: + case 0xf01e: case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: case 0x10000000 ... 0x10007fff: case 0x1000c000 ... 0x1000dfff: case 0x1000f008: - case 0x3fc2bfc4 ... 0x3fc2bfc7: + case 0x1000f021: + case 0x3fc2ab80 ... 0x3fc2abd4: + case 0x3fc2bf80 ... 0x3fc2bf83: + case 0x3fc2bfc0 ... 0x3fc2bfc7: case 0x3fe2e000 ... 0x3fe2e003: case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): return true; default: return false; @@ -1577,7 +3622,7 @@ static const struct regmap_config rt1320_sdw_regmap = { .val_bits = 8, .readable_reg = rt1320_readable_register, .volatile_reg = rt1320_volatile_register, - .max_register = 0x41081488, + .max_register = 0x41081980, .reg_defaults = rt1320_reg_defaults, .num_reg_defaults = ARRAY_SIZE(rt1320_reg_defaults), .cache_type = REGCACHE_MAPLE, @@ -1663,6 +3708,63 @@ static int rt1320_read_prop(struct sdw_slave *slave) return 0; } +static int rt1320_pde_transition_delay(struct rt1320_sdw_priv *rt1320, unsigned char ps) +{ + unsigned int delay = 1000, val; + + pm_runtime_mark_last_busy(&rt1320->sdw_slave->dev); + + /* waiting for Actual PDE becomes to PS0/PS3 */ + while (delay) { + regmap_read(rt1320->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, + RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val); + if (val == ps) + break; + + usleep_range(1000, 1500); + delay--; + } + if (!delay) { + dev_warn(&rt1320->sdw_slave->dev, "%s PDE to %s is NOT ready", __func__, ps?"PS3":"PS0"); + return -ETIMEDOUT; + } + + return 0; +} + +static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320) +{ + struct sdw_slave *slave = rt1320->sdw_slave; + unsigned int i, reg, val, delay, retry, tmp; + + regmap_multi_reg_write(rt1320->regmap, rt1320_vc_blind_write, ARRAY_SIZE(rt1320_vc_blind_write)); + + for (i = 0; i < ARRAY_SIZE(rt1320_vc_patch_code_write); i++) { + reg = rt1320_vc_patch_code_write[i].reg; + val = rt1320_vc_patch_code_write[i].def; + delay = rt1320_vc_patch_code_write[i].delay_us; + + if ((reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) && + (val == 0x00)) { + retry = 200; + while (retry) { + regmap_read(rt1320->regmap, RT1320_KR0_INT_READY, &tmp); + dev_dbg(&slave->dev, "%s, RT1320_KR0_INT_READY=0x%x\n", __func__, tmp); + if (tmp == 0x1f) + break; + usleep_range(1000, 1500); + retry--; + } + if (!retry) + dev_warn(&slave->dev, "%s MCU is NOT ready!", __func__); + } + regmap_write(rt1320->regmap, reg, val); + if (delay) + usleep_range(delay, delay + 1000); + } +} + static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) { struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); @@ -1696,16 +3798,20 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) dev_dbg(dev, "%s amp func_status=0x%x\n", __func__, amp_func_status); /* initialization write */ - if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt1320->first_hw_init)) { - regmap_multi_reg_write(rt1320->regmap, rt1320_blind_write, ARRAY_SIZE(rt1320_blind_write)); - regmap_multi_reg_write(rt1320->regmap, rt1320_patch_code_write, - ARRAY_SIZE(rt1320_patch_code_write)); + if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) { + if (rt1320->version_id < RT1320_VC) { + regmap_multi_reg_write(rt1320->regmap, rt1320_blind_write, ARRAY_SIZE(rt1320_blind_write)); + regmap_multi_reg_write(rt1320->regmap, rt1320_patch_code_write, + ARRAY_SIZE(rt1320_patch_code_write)); + } else if (rt1320->version_id == RT1320_VC) { + rt1320_vc_preset(rt1320); + } regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0), FUNCTION_NEEDS_INITIALIZATION); } - if (!rt1320->first_hw_init) { + if (!rt1320->first_hw_init && rt1320->version_id == RT1320_VA) { regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0); regmap_read(rt1320->regmap, RT1320_HIFI_VER_0, &val); @@ -1776,14 +3882,14 @@ static int rt1320_pde23_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, - RT1320_SDCA_CTL_REQ_POWER_STATE, 0), - ps0); + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps0); + rt1320_pde_transition_delay(rt1320, ps0); break; case SND_SOC_DAPM_PRE_PMD: regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, - RT1320_SDCA_CTL_REQ_POWER_STATE, 0), - ps3); + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), ps3); + rt1320_pde_transition_delay(rt1320, ps3); break; default: break; @@ -1799,7 +3905,7 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); - unsigned int read_l, read_r, gain_l_val, gain_r_val; + unsigned int gain_l_val, gain_r_val; unsigned int lvalue, rvalue; const unsigned int interval_offset = 0xc0; @@ -1828,12 +3934,7 @@ static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol, /* Rch */ regmap_write(rt1320->mbq_regmap, mc->rreg, gain_r_val); - regmap_read(rt1320->mbq_regmap, mc->reg, &read_l); - regmap_read(rt1320->mbq_regmap, mc->rreg, &read_r); - if (read_r == gain_r_val && read_l == gain_l_val) - return 1; - - return -EIO; + return 1; } static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h index b23228e74568..1fbc1fcd71cf 100644 --- a/sound/soc/codecs/rt1320-sdw.h +++ b/sound/soc/codecs/rt1320-sdw.h @@ -18,6 +18,7 @@ #define RT1320_DEV_VERSION_ID_1 0xc404 #define RT1320_KR0_STATUS_CNT 0x1000f008 +#define RT1320_KR0_INT_READY 0x1000f021 #define RT1320_HIFI_VER_0 0x3fe2e000 #define RT1320_HIFI_VER_1 0x3fe2e001 #define RT1320_HIFI_VER_2 0x3fe2e002 @@ -43,6 +44,7 @@ /* RT1320 SDCA control */ #define RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 #define RT1320_SDCA_CTL_REQ_POWER_STATE 0x01 +#define RT1320_SDCA_CTL_ACTUAL_POWER_STATE 0x10 #define RT1320_SDCA_CTL_FU_MUTE 0x01 #define RT1320_SDCA_CTL_FU_VOLUME 0x02 #define RT1320_SDCA_CTL_SAPU_PROTECTION_MODE 0x10 @@ -76,6 +78,7 @@ enum { enum rt1320_version_id { RT1320_VA, RT1320_VB, + RT1320_VC, }; #define RT1320_VER_B_ID 0x07392238 diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index e3aca9c785a0..aa163ec40862 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2903,8 +2903,10 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682) } if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + if (ret) + return ret; } else { ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, init.name, diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index f50f196d700d..ce2e88e066f3 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -2828,7 +2828,9 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component) } if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + if (ret) + return ret; } else { ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, init.name, dev_name(dev)); diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index 862e0b654a1c..310123d2bb5f 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c @@ -28,7 +28,8 @@ static const struct snd_soc_dapm_route dir_routes[] = { { "Capture", NULL, "spdif-in" }, }; -#define STUB_RATES SNDRV_PCM_RATE_8000_192000 +#define STUB_RATES (SNDRV_PCM_RATE_8000_768000 | \ + SNDRV_PCM_RATE_128000) #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index 736518921555..db51a46e689d 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c @@ -21,7 +21,8 @@ #define DRV_NAME "spdif-dit" -#define STUB_RATES SNDRV_PCM_RATE_8000_192000 +#define STUB_RATES (SNDRV_PCM_RATE_8000_768000 | \ + SNDRV_PCM_RATE_128000) #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | \ diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index c421906a0694..4ab15be69f3a 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -63,10 +63,6 @@ struct sti_spdif_audio { struct sti_sas_dev_data { const struct regmap_config *regmap; const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */ - const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */ - const int num_dapm_widgets; /* dapms declaration */ - const struct snd_soc_dapm_route *dapm_routes; /* route declaration */ - const int num_dapm_routes; /* route declaration */ }; /* driver data structure */ @@ -324,10 +320,6 @@ static const struct regmap_config stih407_sas_regmap = { static const struct sti_sas_dev_data stih407_data = { .regmap = &stih407_sas_regmap, .dac_ops = &stih407_dac_ops, - .dapm_widgets = stih407_sas_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), - .dapm_routes = stih407_sas_route, - .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), }; static struct snd_soc_dai_driver sti_sas_dai[] = { @@ -386,12 +378,16 @@ static int sti_sas_component_probe(struct snd_soc_component *component) return sti_sas_init_sas_registers(component, drvdata); } -static struct snd_soc_component_driver sti_sas_driver = { +static const struct snd_soc_component_driver sti_sas_driver = { .probe = sti_sas_component_probe, .resume = sti_sas_resume, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, + .dapm_widgets = stih407_sas_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), + .dapm_routes = stih407_sas_route, + .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), }; static const struct of_device_id sti_sas_dev_match[] = { @@ -446,13 +442,6 @@ static int sti_sas_driver_probe(struct platform_device *pdev) sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; - /* Set dapms*/ - sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; - sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; - - sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes; - sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; - /* Store context */ dev_set_drvdata(&pdev->dev, drvdata); diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 9e68afc09897..684d52ec6600 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -12,7 +12,6 @@ #include <linux/errno.h> #include <linux/device.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 5eaddf07aadc..d482cd194c08 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/regmap.h> diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 5601fba17c96..9f93b230652a 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -14,7 +14,6 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/firmware.h> diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c index 6902bfef185b..a1963415c931 100644 --- a/sound/soc/codecs/tas2780.c +++ b/sound/soc/codecs/tas2780.c @@ -7,7 +7,6 @@ #include <linux/err.h> #include <linux/pm.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/regmap.h> #include <linux/of.h> diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c index 1fbf4560f5cc..1e0b3aa95749 100644 --- a/sound/soc/codecs/tas2781-comlib.c +++ b/sound/soc/codecs/tas2781-comlib.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// TAS2781 Common functions for HDA and ASoC Audio drivers +// TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers // // Copyright 2023 - 2024 Texas Instruments, Inc. // @@ -14,7 +14,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -64,8 +63,8 @@ static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv, */ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0); if (ret < 0) { - dev_err(tas_priv->dev, "%s, E=%d\n", - __func__, ret); + dev_err(tas_priv->dev, "%s, E=%d channel:%d\n", + __func__, ret, chn); goto out; } } @@ -89,6 +88,32 @@ out: return ret; } +int tasdev_chn_switch(struct tasdevice_priv *tas_priv, + unsigned short chn) +{ + struct i2c_client *client = (struct i2c_client *)tas_priv->client; + struct tasdevice *tasdev = &tas_priv->tasdevice[chn]; + struct regmap *map = tas_priv->regmap; + int ret; + + if (client->addr != tasdev->dev_addr) { + client->addr = tasdev->dev_addr; + /* All devices share the same regmap, clear the page + * inside regmap once switching to another device. + * Register 0 at any pages and any books inside tas2781 + * is the same one for page-switching. + */ + ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0); + if (ret < 0) { + dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); + return ret; + } + return 1; + } + return 0; +} +EXPORT_SYMBOL_GPL(tasdev_chn_switch); + int tasdevice_dev_read(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int *val) { @@ -411,8 +436,6 @@ EXPORT_SYMBOL_GPL(tasdevice_dsp_remove); void tasdevice_remove(struct tasdevice_priv *tas_priv) { - if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) - gpio_free(tas_priv->irq_info.irq_gpio); mutex_destroy(&tas_priv->codec_lock); } EXPORT_SYMBOL_GPL(tasdevice_remove); diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 8f9a3ae7153e..3de0132c345d 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -13,7 +13,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -2152,20 +2151,61 @@ static int tasdevice_load_data(struct tasdevice_priv *tas_priv, static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i) { + struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw; + struct calidata *cali_data = &priv->cali_data; + struct cali_reg *p = &cali_data->cali_reg_array; + unsigned char *data = cali_data->data; struct tasdevice_calibration *cal; - struct tasdevice_fw *cal_fmw; + int k = i * (cali_data->cali_dat_sz_per_dev + 1); + int rc; - cal_fmw = priv->tasdevice[i].cali_data_fmw; + /* Load the calibrated data from cal bin file */ + if (!priv->is_user_space_calidata && cal_fmw) { + cal = cal_fmw->calibrations; - /* No calibrated data for current devices, playback will go ahead. */ - if (!cal_fmw) + if (cal) + load_calib_data(priv, &cal->dev_data); return; - - cal = cal_fmw->calibrations; - if (!cal) + } + if (!priv->is_user_space_calidata) + return; + /* load calibrated data from user space */ + if (data[k] != i) { + dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n", + __func__, i); return; + } + k++; - load_calib_data(priv, &cal->dev_data); + rc = tasdevice_dev_bulk_write(priv, i, p->r0_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_reg bulk_wr err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->r0_low_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_low_reg err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->invr0_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d invr0_reg err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->pow_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d pow_reg bulk_wr err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->tlimit_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d tlimit_reg err = %d\n", i, rc); + return; + } } int tasdevice_select_tuningprm_cfg(void *context, int prm_no, @@ -2260,9 +2300,10 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, tas_priv->tasdevice[i].cur_conf = cfg_no; } } - } else + } else { dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n", __func__, cfg_no); + } status |= cfg_info[rca_conf_no]->active_dev; diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index e79d613745b4..d0ba7cbe03a8 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -22,7 +22,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -30,9 +29,73 @@ #include <sound/soc.h> #include <sound/tas2781.h> #include <sound/tlv.h> +#include <sound/tas2563-tlv.h> #include <sound/tas2781-tlv.h> #include <asm/unaligned.h> +#define X2563_CL_STT_VAL(xreg, xval) \ +{ .reg = xreg, \ + .val = { xval }, \ + .val_len = 1, } + +#define X2563_CL_STT_4BYTS(xreg, byte0, byte1, byte2, byte3) \ +{ .reg = xreg, \ + .val = { byte0, byte1, byte2, byte3 }, \ + .val_len = 4, } + +static const struct bulk_reg_val tas2563_cali_start_reg[] = { + X2563_CL_STT_VAL(TAS2563_IDLE, 0x00), + X2563_CL_STT_4BYTS(TAS2563_PRM_ENFF_REG, 0x40, 0x00, 0x00, 0x00), + X2563_CL_STT_4BYTS(TAS2563_PRM_DISTCK_REG, 0x40, 0x00, 0x00, 0x00), + X2563_CL_STT_4BYTS(TAS2563_PRM_TE_SCTHR_REG, 0x7f, 0xff, 0xff, 0xff), + X2563_CL_STT_4BYTS(TAS2563_PRM_PLT_FLAG_REG, 0x40, 0x00, 0x00, 0x00), + X2563_CL_STT_4BYTS(TAS2563_PRM_SINEGAIN_REG, 0x0a, 0x3d, 0x70, 0xa4), + X2563_CL_STT_4BYTS(TAS2563_TE_TA1_REG, 0x00, 0x36, 0x91, 0x5e), + X2563_CL_STT_4BYTS(TAS2563_TE_TA1_AT_REG, 0x00, 0x36, 0x91, 0x5e), + X2563_CL_STT_4BYTS(TAS2563_TE_TA2_REG, 0x00, 0x06, 0xd3, 0x72), + X2563_CL_STT_4BYTS(TAS2563_TE_AT_REG, 0x00, 0x36, 0x91, 0x5e), + X2563_CL_STT_4BYTS(TAS2563_TE_DT_REG, 0x00, 0x36, 0x91, 0x5e), +}; + +#define X2781_CL_STT_VAL(xreg, xval, xlocked) \ +{ .reg = xreg, \ + .val = { xval }, \ + .val_len = 1, \ + .is_locked = xlocked, } + +#define X2781_CL_STT_4BYTS_UNLOCKED(xreg, byte0, byte1, byte2, byte3) \ +{ .reg = xreg, \ + .val = { byte0, byte1, byte2, byte3 }, \ + .val_len = 4, \ + .is_locked = false, } + +#define X2781_CL_STT_LEN_UNLOCKED(xreg) \ +{ .reg = xreg, \ + .val_len = 4, \ + .is_locked = false, } + +static const struct bulk_reg_val tas2781_cali_start_reg[] = { + X2781_CL_STT_VAL(TAS2781_PRM_INT_MASK_REG, 0xfe, false), + X2781_CL_STT_VAL(TAS2781_PRM_CLK_CFG_REG, 0xdd, false), + X2781_CL_STT_VAL(TAS2781_PRM_RSVD_REG, 0x20, false), + X2781_CL_STT_VAL(TAS2781_PRM_TEST_57_REG, 0x14, false), + X2781_CL_STT_VAL(TAS2781_PRM_TEST_62_REG, 0x45, true), + X2781_CL_STT_VAL(TAS2781_PRM_PVDD_UVLO_REG, 0x03, false), + X2781_CL_STT_VAL(TAS2781_PRM_CHNL_0_REG, 0xa8, false), + X2781_CL_STT_VAL(TAS2781_PRM_NG_CFG0_REG, 0xb9, false), + X2781_CL_STT_VAL(TAS2781_PRM_IDLE_CH_DET_REG, 0x92, false), + /* + * This register is pilot tone threshold, different with the + * calibration tool version, it will be updated in + * tas2781_calib_start_put(), set to 1mA. + */ + X2781_CL_STT_4BYTS_UNLOCKED(0, 0x00, 0x00, 0x00, 0x56), + X2781_CL_STT_4BYTS_UNLOCKED(TAS2781_PRM_PLT_FLAG_REG, + 0x40, 0x00, 0x00, 0x00), + X2781_CL_STT_LEN_UNLOCKED(TAS2781_PRM_SINEGAIN_REG), + X2781_CL_STT_LEN_UNLOCKED(TAS2781_PRM_SINEGAIN2_REG), +}; + static const struct i2c_device_id tasdevice_id[] = { { "tas2563", TAS2563 }, { "tas2781", TAS2781 }, @@ -141,6 +204,557 @@ static int tasdev_force_fwload_put(struct snd_kcontrol *kcontrol, return change; } +static int tasdev_cali_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + struct calidata *cali_data = &priv->cali_data; + struct cali_reg *p = &cali_data->cali_reg_array; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned char *data = cali_data->data; + unsigned int i = 0; + unsigned int j, k; + int rc; + + guard(mutex)(&priv->codec_lock); + if (!priv->is_user_space_calidata) + return -1; + + if (!p->r0_reg) + return -1; + + dst[i++] = bytes_ext->max; + dst[i++] = 'r'; + + dst[i++] = TASDEVICE_BOOK_ID(p->r0_reg); + dst[i++] = TASDEVICE_PAGE_ID(p->r0_reg); + dst[i++] = TASDEVICE_PAGE_REG(p->r0_reg); + + dst[i++] = TASDEVICE_BOOK_ID(p->r0_low_reg); + dst[i++] = TASDEVICE_PAGE_ID(p->r0_low_reg); + dst[i++] = TASDEVICE_PAGE_REG(p->r0_low_reg); + + dst[i++] = TASDEVICE_BOOK_ID(p->invr0_reg); + dst[i++] = TASDEVICE_PAGE_ID(p->invr0_reg); + dst[i++] = TASDEVICE_PAGE_REG(p->invr0_reg); + + dst[i++] = TASDEVICE_BOOK_ID(p->pow_reg); + dst[i++] = TASDEVICE_PAGE_ID(p->pow_reg); + dst[i++] = TASDEVICE_PAGE_REG(p->pow_reg); + + dst[i++] = TASDEVICE_BOOK_ID(p->tlimit_reg); + dst[i++] = TASDEVICE_PAGE_ID(p->tlimit_reg); + dst[i++] = TASDEVICE_PAGE_REG(p->tlimit_reg); + + for (j = 0, k = 0; j < priv->ndev; j++) { + if (j == data[k]) { + dst[i++] = j; + k++; + } else { + dev_err(priv->dev, "chn %d device %u not match\n", + j, data[k]); + k += 21; + continue; + } + rc = tasdevice_dev_bulk_read(priv, j, p->r0_reg, &dst[i], 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_reg bulk_rd err = %d\n", + j, rc); + i += 20; + k += 20; + continue; + } + rc = memcmp(&dst[i], &data[k], 4); + if (rc != 0) + dev_dbg(priv->dev, "chn %d r0_data is not same\n", j); + k += 4; + i += 4; + rc = tasdevice_dev_bulk_read(priv, j, p->r0_low_reg, + &dst[i], 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_low bulk_rd err = %d\n", + j, rc); + i += 16; + k += 16; + continue; + } + rc = memcmp(&dst[i], &data[k], 4); + if (rc != 0) + dev_dbg(priv->dev, "chn %d r0_low is not same\n", j); + i += 4; + k += 4; + rc = tasdevice_dev_bulk_read(priv, j, p->invr0_reg, + &dst[i], 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d invr0 bulk_rd err = %d\n", + j, rc); + i += 12; + k += 12; + continue; + } + rc = memcmp(&dst[i], &data[k], 4); + if (rc != 0) + dev_dbg(priv->dev, "chn %d invr0 is not same\n", j); + i += 4; + k += 4; + rc = tasdevice_dev_bulk_read(priv, j, p->pow_reg, &dst[i], 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d pow_reg bulk_rd err = %d\n", + j, rc); + i += 8; + k += 8; + continue; + } + rc = memcmp(&dst[i], &data[k], 4); + if (rc != 0) + dev_dbg(priv->dev, "chn %d pow_reg is not same\n", j); + i += 4; + k += 4; + rc = tasdevice_dev_bulk_read(priv, j, p->tlimit_reg, + &dst[i], 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d tlimit bulk_rd err = %d\n", + j, rc); + } + rc = memcmp(&dst[i], &data[k], 4); + if (rc != 0) + dev_dbg(priv->dev, "chn %d tlimit is not same\n", j); + i += 4; + k += 4; + } + return 0; +} + +static int calib_data_get(struct tasdevice_priv *tas_priv, int reg, + unsigned char *dst) +{ + struct i2c_client *clt = (struct i2c_client *)tas_priv->client; + struct tasdevice *tasdev = tas_priv->tasdevice; + int rc = -1; + int i; + + for (i = 0; i < tas_priv->ndev; i++) { + if (clt->addr == tasdev[i].dev_addr) { + /* First byte is the device index. */ + dst[0] = i; + rc = tasdevice_dev_bulk_read(tas_priv, i, reg, &dst[1], + 4); + break; + } + } + + return rc; +} + +static void sngl_calib_start(struct tasdevice_priv *tas_priv, int i, + int *reg, unsigned char *dat) +{ + struct tasdevice *tasdev = tas_priv->tasdevice; + struct bulk_reg_val *p = tasdev[i].cali_data_backup; + const int sum = ARRAY_SIZE(tas2781_cali_start_reg); + int j; + + if (p == NULL) + return; + + /* Store the current setting from the chip */ + for (j = 0; j < sum; j++) { + if (p[j].val_len == 1) { + if (p[j].is_locked) + tasdevice_dev_write(tas_priv, i, + TAS2781_TEST_UNLOCK_REG, + TAS2781_TEST_PAGE_UNLOCK); + tasdevice_dev_read(tas_priv, i, p[j].reg, + (int *)&p[j].val[0]); + } else { + switch (p[j].reg) { + case 0: { + if (!reg[0]) + continue; + p[j].reg = reg[0]; + } + break; + case TAS2781_PRM_PLT_FLAG_REG: + p[j].reg = reg[1]; + break; + case TAS2781_PRM_SINEGAIN_REG: + p[j].reg = reg[2]; + break; + case TAS2781_PRM_SINEGAIN2_REG: + p[j].reg = reg[3]; + break; + } + tasdevice_dev_bulk_read(tas_priv, i, p[j].reg, + p[j].val, 4); + } + } + + /* Update the setting for calibration */ + for (j = 0; j < sum - 2; j++) { + if (p[j].val_len == 1) { + if (p[j].is_locked) + tasdevice_dev_write(tas_priv, i, + TAS2781_TEST_UNLOCK_REG, + TAS2781_TEST_PAGE_UNLOCK); + tasdevice_dev_write(tas_priv, i, p[j].reg, + tas2781_cali_start_reg[j].val[0]); + } else { + if (!p[j].reg) + continue; + tasdevice_dev_bulk_write(tas_priv, i, p[j].reg, + (unsigned char *) + tas2781_cali_start_reg[j].val, 4); + } + } + + tasdevice_dev_bulk_write(tas_priv, i, p[j].reg, &dat[1], 4); + tasdevice_dev_bulk_write(tas_priv, i, p[j + 1].reg, &dat[5], 4); +} + +static int tas2781_calib_start_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dat = ucontrol->value.bytes.data; + int i, reg[4]; + int j = 0; + + guard(mutex)(&priv->codec_lock); + if (priv->chip_id != TAS2781 || bytes_ext->max != dat[0] || + dat[1] != 'r') { + dev_err(priv->dev, "%s: package fmt or chipid incorrect\n", + __func__); + return 0; + } + j += 2; + /* refresh pilot tone and SineGain register */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + reg[i] = TASDEVICE_REG(dat[j], dat[j + 1], dat[j + 2]); + j += 3; + } + + for (i = 0; i < priv->ndev; i++) { + int k = i * 9 + j; + + if (dat[k] != i) { + dev_err(priv->dev, "%s:no cal-setting for dev %d\n", + __func__, i); + continue; + } + sngl_calib_start(priv, i, reg, dat + k); + } + return 1; +} + +static void tas2781_calib_stop_put(struct tasdevice_priv *tas_priv) +{ + const int sum = ARRAY_SIZE(tas2781_cali_start_reg); + int i, j; + + for (i = 0; i < tas_priv->ndev; i++) { + struct tasdevice *tasdev = tas_priv->tasdevice; + struct bulk_reg_val *p = tasdev[i].cali_data_backup; + + if (p == NULL) + continue; + + for (j = 0; j < sum; j++) { + if (p[j].val_len == 1) { + if (p[j].is_locked) + tasdevice_dev_write(tas_priv, i, + TAS2781_TEST_UNLOCK_REG, + TAS2781_TEST_PAGE_UNLOCK); + tasdevice_dev_write(tas_priv, i, p[j].reg, + p[j].val[0]); + } else { + if (!p[j].reg) + continue; + tasdevice_dev_bulk_write(tas_priv, i, p[j].reg, + p[j].val, 4); + } + } + } +} + +static int tas2563_calib_start_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct bulk_reg_val *q = (struct bulk_reg_val *)tas2563_cali_start_reg; + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + const int sum = ARRAY_SIZE(tas2563_cali_start_reg); + int rc = 1; + int i, j; + + guard(mutex)(&tas_priv->codec_lock); + if (tas_priv->chip_id != TAS2563) { + rc = -1; + goto out; + } + + for (i = 0; i < tas_priv->ndev; i++) { + struct tasdevice *tasdev = tas_priv->tasdevice; + struct bulk_reg_val *p = tasdev[i].cali_data_backup; + + if (p == NULL) + continue; + for (j = 0; j < sum; j++) { + if (p[j].val_len == 1) + tasdevice_dev_read(tas_priv, + i, p[j].reg, + (unsigned int *)&p[j].val[0]); + else + tasdevice_dev_bulk_read(tas_priv, + i, p[j].reg, p[j].val, 4); + } + + for (j = 0; j < sum; j++) { + if (p[j].val_len == 1) + tasdevice_dev_write(tas_priv, i, p[j].reg, + q[j].val[0]); + else + tasdevice_dev_bulk_write(tas_priv, i, p[j].reg, + q[j].val, 4); + } + } +out: + return rc; +} + +static void tas2563_calib_stop_put(struct tasdevice_priv *tas_priv) +{ + const int sum = ARRAY_SIZE(tas2563_cali_start_reg); + int i, j; + + for (i = 0; i < tas_priv->ndev; i++) { + struct tasdevice *tasdev = tas_priv->tasdevice; + struct bulk_reg_val *p = tasdev[i].cali_data_backup; + + if (p == NULL) + continue; + + for (j = 0; j < sum; j++) { + if (p[j].val_len == 1) + tasdevice_dev_write(tas_priv, i, p[j].reg, + p[j].val[0]); + else + tasdevice_dev_bulk_write(tas_priv, i, p[j].reg, + p[j].val, 4); + } + } +} + +static int tasdev_calib_stop_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp); + + guard(mutex)(&priv->codec_lock); + if (priv->chip_id == TAS2563) + tas2563_calib_stop_put(priv); + else + tas2781_calib_stop_put(priv); + + return 1; +} + +static int tasdev_cali_data_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + struct calidata *cali_data = &priv->cali_data; + struct cali_reg *p = &cali_data->cali_reg_array; + unsigned char *src = ucontrol->value.bytes.data; + unsigned char *dst = cali_data->data; + int rc = 1, i = 0; + int j; + + guard(mutex)(&priv->codec_lock); + if (src[0] != bytes_ext->max || src[1] != 'r') { + dev_err(priv->dev, "%s: pkg fmt invalid\n", __func__); + return 0; + } + for (j = 0; j < priv->ndev; j++) { + if (src[17 + j * 21] != j) { + dev_err(priv->dev, "%s: pkg fmt invalid\n", __func__); + return 0; + } + } + i += 2; + priv->is_user_space_calidata = true; + + p->r0_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); + i += 3; + p->r0_low_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); + i += 3; + p->invr0_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); + i += 3; + p->pow_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); + i += 3; + p->tlimit_reg = TASDEVICE_REG(src[i], src[i + 1], src[i + 2]); + i += 3; + + memcpy(dst, &src[i], cali_data->total_sz); + return rc; +} + +static int tas2781_latch_reg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct i2c_client *clt = (struct i2c_client *)tas_priv->client; + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + struct tasdevice *tasdev = tas_priv->tasdevice; + unsigned char *dst = ucontrol->value.bytes.data; + int i, val, rc = -1; + + dst[0] = bytes_ext->max; + guard(mutex)(&tas_priv->codec_lock); + for (i = 0; i < tas_priv->ndev; i++) { + if (clt->addr == tasdev[i].dev_addr) { + /* First byte is the device index. */ + dst[1] = i; + rc = tasdevice_dev_read(tas_priv, i, + TAS2781_RUNTIME_LATCH_RE_REG, &val); + if (rc < 0) + dev_err(tas_priv->dev, "%s, get value error\n", + __func__); + else + dst[2] = val; + + break; + } + } + + return rc; +} + +static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned int reg; + int rc = -1; + + if (tas_priv->chip_id == TAS2781) + reg = TAS2781_RUNTIME_RE_REG_TF; + else + reg = TAS2563_RUNTIME_RE_REG_TF; + + guard(mutex)(&tas_priv->codec_lock); + dst[0] = bytes_ext->max; + rc = calib_data_get(tas_priv, reg, &dst[1]); + + return rc; +} + +static int tasdev_re_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned int reg; + int rc = -1; + + if (tas_priv->chip_id == TAS2781) + reg = TAS2781_RUNTIME_RE_REG; + else + reg = TAS2563_RUNTIME_RE_REG; + guard(mutex)(&tas_priv->codec_lock); + dst[0] = bytes_ext->max; + rc = calib_data_get(tas_priv, reg, &dst[1]); + + return rc; +} + +static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct calidata *cali_data = &tas_priv->cali_data; + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned int reg; + int rc = -1; + + guard(mutex)(&tas_priv->codec_lock); + + if (tas_priv->chip_id == TAS2563) + reg = TAS2563_PRM_R0_REG; + else if (cali_data->cali_reg_array.r0_reg) + reg = cali_data->cali_reg_array.r0_reg; + else + return -1; + dst[0] = bytes_ext->max; + rc = calib_data_get(tas_priv, reg, &dst[1]); + + return rc; +} + +static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned int reg = TASDEVICE_XM_A1_REG; + int rc = -1; + + guard(mutex)(&tas_priv->codec_lock); + dst[0] = bytes_ext->max; + rc = calib_data_get(tas_priv, reg, &dst[1]); + + return rc; +} + +static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); + struct soc_bytes_ext *bytes_ext = + (struct soc_bytes_ext *) kcontrol->private_value; + unsigned char *dst = ucontrol->value.bytes.data; + unsigned int reg = TASDEVICE_XM_A2_REG; + int rc = -1; + + guard(mutex)(&tas_priv->codec_lock); + dst[0] = bytes_ext->max; + rc = calib_data_get(tas_priv, reg, &dst[1]); + + return rc; +} + +static int tasdev_nop_get( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + static int tas2563_digital_gain_get( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -157,7 +771,7 @@ static int tas2563_digital_gain_get( mutex_lock(&tas_dev->codec_lock); /* Read the primary device */ - ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); if (ret) { dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); goto out; @@ -203,7 +817,7 @@ static int tas2563_digital_gain_put( vol = clamp(vol, 0, max); mutex_lock(&tas_dev->codec_lock); /* Read the primary device */ - ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); if (ret) { dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); rc = -1; @@ -241,6 +855,16 @@ static const struct snd_kcontrol_new tasdevice_snd_controls[] = { tasdev_force_fwload_get, tasdev_force_fwload_put), }; +static const struct snd_kcontrol_new tasdevice_cali_controls[] = { + SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0, + tasdev_nop_get, tasdev_calib_stop_put), + SND_SOC_BYTES_EXT("Amp TF Data", 6, tasdev_tf_data_get, NULL), + SND_SOC_BYTES_EXT("Amp RE Data", 6, tasdev_re_data_get, NULL), + SND_SOC_BYTES_EXT("Amp R0 Data", 6, tasdev_r0_data_get, NULL), + SND_SOC_BYTES_EXT("Amp XMA1 Data", 6, tasdev_XMA1_data_get, NULL), + SND_SOC_BYTES_EXT("Amp XMA2 Data", 6, tasdev_XMA2_data_get, NULL), +}; + static const struct snd_kcontrol_new tas2781_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL, 1, 0, 20, 0, tas2781_amp_getvol, @@ -250,6 +874,10 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_digital_putvol, dvc_tlv), }; +static const struct snd_kcontrol_new tas2781_cali_controls[] = { + SND_SOC_BYTES_EXT("Amp Latch Data", 3, tas2781_latch_reg_get, NULL), +}; + static const struct snd_kcontrol_new tas2563_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2563_DVC_LVL, 0, 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0, @@ -257,6 +885,11 @@ static const struct snd_kcontrol_new tas2563_snd_controls[] = { tas2563_dvc_tlv), }; +static const struct snd_kcontrol_new tas2563_cali_controls[] = { + SOC_SINGLE_EXT("Calibration Start", SND_SOC_NOPM, 0, 1, 0, + tasdev_nop_get, tas2563_calib_start_put), +}; + static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -274,6 +907,31 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol, return ret; } +static int tasdevice_info_active_num(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = tas_priv->ndev - 1; + + return 0; +} + +static int tasdevice_info_chip_id(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = TAS2563; + uinfo->value.integer.max = TAS2781; + + return 0; +} + static int tasdevice_info_programs(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -330,6 +988,17 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol, return 0; } +static int tasdevice_get_chip_id(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas_priv->chip_id; + + return 0; +} + static int tasdevice_create_control(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *prof_ctrls; @@ -346,13 +1015,11 @@ static int tasdevice_create_control(struct tasdevice_priv *tas_priv) } /* Create a mixer item for selecting the active profile */ - name = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, - GFP_KERNEL); + name = devm_kstrdup(tas_priv->dev, "Speaker Profile Id", GFP_KERNEL); if (!name) { ret = -ENOMEM; goto out; } - scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "Speaker Profile Id"); prof_ctrls[mix_index].name = name; prof_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; prof_ctrls[mix_index].info = tasdevice_info_profile; @@ -423,12 +1090,47 @@ static int tasdevice_configuration_put( return ret; } -static int tasdevice_dsp_create_ctrls( - struct tasdevice_priv *tas_priv) +static int tasdevice_active_num_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); + struct i2c_client *clt = (struct i2c_client *)tas_priv->client; + struct tasdevice *tasdev = tas_priv->tasdevice; + int i; + + for (i = 0; i < tas_priv->ndev; i++) { + if (clt->addr == tasdev[i].dev_addr) { + ucontrol->value.integer.value[0] = i; + return 0; + } + } + + return -1; +} + +static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); + int dev_id = ucontrol->value.integer.value[0]; + int max = tas_priv->ndev - 1, rc; + + dev_id = clamp(dev_id, 0, max); + + guard(mutex)(&tas_priv->codec_lock); + rc = tasdev_chn_switch(tas_priv, dev_id); + + return rc; +} + +static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *dsp_ctrls; - char *prog_name, *conf_name; - int nr_controls = 2; + char *active_dev_num, *chip_id; + char *conf_name, *prog_name; + int nr_controls = 4; int mix_index = 0; int ret; @@ -442,18 +1144,13 @@ static int tasdevice_dsp_create_ctrls( goto out; } - /* Create a mixer item for selecting the active profile */ - prog_name = devm_kzalloc(tas_priv->dev, - SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL); - conf_name = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + /* Create mixer items for selecting the active Program and Config */ + prog_name = devm_kstrdup(tas_priv->dev, "Speaker Program Id", GFP_KERNEL); - if (!prog_name || !conf_name) { + if (!prog_name) { ret = -ENOMEM; goto out; } - - scnprintf(prog_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, - "Speaker Program Id"); dsp_ctrls[mix_index].name = prog_name; dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; dsp_ctrls[mix_index].info = tasdevice_info_programs; @@ -461,8 +1158,12 @@ static int tasdevice_dsp_create_ctrls( dsp_ctrls[mix_index].put = tasdevice_program_put; mix_index++; - scnprintf(conf_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, - "Speaker Config Id"); + conf_name = devm_kstrdup(tas_priv->dev, "Speaker Config Id", + GFP_KERNEL); + if (!conf_name) { + ret = -ENOMEM; + goto out; + } dsp_ctrls[mix_index].name = conf_name; dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; dsp_ctrls[mix_index].info = tasdevice_info_configurations; @@ -470,6 +1171,30 @@ static int tasdevice_dsp_create_ctrls( dsp_ctrls[mix_index].put = tasdevice_configuration_put; mix_index++; + active_dev_num = devm_kstrdup(tas_priv->dev, "Activate Tasdevice Num", + GFP_KERNEL); + if (!active_dev_num) { + ret = -ENOMEM; + goto out; + } + dsp_ctrls[mix_index].name = active_dev_num; + dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + dsp_ctrls[mix_index].info = tasdevice_info_active_num; + dsp_ctrls[mix_index].get = tasdevice_active_num_get; + dsp_ctrls[mix_index].put = tasdevice_active_num_put; + mix_index++; + + chip_id = devm_kstrdup(tas_priv->dev, "Tasdevice Chip Id", GFP_KERNEL); + if (!chip_id) { + ret = -ENOMEM; + goto out; + } + dsp_ctrls[mix_index].name = chip_id; + dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + dsp_ctrls[mix_index].info = tasdevice_info_chip_id; + dsp_ctrls[mix_index].get = tasdevice_get_chip_id; + mix_index++; + ret = snd_soc_add_component_controls(tas_priv->codec, dsp_ctrls, nr_controls < mix_index ? nr_controls : mix_index); @@ -477,6 +1202,149 @@ out: return ret; } +static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv) +{ + struct calidata *cali_data = &priv->cali_data; + struct tasdevice *tasdev = priv->tasdevice; + struct soc_bytes_ext *ext_cali_data; + struct snd_kcontrol_new *cali_ctrls; + unsigned int nctrls; + char *cali_name; + int rc, i; + + rc = snd_soc_add_component_controls(priv->codec, + tasdevice_cali_controls, ARRAY_SIZE(tasdevice_cali_controls)); + if (rc < 0) { + dev_err(priv->dev, "%s: Add cali controls err rc = %d", + __func__, rc); + return rc; + } + + if (priv->chip_id == TAS2781) { + cali_ctrls = (struct snd_kcontrol_new *)tas2781_cali_controls; + nctrls = ARRAY_SIZE(tas2781_cali_controls); + for (i = 0; i < priv->ndev; i++) { + tasdev[i].cali_data_backup = + kmemdup(tas2781_cali_start_reg, + sizeof(tas2781_cali_start_reg), GFP_KERNEL); + if (!tasdev[i].cali_data_backup) + return -ENOMEM; + } + } else { + cali_ctrls = (struct snd_kcontrol_new *)tas2563_cali_controls; + nctrls = ARRAY_SIZE(tas2563_cali_controls); + for (i = 0; i < priv->ndev; i++) { + tasdev[i].cali_data_backup = + kmemdup(tas2563_cali_start_reg, + sizeof(tas2563_cali_start_reg), GFP_KERNEL); + if (!tasdev[i].cali_data_backup) + return -ENOMEM; + } + } + + rc = snd_soc_add_component_controls(priv->codec, cali_ctrls, nctrls); + if (rc < 0) { + dev_err(priv->dev, "%s: Add chip cali ctrls err rc = %d", + __func__, rc); + return rc; + } + + /* index for cali_ctrls */ + i = 0; + if (priv->chip_id == TAS2781) + nctrls = 2; + else + nctrls = 1; + + /* + * Alloc kcontrol via devm_kzalloc(), which don't manually + * free the kcontrol。 + */ + cali_ctrls = devm_kcalloc(priv->dev, nctrls, + sizeof(cali_ctrls[0]), GFP_KERNEL); + if (!cali_ctrls) + return -ENOMEM; + + ext_cali_data = devm_kzalloc(priv->dev, sizeof(*ext_cali_data), + GFP_KERNEL); + if (!ext_cali_data) + return -ENOMEM; + + cali_name = devm_kstrdup(priv->dev, "Speaker Calibrated Data", + GFP_KERNEL); + if (!cali_name) + return -ENOMEM; + /* the number of calibrated data per tas2563/tas2781 */ + cali_data->cali_dat_sz_per_dev = 20; + /* + * Data structure for tas2563/tas2781 calibrated data: + * Pkg len (1 byte) + * Reg id (1 byte, constant 'r') + * book, page, register array for calibrated data (15 bytes) + * for (i = 0; i < Device-Sum; i++) { + * Device #i index_info (1 byte) + * Calibrated data for Device #i (20 bytes) + * } + */ + ext_cali_data->max = priv->ndev * + (cali_data->cali_dat_sz_per_dev + 1) + 1 + 15 + 1; + priv->cali_data.total_sz = priv->ndev * + (cali_data->cali_dat_sz_per_dev + 1); + priv->cali_data.data = devm_kzalloc(priv->dev, + ext_cali_data->max, GFP_KERNEL); + cali_ctrls[i].name = cali_name; + cali_ctrls[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + cali_ctrls[i].info = snd_soc_bytes_info_ext; + cali_ctrls[i].get = tasdev_cali_data_get; + cali_ctrls[i].put = tasdev_cali_data_put; + cali_ctrls[i].private_value = (unsigned long)ext_cali_data; + i++; + + cali_data->data = devm_kzalloc(priv->dev, cali_data->total_sz, + GFP_KERNEL); + if (!cali_data->data) + return -ENOMEM; + + if (priv->chip_id == TAS2781) { + struct soc_bytes_ext *ext_cali_start; + char *cali_start_name; + + ext_cali_start = devm_kzalloc(priv->dev, + sizeof(*ext_cali_start), GFP_KERNEL); + if (!ext_cali_start) + return -ENOMEM; + + cali_start_name = devm_kstrdup(priv->dev, + "Calibration Start", GFP_KERNEL); + if (!cali_start_name) + return -ENOMEM; + /* + * package structure for tas2781 ftc start: + * Pkg len (1 byte) + * Reg id (1 byte, constant 'r') + * book, page, register for pilot threshold, pilot tone + * and sine gain (12 bytes) + * for (i = 0; i < Device-Sum; i++) { + * Device #i index_info (1 byte) + * Sine gain for Device #i (8 bytes) + * } + */ + ext_cali_start->max = 14 + priv->ndev * 9; + cali_ctrls[i].name = cali_start_name; + cali_ctrls[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + cali_ctrls[i].info = snd_soc_bytes_info_ext; + cali_ctrls[i].put = tas2781_calib_start_put; + cali_ctrls[i].get = tasdev_nop_get; + cali_ctrls[i].private_value = (unsigned long)ext_cali_start; + i++; + } + + rc = snd_soc_add_component_controls(priv->codec, cali_ctrls, + nctrls < i ? nctrls : i); + + return rc; +} + static void tasdevice_fw_ready(const struct firmware *fmw, void *context) { @@ -502,7 +1370,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw, */ tas_priv->fw_state = TASDEVICE_RCA_FW_OK; if (tas_priv->name_prefix) - scnprintf(tas_priv->rca_binaryname, 64, "%s-%s_coef.bin", + scnprintf(tas_priv->coef_binaryname, 64, "%s-%s_coef.bin", tas_priv->name_prefix, tas_priv->dev_name); else scnprintf(tas_priv->coef_binaryname, 64, "%s_coef.bin", @@ -523,6 +1391,12 @@ static void tasdevice_fw_ready(const struct firmware *fmw, goto out; } + ret = tasdevice_create_cali_ctrls(tas_priv); + if (ret) { + dev_err(tas_priv->dev, "cali controls error\n"); + goto out; + } + tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; /* If calibrated data occurs error, dsp will still works with default @@ -583,13 +1457,13 @@ static const struct snd_soc_dapm_widget tasdevice_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SPK("SPK", tasdevice_dapm_event), SND_SOC_DAPM_OUTPUT("OUT"), - SND_SOC_DAPM_INPUT("DMIC") + SND_SOC_DAPM_INPUT("DMIC"), }; static const struct snd_soc_dapm_route tasdevice_audio_map[] = { {"SPK", NULL, "ASI"}, {"OUT", NULL, "SPK"}, - {"ASI OUT", NULL, "DMIC"} + {"ASI OUT", NULL, "DMIC"}, }; static int tasdevice_startup(struct snd_pcm_substream *substream, @@ -672,7 +1546,7 @@ static const struct snd_soc_dai_ops tasdevice_dai_ops = { static struct snd_soc_dai_driver tasdevice_dai_driver[] = { { - .name = "tas2781_codec", + .name = "tasdev_codec", .id = 0, .playback = { .stream_name = "Playback", @@ -724,6 +1598,11 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) static void tasdevice_deinit(void *context) { struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context; + struct tasdevice *tasdev = tas_priv->tasdevice; + int i; + + for (i = 0; i < tas_priv->ndev; i++) + kfree(tasdev[i].cali_data_backup); tasdevice_config_info_remove(tas_priv); tasdevice_dsp_remove(tas_priv); @@ -731,8 +1610,7 @@ static void tasdevice_deinit(void *context) tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; } -static void tasdevice_codec_remove( - struct snd_soc_component *codec) +static void tasdevice_codec_remove(struct snd_soc_component *codec) { struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); @@ -757,7 +1635,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) { struct i2c_client *client = (struct i2c_client *)tas_priv->client; unsigned int dev_addrs[TASDEVICE_MAX_CHANNELS]; - int rc, i, ndev = 0; + int i, ndev = 0; if (tas_priv->isacpi) { ndev = device_property_read_u32_array(&client->dev, @@ -772,7 +1650,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) "ti,audio-slots", dev_addrs, ndev); } - tas_priv->irq_info.irq_gpio = + tas_priv->irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(&client->dev), 0); } else if (IS_ENABLED(CONFIG_OF)) { struct device_node *np = tas_priv->dev->of_node; @@ -784,7 +1662,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) dev_addrs[ndev++] = addr; } - tas_priv->irq_info.irq_gpio = of_irq_get(np, 0); + tas_priv->irq = of_irq_get(np, 0); } else { ndev = 1; dev_addrs[0] = client->addr; @@ -794,29 +1672,12 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) tas_priv->tasdevice[i].dev_addr = dev_addrs[i]; tas_priv->reset = devm_gpiod_get_optional(&client->dev, - "reset-gpios", GPIOD_OUT_HIGH); + "reset", GPIOD_OUT_HIGH); if (IS_ERR(tas_priv->reset)) dev_err(tas_priv->dev, "%s Can't get reset GPIO\n", __func__); strcpy(tas_priv->dev_name, tasdevice_id[tas_priv->chip_id].name); - - if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) { - rc = gpio_request(tas_priv->irq_info.irq_gpio, - "AUDEV-IRQ"); - if (!rc) { - gpio_direction_input( - tas_priv->irq_info.irq_gpio); - - tas_priv->irq_info.irq = - gpio_to_irq(tas_priv->irq_info.irq_gpio); - } else - dev_err(tas_priv->dev, "%s: GPIO %d request error\n", - __func__, tas_priv->irq_info.irq_gpio); - } else - dev_err(tas_priv->dev, - "Looking up irq-gpio property failed %d\n", - tas_priv->irq_info.irq_gpio); } static int tasdevice_i2c_probe(struct i2c_client *i2c) diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 4bc1fdd232bb..b97c0e885713 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -463,9 +463,9 @@ static void tas5086_reset(struct tas5086_private *priv) { if (priv->reset) { /* Reset codec - minimum assertion time is 400ns */ - gpiod_direction_output(priv->reset, 1); + gpiod_set_value_cansleep(priv->reset, 1); udelay(1); - gpiod_set_value(priv->reset, 0); + gpiod_set_value_cansleep(priv->reset, 0); /* Codec needs ~15ms to wake up */ msleep(15); @@ -866,9 +866,10 @@ static void tas5086_remove(struct snd_soc_component *component) { struct tas5086_private *priv = snd_soc_component_get_drvdata(component); - if (priv->reset) + if (priv->reset) { /* Set codec to the reset state */ - gpiod_set_value(priv->reset, 1); + gpiod_set_value_cansleep(priv->reset, 1); + } regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); }; diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 386b99c8023b..7d6fcba9986e 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -623,6 +623,7 @@ static const struct of_device_id tda7419_of_match[] = { { .compatible = "st,tda7419" }, { }, }; +MODULE_DEVICE_TABLE(of, tda7419_of_match); static struct i2c_driver tda7419_driver = { .driver = { diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 2f94cfda0e33..187d68e8688c 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -12,6 +12,7 @@ * and mono/stereo Class-D speaker driver. */ +#include <asm/unaligned.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> @@ -22,6 +23,7 @@ #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/acpi.h> +#include <linux/firmware.h> #include <linux/of.h> #include <linux/slab.h> #include <sound/core.h> @@ -893,7 +895,7 @@ static int aic31xx_setup_pll(struct snd_soc_component *component, dev_err(component->dev, "%s: Sample rate (%u) and format not supported\n", __func__, params_rate(params)); - /* See bellow for details how fix this. */ + /* See below for details on how to fix this. */ return -EINVAL; } if (bclk_score != 0) { @@ -1638,6 +1640,98 @@ static const struct i2c_device_id aic31xx_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); +static int tlv320dac3100_fw_load(struct aic31xx_priv *aic31xx, + const u8 *data, size_t size) +{ + int ret, reg; + u16 val16; + + /* + * Coefficients firmware binary structure. Multi-byte values are big-endian. + * + * @0, 16bits: Magic (0xB30C) + * @2, 16bits: Version (0x0100 for version 1.0) + * @4, 8bits: DAC Processing Block Selection + * @5, 62 16-bit values: Page 8 buffer A DAC programmable filter coefficients + * @129, 12 16-bit values: Page 9 Buffer A DAC programmable filter coefficients + * + * Filter coefficients are interpreted as two's complement values + * ranging from -32 768 to 32 767. For more details on filter coefficients, + * please refer to the TLV320DAC3100 datasheet, tables 6-120 and 6-123. + */ + + if (size != 153) { + dev_err(aic31xx->dev, "firmware size is %zu, expected 153 bytes\n", size); + return -EINVAL; + } + + /* Check magic */ + val16 = get_unaligned_be16(data); + if (val16 != 0xb30c) { + dev_err(aic31xx->dev, "fw magic is 0x%04x expected 0xb30c\n", val16); + return -EINVAL; + } + data += 2; + + /* Check version */ + val16 = get_unaligned_be16(data); + if (val16 != 0x0100) { + dev_err(aic31xx->dev, "invalid firmware version 0x%04x! expected 1", val16); + return -EINVAL; + } + data += 2; + + ret = regmap_write(aic31xx->regmap, AIC31XX_DACPRB, *data); + if (ret) { + dev_err(aic31xx->dev, "failed to write PRB index: err %d\n", ret); + return ret; + } + data += 1; + + /* Page 8 Buffer A coefficients */ + for (reg = 2; reg < 126; reg++) { + ret = regmap_write(aic31xx->regmap, AIC31XX_REG(8, reg), *data); + if (ret) { + dev_err(aic31xx->dev, + "failed to write page 8 filter coefficient %d: err %d\n", reg, ret); + return ret; + } + data++; + } + + /* Page 9 Buffer A coefficients */ + for (reg = 2; reg < 26; reg++) { + ret = regmap_write(aic31xx->regmap, AIC31XX_REG(9, reg), *data); + if (ret) { + dev_err(aic31xx->dev, + "failed to write page 9 filter coefficient %d: err %d\n", reg, ret); + return ret; + } + data++; + } + + dev_info(aic31xx->dev, "done loading DAC filter coefficients\n"); + + return ret; +} + +static int tlv320dac3100_load_coeffs(struct aic31xx_priv *aic31xx, + const char *fw_name) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, fw_name, aic31xx->dev); + if (ret) + return ret; + + ret = tlv320dac3100_fw_load(aic31xx, fw->data, fw->size); + + release_firmware(fw); + + return ret; +} + static int aic31xx_i2c_probe(struct i2c_client *i2c) { struct aic31xx_priv *aic31xx; @@ -1727,6 +1821,12 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c) } } + if (aic31xx->codec_type == DAC3100) { + ret = tlv320dac3100_load_coeffs(aic31xx, "tlv320dac3100-coeffs.bin"); + if (ret) + dev_warn(aic31xx->dev, "Did not load any filter coefficients\n"); + } + if (aic31xx->codec_type & DAC31XX_BIT) return devm_snd_soc_register_component(&i2c->dev, &soc_codec_driver_aic31xx, diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 5c0c81da06db..54ea4bc58c27 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -1073,6 +1073,13 @@ static int aic32x4_component_probe(struct snd_soc_component *component) return 0; } +static int aic32x4_of_xlate_dai_id(struct snd_soc_component *component, + struct device_node *endpoint) +{ + /* return dai id 0, whatever the endpoint index */ + return 0; +} + static const struct snd_soc_component_driver soc_component_dev_aic32x4 = { .probe = aic32x4_component_probe, .set_bias_level = aic32x4_set_bias_level, @@ -1082,6 +1089,7 @@ static const struct snd_soc_component_driver soc_component_dev_aic32x4 = { .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), .dapm_routes = aic32x4_dapm_routes, .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), + .of_xlate_dai_id = aic32x4_of_xlate_dai_id, .suspend_bias_off = 1, .idle_bias_on = 1, .use_pmdown_time = 1, @@ -1203,6 +1211,7 @@ static const struct snd_soc_component_driver soc_component_dev_aic32x4_tas2505 = .num_dapm_widgets = ARRAY_SIZE(aic32x4_tas2505_dapm_widgets), .dapm_routes = aic32x4_tas2505_dapm_routes, .num_dapm_routes = ARRAY_SIZE(aic32x4_tas2505_dapm_routes), + .of_xlate_dai_id = aic32x4_of_xlate_dai_id, .suspend_bias_off = 1, .idle_bias_on = 1, .use_pmdown_time = 1, diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 291d0c80a6fc..910852eb9698 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -2643,8 +2643,8 @@ static void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x, s16 c1; s32 x1, d1; int32_t denom; - int minCode_param[] = { - 3277, 1639, 820, 410, 205, 103, 52, 26 + static const int minCode_param[] = { + 3277, 1639, 820, 410, 205, 103, 52, 26 }; regmap_update_bits(wcd934x->regmap, WCD934X_ANA_MBHC_ZDET, 0x20, 0x20); diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index af296b77a723..45f32d281908 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -2957,7 +2957,7 @@ MODULE_DEVICE_TABLE(of, wcd937x_of_match); static struct platform_driver wcd937x_codec_driver = { .probe = wcd937x_probe, - .remove_new = wcd937x_remove, + .remove = wcd937x_remove, .driver = { .name = "wcd937x_codec", .of_match_table = of_match_ptr(wcd937x_of_match), diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h index 37bff16e88dd..35f3d48bd7dd 100644 --- a/sound/soc/codecs/wcd937x.h +++ b/sound/soc/codecs/wcd937x.h @@ -484,10 +484,25 @@ #define WCD937X_MAX_MICBIAS 3 #define WCD937X_MAX_BULK_SUPPLY 4 -#define WCD937X_MAX_TX_SWR_PORTS 4 -#define WCD937X_MAX_SWR_PORTS 5 #define WCD937X_MAX_SWR_CH_IDS 15 +enum wcd937x_tx_sdw_ports { + WCD937X_ADC_1_PORT = 1, + WCD937X_ADC_2_3_PORT, + WCD937X_DMIC_0_3_MBHC_PORT, + WCD937X_DMIC_4_6_PORT, + WCD937X_MAX_TX_SWR_PORTS = WCD937X_DMIC_4_6_PORT, +}; + +enum wcd937x_rx_sdw_ports { + WCD937X_HPH_PORT = 1, + WCD937X_CLSH_PORT, + WCD937X_COMP_PORT, + WCD937X_LO_PORT, + WCD937X_DSD_PORT, + WCD937X_MAX_SWR_PORTS = WCD937X_DSD_PORT, +}; + struct wcd937x_sdw_ch_info { int port_num; unsigned int ch_mask; @@ -581,13 +596,6 @@ enum { WCD937X_NUM_IRQS, }; -enum wcd937x_tx_sdw_ports { - WCD937X_ADC_1_PORT = 1, - WCD937X_ADC_2_3_PORT, - WCD937X_DMIC_0_3_MBHC_PORT, - WCD937X_DMIC_4_6_PORT, -}; - enum wcd937x_tx_sdw_channels { WCD937X_ADC1, WCD937X_ADC2, @@ -602,14 +610,6 @@ enum wcd937x_tx_sdw_channels { WCD937X_DMIC6, }; -enum wcd937x_rx_sdw_ports { - WCD937X_HPH_PORT = 1, - WCD937X_CLSH_PORT, - WCD937X_COMP_PORT, - WCD937X_LO_PORT, - WCD937X_DSD_PORT, -}; - enum wcd937x_rx_sdw_channels { WCD937X_HPH_L, WCD937X_HPH_R, diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 12b32d5dc580..f2a4f3262bdb 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -29,7 +29,6 @@ #define WCD938X_MAX_SUPPLY (4) #define WCD938X_MBHC_MAX_BUTTONS (8) #define TX_ADC_MAX (4) -#define WCD938X_TX_MAX_SWR_PORTS (5) #define WCD938X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -39,8 +38,6 @@ SNDRV_PCM_RATE_176400) #define WCD938X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_LE) -/* Convert from vout ctl to micbias voltage in mV */ -#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) #define SWR_CLK_RATE_0P6MHZ (600000) #define SWR_CLK_RATE_1P2MHZ (1200000) #define SWR_CLK_RATE_2P4MHZ (2400000) @@ -48,8 +45,6 @@ #define SWR_CLK_RATE_9P6MHZ (9600000) #define SWR_CLK_RATE_11P2896MHZ (1128960) -#define WCD938X_DRV_NAME "wcd938x_codec" -#define WCD938X_VERSION_1_0 (1) #define EAR_RX_PATH_AUX (1) #define ADC_MODE_VAL_HIFI 0x01 @@ -72,7 +67,6 @@ /* Z value compared in milliOhm */ #define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) #define WCD938X_MBHC_ZDET_CONST (86 * 16384) -#define WCD938X_MBHC_MOISTURE_RREF R_24_KOHM #define WCD_MBHC_HS_V_MAX 1600 #define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ @@ -90,18 +84,6 @@ enum { }; enum { - TX_HDR12 = 0, - TX_HDR34, - TX_HDR_MAX, -}; - -enum { - WCD_RX1, - WCD_RX2, - WCD_RX3 -}; - -enum { /* INTR_CTRL_INT_MASK_0 */ WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0, WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, @@ -3614,7 +3596,7 @@ MODULE_DEVICE_TABLE(of, wcd938x_dt_match); static struct platform_driver wcd938x_codec_driver = { .probe = wcd938x_probe, - .remove_new = wcd938x_remove, + .remove = wcd938x_remove, .driver = { .name = "wcd938x_codec", .of_match_table = of_match_ptr(wcd938x_dt_match), diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h index b2ad98026ae2..fb6a0e4ef337 100644 --- a/sound/soc/codecs/wcd938x.h +++ b/sound/soc/codecs/wcd938x.h @@ -585,8 +585,6 @@ #define WCD938X_DIGITAL_DEM_BYPASS_DATA3 (0x34D8) #define WCD938X_MAX_REGISTER (WCD938X_DIGITAL_DEM_BYPASS_DATA3) -#define WCD938X_MAX_SWR_PORTS 5 -#define WCD938X_MAX_TX_SWR_PORTS 4 #define WCD938X_MAX_SWR_CH_IDS 15 struct wcd938x_sdw_ch_info { @@ -606,6 +604,7 @@ enum wcd938x_tx_sdw_ports { /* DMIC0_0, DMIC0_1, DMIC1_0, DMIC1_1 */ WCD938X_DMIC_0_3_MBHC_PORT, WCD938X_DMIC_4_7_PORT, + WCD938X_MAX_TX_SWR_PORTS = WCD938X_DMIC_4_7_PORT, }; enum wcd938x_tx_sdw_channels { @@ -630,6 +629,7 @@ enum wcd938x_rx_sdw_ports { WCD938X_COMP_PORT, WCD938X_LO_PORT, WCD938X_DSD_PORT, + WCD938X_MAX_SWR_PORTS = WCD938X_DSD_PORT, }; enum wcd938x_rx_sdw_channels { diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c index 68fc591670dc..4a417a92514d 100644 --- a/sound/soc/codecs/wcd939x.c +++ b/sound/soc/codecs/wcd939x.c @@ -3683,7 +3683,7 @@ MODULE_DEVICE_TABLE(of, wcd939x_dt_match); static struct platform_driver wcd939x_codec_driver = { .probe = wcd939x_probe, - .remove_new = wcd939x_remove, + .remove = wcd939x_remove, .driver = { .name = "wcd939x_codec", .of_match_table = of_match_ptr(wcd939x_dt_match), diff --git a/sound/soc/codecs/wcd939x.h b/sound/soc/codecs/wcd939x.h index 1571c2120cfc..3204fb10b58d 100644 --- a/sound/soc/codecs/wcd939x.h +++ b/sound/soc/codecs/wcd939x.h @@ -842,9 +842,6 @@ #define WCD939X_DSD_HPHR_CFG5 (0x35a6) #define WCD939X_MAX_REGISTER (WCD939X_DSD_HPHR_CFG5) -#define WCD939X_MAX_SWR_PORTS (6) -#define WCD939X_MAX_RX_SWR_PORTS (6) -#define WCD939X_MAX_TX_SWR_PORTS (4) #define WCD939X_MAX_SWR_CH_IDS (15) struct wcd939x_sdw_ch_info { @@ -863,6 +860,7 @@ enum wcd939x_tx_sdw_ports { WCD939X_ADC_DMIC_1_2_PORT, WCD939X_DMIC_0_3_MBHC_PORT, WCD939X_DMIC_3_7_PORT, + WCD939X_MAX_TX_SWR_PORTS = WCD939X_DMIC_3_7_PORT, }; enum wcd939x_tx_sdw_channels { @@ -888,6 +886,8 @@ enum wcd939x_rx_sdw_ports { WCD939X_LO_PORT, WCD939X_DSD_PORT, WCD939X_HIFI_PCM_PORT, + WCD939X_MAX_RX_SWR_PORTS = WCD939X_HIFI_PCM_PORT, + WCD939X_MAX_SWR_PORTS = WCD939X_MAX_RX_SWR_PORTS, }; enum wcd939x_rx_sdw_channels { diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 4ecf07c7448c..651f1319204d 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2174,7 +2174,7 @@ static struct platform_driver wm5102_codec_driver = { .name = "wm5102-codec", }, .probe = wm5102_probe, - .remove_new = wm5102_remove, + .remove = wm5102_remove, }; module_platform_driver(wm5102_codec_driver); diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 0f299cd07b2e..502196253d42 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2534,7 +2534,7 @@ static struct platform_driver wm5110_codec_driver = { .name = "wm5110-codec", }, .probe = wm5110_probe, - .remove_new = wm5110_remove, + .remove = wm5110_remove, }; module_platform_driver(wm5110_codec_driver); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a99908582a50..a4abe6e53bfc 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4699,7 +4699,7 @@ static struct platform_driver wm8994_codec_driver = { .pm = &wm8994_pm_ops, }, .probe = wm8994_probe, - .remove_new = wm8994_remove, + .remove = wm8994_remove, }; module_platform_driver(wm8994_codec_driver); diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 87442840f0af..5389c363b14e 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1210,7 +1210,7 @@ static struct platform_driver wm8997_codec_driver = { .name = "wm8997-codec", }, .probe = wm8997_probe, - .remove_new = wm8997_remove, + .remove = wm8997_remove, }; module_platform_driver(wm8997_codec_driver); diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 3c2c4d12c08e..b72b8a64be8f 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1426,7 +1426,7 @@ static struct platform_driver wm8998_codec_driver = { .name = "wm8998-codec", }, .probe = wm8998_probe, - .remove_new = wm8998_remove, + .remove = wm8998_remove, }; module_platform_driver(wm8998_codec_driver); diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index fb9e92f08d98..dd2d6661adc7 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -386,33 +386,32 @@ enum wsa_port_ids { /* 4 ports */ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = { - { - /* DAC */ - .num = 1, + [WSA881X_PORT_DAC] = { + .num = WSA881X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* COMP */ - .num = 2, + }, + [WSA881X_PORT_COMP] = { + .num = WSA881X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* BOOST */ - .num = 3, + }, + [WSA881X_PORT_BOOST] = { + .num = WSA881X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* VISENSE */ - .num = 4, + }, + [WSA881X_PORT_VISENSE] = { + .num = WSA881X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, @@ -422,17 +421,20 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa881x_pconfig[WSA881X_MAX_SWR_PORTS] = { - { - .num = 1, + [WSA881X_PORT_DAC] = { + .num = WSA881X_PORT_DAC + 1, .ch_mask = 0x1, - }, { - .num = 2, + }, + [WSA881X_PORT_COMP] = { + .num = WSA881X_PORT_COMP + 1, .ch_mask = 0xf, - }, { - .num = 3, + }, + [WSA881X_PORT_BOOST] = { + .num = WSA881X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { /* IV feedback */ - .num = 4, + }, + [WSA881X_PORT_VISENSE] = { + .num = WSA881X_PORT_VISENSE + 1, .ch_mask = 0x3, }, }; @@ -680,7 +682,6 @@ struct wsa881x_priv { * For backwards compatibility. */ unsigned int sd_n_val; - int version; int active_ports; bool port_prepared[WSA881X_MAX_SWR_PORTS]; bool port_enable[WSA881X_MAX_SWR_PORTS]; @@ -691,7 +692,6 @@ static void wsa881x_init(struct wsa881x_priv *wsa881x) struct regmap *rm = wsa881x->regmap; unsigned int val = 0; - regmap_read(rm, WSA881X_CHIP_ID1, &wsa881x->version); regmap_register_patch(wsa881x->regmap, wsa881x_rev_2_0, ARRAY_SIZE(wsa881x_rev_2_0)); diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index 3e4fdaa3f44f..47da5674d7c9 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -438,8 +438,6 @@ struct wsa883x_priv { struct gpio_desc *sd_n; bool port_prepared[WSA883X_MAX_SWR_PORTS]; bool port_enable[WSA883X_MAX_SWR_PORTS]; - int version; - int variant; int active_ports; int dev_mode; int comp_offset; @@ -482,33 +480,32 @@ static const struct soc_enum wsa_dev_mode_enum = /* 4 ports */ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = { - { - /* DAC */ - .num = 1, + [WSA883X_PORT_DAC] = { + .num = WSA883X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* COMP */ - .num = 2, + }, + [WSA883X_PORT_COMP] = { + .num = WSA883X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* BOOST */ - .num = 3, + }, + [WSA883X_PORT_BOOST] = { + .num = WSA883X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* VISENSE */ - .num = 4, + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, @@ -518,17 +515,20 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { - { - .num = 1, + [WSA883X_PORT_DAC] = { + .num = WSA883X_PORT_DAC + 1, .ch_mask = 0x1, - }, { - .num = 2, + }, + [WSA883X_PORT_COMP] = { + .num = WSA883X_PORT_COMP + 1, .ch_mask = 0xf, - }, { - .num = 3, + }, + [WSA883X_PORT_BOOST] = { + .num = WSA883X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { /* IV feedback */ - .num = 4, + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, .ch_mask = 0x3, }, }; @@ -997,33 +997,36 @@ static const struct reg_sequence reg_init[] = { {WSA883X_GMAMP_SUP1, 0xE2}, }; -static void wsa883x_init(struct wsa883x_priv *wsa883x) +static int wsa883x_init(struct wsa883x_priv *wsa883x) { struct regmap *regmap = wsa883x->regmap; - int variant, version; + int variant, version, ret; - regmap_read(regmap, WSA883X_OTP_REG_0, &variant); - wsa883x->variant = variant & WSA883X_ID_MASK; + ret = regmap_read(regmap, WSA883X_OTP_REG_0, &variant); + if (ret) + return ret; + variant = variant & WSA883X_ID_MASK; - regmap_read(regmap, WSA883X_CHIP_ID0, &version); - wsa883x->version = version; + ret = regmap_read(regmap, WSA883X_CHIP_ID0, &version); + if (ret) + return ret; - switch (wsa883x->variant) { + switch (variant) { case WSA8830: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8830\n", - wsa883x->version); + version); break; case WSA8835: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835\n", - wsa883x->version); + version); break; case WSA8832: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8832\n", - wsa883x->version); + version); break; case WSA8835_V2: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835_V2\n", - wsa883x->version); + version); break; default: break; @@ -1034,12 +1037,14 @@ static void wsa883x_init(struct wsa883x_priv *wsa883x) /* Initial settings */ regmap_multi_reg_write(regmap, reg_init, ARRAY_SIZE(reg_init)); - if (wsa883x->variant == WSA8830 || wsa883x->variant == WSA8832) { + if (variant == WSA8830 || variant == WSA8832) { wsa883x->comp_offset = COMP_OFFSET3; regmap_update_bits(regmap, WSA883X_DRE_CTL_0, WSA883X_DRE_OFFSET_MASK, wsa883x->comp_offset); } + + return 0; } static int wsa883x_update_status(struct sdw_slave *slave, @@ -1048,7 +1053,7 @@ static int wsa883x_update_status(struct sdw_slave *slave, struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev); if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0) - wsa883x_init(wsa883x); + return wsa883x_init(wsa883x); return 0; } diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c index 89eb5e03a617..86df5152c547 100644 --- a/sound/soc/codecs/wsa884x.c +++ b/sound/soc/codecs/wsa884x.c @@ -5,11 +5,14 @@ */ #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/device.h> #include <linux/gpio/consumer.h> +#include <linux/hwmon.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> @@ -301,8 +304,28 @@ #define WSA884X_PA_FSM_MSK1 (WSA884X_DIG_CTRL0_BASE + 0x3b) #define WSA884X_PA_FSM_BYP_CTL (WSA884X_DIG_CTRL0_BASE + 0x3c) #define WSA884X_PA_FSM_BYP0 (WSA884X_DIG_CTRL0_BASE + 0x3d) +#define WSA884X_PA_FSM_BYP0_DC_CAL_EN_MASK 0x01 +#define WSA884X_PA_FSM_BYP0_DC_CAL_EN_SHIFT 0 +#define WSA884X_PA_FSM_BYP0_CLK_WD_EN_MASK 0x02 +#define WSA884X_PA_FSM_BYP0_CLK_WD_EN_SHIFT 1 +#define WSA884X_PA_FSM_BYP0_BG_EN_MASK 0x04 +#define WSA884X_PA_FSM_BYP0_BG_EN_SHIFT 2 +#define WSA884X_PA_FSM_BYP0_BOOST_EN_MASK 0x08 +#define WSA884X_PA_FSM_BYP0_BOOST_EN_SHIFT 3 +#define WSA884X_PA_FSM_BYP0_PA_EN_MASK 0x10 +#define WSA884X_PA_FSM_BYP0_PA_EN_SHIFT 4 +#define WSA884X_PA_FSM_BYP0_D_UNMUTE_MASK 0x20 +#define WSA884X_PA_FSM_BYP0_D_UNMUTE_SHIFT 5 +#define WSA884X_PA_FSM_BYP0_SPKR_PROT_EN_MASK 0x40 +#define WSA884X_PA_FSM_BYP0_SPKR_PROT_EN_SHIFT 6 +#define WSA884X_PA_FSM_BYP0_TSADC_EN_MASK 0x80 +#define WSA884X_PA_FSM_BYP0_TSADC_EN_SHIFT 7 #define WSA884X_PA_FSM_BYP1 (WSA884X_DIG_CTRL0_BASE + 0x3e) #define WSA884X_TADC_VALUE_CTL (WSA884X_DIG_CTRL0_BASE + 0x50) +#define WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK 0x01 +#define WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_SHIFT 0 +#define WSA884X_TADC_VALUE_CTL_VBAT_VALUE_RD_EN_MASK 0x02 +#define WSA884X_TADC_VALUE_CTL_VBAT_VALUE_RD_EN_SHIFT 1 #define WSA884X_TEMP_DETECT_CTL (WSA884X_DIG_CTRL0_BASE + 0x51) #define WSA884X_TEMP_DIN_MSB (WSA884X_DIG_CTRL0_BASE + 0x52) #define WSA884X_TEMP_DIN_LSB (WSA884X_DIG_CTRL0_BASE + 0x53) @@ -691,6 +714,17 @@ SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) +/* Two-point trimming for temperature calibration */ +#define WSA884X_T1_TEMP -10L +#define WSA884X_T2_TEMP 150L + +/* + * Device will report senseless data in many cases, so discard any measurements + * outside of valid range. + */ +#define WSA884X_LOW_TEMP_THRESHOLD 5 +#define WSA884X_HIGH_TEMP_THRESHOLD 45 + struct wsa884x_priv { struct regmap *regmap; struct device *dev; @@ -703,10 +737,16 @@ struct wsa884x_priv { struct reset_control *sd_reset; bool port_prepared[WSA884X_MAX_SWR_PORTS]; bool port_enable[WSA884X_MAX_SWR_PORTS]; - unsigned int variant; int active_ports; int dev_mode; bool hw_init; + /* + * Protects temperature reading code (related to speaker protection) and + * fields: temperature and pa_on. + */ + struct mutex sp_lock; + unsigned int temperature; + bool pa_on; }; enum { @@ -782,42 +822,47 @@ static const struct soc_enum wsa884x_dev_mode_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa884x_dev_mode_text), wsa884x_dev_mode_text); static struct sdw_dpn_prop wsa884x_sink_dpn_prop[WSA884X_MAX_SWR_PORTS] = { - { + [WSA884X_PORT_DAC] = { .num = WSA884X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_COMP] = { .num = WSA884X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_BOOST] = { .num = WSA884X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_PBR] = { .num = WSA884X_PORT_PBR + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_VISENSE] = { .num = WSA884X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_CPS] = { .num = WSA884X_PORT_CPS + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, @@ -828,22 +873,27 @@ static struct sdw_dpn_prop wsa884x_sink_dpn_prop[WSA884X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = { - { + [WSA884X_PORT_DAC] = { .num = WSA884X_PORT_DAC + 1, .ch_mask = 0x1, - }, { + }, + [WSA884X_PORT_COMP] = { .num = WSA884X_PORT_COMP + 1, .ch_mask = 0xf, - }, { + }, + [WSA884X_PORT_BOOST] = { .num = WSA884X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { + }, + [WSA884X_PORT_PBR] = { .num = WSA884X_PORT_PBR + 1, .ch_mask = 0x1, - }, { + }, + [WSA884X_PORT_VISENSE] = { .num = WSA884X_PORT_VISENSE + 1, .ch_mask = 0x3, - }, { + }, + [WSA884X_PORT_CPS] = { .num = WSA884X_PORT_CPS + 1, .ch_mask = 0x3, }, @@ -1465,7 +1515,7 @@ static void wsa884x_init(struct wsa884x_priv *wsa884x) unsigned int variant = 0; if (!regmap_read(wsa884x->regmap, WSA884X_OTP_REG_0, &variant)) - wsa884x->variant = variant & WSA884X_OTP_REG_0_ID_MASK; + variant = variant & WSA884X_OTP_REG_0_ID_MASK; regmap_multi_reg_write(wsa884x->regmap, wsa884x_reg_init, ARRAY_SIZE(wsa884x_reg_init)); @@ -1474,7 +1524,7 @@ static void wsa884x_init(struct wsa884x_priv *wsa884x) wo_ctl_0 |= FIELD_PREP(WSA884X_ANA_WO_CTL_0_DAC_CM_CLAMP_EN_MASK, WSA884X_ANA_WO_CTL_0_DAC_CM_CLAMP_EN_MODE_SPEAKER); /* Assume that compander is enabled by default unless it is haptics sku */ - if (wsa884x->variant == WSA884X_OTP_ID_WSA8845H) + if (variant == WSA884X_OTP_ID_WSA8845H) wo_ctl_0 |= FIELD_PREP(WSA884X_ANA_WO_CTL_0_PA_AUX_GAIN_MASK, WSA884X_ANA_WO_CTL_0_PA_AUX_18_DB); else @@ -1651,6 +1701,10 @@ static int wsa884x_spkr_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: + mutex_lock(&wsa884x->sp_lock); + wsa884x->pa_on = true; + mutex_unlock(&wsa884x->sp_lock); + wsa884x_spkr_post_pmu(component, wsa884x); snd_soc_component_write_field(component, WSA884X_PDM_WD_CTL, @@ -1662,6 +1716,10 @@ static int wsa884x_spkr_event(struct snd_soc_dapm_widget *w, snd_soc_component_write_field(component, WSA884X_PDM_WD_CTL, WSA884X_PDM_WD_CTL_PDM_WD_EN_MASK, 0x0); + + mutex_lock(&wsa884x->sp_lock); + wsa884x->pa_on = false; + mutex_unlock(&wsa884x->sp_lock); break; } @@ -1801,6 +1859,144 @@ static struct snd_soc_dai_driver wsa884x_dais[] = { }, }; +static int wsa884x_get_temp(struct wsa884x_priv *wsa884x, long *temp) +{ + unsigned int d1_msb = 0, d1_lsb = 0, d2_msb = 0, d2_lsb = 0; + unsigned int dmeas_msb = 0, dmeas_lsb = 0; + int d1, d2, dmeas; + unsigned int mask; + long val; + int ret; + + guard(mutex)(&wsa884x->sp_lock); + + if (wsa884x->pa_on) { + /* + * Reading temperature is possible only when Power Amplifier is + * off. Report last cached data. + */ + *temp = wsa884x->temperature; + return 0; + } + + ret = pm_runtime_resume_and_get(wsa884x->dev); + if (ret < 0) + return ret; + + mask = WSA884X_PA_FSM_BYP0_DC_CAL_EN_MASK | + WSA884X_PA_FSM_BYP0_CLK_WD_EN_MASK | + WSA884X_PA_FSM_BYP0_BG_EN_MASK | + WSA884X_PA_FSM_BYP0_D_UNMUTE_MASK | + WSA884X_PA_FSM_BYP0_SPKR_PROT_EN_MASK | + WSA884X_PA_FSM_BYP0_TSADC_EN_MASK; + /* + * Here and further do not care about read or update failures. + * For example, before turning on Power Amplifier for the first + * time, reading WSA884X_TEMP_DIN_MSB will always return 0. + * Instead, check if returned value is within reasonable + * thresholds. + */ + regmap_update_bits(wsa884x->regmap, WSA884X_PA_FSM_BYP0, mask, mask); + + regmap_update_bits(wsa884x->regmap, WSA884X_TADC_VALUE_CTL, + WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, + FIELD_PREP(WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, 0x0)); + + regmap_read(wsa884x->regmap, WSA884X_TEMP_DIN_MSB, &dmeas_msb); + regmap_read(wsa884x->regmap, WSA884X_TEMP_DIN_LSB, &dmeas_lsb); + + regmap_update_bits(wsa884x->regmap, WSA884X_TADC_VALUE_CTL, + WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, + FIELD_PREP(WSA884X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, 0x1)); + + regmap_read(wsa884x->regmap, WSA884X_OTP_REG_1, &d1_msb); + regmap_read(wsa884x->regmap, WSA884X_OTP_REG_2, &d1_lsb); + regmap_read(wsa884x->regmap, WSA884X_OTP_REG_3, &d2_msb); + regmap_read(wsa884x->regmap, WSA884X_OTP_REG_4, &d2_lsb); + + regmap_update_bits(wsa884x->regmap, WSA884X_PA_FSM_BYP0, mask, 0x0); + + dmeas = (((dmeas_msb & 0xff) << 0x8) | (dmeas_lsb & 0xff)) >> 0x6; + d1 = (((d1_msb & 0xff) << 0x8) | (d1_lsb & 0xff)) >> 0x6; + d2 = (((d2_msb & 0xff) << 0x8) | (d2_lsb & 0xff)) >> 0x6; + + if (d1 == d2) { + /* Incorrect data in OTP? */ + ret = -EINVAL; + goto out; + } + + val = WSA884X_T1_TEMP + (((dmeas - d1) * (WSA884X_T2_TEMP - WSA884X_T1_TEMP))/(d2 - d1)); + + dev_dbg(wsa884x->dev, "Measured temp %ld (dmeas=%d, d1=%d, d2=%d)\n", + val, dmeas, d1, d2); + + if ((val > WSA884X_LOW_TEMP_THRESHOLD) && + (val < WSA884X_HIGH_TEMP_THRESHOLD)) { + wsa884x->temperature = val; + *temp = val; + ret = 0; + } else { + ret = -EAGAIN; + } + +out: + pm_runtime_mark_last_busy(wsa884x->dev); + pm_runtime_put_autosuspend(wsa884x->dev); + + return ret; +} + +static umode_t wsa884x_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + return 0444; + default: + break; + } + + return 0; +} + +static int wsa884x_hwmon_read(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, long *temp) +{ + int ret; + + switch (attr) { + case hwmon_temp_input: + ret = wsa884x_get_temp(dev_get_drvdata(dev), temp); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static const struct hwmon_channel_info *const wsa884x_hwmon_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), + NULL +}; + +static const struct hwmon_ops wsa884x_hwmon_ops = { + .is_visible = wsa884x_hwmon_is_visible, + .read = wsa884x_hwmon_read, +}; + +static const struct hwmon_chip_info wsa884x_hwmon_chip_info = { + .ops = &wsa884x_hwmon_ops, + .info = wsa884x_hwmon_info, +}; + static void wsa884x_reset_powerdown(void *data) { struct wsa884x_priv *wsa884x = data; @@ -1857,6 +2053,8 @@ static int wsa884x_probe(struct sdw_slave *pdev, if (!wsa884x) return -ENOMEM; + mutex_init(&wsa884x->sp_lock); + for (i = 0; i < WSA884X_SUPPLIES_NUM; i++) wsa884x->supplies[i].supply = wsa884x_supply_name[i]; @@ -1914,6 +2112,18 @@ static int wsa884x_probe(struct sdw_slave *pdev, regcache_cache_only(wsa884x->regmap, true); wsa884x->hw_init = true; + if (IS_REACHABLE(CONFIG_HWMON)) { + struct device *hwmon; + + hwmon = devm_hwmon_device_register_with_info(dev, "wsa884x", + wsa884x, + &wsa884x_hwmon_chip_info, + NULL); + if (IS_ERR(hwmon)) + return dev_err_probe(dev, PTR_ERR(hwmon), + "Failed to register hwmon sensor\n"); + } + pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); pm_runtime_mark_last_busy(dev); |