LINUX.ORG.RU

История изменений

Исправление metawishmaster, (текущая версия) :

вообще-то, чтобы хоть как-то работало я изменил две функции:

static int avs_es8336_speaker_power_event(struct snd_soc_dapm_widget *w,
					  struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_card *card = w->dapm->card;
	struct snd_soc_dai *codec_dai;
	struct gpio_desc *gpio;
	bool speaker_en;

	codec_dai = snd_soc_card_get_codec_dai(card, ES8336_CODEC_DAI);
//	gpio = gpiod_get_optional(codec_dai->dev, "speakers-enable", GPIOD_OUT_LOW);
	speaker_en = !SND_SOC_DAPM_EVENT_ON(event);

	if (SND_SOC_DAPM_EVENT_ON(event))
		msleep(70);

//	printk("gpiod_set_value_cansleep(gpio, %d)\n", speaker_en);
//	gpiod_set_value_cansleep(gpio, speaker_en);
	return 0;
}

и
static irqreturn_t es8316_irq(int irq, void *data)
{
	struct es8316_priv *es8316 = data;
	struct snd_soc_component *comp = es8316->component;
	static struct gpio_desc *gpio = NULL;
	unsigned int flags;

	mutex_lock(&es8316->lock);

	regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
	if (flags == 0x00)
		goto out; /* Powered-down / reset */

	/* Catch spurious IRQ before set_jack is called */
	if (!es8316->jack)
		goto out;

	if (es8316->jd_inverted)
		flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;

	dev_info(comp->dev, "gpio flags %#04x\n", flags);
	if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
		/* Jack removed, or spurious IRQ? */
		if (es8316->jack->status & SND_JACK_MICROPHONE)
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);

		if (es8316->jack->status & SND_JACK_HEADPHONE) {
			snd_soc_jack_report(es8316->jack, 0,
					    SND_JACK_HEADSET | SND_JACK_BTN_0);
			dev_info(comp->dev, "jack unplugged\n");

			if (gpio)
				devm_gpiod_put(comp->dev, gpio);
			gpio = devm_gpiod_get_optional(comp->dev, "speakers-enable", GPIOD_OUT_LOW);
			gpiod_set_value_cansleep(gpio, 0);

			if (IS_ERR(gpio))
				return dev_err_probe(comp->dev, PTR_ERR(gpio), "Get gpiod failed: %ld\n",
							 PTR_ERR(gpio));
		} printk("spurious IRQ\n");
	} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
		/* Jack inserted, determine type */
		es8316_enable_micbias_for_mic_gnd_short_detect(comp);
		regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
		if (es8316->jd_inverted)
			flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
		dev_info(comp->dev, "gpio flags %#04x\n", flags);
		if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
			/* Jack unplugged underneath us */
			printk("Jack unplugged underneath u\n");
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
		} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
			printk("Open, headset\n");
			/* Open, headset */
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_HEADSET,
					    SND_JACK_HEADSET);
			/* Keep mic-gnd-short detection on for button press */
		} else {
			printk("HEADPHONES\n");
			if (gpio)
				devm_gpiod_put(comp->dev, gpio);
			gpio = devm_gpiod_get_optional(comp->dev, "speakers-enable", GPIOD_OUT_HIGH);
			/* Shorted, headphones */
			gpiod_set_value_cansleep(gpio, 1);
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_HEADPHONE,
					    SND_JACK_HEADSET);
			/* No longer need mic-gnd-short detection */
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
		}
	} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
		/* Interrupt while jack inserted, report button state */
		if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
			/* Open, button release */
			printk("Jack button released\n");
			snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
		} else {
			/* Short, button press */
			printk("Jack button pressed\n");
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_BTN_0,
					    SND_JACK_BTN_0);
		}
	}

out:
	mutex_unlock(&es8316->lock);
	return IRQ_HANDLED;
}


но, конечно «struct gpio_desc *gpio» хотелось бы заныкать в какое-нить private поле (что-то похожее было в том патче, который выводил ядро из душевного равновесия)

но в какое - я пока не разобрался :-\
там же у одной карточки есть (или может быть?) несколько поддевайсов, и на какое приходит прерывание тоже пока не понятно :-\

Вы не можете подсказать, в каком направлении копать?

Исходная версия metawishmaster, :

вообще-то, чтобы хоть как-то работало я изменил две функции?

static int avs_es8336_speaker_power_event(struct snd_soc_dapm_widget *w,
					  struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_card *card = w->dapm->card;
	struct snd_soc_dai *codec_dai;
	struct gpio_desc *gpio;
	bool speaker_en;

	codec_dai = snd_soc_card_get_codec_dai(card, ES8336_CODEC_DAI);
//	gpio = gpiod_get_optional(codec_dai->dev, "speakers-enable", GPIOD_OUT_LOW);
	speaker_en = !SND_SOC_DAPM_EVENT_ON(event);

	if (SND_SOC_DAPM_EVENT_ON(event))
		msleep(70);

//	printk("gpiod_set_value_cansleep(gpio, %d)\n", speaker_en);
//	gpiod_set_value_cansleep(gpio, speaker_en);
	return 0;
}

и
static irqreturn_t es8316_irq(int irq, void *data)
{
	struct es8316_priv *es8316 = data;
	struct snd_soc_component *comp = es8316->component;
	static struct gpio_desc *gpio = NULL;
	unsigned int flags;

	mutex_lock(&es8316->lock);

	regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
	if (flags == 0x00)
		goto out; /* Powered-down / reset */

	/* Catch spurious IRQ before set_jack is called */
	if (!es8316->jack)
		goto out;

	if (es8316->jd_inverted)
		flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;

	dev_info(comp->dev, "gpio flags %#04x\n", flags);
	if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
		/* Jack removed, or spurious IRQ? */
		if (es8316->jack->status & SND_JACK_MICROPHONE)
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);

		if (es8316->jack->status & SND_JACK_HEADPHONE) {
			snd_soc_jack_report(es8316->jack, 0,
					    SND_JACK_HEADSET | SND_JACK_BTN_0);
			dev_info(comp->dev, "jack unplugged\n");

			if (gpio)
				devm_gpiod_put(comp->dev, gpio);
			gpio = devm_gpiod_get_optional(comp->dev, "speakers-enable", GPIOD_OUT_LOW);
			gpiod_set_value_cansleep(gpio, 0);

			if (IS_ERR(gpio))
				return dev_err_probe(comp->dev, PTR_ERR(gpio), "Get gpiod failed: %ld\n",
							 PTR_ERR(gpio));
		} printk("spurious IRQ\n");
	} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
		/* Jack inserted, determine type */
		es8316_enable_micbias_for_mic_gnd_short_detect(comp);
		regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
		if (es8316->jd_inverted)
			flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
		dev_info(comp->dev, "gpio flags %#04x\n", flags);
		if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
			/* Jack unplugged underneath us */
			printk("Jack unplugged underneath u\n");
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
		} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
			printk("Open, headset\n");
			/* Open, headset */
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_HEADSET,
					    SND_JACK_HEADSET);
			/* Keep mic-gnd-short detection on for button press */
		} else {
			printk("HEADPHONES\n");
			if (gpio)
				devm_gpiod_put(comp->dev, gpio);
			gpio = devm_gpiod_get_optional(comp->dev, "speakers-enable", GPIOD_OUT_HIGH);
			/* Shorted, headphones */
			gpiod_set_value_cansleep(gpio, 1);
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_HEADPHONE,
					    SND_JACK_HEADSET);
			/* No longer need mic-gnd-short detection */
			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
		}
	} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
		/* Interrupt while jack inserted, report button state */
		if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
			/* Open, button release */
			printk("Jack button released\n");
			snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
		} else {
			/* Short, button press */
			printk("Jack button pressed\n");
			snd_soc_jack_report(es8316->jack,
					    SND_JACK_BTN_0,
					    SND_JACK_BTN_0);
		}
	}

out:
	mutex_unlock(&es8316->lock);
	return IRQ_HANDLED;
}


но, конечно «struct gpio_desc *gpio» хотелось бы заныкать в какое-нить private поле (что-то похожее было в том патче, который выводил ядро из душевного равновесия)

но в какое - я пока не разобрался :-\
там же у одной карточки есть (или может быть?) несколько поддевайсов, и на какое приходит прерывание тоже пока не понятно :-\

Вы не можете подсказать, в каком направлении копать?