Skip to content

Commit 2b9c8d2

Browse files
oder-chioubroonie
authored andcommitted
ASoC: rt5640: Add the HDA header support
The patch adds the HDA header support. Signed-off-by: Oder Chiou <oder_chiou@realtek.com> Link: https://lore.kernel.org/r/20211125055812.8911-2-oder_chiou@realtek.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 083a7fb commit 2b9c8d2

1 file changed

Lines changed: 94 additions & 3 deletions

File tree

sound/soc/codecs/rt5640.c

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ static bool rt5640_volatile_register(struct device *dev, unsigned int reg)
195195
case RT5640_PRIV_DATA:
196196
case RT5640_PGM_REG_ARR1:
197197
case RT5640_PGM_REG_ARR3:
198+
case RT5640_DUMMY2:
198199
case RT5640_VENDOR_ID:
199200
case RT5640_VENDOR_ID1:
200201
case RT5640_VENDOR_ID2:
@@ -2301,6 +2302,38 @@ static void rt5640_jack_work(struct work_struct *work)
23012302
struct snd_soc_component *component = rt5640->component;
23022303
int status;
23032304

2305+
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
2306+
int val, jack_type = 0, hda_mic_plugged, hda_hp_plugged;
2307+
2308+
/* mic jack */
2309+
val = snd_soc_component_read(component, RT5640_INT_IRQ_ST);
2310+
hda_mic_plugged = !(val & RT5640_JD_STATUS);
2311+
dev_dbg(component->dev, "mic jack status %d\n",
2312+
hda_mic_plugged);
2313+
2314+
snd_soc_component_update_bits(component, RT5640_IRQ_CTRL1,
2315+
RT5640_JD_P_MASK, !hda_mic_plugged << RT5640_JD_P_SFT);
2316+
2317+
if (hda_mic_plugged)
2318+
jack_type |= SND_JACK_MICROPHONE;
2319+
2320+
/* headphone jack */
2321+
val = snd_soc_component_read(component, RT5640_DUMMY2);
2322+
hda_hp_plugged = !(val & (0x1 << 11));
2323+
dev_dbg(component->dev, "headphone jack status %d\n",
2324+
hda_hp_plugged);
2325+
2326+
snd_soc_component_update_bits(component, RT5640_DUMMY2,
2327+
(0x1 << 10), !hda_hp_plugged << 10);
2328+
2329+
if (hda_hp_plugged)
2330+
jack_type |= SND_JACK_HEADPHONE;
2331+
2332+
snd_soc_jack_report(rt5640->jack, jack_type, SND_JACK_HEADSET);
2333+
2334+
return;
2335+
}
2336+
23042337
if (!rt5640_jack_inserted(component)) {
23052338
/* Jack removed, or spurious IRQ? */
23062339
if (rt5640->jack->status & SND_JACK_HEADPHONE) {
@@ -2478,13 +2511,57 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
24782511
queue_work(system_long_wq, &rt5640->jack_work);
24792512
}
24802513

2514+
static void rt5640_enable_hda_jack_detect(
2515+
struct snd_soc_component *component, struct snd_soc_jack *jack)
2516+
{
2517+
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
2518+
int ret;
2519+
2520+
/* Select JD1 for Mic */
2521+
snd_soc_component_update_bits(component, RT5640_JD_CTRL,
2522+
RT5640_JD_MASK, RT5640_JD_JD1_IN4P);
2523+
snd_soc_component_write(component, RT5640_IRQ_CTRL1, RT5640_IRQ_JD_NOR);
2524+
2525+
/* Select JD2 for Headphone */
2526+
snd_soc_component_update_bits(component, RT5640_DUMMY2, 0x1100, 0x1100);
2527+
2528+
/* Selecting GPIO01 as an interrupt */
2529+
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1,
2530+
RT5640_GP1_PIN_MASK, RT5640_GP1_PIN_IRQ);
2531+
2532+
/* Set GPIO1 output */
2533+
snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3,
2534+
RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT);
2535+
2536+
snd_soc_component_update_bits(component, RT5640_DUMMY1, 0x700, 0x300);
2537+
2538+
rt5640->jack = jack;
2539+
2540+
ret = request_irq(rt5640->irq, rt5640_irq,
2541+
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
2542+
if (ret) {
2543+
dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
2544+
rt5640->irq = -ENXIO;
2545+
return;
2546+
}
2547+
2548+
/* sync initial jack state */
2549+
queue_work(system_long_wq, &rt5640->jack_work);
2550+
}
2551+
24812552
static int rt5640_set_jack(struct snd_soc_component *component,
24822553
struct snd_soc_jack *jack, void *data)
24832554
{
2484-
if (jack)
2485-
rt5640_enable_jack_detect(component, jack);
2486-
else
2555+
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
2556+
2557+
if (jack) {
2558+
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
2559+
rt5640_enable_hda_jack_detect(component, jack);
2560+
else
2561+
rt5640_enable_jack_detect(component, jack);
2562+
} else {
24872563
rt5640_disable_jack_detect(component);
2564+
}
24882565

24892566
return 0;
24902567
}
@@ -2576,6 +2653,8 @@ static int rt5640_probe(struct snd_soc_component *component)
25762653
"realtek,jack-detect-source", &val) == 0) {
25772654
if (val <= RT5640_JD_SRC_GPIO4)
25782655
rt5640->jd_src = val << RT5640_JD_SFT;
2656+
else if (val == RT5640_JD_SRC_HDA_HEADER)
2657+
rt5640->jd_src = RT5640_JD_SRC_HDA_HEADER;
25792658
else
25802659
dev_warn(component->dev, "Warning: Invalid jack-detect-source value: %d, leaving jack-detect disabled\n",
25812660
val);
@@ -2632,6 +2711,7 @@ static int rt5640_suspend(struct snd_soc_component *component)
26322711
{
26332712
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
26342713

2714+
rt5640_cancel_work(rt5640);
26352715
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
26362716
rt5640_reset(component);
26372717
regcache_cache_only(rt5640->regmap, true);
@@ -2654,6 +2734,17 @@ static int rt5640_resume(struct snd_soc_component *component)
26542734
regcache_cache_only(rt5640->regmap, false);
26552735
regcache_sync(rt5640->regmap);
26562736

2737+
if (rt5640->jd_src) {
2738+
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
2739+
snd_soc_component_update_bits(component,
2740+
RT5640_DUMMY2, 0x1100, 0x1100);
2741+
else
2742+
snd_soc_component_write(component, RT5640_DUMMY2,
2743+
0x4001);
2744+
2745+
queue_work(system_long_wq, &rt5640->jack_work);
2746+
}
2747+
26572748
return 0;
26582749
}
26592750
#else

0 commit comments

Comments
 (0)