Skip to content

Commit 837dedf

Browse files
committed
ASoC: rk3308_codec: clean up and add support headphone detection
Since this signal line is directly connected to the GIC, it has not been processed by the logic gate. Therefore, when the headphone is plugged in, the status register will remain high and when pulled out, the status register will be converted to a low level. However, the GIC can only accept high and rising edge triggers, so when the headset is plugged in, it needs to poll (~2s) to detect whether plug the headphone. Change-Id: I321cd363103127911c503a63008882ffbc9c3633 Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
1 parent ebe374e commit 837dedf

2 files changed

Lines changed: 71 additions & 14 deletions

File tree

sound/soc/codecs/rk3308_codec.c

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
#include <sound/core.h>
3636
#include <sound/dmaengine_pcm.h>
3737
#include <sound/initval.h>
38+
#include <sound/jack.h>
3839
#include <sound/pcm.h>
3940
#include <sound/pcm_params.h>
41+
#include <sound/simple_card.h>
4042
#include <sound/soc.h>
4143
#include <sound/tlv.h>
4244

@@ -53,6 +55,7 @@
5355
#define ADC_LR_GROUP_MAX 4
5456
#define DEBUG_POP_ALWAYS 0
5557
#define ENABLE_AGC 0
58+
#define HPDET_POLL_MS 2000
5659

5760
enum {
5861
ADC_GRP0_MICIN = 0,
@@ -75,6 +78,7 @@ struct rk3308_codec_priv {
7578
struct clk *mclk_tx;
7679
struct gpio_desc *hp_ctl_gpio;
7780
struct gpio_desc *spk_ctl_gpio;
81+
int irq;
7882
/*
7983
* To select ADCs for groups:
8084
*
@@ -89,6 +93,9 @@ struct rk3308_codec_priv {
8993
/* 0: line out, 1: hp out, 11: lineout and hpout */
9094
int dac_output;
9195

96+
bool hp_plugged;
97+
struct delayed_work hpdet_work;
98+
9299
#if defined(CONFIG_DEBUG_FS)
93100
struct dentry *dbg_codec;
94101
#endif
@@ -1201,9 +1208,6 @@ static int rk3308_codec_power_off(struct snd_soc_codec *codec)
12011208

12021209
static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308)
12031210
{
1204-
/* HACK: headset_detect bypass */
1205-
return 0;
1206-
12071211
/*
12081212
* Set ACODEC_DAC_ANA_CON0[1] to 0x1, to enable the headset insert
12091213
* detection
@@ -1220,9 +1224,6 @@ static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308)
12201224

12211225
static int rk3308_codec_headset_detect_disable(struct rk3308_codec_priv *rk3308)
12221226
{
1223-
/* HACK: headset_detect bypass */
1224-
return 0;
1225-
12261227
/*
12271228
* Set ACODEC_DAC_ANA_CON0[1] to 0x0, to disable the headset insert
12281229
* detection
@@ -1570,7 +1571,6 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
15701571
RK3308_ADC_CH2_MIC_UNMUTE,
15711572
RK3308_ADC_CH1_MIC_UNMUTE |
15721573
RK3308_ADC_CH2_MIC_UNMUTE);
1573-
15741574
/*
15751575
* 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source
15761576
* of audio
@@ -2009,8 +2009,56 @@ static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg)
20092009
return true;
20102010
}
20112011

2012-
static irqreturn_t rk3308_codec_headset_isr(int irq, void *dev_id)
2012+
static void rk3308_codec_hpdetect_work(struct work_struct *work)
2013+
{
2014+
struct rk3308_codec_priv *rk3308 =
2015+
container_of(work, struct rk3308_codec_priv, hpdet_work.work);
2016+
unsigned int val;
2017+
int need_poll = 0, need_irq = 0;
2018+
int need_report = 0, report_type = 0;
2019+
2020+
regmap_read(rk3308->regmap, RK3308_DAC_DIG_CON14, &val);
2021+
if (!val) {
2022+
rk3308->hp_plugged = false;
2023+
2024+
report_type = 0;
2025+
need_report = 1;
2026+
need_irq = 1;
2027+
} else {
2028+
if (!rk3308->hp_plugged) {
2029+
rk3308->hp_plugged = true;
2030+
report_type = SND_JACK_HEADPHONE;
2031+
need_report = 1;
2032+
}
2033+
need_poll = 1;
2034+
}
2035+
2036+
if (need_poll)
2037+
queue_delayed_work(system_power_efficient_wq,
2038+
&rk3308->hpdet_work,
2039+
msecs_to_jiffies(HPDET_POLL_MS));
2040+
2041+
if (need_report)
2042+
snd_soc_jack_report(asoc_simple_card_get_hp_jack(),
2043+
report_type,
2044+
SND_JACK_HEADPHONE);
2045+
2046+
if (need_irq)
2047+
enable_irq(rk3308->irq);
2048+
}
2049+
2050+
static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data)
20132051
{
2052+
struct rk3308_codec_priv *rk3308 = data;
2053+
2054+
/*
2055+
* For the high level irq trigger, disable irq and avoid a lot of
2056+
* repeated irq handlers entry.
2057+
*/
2058+
disable_irq_nosync(rk3308->irq);
2059+
queue_delayed_work(system_power_efficient_wq,
2060+
&rk3308->hpdet_work, msecs_to_jiffies(10));
2061+
20142062
return IRQ_HANDLED;
20152063
}
20162064

@@ -2306,7 +2354,6 @@ static int rk3308_platform_probe(struct platform_device *pdev)
23062354
struct resource *res;
23072355
struct regmap *grf;
23082356
void __iomem *base;
2309-
int irq;
23102357
int ret;
23112358

23122359
grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
@@ -2430,14 +2477,19 @@ static int rk3308_platform_probe(struct platform_device *pdev)
24302477
goto failed;
24312478
}
24322479

2433-
irq = platform_get_irq(pdev, 0);
2434-
if (irq < 0) {
2480+
rk3308->irq = platform_get_irq(pdev, 0);
2481+
if (rk3308->irq < 0) {
24352482
dev_err(&pdev->dev, "Can not get codec irq\n");
24362483
goto failed;
24372484
}
24382485

2439-
ret = devm_request_irq(&pdev->dev, irq, rk3308_codec_headset_isr,
2440-
0, "headset-irq", rk3308);
2486+
INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work);
2487+
2488+
ret = devm_request_irq(&pdev->dev, rk3308->irq,
2489+
rk3308_codec_hpdet_isr,
2490+
0,
2491+
"acodec-hpdet",
2492+
rk3308);
24412493
if (ret < 0) {
24422494
dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret);
24432495
goto failed;

sound/soc/codecs/rk3308_codec.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@
6767
/* Resevred REG 0x06 ~ 0x09 */
6868
#define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */
6969
#define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */
70-
/* Resevred REG 0x0c ~ 0x0f */
70+
/* Resevred REG 0x0c */
71+
#define ACODEC_DAC_HPDET_DELAYTIME 0x34 /* REG 0x0d */
72+
#define ACODEC_DAC_HPDET_STATUS 0x38 /* REG 0x0e, Read-only */
73+
/* Resevred REG 0x0f */
7174

7275
/* ADC ANALOG REGISTERS */
7376
#define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */
@@ -156,6 +159,8 @@
156159
#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL)
157160
#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI)
158161
#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO)
162+
#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_DELAYTIME)
163+
#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_STATUS)
159164

160165
/* ADC ANALOG REGISTERS */
161166
/*

0 commit comments

Comments
 (0)