orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Mute GPIO

Wed Dec 06, 2017 5:39 pm

I am working on creating a DAC for the PI. I have finalized my overlay except for mute function:

I have been reviewing this overlay:
https://github.com/raspberrypi/linux/bl ... verlay.dts

towards the end of the overlay there is mute functionality:

Code: Select all

	
		fragment@2 {
		target = <&sound>;
		iqaudio_dac: __overlay__ {
			compatible = "iqaudio,iqaudio-dac";
			i2s-controller = <&i2s>;
			mute-gpios = <&gpio 22 0>;
			status = "okay";
		};
	};

	__overrides__ {
		24db_digital_gain = <&iqaudio_dac>,"iqaudio,24db_digital_gain?";
		auto_mute_amp = <&iqaudio_dac>,"iqaudio-dac,auto-mute-amp?";
		unmute_amp = <&iqaudio_dac>,"iqaudio-dac,unmute-amp?";
	};
I see that GPIO 22 (PIN 15) is being used for mute.

What I am trying to figure out is under what conditions does the GPIO actually toggle mute and also if the GPIO is input or output?
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Wed Dec 06, 2017 5:49 pm

It's a feature of the iqaudio-dac driver. The GPIO is an output, and it is driven high (mute) when ALSA sets the bias level to BIAS_STANDBY, and low (unmute) when the bias level is set to BIAS_PREPARE, provided the auto_mute_amp DT parameter is used.

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Wed Dec 06, 2017 6:03 pm

PhilE wrote:
Wed Dec 06, 2017 5:49 pm
It's a feature of the iqaudio-dac driver. The GPIO is an output, and it is driven high (mute) when ALSA sets the bias level to BIAS_STANDBY, and low (unmute) when the bias level is set to BIAS_PREPARE, provided the auto_mute_amp DT parameter is used.
That is exactly the functionality that I need on my DAC as well, what would I need to do in my overlay to add that functionality?

Here is my existing overlay:

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2708";

    fragment@0 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            simple-audio-card,name = "I2S_DAC";

            status="okay";

            playback_link: simple-audio-card,dai-link@1 {
                format = "i2s";

                p_cpu_dai: cpu {
                    sound-dai = <&i2s>;
                    dai-tdm-slot-num = <2>;
                    dai-tdm-slot-width = <32>;
                };

                p_codec_dai: codec {
                    sound-dai = <&codec_out>;
                };
            };
        };
    };

    fragment@1 {
        target-path = "/";
        __overlay__ {
            codec_out: pcm1794a-codec {
                compatible = "ti,pcm1794a";
                status = "okay";
            };
        };
    };

    fragment@2 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };
};

Will this be the correct way to modify it to add the mute functionality:

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2708";

    fragment@0 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            simple-audio-card,name = "I2S_DAC";

            status="okay";

            playback_link: simple-audio-card,dai-link@1 {
                format = "i2s";

                p_cpu_dai: cpu {
                    sound-dai = <&i2s>;
                    dai-tdm-slot-num = <2>;
                    dai-tdm-slot-width = <32>;
                };

                p_codec_dai: codec {
                    sound-dai = <&codec_out>;
                };
            };
        };
    };

    fragment@1 {
        target-path = "/";
        __overlay__ {
            codec_out: pcm1794a-codec {
                #sound-dai-cells = <0>;
                compatible = "ti,pcm1794a";
                status = "okay";
            };
        };
    };

    fragment@2 {
        target = <&i2s>;
        __overlay__ {
	    mute-gpios = <&gpio 22 0>;
            status = "okay";
        };
    };
    __overrides__ {
            auto_mute_amp = <&iqaudio_dac>,"iqaudio-dac,auto-mute-amp?";
            unmute_amp = <&iqaudio_dac>,"iqaudio-dac,unmute-amp?";
    };
};
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Wed Dec 06, 2017 8:15 pm

Unfortunately, adding mute functionality is not that simple:
1. Your overlay would fail to load because there is no "iqaudio_dac" label anywhere.
2. The gpio mute functionality has to be provided by a driver. Your overlay is using two drivers - the generic "simple-audio-card" driver and the pcm1794a codec driver - neither of which supports a mute gpio. Only one other sound-card in the tree uses the pcm1794 DAC - the rpi-dac - and that doesn't make use of the mute pin. That means you are going to need a sound-card driver for your board.

The good news is that you should be able to do a relatively simple copy-and-paste/cut-and-shut on the rpi-dac and iqaudio-dac drivers to produce a custom driver for your board. There are plenty of precedents of drivers borrowing from other drivers - just mention your sources to be polite.

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Wed Dec 06, 2017 11:11 pm

PhilE wrote:
Wed Dec 06, 2017 8:15 pm
Unfortunately, adding mute functionality is not that simple:
1. Your overlay would fail to load because there is no "iqaudio_dac" label anywhere.
2. The gpio mute functionality has to be provided by a driver. Your overlay is using two drivers - the generic "simple-audio-card" driver and the pcm1794a codec driver - neither of which supports a mute gpio. Only one other sound-card in the tree uses the pcm1794 DAC - the rpi-dac - and that doesn't make use of the mute pin. That means you are going to need a sound-card driver for your board.

The good news is that you should be able to do a relatively simple copy-and-paste/cut-and-shut on the rpi-dac and iqaudio-dac drivers to produce a custom driver for your board. There are plenty of precedents of drivers borrowing from other drivers - just mention your sources to be polite.
Is there a howto somewhere on how to make the drivers? Where do I locate the rpi-dac and iqaudio-dac drivers?
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Thu Dec 07, 2017 9:24 am

I'm not aware of any HowTo, but there are a few forum threads where we've helped people through the process. This is the most recent thread: viewtopic.php?f=107&t=193550

The source for the sound card drivers is here: https://github.com/raspberrypi/linux/tr ... nd/soc/bcm
And the codecs are here: https://github.com/raspberrypi/linux/tr ... soc/codecs

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Thu Dec 07, 2017 2:49 pm

PhilE wrote:
Thu Dec 07, 2017 9:24 am
I'm not aware of any HowTo, but there are a few forum threads where we've helped people through the process. This is the most recent thread: viewtopic.php?f=107&t=193550

The source for the sound card drivers is here: https://github.com/raspberrypi/linux/tr ... nd/soc/bcm
And the codecs are here: https://github.com/raspberrypi/linux/tr ... soc/codecs
I am not a software person except for my single programming 101 class in college more than 10 years ago. I am going to need help...

I took a look at the sound card drivers for iqaudio dac and rpi dacs
Here:
https://github.com/raspberrypi/linux/bl ... udio-dac.c
and
Here:
https://github.com/raspberrypi/linux/bl ... /rpi-dac.c

From what I can tell I should be able to use the rpi-dac driver as is but I need the mute functionality from the iqaudio dac driver.

so it seems like the section that I need to modify would be the following

Code: Select all

 
static int snd_rpi_rpi_dac_probe(struct platform_device *pdev)
{
	int ret = 0;

	snd_rpi_rpi_dac.dev = &pdev->dev;
	
	if (pdev->dev.of_node) {
		struct device_node *i2s_node;
		struct snd_soc_dai_link *dai = &snd_rpi_rpi_dac_dai[0];
		i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);

		if (i2s_node) {
			dai->cpu_dai_name = NULL;
			dai->cpu_of_node = i2s_node;
			dai->platform_name = NULL;
			dai->platform_of_node = i2s_node;
		}
	}
	
	ret = snd_soc_register_card(&snd_rpi_rpi_dac);
	if (ret && ret != -EPROBE_DEFER)
		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);

	return ret;
}
} 

In the iqaudio dac the same sections is a lot more involved:

Code: Select all

static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev)
{
	int ret = 0;
	bool gpio_unmute = false;

	snd_rpi_iqaudio_dac.dev = &pdev->dev;

	if (pdev->dev.of_node) {
		struct device_node *i2s_node;
		struct snd_soc_card *card = &snd_rpi_iqaudio_dac;
		struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0];
		bool auto_gpio_mute = false;

		i2s_node = of_parse_phandle(pdev->dev.of_node,
					    "i2s-controller", 0);
		if (i2s_node) {
			dai->cpu_dai_name = NULL;
			dai->cpu_of_node = i2s_node;
			dai->platform_name = NULL;
			dai->platform_of_node = i2s_node;
		}

		digital_gain_0db_limit = !of_property_read_bool(
			pdev->dev.of_node, "iqaudio,24db_digital_gain");

		if (of_property_read_string(pdev->dev.of_node, "card_name",
					    &card->name))
			card->name = "IQaudIODAC";

		if (of_property_read_string(pdev->dev.of_node, "dai_name",
					    &dai->name))
			dai->name = "IQaudIO DAC";

		if (of_property_read_string(pdev->dev.of_node,
					"dai_stream_name", &dai->stream_name))
			dai->stream_name = "IQaudIO DAC HiFi";

		/* gpio_unmute - one time unmute amp using GPIO */
		gpio_unmute = of_property_read_bool(pdev->dev.of_node,
						    "iqaudio-dac,unmute-amp");

		/* auto_gpio_mute - mute/unmute amp using GPIO */
		auto_gpio_mute = of_property_read_bool(pdev->dev.of_node,
						"iqaudio-dac,auto-mute-amp");

		if (auto_gpio_mute || gpio_unmute) {
			mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
							    GPIOD_OUT_LOW);
			if (IS_ERR(mute_gpio)) {
				ret = PTR_ERR(mute_gpio);
				dev_err(&pdev->dev,
					"Failed to get mute gpio: %d\n", ret);
				return ret;
			}

			if (auto_gpio_mute && mute_gpio)
				snd_rpi_iqaudio_dac.set_bias_level =
						snd_rpi_iqaudio_set_bias_level;
		}
	}

	ret = snd_soc_register_card(&snd_rpi_iqaudio_dac);
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev,
				"snd_soc_register_card() failed: %d\n", ret);
		return ret;
	}

	if (gpio_unmute && mute_gpio)
		snd_rpi_iqaudio_gpio_unmute(&snd_rpi_iqaudio_dac);

	return 0;
}

I do not have the capability to be able to figure out how they need to be combined. Please help.

I gave it a shot, take a look here:

Code: Select all

#include <linux/module.h>
#include <linux/platform_device.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>

static bool digital_gain_0db_limit = true;
static struct gpio_desc *mute_gpio;

static int snd_applepi_dac_init(struct snd_soc_pcm_runtime *rtd)
{
	return 0;
}

static int snd_applepi_dac_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;

	return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
}

/* machine stream operations */
static struct snd_soc_ops snd_applepi_dac_ops = {
	.hw_params = snd_applepi_dac_hw_params,
};

static struct snd_soc_dai_link snd_applepi_dac_dai[] = {
{
	.name		= "ApplePi-DAC",
	.stream_name	= "ApplePi-DAC HiFi",
	.cpu_dai_name	= "bcm2708-i2s.0",
	.codec_dai_name	= "pcm1794a-hifi",
	.platform_name	= "bcm2708-i2s.0",
	.codec_name	= "pcm1794a-codec",
	.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
				SND_SOC_DAIFMT_CBS_CFS,
	.ops		= &snd_applepi_dac_ops,
	.init		= snd_applepi_dac_init,
},
};

/* audio machine driver */
static struct snd_soc_card snd_applepi_dac = {
	.name         = "snd_applepi_dac",
	.owner        = THIS_MODULE,
	.dai_link     = snd_applepi_dac_dai,
	.num_links    = ARRAY_SIZE(snd_applepi_dac_dai),
};

static int snd_applepi_dac_probe(struct platform_device *pdev)
{
	int ret = 0;
	bool gpio_unmute = false;
	
	snd_applepi_dac.dev = &pdev->dev;
	
	if (pdev->dev.of_node) {
		struct device_node *i2s_node;
		struct snd_soc_card *card = &snd_applepi_dac;
		struct snd_soc_dai_link *dai = &snd_applepi_dac_dai[0];
		bool auto_gpio_mute = false;

		i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
		
		if (i2s_node) {
			dai->cpu_dai_name = NULL;
			dai->cpu_of_node = i2s_node;
			dai->platform_name = NULL;
			dai->platform_of_node = i2s_node;
		}
		
		digital_gain_0db_limit = !of_property_read_bool(
			pdev->dev.of_node, "applepi,24db_digital_gain");

		if (of_property_read_string(pdev->dev.of_node, "card_name",
					    &card->name))
			card->name = "ApplePi-DAC";

		if (of_property_read_string(pdev->dev.of_node, "dai_name",
					    &dai->name))
			dai->name = "ApplePi-DAC";

		if (of_property_read_string(pdev->dev.of_node,
					"dai_stream_name", &dai->stream_name))
			dai->stream_name = "ApplePi-DAC HiFi";

		/* gpio_unmute - one time unmute amp using GPIO */
		gpio_unmute = of_property_read_bool(pdev->dev.of_node,
						    "applepi-dac,unmute-amp");

		/* auto_gpio_mute - mute/unmute amp using GPIO */
		auto_gpio_mute = of_property_read_bool(pdev->dev.of_node,
						"applepi-dac,auto-mute-amp");

		if (auto_gpio_mute || gpio_unmute) {
			mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
							    GPIOD_OUT_LOW);
			if (IS_ERR(mute_gpio)) {
				ret = PTR_ERR(mute_gpio);
				dev_err(&pdev->dev,
					"Failed to get mute gpio: %d\n", ret);
				return ret;
			}

			if (auto_gpio_mute && mute_gpio)
				snd_applepi_dac.set_bias_level =
						snd_rpi_iqaudio_set_bias_level;
		}
	}
		
	ret = snd_soc_register_card(&snd_applepi_dac);
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev,
				"snd_soc_register_card() failed: %d\n", ret);
		return ret;
	}
	
	if (gpio_unmute && mute_gpio)
		snd_applepi_gpio_unmute(&snd_applepi_dac);

	return 0;
}

static int snd_applepi_dac_remove(struct platform_device *pdev)
{
	snd_applepi_gpio_mute(&snd_applepi_dac);
	
	return snd_soc_unregister_card(&snd_applepi_dac);
}

static const struct of_device_id snd_applepi_dac_of_match[] = {
	{ .compatible = "applepi,applepi-dac", },
	{},
};
MODULE_DEVICE_TABLE(of, snd_applepi_dac_of_match);

static struct platform_driver snd_applepi_dac_driver = {
        .driver = {
                .name   = "snd-applepi-dac",
                .owner  = THIS_MODULE,
                .of_match_table = snd_applepi_dac_of_match,
        },
        .probe          = snd_applepi_dac_probe,
        .remove         = snd_applepi_dac_remove,
};

module_platform_driver(snd_applepi_dac_driver);
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Thu Dec 07, 2017 4:19 pm

That's a great start. The next step is to clone and rename the snd_rpi_iqaudio_set_bias_level and snd_rpi_iqaudio_gpio_mute/unmute functions, patching up the calls to the (un)mute functions as you go, then rename the reference to it:

Code: Select all

snd_applepi_dac.set_bias_level =
						snd_applepi_dac_set_bias_level;
to use the name of your clone function.

Once you've done that it should be close to working.

You'll need to add an entry to the Makefile in the sound/soc/bcm for your card and a Kconfig entry as well (although as a short-term measure you could reuse one of the existing config symbols such as SND_BCM2708_SOC_RPI_DAC).

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Thu Dec 07, 2017 5:38 pm

I made the modification you suggested.

Code: Select all

#include <linux/module.h>
#include <linux/platform_device.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>

static bool digital_gain_0db_limit = true;
static struct gpio_desc *mute_gpio;

static int snd_applepi_dac_init(struct snd_soc_pcm_runtime *rtd)
{
	return 0;
}

static int snd_applepi_dac_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;

	return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
}

/* machine stream operations */
static struct snd_soc_ops snd_applepi_dac_ops = {
	.hw_params = snd_applepi_dac_hw_params,
};

static struct snd_soc_dai_link snd_applepi_dac_dai[] = {
{
	.name		= "ApplePi-DAC",
	.stream_name	= "ApplePi-DAC HiFi",
	.cpu_dai_name	= "bcm2708-i2s.0",
	.codec_dai_name	= "pcm1794a-hifi",
	.platform_name	= "bcm2708-i2s.0",
	.codec_name	= "pcm1794a-codec",
	.dai_fmt	= SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
				SND_SOC_DAIFMT_CBS_CFS,
	.ops		= &snd_applepi_dac_ops,
	.init		= snd_applepi_dac_init,
},
};

/* audio machine driver */
static struct snd_soc_card snd_applepi_dac = {
	.name         = "snd_applepi_dac",
	.owner        = THIS_MODULE,
	.dai_link     = snd_applepi_dac_dai,
	.num_links    = ARRAY_SIZE(snd_applepi_dac_dai),
};

static int snd_applepi_dac_probe(struct platform_device *pdev)
{
	int ret = 0;
	bool gpio_unmute = false;
	
	snd_applepi_dac.dev = &pdev->dev;
	
	if (pdev->dev.of_node) {
		struct device_node *i2s_node;
		struct snd_soc_card *card = &snd_applepi_dac;
		struct snd_soc_dai_link *dai = &snd_applepi_dac_dai[0];
		bool auto_gpio_mute = false;

		i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
		
		if (i2s_node) {
			dai->cpu_dai_name = NULL;
			dai->cpu_of_node = i2s_node;
			dai->platform_name = NULL;
			dai->platform_of_node = i2s_node;
		}
		
		digital_gain_0db_limit = !of_property_read_bool(
			pdev->dev.of_node, "applepi,24db_digital_gain");

		if (of_property_read_string(pdev->dev.of_node, "card_name",
					    &card->name))
			card->name = "ApplePi-DAC";

		if (of_property_read_string(pdev->dev.of_node, "dai_name",
					    &dai->name))
			dai->name = "ApplePi-DAC";

		if (of_property_read_string(pdev->dev.of_node,
					"dai_stream_name", &dai->stream_name))
			dai->stream_name = "ApplePi-DAC HiFi";

		/* gpio_unmute - one time unmute amp using GPIO */
		gpio_unmute = of_property_read_bool(pdev->dev.of_node,
						    "applepi-dac,unmute-amp");

		/* auto_gpio_mute - mute/unmute amp using GPIO */
		auto_gpio_mute = of_property_read_bool(pdev->dev.of_node,
						"applepi-dac,auto-mute-amp");

		if (auto_gpio_mute || gpio_unmute) {
			mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
							    GPIOD_OUT_LOW);
			if (IS_ERR(mute_gpio)) {
				ret = PTR_ERR(mute_gpio);
				dev_err(&pdev->dev,
					"Failed to get mute gpio: %d\n", ret);
				return ret;
			}

			if (auto_gpio_mute && mute_gpio)
				snd_applepi_dac.set_bias_level =
						snd_applepi_dac_set_bias_level;
		}
	}
		
	ret = snd_soc_register_card(&snd_applepi_dac);
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev,
				"snd_soc_register_card() failed: %d\n", ret);
		return ret;
	}
	
	if (gpio_unmute && mute_gpio)
		snd_applepi_gpio_unmute(&snd_applepi_dac);

	return 0;
}

static int snd_applepi_dac_remove(struct platform_device *pdev)
{
	snd_applepi_gpio_mute(&snd_applepi_dac);
	
	return snd_soc_unregister_card(&snd_applepi_dac);
}

static const struct of_device_id snd_applepi_dac_of_match[] = {
	{ .compatible = "applepi,applepi-dac", },
	{},
};
MODULE_DEVICE_TABLE(of, snd_applepi_dac_of_match);

static struct platform_driver snd_applepi_dac_driver = {
        .driver = {
                .name   = "snd-applepi-dac",
                .owner  = THIS_MODULE,
                .of_match_table = snd_applepi_dac_of_match,
        },
        .probe          = snd_applepi_dac_probe,
        .remove         = snd_applepi_dac_remove,
};

module_platform_driver(snd_applepi_dac_driver);

How do I test the driver to make sure that it works before going any further?

Also I will need to modify my overlay to work with this driver correct? How do I do that?
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Thu Dec 07, 2017 5:51 pm

1. Copy rpi-dac-overlay.dts (https://github.com/raspberrypi/linux/bl ... verlay.dts) then change the compatible string to be yours ("applepi,applepi-dac"). Also graft in the mute-gpios declaration from the iqaudio-dacplus overlay (https://github.com/raspberrypi/linux/bl ... verlay.dts); you can choose your own pin.

2. Add your overlay to the Makefile in the overlays directory. Eventually you'll need a README entry for it, but skip that for now.

3. Next you'll need to build the module, if you haven't already done so. The best way is to build your own kernel (https://www.raspberrypi.org/documentati ... uilding.md), having first changed the Makefile as mentioned earlier - use the RPI_DAC config symbol for now. It will be slow the first time, but you'll have to do it eventually and it will save you having to invent workarounds.

4. You should now have a fresh kernel, including a kernel module for your soundcard and an overlay, on an SD card. Boot it. If it starts up OK, add "dtoverlay=applepi-dac" (or whatever you've called your overlay) to config.txt and reboot.

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Thu Dec 07, 2017 6:24 pm

PhilE wrote:
Thu Dec 07, 2017 5:51 pm
1. Copy rpi-dac-overlay.dts (https://github.com/raspberrypi/linux/bl ... verlay.dts) then change the compatible string to be yours ("applepi,applepi-dac"). Also graft in the mute-gpios declaration from the iqaudio-dacplus overlay (https://github.com/raspberrypi/linux/bl ... verlay.dts); you can choose your own pin.

2. Add your overlay to the Makefile in the overlays directory. Eventually you'll need a README entry for it, but skip that for now.

3. Next you'll need to build the module, if you haven't already done so. The best way is to build your own kernel (https://www.raspberrypi.org/documentati ... uilding.md), having first changed the Makefile as mentioned earlier - use the RPI_DAC config symbol for now. It will be slow the first time, but you'll have to do it eventually and it will save you having to invent workarounds.

4. You should now have a fresh kernel, including a kernel module for your soundcard and an overlay, on an SD card. Boot it. If it starts up OK, add "dtoverlay=applepi-dac" (or whatever you've called your overlay) to config.txt and reboot.
I understand #1.

2-4 are like reading a different language, I do not know what you are asking me to do.

In general I am a pretty technical person and I have gotten by with copying or duplicating somebody else's work but that does not mean that I understand everything behind what I am actually doing.

Also keep in mind that I have never used linux before this.
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Thu Dec 07, 2017 7:01 pm

Is there really no easier way to get around this somehow?

All I need is I2S and mute pin, can the iqaudio-dacplus overlay be modified to provide this functionality? I do not specifically need the 1794A codec, all of the I2S codecs are all the same anyway?

The interesting thing is that I have tried to compile iqaudio-dacplus-overlay.dts with the following command:

Code: Select all

dtc -@ -H epapr -O dtb -o Test_Overlay.dtbo -Wno-unit_address_vs_reg iqaudio-dacplus-overlay.dts
and it does not work. I get error messages.

So is there something wrong with the iqaudio dac plus overlay to begin with?

I have also tried to load the overlay using the dtoverlay command and using the config file and in both cases the aplay -l command shows that there is no sound card.

Maybe something like this?

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2708";

    fragment@0 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            simple-audio-card,name = "I2S_DAC";

            status="okay";

            playback_link: simple-audio-card,dai-link@1 {
                format = "i2s";

                p_cpu_dai: cpu {
                    sound-dai = <&i2s>;
                    dai-tdm-slot-num = <2>;
                    dai-tdm-slot-width = <32>;
                };
            };
        };
    };

    fragment@1 {
        target-path = "/";
		iqaudio_dac: __overlay__ {
			compatible = "iqaudio,iqaudio-dac";
			i2s-controller = <&i2s>;
			mute-gpios = <&gpio 22 0>;
			status = "okay";
		};
	};

    fragment@2 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };
	
	__overrides__ {
		24db_digital_gain = <&iqaudio_dac>,"iqaudio,24db_digital_gain?";
		auto_mute_amp = <&iqaudio_dac>,"iqaudio-dac,auto-mute-amp?";
		unmute_amp = <&iqaudio_dac>,"iqaudio-dac,unmute-amp?";
	};
};

/* compile with:
   dtc -@ -H epapr -O dtb -o dual.dtbo -Wno-unit_address_vs_reg dual.dts
*/
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Thu Dec 07, 2017 9:20 pm

There are so many examples now it is possible to largely create a new soundcard driver by analogy without necessarily understanding every line.

Steps 2 and 3 amount to:

Code: Select all

git clone https://github.com/raspberrypi/linux.git
cd linux
git grep -i -E "RPI[-_]DAC"
Open every file with a match and either copy the whole file or make a copy of the matching lines and replace rpi_dac with applepi-dac etc.

Then follow the instructions for building the kernel.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Thu Dec 07, 2017 10:08 pm

Your question about using an existing driver/overlay even if for a different codec is a good one, but it would only work if both the codec you are using and the one for which the driver was intended didn't have an I2C control interface. This is true for the rpi-dac, but both the iqaudio-dac and -dacplus overlays are for I2C codecs.

If you can find an existing soundcard with mute functionality that uses a passive, non-I2C codec then we could use that, but a brief search makes me think there isn't one.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Fri Dec 08, 2017 10:56 am

I tried compiling iqaudio-dacplus overlay using your command line and there were no errors and no warnings - it just worked.

Which version of dtc are you using (dtc -v)? Newer versions are adding more and more warnings, but they should still generate the same output.

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Fri Dec 08, 2017 7:13 pm

PhilE wrote:
Fri Dec 08, 2017 10:56 am
I tried compiling iqaudio-dacplus overlay using your command line and there were no errors and no warnings - it just worked.

Which version of dtc are you using (dtc -v)? Newer versions are adding more and more warnings, but they should still generate the same output.
The interesting thing is if you create the DTS file with a GUI text editor the compile fails but if you create it with an editor like nano it works.
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

orchardaudio
Posts: 37
Joined: Wed Feb 03, 2016 11:19 pm
Contact: Website Facebook Twitter

Re: Mute GPIO

Fri Dec 08, 2017 7:15 pm

PhilE wrote:
Thu Dec 07, 2017 10:08 pm
Your question about using an existing driver/overlay even if for a different codec is a good one, but it would only work if both the codec you are using and the one for which the driver was intended didn't have an I2C control interface. This is true for the rpi-dac, but both the iqaudio-dac and -dacplus overlays are for I2C codecs.

If you can find an existing soundcard with mute functionality that uses a passive, non-I2C codec then we could use that, but a brief search makes me think there isn't one.
Yep I looked and the only sound cards with mute functions are ones with I2C.

I was thinking about a different approach all together though? Can a driver be written for just the mute pin functionality? Then in the overlay link to both drivers? Instead of having a single driver that does mute and I2S?
~~Orchard Audio~~
How do you like them apples?
www.orchardaudio.com
www.facebook.com/orchardaudio

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 1419
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Mute GPIO

Fri Dec 08, 2017 8:59 pm

In order to be useful, the mute pin driver would have to hook into ALSA and be called at appropriate times. ALSA understands three roles (excluding mixers and other exotic features) - the CPU Digital Audio Interface (DAI), the codec and the soundcard that connects the two. The mute pin driver as a standalone function doesn't fit into this model, so you need to customise one of the existing three drivers.

Codecs are standard components, and their drivers are supposed to work for all uses of the codec IC. In other words, they must be application agnostic. All application-specific logic should go in the soundcard driver, which is what we were doing. If you feel you can't manage to finish the task then you should engage the services of a software engineer, but hold on a bit longer - I'd say you were at least half way there.

Return to “Device Tree”

Who is online

Users browsing this forum: No registered users and 1 guest