From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 07:24:11 +0000
Subject: [PATCH] add stmac read mac form eeprom
---
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