Unverified Commit 2c172778 authored by David Rau's avatar David Rau Committed by Mark Brown
Browse files

ASoC: da7219: Improve the relability of AAD IRQ process



- Configure the default gound switch delay time before enabling IRQ
  to avoid the unexpected delay time is set up
- Apply DA7219 AAD own work queue to handle AAD events
- Replace msleep with queue_delayed_work to have better relability

This commit improves the control of ground switches in AAD IRQ

Signed-off-by: default avatarDavid Rau <David.Rau.opensource@dm.renesas.com>
Link: https://lore.kernel.org/r/20230413024134.8612-1-David.Rau.opensource@dm.renesas.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 27ff688a
Loading
Loading
Loading
Loading
+29 −31
Original line number Diff line number Diff line
@@ -342,36 +342,17 @@ static void da7219_aad_hptest_work(struct work_struct *work)
static void da7219_aad_jack_det_work(struct work_struct *work)
{
	struct da7219_aad_priv *da7219_aad =
		container_of(work, struct da7219_aad_priv, jack_det_work);
		container_of(work, struct da7219_aad_priv, jack_det_work.work);
	struct snd_soc_component *component = da7219_aad->component;
	u8 srm_st;

	mutex_lock(&da7219_aad->jack_det_mutex);

	srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
	msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4);
	/* Enable ground switch */
	snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);

	mutex_unlock(&da7219_aad->jack_det_mutex);
}


/*
 * IRQ
 */

static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data)
{

	struct da7219_aad_priv *da7219_aad = data;

	if (!da7219_aad->jack_inserted)
		schedule_work(&da7219_aad->jack_det_work);

	return IRQ_WAKE_THREAD;
}

static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
{
	struct da7219_aad_priv *da7219_aad = data;
@@ -392,6 +373,18 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
	/* Read status register for jack insertion & type status */
	statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A);

	if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_INSERTED_MASK) {
		u8 srm_st;
		int delay = 0;

		srm_st = snd_soc_component_read(component,
					DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
		delay = (da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 2);
		queue_delayed_work(da7219_aad->aad_wq,
							&da7219_aad->jack_det_work,
							msecs_to_jiffies(delay));
	}

	/* Clear events */
	regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
			  events, DA7219_AAD_IRQ_REG_MAX);
@@ -400,9 +393,6 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
		events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
		statusa);

	if (!da7219_aad->jack_inserted)
		cancel_work_sync(&da7219_aad->jack_det_work);

	if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
		/* Jack Insertion */
		if (events[DA7219_AAD_IRQ_REG_A] &
@@ -430,9 +420,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
			if (statusa & DA7219_JACK_TYPE_STS_MASK) {
				report |= SND_JACK_HEADSET;
				mask |=	SND_JACK_HEADSET | SND_JACK_LINEOUT;
				schedule_work(&da7219_aad->btn_det_work);
				queue_work(da7219_aad->aad_wq, &da7219_aad->btn_det_work);
			} else {
				schedule_work(&da7219_aad->hptest_work);
				queue_work(da7219_aad->aad_wq, &da7219_aad->hptest_work);
			}
		}

@@ -465,6 +455,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
			da7219_aad->jack_inserted = false;

			/* Cancel any pending work */
			cancel_delayed_work_sync(&da7219_aad->jack_det_work);
			cancel_work_sync(&da7219_aad->btn_det_work);
			cancel_work_sync(&da7219_aad->hptest_work);

@@ -964,13 +955,19 @@ int da7219_aad_init(struct snd_soc_component *component)
	snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
			    DA7219_BUTTON_CONFIG_MASK, 0);

	da7219_aad_handle_gnd_switch_time(component);

	da7219_aad->aad_wq = create_singlethread_workqueue("da7219-aad");
	if (!da7219_aad->aad_wq) {
		dev_err(component->dev, "Failed to create aad workqueue\n");
		return -ENOMEM;
	}

	INIT_DELAYED_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work);
	INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
	INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
	INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work);

	mutex_init(&da7219_aad->jack_det_mutex);

	ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread,
	ret = request_threaded_irq(da7219_aad->irq, NULL,
				   da7219_aad_irq_thread,
				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				   "da7219-aad", da7219_aad);
@@ -984,8 +981,6 @@ int da7219_aad_init(struct snd_soc_component *component)
	regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
			  &mask, DA7219_AAD_IRQ_REG_MAX);

	da7219_aad_handle_gnd_switch_time(component);

	return 0;
}

@@ -1002,8 +997,10 @@ void da7219_aad_exit(struct snd_soc_component *component)

	free_irq(da7219_aad->irq, da7219_aad);

	cancel_delayed_work_sync(&da7219_aad->jack_det_work);
	cancel_work_sync(&da7219_aad->btn_det_work);
	cancel_work_sync(&da7219_aad->hptest_work);
	destroy_workqueue(da7219_aad->aad_wq);
}

/*
@@ -1031,4 +1028,5 @@ int da7219_aad_probe(struct i2c_client *i2c)

MODULE_DESCRIPTION("ASoC DA7219 AAD Driver");
MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
MODULE_AUTHOR("David Rau <David.Rau.opensource@dm.renesas.com>");
MODULE_LICENSE("GPL");
+2 −3
Original line number Diff line number Diff line
@@ -197,9 +197,8 @@ struct da7219_aad_priv {

	struct work_struct btn_det_work;
	struct work_struct hptest_work;
	struct work_struct jack_det_work;

	struct mutex  jack_det_mutex;
	struct delayed_work jack_det_work;
	struct workqueue_struct *aad_wq;

	struct snd_soc_jack *jack;
	bool micbias_resume_enable;