mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-04 10:33:13 +00:00
ASoC: cs42l42: Report jack and button detection
Report the Jack events to the user space through ALSA. Also moves request_threaded_irq() to component_probe so it don't get interrupts before the initialization the struct snd_soc_jack. Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com> Link: https://lore.kernel.org/r/20210306185553.62053-12-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
585e7079de
commit
c5b8ee0879
@ -522,10 +522,18 @@ static int cs42l42_component_probe(struct snd_soc_component *component)
|
|||||||
{
|
{
|
||||||
struct cs42l42_private *cs42l42 =
|
struct cs42l42_private *cs42l42 =
|
||||||
(struct cs42l42_private *)snd_soc_component_get_drvdata(component);
|
(struct cs42l42_private *)snd_soc_component_get_drvdata(component);
|
||||||
|
struct snd_soc_card *crd = component->card;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
cs42l42->component = component;
|
cs42l42->component = component;
|
||||||
|
|
||||||
return 0;
|
ret = snd_soc_card_jack_new(crd, "CS42L42 Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 |
|
||||||
|
SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3,
|
||||||
|
&cs42l42->jack, NULL, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(component->dev, "Cannot create CS42L42 Headset: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
|
static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
|
||||||
@ -1198,7 +1206,7 @@ static void cs42l42_cancel_hs_type_detect(struct cs42l42_private *cs42l42)
|
|||||||
(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42)
|
static int cs42l42_handle_button_press(struct cs42l42_private *cs42l42)
|
||||||
{
|
{
|
||||||
int bias_level;
|
int bias_level;
|
||||||
unsigned int detect_status;
|
unsigned int detect_status;
|
||||||
@ -1241,17 +1249,24 @@ static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42)
|
|||||||
|
|
||||||
switch (bias_level) {
|
switch (bias_level) {
|
||||||
case 1: /* Function C button press */
|
case 1: /* Function C button press */
|
||||||
|
bias_level = SND_JACK_BTN_2;
|
||||||
dev_dbg(cs42l42->component->dev, "Function C button press\n");
|
dev_dbg(cs42l42->component->dev, "Function C button press\n");
|
||||||
break;
|
break;
|
||||||
case 2: /* Function B button press */
|
case 2: /* Function B button press */
|
||||||
|
bias_level = SND_JACK_BTN_1;
|
||||||
dev_dbg(cs42l42->component->dev, "Function B button press\n");
|
dev_dbg(cs42l42->component->dev, "Function B button press\n");
|
||||||
break;
|
break;
|
||||||
case 3: /* Function D button press */
|
case 3: /* Function D button press */
|
||||||
|
bias_level = SND_JACK_BTN_3;
|
||||||
dev_dbg(cs42l42->component->dev, "Function D button press\n");
|
dev_dbg(cs42l42->component->dev, "Function D button press\n");
|
||||||
break;
|
break;
|
||||||
case 4: /* Function A button press */
|
case 4: /* Function A button press */
|
||||||
|
bias_level = SND_JACK_BTN_0;
|
||||||
dev_dbg(cs42l42->component->dev, "Function A button press\n");
|
dev_dbg(cs42l42->component->dev, "Function A button press\n");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
bias_level = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set button detect level sensitivity back to default */
|
/* Set button detect level sensitivity back to default */
|
||||||
@ -1281,6 +1296,8 @@ static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42)
|
|||||||
(0 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
|
(0 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
|
||||||
(1 << CS42L42_M_SHORT_RLS_SHIFT) |
|
(1 << CS42L42_M_SHORT_RLS_SHIFT) |
|
||||||
(1 << CS42L42_M_SHORT_DET_SHIFT));
|
(1 << CS42L42_M_SHORT_DET_SHIFT));
|
||||||
|
|
||||||
|
return bias_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cs42l42_irq_params {
|
struct cs42l42_irq_params {
|
||||||
@ -1325,6 +1342,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
|||||||
unsigned int current_plug_status;
|
unsigned int current_plug_status;
|
||||||
unsigned int current_button_status;
|
unsigned int current_button_status;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int report = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Read sticky registers to clear interurpt */
|
/* Read sticky registers to clear interurpt */
|
||||||
for (i = 0; i < ARRAY_SIZE(stickies); i++) {
|
for (i = 0; i < ARRAY_SIZE(stickies); i++) {
|
||||||
@ -1351,9 +1370,20 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
|||||||
if ((~masks[5]) & irq_params_table[5].mask) {
|
if ((~masks[5]) & irq_params_table[5].mask) {
|
||||||
if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
|
if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
|
||||||
cs42l42_process_hs_type_detect(cs42l42);
|
cs42l42_process_hs_type_detect(cs42l42);
|
||||||
dev_dbg(component->dev,
|
switch(cs42l42->hs_type){
|
||||||
"Auto detect done (%d)\n",
|
case CS42L42_PLUG_CTIA:
|
||||||
cs42l42->hs_type);
|
case CS42L42_PLUG_OMTP:
|
||||||
|
snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADSET,
|
||||||
|
SND_JACK_HEADSET);
|
||||||
|
break;
|
||||||
|
case CS42L42_PLUG_HEADPHONE:
|
||||||
|
snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADPHONE,
|
||||||
|
SND_JACK_HEADPHONE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dev_dbg(component->dev, "Auto detect done (%d)\n", cs42l42->hs_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,8 +1401,19 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
|||||||
if (cs42l42->plug_state != CS42L42_TS_UNPLUG) {
|
if (cs42l42->plug_state != CS42L42_TS_UNPLUG) {
|
||||||
cs42l42->plug_state = CS42L42_TS_UNPLUG;
|
cs42l42->plug_state = CS42L42_TS_UNPLUG;
|
||||||
cs42l42_cancel_hs_type_detect(cs42l42);
|
cs42l42_cancel_hs_type_detect(cs42l42);
|
||||||
dev_dbg(component->dev,
|
|
||||||
"Unplug event\n");
|
switch(cs42l42->hs_type){
|
||||||
|
case CS42L42_PLUG_CTIA:
|
||||||
|
case CS42L42_PLUG_OMTP:
|
||||||
|
snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADSET);
|
||||||
|
break;
|
||||||
|
case CS42L42_PLUG_HEADPHONE:
|
||||||
|
snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADPHONE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dev_dbg(component->dev, "Unplug event\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1387,14 +1428,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
|
|||||||
if (!(current_button_status &
|
if (!(current_button_status &
|
||||||
CS42L42_M_HSBIAS_HIZ_MASK)) {
|
CS42L42_M_HSBIAS_HIZ_MASK)) {
|
||||||
|
|
||||||
if (current_button_status &
|
if (current_button_status & CS42L42_M_DETECT_TF_MASK) {
|
||||||
CS42L42_M_DETECT_TF_MASK) {
|
dev_dbg(component->dev, "Button released\n");
|
||||||
dev_dbg(component->dev,
|
report = 0;
|
||||||
"Button released\n");
|
} else if (current_button_status & CS42L42_M_DETECT_FT_MASK) {
|
||||||
} else if (current_button_status &
|
report = cs42l42_handle_button_press(cs42l42);
|
||||||
CS42L42_M_DETECT_FT_MASK) {
|
|
||||||
cs42l42_handle_button_press(cs42l42);
|
|
||||||
}
|
}
|
||||||
|
snd_soc_jack_report(&cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
|
||||||
|
SND_JACK_BTN_2 | SND_JACK_BTN_3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#ifndef __CS42L42_H__
|
#ifndef __CS42L42_H__
|
||||||
#define __CS42L42_H__
|
#define __CS42L42_H__
|
||||||
|
|
||||||
|
#include <sound/jack.h>
|
||||||
|
|
||||||
#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */
|
#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */
|
||||||
#define CS42L42_WIN_START 0x00
|
#define CS42L42_WIN_START 0x00
|
||||||
#define CS42L42_WIN_LEN 0x100
|
#define CS42L42_WIN_LEN 0x100
|
||||||
@ -768,6 +770,7 @@ struct cs42l42_private {
|
|||||||
struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES];
|
struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES];
|
||||||
struct gpio_desc *reset_gpio;
|
struct gpio_desc *reset_gpio;
|
||||||
struct completion pdn_done;
|
struct completion pdn_done;
|
||||||
|
struct snd_soc_jack jack;
|
||||||
u32 sclk;
|
u32 sclk;
|
||||||
u32 srate;
|
u32 srate;
|
||||||
u8 plug_state;
|
u8 plug_state;
|
||||||
|
Loading…
Reference in New Issue
Block a user