From 01573e231f18eb2d99162747186f59511f56b64d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 08 Dec 2023 10:40:48 +0000 Subject: [PATCH] 移去rt --- kernel/sound/soc/codecs/rt5651.c | 140 +++++++++++++++++++++++++++++++++------------- 1 files changed, 100 insertions(+), 40 deletions(-) diff --git a/kernel/sound/soc/codecs/rt5651.c b/kernel/sound/soc/codecs/rt5651.c index 89f332a..2dd8d6d 100644 --- a/kernel/sound/soc/codecs/rt5651.c +++ b/kernel/sound/soc/codecs/rt5651.c @@ -1,19 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rt5651.c -- RT5651 ALSA SoC audio codec driver * * Copyright 2014 Realtek Semiconductor Corp. * Author: Bard Liao <bardliao@realtek.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/regmap.h> #include <linux/platform_device.h> @@ -316,8 +313,7 @@ regmap_write(rt5651->regmap, 0x83, 0x1000); regmap_write(rt5651->regmap, 0x84, 0x7000); snd_soc_component_update_bits(component, 0x64, 0x0200, 0x0200); - snd_soc_component_update_bits(component, RT5651_D_MISC, 0xc00, - 0xc00); + snd_soc_component_update_bits(component, RT5651_D_MISC, 0xc00, 0xc00); } else { regmap_write(rt5651->regmap, 0x83, 0x0); regmap_write(rt5651->regmap, 0x84, 0x0); @@ -793,11 +789,11 @@ RT5651_HP_CP_PD | RT5651_HP_SG_EN); regmap_update_bits(rt5651->regmap, RT5651_PR_BASE + RT5651_CHPUMP_INT_REG1, 0x0700, 0x0400); - rt5651->hp_mute = 0; + rt5651->hp_mute = false; break; case SND_SOC_DAPM_PRE_PMD: - rt5651->hp_mute = 1; + rt5651->hp_mute = true; usleep_range(70000, 75000); break; @@ -1566,7 +1562,7 @@ if (SND_SOC_BIAS_STANDBY == snd_soc_component_get_bias_level(component)) { if (!IS_ERR(rt5651->mclk)) clk_prepare_enable(rt5651->mclk); - if (snd_soc_component_read32(component, RT5651_PLL_MODE_1) & 0x9200) + if (snd_soc_component_read(component, RT5651_PLL_MODE_1) & 0x9200) snd_soc_component_update_bits(component, RT5651_D_MISC, 0xc00, 0xc00); } @@ -1663,7 +1659,7 @@ { int val; - val = snd_soc_component_read32(component, RT5651_IRQ_CTRL2); + val = snd_soc_component_read(component, RT5651_IRQ_CTRL2); dev_dbg(component->dev, "irq ctrl2 %#04x\n", val); return (val & RT5651_MB1_OC_CLR); @@ -1674,7 +1670,13 @@ struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); int val; - val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST); + if (rt5651->gpiod_hp_det) { + val = gpiod_get_value_cansleep(rt5651->gpiod_hp_det); + dev_dbg(component->dev, "jack-detect gpio %d\n", val); + return val; + } + + val = snd_soc_component_read(component, RT5651_INT_IRQ_ST); dev_dbg(component->dev, "irq status %#04x\n", val); switch (rt5651->jd_src) { @@ -1691,7 +1693,10 @@ break; } - return val == 0; + if (rt5651->jd_active_high) + return val != 0; + else + return val == 0; } /* Jack detect and button-press timings */ @@ -1814,6 +1819,16 @@ return SND_JACK_HEADPHONE; } +static bool rt5651_support_button_press(struct rt5651_priv *rt5651) +{ + if (!rt5651->hp_jack) + return false; + + /* Button press support only works with internal jack-detection */ + return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) && + rt5651->gpiod_hp_det == NULL; +} + static void rt5651_jack_detect_work(struct work_struct *work) { struct rt5651_priv *rt5651 = @@ -1838,15 +1853,15 @@ WARN_ON(rt5651->ovcd_irq_enabled); rt5651_enable_micbias1_for_ovcd(component); report = rt5651_detect_headset(component); - if (report == SND_JACK_HEADSET) { + dev_dbg(component->dev, "detect report %#02x\n", report); + snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET); + if (rt5651_support_button_press(rt5651)) { /* Enable ovcd IRQ for button press detect. */ rt5651_enable_micbias1_ovcd_irq(component); } else { /* No more need for overcurrent detect. */ rt5651_disable_micbias1_for_ovcd(component); } - dev_dbg(component->dev, "detect report %#02x\n", report); - snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET); } else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) { dev_dbg(component->dev, "OVCD IRQ\n"); @@ -1890,44 +1905,79 @@ } static void rt5651_enable_jack_detect(struct snd_soc_component *component, - struct snd_soc_jack *hp_jack) + struct snd_soc_jack *hp_jack, + struct gpio_desc *gpiod_hp_det) { struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); - - /* IRQ output on GPIO1 */ - snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1, - RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ); + bool using_internal_jack_detect = true; /* Select jack detect source */ switch (rt5651->jd_src) { + case RT5651_JD_NULL: + rt5651->gpiod_hp_det = gpiod_hp_det; + if (!rt5651->gpiod_hp_det) + return; /* No jack detect */ + using_internal_jack_detect = false; + break; case RT5651_JD1_1: snd_soc_component_update_bits(component, RT5651_JD_CTRL2, RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD1_1); - snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1, - RT5651_JD1_1_IRQ_EN, RT5651_JD1_1_IRQ_EN); + /* active-low is normal, set inv flag for active-high */ + if (rt5651->jd_active_high) + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD1_1_IRQ_EN | RT5651_JD1_1_INV, + RT5651_JD1_1_IRQ_EN | RT5651_JD1_1_INV); + else + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD1_1_IRQ_EN | RT5651_JD1_1_INV, + RT5651_JD1_1_IRQ_EN); break; case RT5651_JD1_2: snd_soc_component_update_bits(component, RT5651_JD_CTRL2, RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD1_2); - snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1, - RT5651_JD1_2_IRQ_EN, RT5651_JD1_2_IRQ_EN); + /* active-low is normal, set inv flag for active-high */ + if (rt5651->jd_active_high) + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD1_2_IRQ_EN | RT5651_JD1_2_INV, + RT5651_JD1_2_IRQ_EN | RT5651_JD1_2_INV); + else + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD1_2_IRQ_EN | RT5651_JD1_2_INV, + RT5651_JD1_2_IRQ_EN); break; case RT5651_JD2: snd_soc_component_update_bits(component, RT5651_JD_CTRL2, RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD2); - snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1, - RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN); + /* active-low is normal, set inv flag for active-high */ + if (rt5651->jd_active_high) + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD2_IRQ_EN | RT5651_JD2_INV, + RT5651_JD2_IRQ_EN | RT5651_JD2_INV); + else + snd_soc_component_update_bits(component, + RT5651_IRQ_CTRL1, + RT5651_JD2_IRQ_EN | RT5651_JD2_INV, + RT5651_JD2_IRQ_EN); break; - case RT5651_JD_NULL: - return; default: dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n"); return; } - /* Enable jack detect power */ - snd_soc_component_update_bits(component, RT5651_PWR_ANLG2, - RT5651_PWR_JD_M, RT5651_PWR_JD_M); + if (using_internal_jack_detect) { + /* IRQ output on GPIO1 */ + snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1, + RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ); + + /* Enable jack detect power */ + snd_soc_component_update_bits(component, RT5651_PWR_ANLG2, + RT5651_PWR_JD_M, RT5651_PWR_JD_M); + } /* Set OVCD threshold current and scale-factor */ snd_soc_component_write(component, RT5651_PR_BASE + RT5651_BIAS_CUR4, @@ -1956,7 +2006,7 @@ RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN); rt5651->hp_jack = hp_jack; - if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { + if (rt5651_support_button_press(rt5651)) { rt5651_enable_micbias1_for_ovcd(component); rt5651_enable_micbias1_ovcd_irq(component); } @@ -1973,7 +2023,7 @@ disable_irq(rt5651->irq); rt5651_cancel_work(rt5651); - if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { + if (rt5651_support_button_press(rt5651)) { rt5651_disable_micbias1_ovcd_irq(component); rt5651_disable_micbias1_for_ovcd(component); snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0); @@ -1986,7 +2036,7 @@ struct snd_soc_jack *jack, void *data) { if (jack) - rt5651_enable_jack_detect(component, jack); + rt5651_enable_jack_detect(component, jack, data); else rt5651_disable_jack_detect(component); @@ -2016,6 +2066,9 @@ if (device_property_read_u32(component->dev, "realtek,jack-detect-source", &val) == 0) rt5651->jd_src = val; + + if (device_property_read_bool(component->dev, "realtek,jack-detect-not-inverted")) + rt5651->jd_active_high = true; /* * Testing on various boards has shown that good defaults for the OVCD @@ -2080,7 +2133,7 @@ gpiod_set_value(rt5651->gpiod_spk_ctl, enable); } -static int rt5651_mute(struct snd_soc_dai *dai, int mute) +static int rt5651_mute(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component = dai->component; struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); @@ -2125,7 +2178,8 @@ .set_fmt = rt5651_set_dai_fmt, .set_sysclk = rt5651_set_dai_sysclk, .set_pll = rt5651_set_dai_pll, - .digital_mute = rt5651_mute, + .mute_stream = rt5651_mute, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver rt5651_dai[] = { @@ -2200,7 +2254,8 @@ .num_reg_defaults = ARRAY_SIZE(rt5651_reg), .ranges = rt5651_ranges, .num_ranges = ARRAY_SIZE(rt5651_ranges), - .use_single_rw = true, + .use_single_read = true, + .use_single_write = true, }; #if defined(CONFIG_OF) @@ -2214,6 +2269,7 @@ #ifdef CONFIG_ACPI static const struct acpi_device_id rt5651_acpi_match[] = { { "10EC5651", 0 }, + { "10EC5640", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match); @@ -2234,6 +2290,7 @@ { struct rt5651_priv *rt5651; int ret; + int err; rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651), GFP_KERNEL); @@ -2250,7 +2307,10 @@ return ret; } - regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret); + err = regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret); + if (err) + return err; + if (ret != RT5651_DEVICE_ID_VALUE) { dev_err(&i2c->dev, "Device with ID register %#x is not rt5651\n", ret); @@ -2265,7 +2325,7 @@ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); rt5651->irq = i2c->irq; - rt5651->hp_mute = 1; + rt5651->hp_mute = true; INIT_DELAYED_WORK(&rt5651->bp_work, rt5651_button_press_work); INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work); -- Gitblit v1.6.2