Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2d2362e authored by Jorge Eduardo Candelaria's avatar Jorge Eduardo Candelaria Committed by Liam Girdwood
Browse files

ASoC: twl6040: Add jack support for headset and handset



This patch adds support for reporting twl6040 headset and
handset jack events.

The machine driver retrieves and report the status  through
twl6040_hs_jack_detect.

A workq is used to debounce of the irq.

Signed-off-by: default avatarJorge Eduardo Candelaria <jorge.candelaria@ti.com>
Signed-off-by: default avatarMisael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: default avatarMargarita Olaya Cabrera <magi.olaya@ti.com>
Signed-off-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
parent dcdeda4a
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -42,6 +42,11 @@
#define TWL6040_RATES	 (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define TWL6040_FORMATS	 (SNDRV_PCM_FMTBIT_S32_LE)

struct twl6040_jack_data {
	struct snd_soc_jack *jack;
	int report;
};

/* codec private data */
struct twl6040_data {
	int audpwron;
@@ -52,6 +57,11 @@ struct twl6040_data {
	unsigned int sysclk;
	struct snd_pcm_hw_constraint_list *sysclk_constraints;
	struct completion ready;
	struct twl6040_jack_data hs_jack;
	struct snd_soc_codec *codec;
	struct workqueue_struct *workqueue;
	struct delayed_work delayed_work;
	struct mutex mutex;
};

/*
@@ -381,6 +391,47 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
	return 0;
}

void twl6040_hs_jack_report(struct snd_soc_codec *codec,
				struct snd_soc_jack *jack, int report)
{
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
	int status;

	mutex_lock(&priv->mutex);

	/* Sync status */
	status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
	if (status & TWL6040_PLUGCOMP)
		snd_soc_jack_report(jack, report, report);
	else
		snd_soc_jack_report(jack, 0, report);

	mutex_unlock(&priv->mutex);
}

void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
				struct snd_soc_jack *jack, int report)
{
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
	struct twl6040_jack_data *hs_jack = &priv->hs_jack;

	hs_jack->jack = jack;
	hs_jack->report = report;

	twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
}
EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);

static void twl6040_accessory_work(struct work_struct *work)
{
	struct twl6040_data *priv = container_of(work,
					struct twl6040_data, delayed_work.work);
	struct snd_soc_codec *codec = priv->codec;
	struct twl6040_jack_data *hs_jack = &priv->hs_jack;

	twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
}

/* audio interrupt handler */
static irqreturn_t twl6040_naudint_handler(int irq, void *data)
{
@@ -396,6 +447,9 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
		break;
	case TWL6040_PLUGINT:
	case TWL6040_UNPLUGINT:
		queue_delayed_work(priv->workqueue, &priv->delayed_work,
							msecs_to_jiffies(200));
		break;
	case TWL6040_HOOKINT:
		break;
	case TWL6040_HFINT:
@@ -1023,6 +1077,8 @@ static int twl6040_probe(struct snd_soc_codec *codec)
		return -ENOMEM;
	snd_soc_codec_set_drvdata(codec, priv);

	priv->codec = codec;

	if (twl_codec) {
		audpwron = twl_codec->audpwron_gpio;
		naudint = twl_codec->naudint_irq;
@@ -1033,6 +1089,14 @@ static int twl6040_probe(struct snd_soc_codec *codec)

	priv->audpwron = audpwron;
	priv->naudint = naudint;
	priv->workqueue = create_singlethread_workqueue("twl6040-codec");

	if (!priv->workqueue)
		goto work_err;

	INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);

	mutex_init(&priv->mutex);

	init_completion(&priv->ready);

@@ -1089,6 +1153,8 @@ static int twl6040_probe(struct snd_soc_codec *codec)
	if (gpio_is_valid(audpwron))
		gpio_free(audpwron);
gpio1_err:
	destroy_workqueue(priv->workqueue);
work_err:
	kfree(priv);
	return ret;
}
@@ -1107,6 +1173,7 @@ static int twl6040_remove(struct snd_soc_codec *codec)
	if (naudint)
		free_irq(naudint, codec);

	destroy_workqueue(priv->workqueue);
	kfree(priv);

	return 0;
+7 −0
Original line number Diff line number Diff line
@@ -135,4 +135,11 @@
#define TWL6040_HPPLL_ID		1
#define TWL6040_LPPLL_ID		2

/* STATUS (0x2E) fields */

#define TWL6040_PLUGCOMP		0x02

void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
			    struct snd_soc_jack *jack, int report);

#endif /* End of __TWL6040_H__ */