ALSA driver configuration external HP MIC SPK

Posted by goldberg on Mon, 06 Apr 2020 08:38:43 +0200

Overall program structure

Take sound/soc/pxa/corgi.c as an example

  • To describe the sound card, define the snd SOC card instance and fill in the Dai link member.
  • In order to control the opening and closing of SPK, HP and MIC in the upper layer of ALSA, kcontrol instances are defined.
  • To enable ALSA to automatically control the power consumption of SPK, HP and mic, define widget and route instances.
  • In snd SOC card Dai link init, register the kcontrol, widget and route instances declared above.

Take the kcontrol, widget and route of SPK as an example to analyze the definitions of three data structures

The implementation of kcontrol

Define the kcontrol array, which provides the up parameter and the down actual control function.

  • The up parameter is used by the upper amixer program to set the control to different functions.
  • The down actual control function is used by the underlying driver to control the switch of HP MIC SPK.
static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", "Off"};
static const char *spk_function[] = {"On", "Off"};
static const struct soc_enum corgi_enum[] = {
    SOC_ENUM_SINGLE_EXT(5, jack_function),//Control parameters 1-4
    SOC_ENUM_SINGLE_EXT(2, spk_function),//Control parameter 0-1
};
static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
    SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
        corgi_set_jack),//get,set read and set hardware working modes respectively
    SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
        corgi_set_spk),
};

get, implementation of set function

static int corgi_get_spk(struct snd_kcontrol *kcontrol,
    struct snd_ctl_elem_value *ucontrol)
{
    ucontrol->value.integer.value[0] = corgi_spk_func;  //A global variable of 0-1 means ON OFF
    return 0;
}

static int corgi_set_spk(struct snd_kcontrol *kcontrol,
    struct snd_ctl_elem_value *ucontrol)
{
    struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);

    if (corgi_spk_func == ucontrol->value.integer.value[0])
        return 0;

    corgi_spk_func = ucontrol->value.integer.value[0];//Save the parameters set in the upper layer
    corgi_ext_control(codec);//Set SPK to ON OFF mode
    return 1;
}
//The implementation of Corgi ext control function
static void corgi_ext_control(struct snd_soc_codec *codec)
{
    if (corgi_spk_func == CORGI_SPK_ON)
        snd_soc_dapm_enable_pin(dapm, "Ext Spk");  
        //Turn on the power through the enable widget. The implementation of the widget is described later
    else
        snd_soc_dapm_disable_pin(dapm, "Ext Spk");//Turn off the power through the disable widget

    /* signal a DAPM event */
    snd_soc_dapm_sync(dapm);
}

In snd SOC card > Dai link > init, register control through snd SOC add controls.

Implementation of widget

//Define widget
/* corgi machine dapm widgets */
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),//Define widget name and set power control interface
};
//Implementation of power control interface
static int corgi_amp_event(struct snd_soc_dapm_widget *w,
    struct snd_kcontrol *k, int event)
{
    //Preamplifier via GPIO switch SPK
    gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
    return 0;
}

In snd SOC card > Dai link > init, register the widget through snd SOC DAPM new controls.

The implementation of route

//Define route
/* Corgi machine audio map (connections to the codec pins) */
static const struct snd_soc_dapm_route audio_map[] = {
    /* speaker connected to LOUT, ROUT */
    {"Ext Spk", NULL, "ROUT"},//Set the ROUT and Laut of SPK direct connection codec
    {"Ext Spk", NULL, "LOUT"},
};

In snd SOC card > Dai link > init, register route through snd SOC DAPM add routes.

From the datesheet, you can see that ROUT and LOUT are used to plug in SPK.

From the codec driver, you can see the widget definitions of route and route.

static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("LOUT"),
SND_SOC_DAPM_OUTPUT("LHPOUT"),
SND_SOC_DAPM_OUTPUT("ROUT"),
};

Add machine driver, codec driver and manual to the link:
http://download.csdn.net/download/a903265446/10235150
For general product development, codec driver and platform driver are provided by chip manufacturers, and only machine driver needs to be developed.

This article is published by the headline "embedded FM106 point 1", all kinds of original technology dry goods, welcome to pay attention.

Topics: codec