sound/soc/codecs/rt5659.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/rt5659.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/rt5659.c
Extension
.c
Size
133719 bytes
Lines
4346
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while (i < 5) {
			msleep(sleep_time[i]);
			val = snd_soc_component_read(component, RT5659_EJD_CTRL_2) & 0x0003;
			i++;
			if (val == 0x1 || val == 0x2 || val == 0x3)
				break;
		}

		switch (val) {
		case 1:
			rt5659->jack_type = SND_JACK_HEADSET;
			rt5659_enable_push_button_irq(component, true);
			break;
		default:
			snd_soc_component_write(component, RT5659_PWR_ANLG_1, reg_63);
			rt5659->jack_type = SND_JACK_HEADPHONE;
			snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
			snd_soc_dapm_sync(dapm);
			break;
		}
	} else {
		snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
		snd_soc_dapm_sync(dapm);
		if (rt5659->jack_type == SND_JACK_HEADSET)
			rt5659_enable_push_button_irq(component, false);
		rt5659->jack_type = 0;
	}

	dev_dbg(component->dev, "jack_type = %d\n", rt5659->jack_type);
	return rt5659->jack_type;
}

static int rt5659_button_detect(struct snd_soc_component *component)
{
	int btn_type, val;

	val = snd_soc_component_read(component, RT5659_4BTN_IL_CMD_1);
	btn_type = val & 0xfff0;
	snd_soc_component_write(component, RT5659_4BTN_IL_CMD_1, val);

	return btn_type;
}

static irqreturn_t rt5659_irq(int irq, void *data)
{
	struct rt5659_priv *rt5659 = data;

	queue_delayed_work(system_power_efficient_wq,
			   &rt5659->jack_detect_work, msecs_to_jiffies(250));

	return IRQ_HANDLED;
}

int rt5659_set_jack_detect(struct snd_soc_component *component,
	struct snd_soc_jack *hs_jack)
{
	struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component);

	rt5659->hs_jack = hs_jack;

	rt5659_irq(0, rt5659);

	return 0;
}
EXPORT_SYMBOL_GPL(rt5659_set_jack_detect);

static void rt5659_jack_detect_work(struct work_struct *work)
{
	struct rt5659_priv *rt5659 =
		container_of(work, struct rt5659_priv, jack_detect_work.work);
	int val, btn_type, report = 0;

	if (!rt5659->component)
		return;

	val = snd_soc_component_read(rt5659->component, RT5659_INT_ST_1) & 0x0080;
	if (!val) {
		/* jack in */
		if (rt5659->jack_type == 0) {
			/* jack was out, report jack type */
			report = rt5659_headset_detect(rt5659->component, 1);
		} else {
			/* jack is already in, report button event */
			report = SND_JACK_HEADSET;
			btn_type = rt5659_button_detect(rt5659->component);
			/**
			 * rt5659 can report three kinds of button behavior,
			 * one click, double click and hold. However,
			 * currently we will report button pressed/released
			 * event. So all the three button behaviors are

Annotation

Implementation Notes