Unverified Commit c5b8ee08 authored by Lucas Tanure's avatar Lucas Tanure Committed by Mark Brown
Browse files

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: default avatarLucas Tanure <tanureal@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210306185553.62053-12-tanureal@opensource.cirrus.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 585e7079
Loading
Loading
Loading
Loading
+56 −14
Original line number Diff line number Diff line
@@ -522,10 +522,18 @@ static int cs42l42_component_probe(struct snd_soc_component *component)
{
	struct cs42l42_private *cs42l42 =
		(struct cs42l42_private *)snd_soc_component_get_drvdata(component);
	struct snd_soc_card *crd = component->card;
	int ret = 0;

	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 = {
@@ -1198,7 +1206,7 @@ static void cs42l42_cancel_hs_type_detect(struct cs42l42_private *cs42l42)
				(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;
	unsigned int detect_status;
@@ -1241,17 +1249,24 @@ static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42)

	switch (bias_level) {
	case 1: /* Function C button press */
		bias_level = SND_JACK_BTN_2;
		dev_dbg(cs42l42->component->dev, "Function C button press\n");
		break;
	case 2: /* Function B button press */
		bias_level = SND_JACK_BTN_1;
		dev_dbg(cs42l42->component->dev, "Function B button press\n");
		break;
	case 3: /* Function D button press */
		bias_level = SND_JACK_BTN_3;
		dev_dbg(cs42l42->component->dev, "Function D button press\n");
		break;
	case 4: /* Function A button press */
		bias_level = SND_JACK_BTN_0;
		dev_dbg(cs42l42->component->dev, "Function A button press\n");
		break;
	default:
		bias_level = 0;
		break;
	}

	/* 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) |
		(1 << CS42L42_M_SHORT_RLS_SHIFT) |
		(1 << CS42L42_M_SHORT_DET_SHIFT));

	return bias_level;
}

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_button_status;
	unsigned int i;
	int report = 0;


	/* Read sticky registers to clear interurpt */
	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 (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
			cs42l42_process_hs_type_detect(cs42l42);
			dev_dbg(component->dev,
				"Auto detect done (%d)\n",
				cs42l42->hs_type);
			switch(cs42l42->hs_type){
			case CS42L42_PLUG_CTIA:
			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) {
				cs42l42->plug_state = CS42L42_TS_UNPLUG;
				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;

@@ -1387,14 +1428,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
		if (!(current_button_status &
			CS42L42_M_HSBIAS_HIZ_MASK)) {

			if (current_button_status &
				CS42L42_M_DETECT_TF_MASK) {
				dev_dbg(component->dev,
					"Button released\n");
			} else if (current_button_status &
				CS42L42_M_DETECT_FT_MASK) {
				cs42l42_handle_button_press(cs42l42);
			if (current_button_status & CS42L42_M_DETECT_TF_MASK) {
				dev_dbg(component->dev, "Button released\n");
				report = 0;
			} else if (current_button_status & CS42L42_M_DETECT_FT_MASK) {
				report = 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);
		}
	}

+3 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@
#ifndef __CS42L42_H__
#define __CS42L42_H__

#include <sound/jack.h>

#define CS42L42_PAGE_REGISTER	0x00	/* Page Select Register */
#define CS42L42_WIN_START	0x00
#define CS42L42_WIN_LEN		0x100
@@ -768,6 +770,7 @@ struct cs42l42_private {
	struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES];
	struct gpio_desc *reset_gpio;
	struct completion pdn_done;
	struct snd_soc_jack jack;
	u32 sclk;
	u32 srate;
	u8 plug_state;