blob: eb8fd85b7760c11b5d2f25f24a477bc0378d2eff [file] [log] [blame]
/*
* card-omap-common-4-5.h
*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __AUDIO_TOOL_CARD_OMAP_COMMON_4_5_H__
#define __AUDIO_TOOL_CARD_OMAP_COMMON_4_5_H__
#else
#error This file should be treated as code and not as a header.
#endif
/*
* Code common between cards SDP4430 and OMAP45
*
* When matching ABE versions, the ABE FW version is attached.
*
* Symbols are not versioned until versioning is required.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <tinyalsa/asoundlib.h>
#include "module.h"
#include "alsa-control.h"
#include "mixer_cache.h"
static struct audio_tool_mixer_control_info g_defaults_common[] = {
{
.id = -1,
.name = "DL1 Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Flat response",
"",
"",
"",
},
},
{
.id = -1,
.name = "DL2 Left Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"High-pass 0dB",
"",
"",
"",
},
},
{
.id = -1,
.name = "DL2 Right Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"High-pass 0dB",
"",
"",
"",
},
},
{
.id = -1,
.name = "Sidetone Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Flat response",
"",
"",
"",
},
},
{
.id = -1,
.name = "AMIC Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"High-pass 0dB",
"",
"",
"",
},
},
{
.id = -1,
.name = "DMIC Equalizer",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"High-pass 0dB",
"",
"",
"",
},
},
{
.id = -1,
.name = "DL1 Media Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
118,
},
},
{
.id = -1,
.name = "DL1 Tones Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 Voice Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
120,
},
},
{
.id = -1,
.name = "DL1 Capture Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "VXREC Media Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "VXREC Tones Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "VXREC Voice DL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "VXREC Voice UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "AUDUL Media Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "AUDUL Tones Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "AUDUL Voice UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
120,
},
},
{
.id = -1,
.name = "AUDUL Voice DL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "SDT UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
101,
},
},
{
.id = -1,
.name = "SDT DL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
120,
},
},
{
.id = -1,
.name = "DMIC1 UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
120,
120,
},
},
{
.id = -1,
.name = "DMIC2 UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
120,
120,
},
},
{
.id = -1,
.name = "DMIC3 UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
120,
120,
},
},
{
.id = -1,
.name = "AMIC UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
120,
120,
},
},
{
.id = -1,
.name = "BT UL Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
120,
120,
},
},
{
.id = -1,
.name = "DL1 Mono Mixer",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "AUDUL Mono Mixer",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 MM_EXT Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 BT_VX Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 PDM Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Sidetone Mixer Capture",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Sidetone Mixer Playback",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
1,
},
},
{
.id = -1,
.name = "Capture Mixer Tones",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Capture Mixer Voice Playback",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Capture Mixer Voice Capture",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Capture Mixer Media Playback",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Voice Capture Mixer Tones Playback",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Voice Capture Mixer Media Playback",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Voice Capture Mixer Capture",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 Mixer Tones",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 Mixer Voice",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 Mixer Capture",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL1 Mixer Multimedia",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "MUX_VX1",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_VX0",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL11",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL10",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL07",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL06",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL05",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL04",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL03",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL02",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL01",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "MUX_UL00",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"None",
"",
"",
"",
},
},
{
.id = -1,
.name = "Capture Preamplifier Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
1,
1,
},
},
{
.id = -1,
.name = "Capture Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
4,
4,
},
},
{
.id = -1,
.name = "Aux FM Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
3,
3,
},
},
{
.id = -1,
.name = "Headset Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
15,
15,
},
},
{
.id = -1,
.name = "Handsfree Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 2,
.value.integer = {
26,
26,
},
},
{
.id = -1,
.name = "Earphone Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
14,
},
},
{
.id = -1,
.name = "Headset Power Mode",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Low-Power",
"",
"",
"",
},
},
{
.id = -1,
.name = "Earphone Playback Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Headset Right Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Off",
"",
"",
"",
},
},
{
.id = -1,
.name = "Headset Left Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Off",
"",
"",
"",
},
},
{
.id = -1,
.name = "Handsfree Right Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"HF DAC",
"",
"",
"",
},
},
{
.id = -1,
.name = "Handsfree Left Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"HF DAC",
"",
"",
"",
},
},
{
.id = -1,
.name = "Analog Right Capture Route",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Off",
"",
"",
"",
},
},
{
.id = -1,
.name = "Analog Left Capture Route",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Off",
"",
"",
"",
},
},
{
.id = -1,
.name = "TWL6040 Power Mode",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Low-Power",
"",
"",
"",
},
},
};
/* The AUX switch hasn't really been associated to an ABE FW version,
* so we check for it specifically.
*/
static struct audio_tool_mixer_control_info g_defaults_aux_switch[] = {
{
.id = -1,
.name = "Aux Left Playback Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Aux Right Playback Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
};
static struct audio_tool_mixer_control_info g_defaults_0951[] = {
{
.id = -1,
.name = "DL2 Media Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
118,
},
},
{
.id = -1,
.name = "DL2 Tones Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Voice Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
120,
},
},
{
.id = -1,
.name = "DL2 Capture Playback Volume",
.type = MIXER_CTL_TYPE_INT,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Mono Mixer",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Mixer Tones",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Mixer Voice",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Mixer Capture",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "DL2 Mixer Multimedia",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
1,
},
},
};
static struct audio_tool_mixer_control_info g_defaults_0956[] = {
{
.id = -1,
.name = "DL1 PDM_DL2 Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
1,
},
},
{
.id = -1,
.name = "PLL Selection",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Low-Power",
"",
"",
"",
},
},
{
.id = -1,
.name = "AUXR Playback Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "AUXL Playback Switch",
.type = MIXER_CTL_TYPE_BOOL,
.num_values = 1,
.value.integer = {
0,
},
},
{
.id = -1,
.name = "Vibra Right Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Input FF",
"",
"",
"",
},
},
{
.id = -1,
.name = "Vibra Left Playback",
.type = MIXER_CTL_TYPE_ENUM,
.num_values = 1,
.value.enumerated = {
"Input FF",
"",
"",
"",
},
},
};
#define ABE_API_NULL 0L
#define ABE_API_0951 951L
#define ABE_API_0956 956L
static int g_abe_api = ABE_API_NULL;
static struct audio_tool_mixer_cache g_card_mix_defaults = {
.count = 0,
.ctrls = 0,
};
static char* g_playback_frontends[] = {
"Multimedia",
"Voice",
"Tones",
"MultimediaLP",
0,
};
static char* g_playback_backends[] = {
"Headset",
"Handsfree",
"Earpiece",
"Bluetooth",
0,
};
static char *g_capture_frontends[] = {
"Multimedia",
"Multimedia2",
"Voice",
0,
};
static char *g_capture_backends[] = {
"HeadsetMic",
"OnboardMic",
"Aux/FM",
"DMic0",
"DMic1",
"DMic2",
"Bluetooth",
"Echo",
"VoiceRec",
0,
};
struct route_setting
{
char *ctl_name;
int intval;
char *strval;
};
#define RS_INT(str, val) { .ctl_name = str, .intval = val }
#define RS_ENUM(str, val) { .ctl_name = str, .strval = val }
#define RS_NULL { 0, 0, 0, }
/***************************************************************************
* PLAYBACK ROUTE SETTINGS
***************************************************************************
*/
/* For Frontend := { Multimedia, MultimediaLP }
* For Backend := { Headset, Earpiece, Bluetooth }
*/
static struct route_setting g_playback_multimedia_accessory_mix[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Multimedia", 1),
RS_INT("DL1 Media Playback Volume", 118),
RS_NULL,
};
/* For Frontend := { Multimedia, MultimediaLP }
* For Backend := { Handsfree }
*/
static struct route_setting *g_playback_multimedia_handsfree_mix = 0;
static struct route_setting g_playback_multimedia_handsfree_mix_0951[] = {
RS_INT("DL2 Mixer Multimedia", 1),
RS_INT("DL2 Media Playback Volume", 118),
RS_NULL,
};
static struct route_setting g_playback_multimedia_handsfree_mix_0956[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Multimedia", 1),
RS_INT("DL1 Media Playback Volume", 118),
RS_NULL,
};
/* For Frontend := { Voice }
* For Backend := { Headset, Earpiece, Bluetooth }
*/
static struct route_setting g_playback_voice_accessory_mix[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Voice", 1),
RS_INT("DL1 Voice Playback Volume", 118),
RS_NULL,
};
/* For Frontend := { Voice }
* For Backend := { Handsfree }
*/
static struct route_setting *g_playback_voice_handsfree_mix = 0;
static struct route_setting g_playback_voice_handsfree_mix_0951[] = {
RS_INT("DL2 Mixer Voice", 1),
RS_INT("DL2 Voice Playback Volume", 118),
RS_NULL,
};
static struct route_setting g_playback_voice_handsfree_mix_0956[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Voice", 1),
RS_INT("DL1 Voice Playback Volume", 118),
RS_NULL,
};
/* For Frontend := { Tones }
* For Backend := { Headset, Earpiece, Bluetooth }
*/
static struct route_setting g_playback_tones_accessory_mix[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Tones", 1),
RS_INT("DL1 Tones Playback Volume", 118),
RS_NULL,
};
/* For Frontend := { Tones }
* For Backend := { Handsfree }
*/
static struct route_setting *g_playback_tones_handsfree_mix = 0;
static struct route_setting g_playback_tones_handsfree_mix_0951[] = {
RS_INT("DL2 Mixer Tones", 1),
RS_INT("DL2 Tones Playback Volume", 118),
RS_NULL,
};
static struct route_setting g_playback_tones_handsfree_mix_0956[] = {
RS_INT("Sidetone Mixer Playback", 1),
RS_INT("SDT DL Volume", 120),
RS_INT("DL1 Mixer Tones", 1),
RS_INT("DL1 Tones Playback Volume", 118),
RS_NULL,
};
static struct route_setting g_playback_be_headset_mix[] = {
RS_INT("DL1 PDM Switch", 1),
RS_ENUM("Headset Left Playback", "HS DAC"),
RS_ENUM("Headset Right Playback", "HS DAC"),
RS_INT("Headset Playback Volume", 13),
RS_NULL,
};
static struct route_setting *g_playback_be_earpiece_mix = 0;
static struct route_setting g_playback_be_earpiece_mix_0951[] = {
RS_INT("DL1 PDM Switch", 1),
RS_INT("Earphone Playback Switch", 1),
RS_INT("Earphone Playback Volume", 13),
RS_NULL,
};
static struct route_setting g_playback_be_earpiece_mix_0956[] = {
RS_INT("DL1 PDM Switch", 1),
RS_INT("Earphone Playback Switch", 1),
RS_INT("Earphone Playback Volume", 13),
RS_NULL,
};
static struct route_setting g_playback_be_bluetooth_mix[] = {
RS_INT("DL1 BT_VX Switch", 1),
RS_INT("BT UL Volume", 120),
RS_NULL,
};
static struct route_setting *g_playback_be_handsfree_mix = 0;
static struct route_setting g_playback_be_handsfree_mix_0951[] = {
RS_ENUM("Handsfree Left Playback", "HF DAC"),
RS_ENUM("Handsfree Right Playback", "HF DAC"),
RS_INT("Handsfree Playback Volume", 23),
RS_NULL,
};
static struct route_setting g_playback_be_handsfree_mix_0956[] = {
RS_INT("DL1 PDM_DL2 Switch", 1),
RS_ENUM("Handsfree Left Playback", "HF DAC"),
RS_ENUM("Handsfree Right Playback", "HF DAC"),
RS_INT("Handsfree Playback Volume", 23),
RS_NULL,
};
/***************************************************************************
* CAPTURE ROUTE SETTINGS
***************************************************************************
*/
static struct route_setting g_capture_multimedia_amic_mix[] = {
RS_ENUM("MUX_UL00", "AMic0"),
RS_ENUM("MUX_UL01", "AMic1"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_dmic0_mix[] = {
RS_ENUM("MUX_UL00", "DMic0L"),
RS_ENUM("MUX_UL01", "DMic0R"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_dmic1_mix[] = {
RS_ENUM("MUX_UL00", "DMic1L"),
RS_ENUM("MUX_UL01", "DMic1R"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_dmic2_mix[] = {
RS_ENUM("MUX_UL00", "DMic2L"),
RS_ENUM("MUX_UL01", "DMic2R"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_bluetooth_mix[] = {
RS_ENUM("MUX_UL00", "BT Left"),
RS_ENUM("MUX_UL01", "BT Right"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_echo_mix[] = {
RS_ENUM("MUX_UL00", "Echo Left"),
RS_ENUM("MUX_UL01", "Echo Right"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia_vxrec_mix[] = {
RS_ENUM("MUX_UL00", "VX Left"),
RS_ENUM("MUX_UL01", "VX Right"),
RS_ENUM("MUX_UL02", "None"),
RS_ENUM("MUX_UL03", "None"),
RS_ENUM("MUX_UL04", "None"),
RS_ENUM("MUX_UL05", "None"),
RS_ENUM("MUX_UL06", "None"),
RS_ENUM("MUX_UL07", "None"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_amic_mix[] = {
RS_ENUM("MUX_UL10", "AMic0"),
RS_ENUM("MUX_UL11", "AMic1"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_dmic0_mix[] = {
RS_ENUM("MUX_UL10", "DMic0L"),
RS_ENUM("MUX_UL11", "DMic0R"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_dmic1_mix[] = {
RS_ENUM("MUX_UL10", "DMic1L"),
RS_ENUM("MUX_UL11", "DMic1R"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_dmic2_mix[] = {
RS_ENUM("MUX_UL10", "DMic2L"),
RS_ENUM("MUX_UL11", "DMic2R"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_bluetooth_mix[] = {
RS_ENUM("MUX_UL10", "BT Left"),
RS_ENUM("MUX_UL11", "BT Right"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_echo_mix[] = {
RS_ENUM("MUX_UL10", "Echo Left"),
RS_ENUM("MUX_UL11", "Echo Right"),
RS_NULL,
};
static struct route_setting g_capture_multimedia2_vxrec_mix[] = {
RS_ENUM("MUX_UL10", "VX Left"),
RS_ENUM("MUX_UL11", "VX Right"),
RS_NULL,
};
static struct route_setting g_capture_voice_amic_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "AMic0"),
RS_ENUM("MUX_VX1", "AMic1"),
RS_NULL,
};
static struct route_setting g_capture_voice_dmic0_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "DMic0L"),
RS_ENUM("MUX_VX1", "DMic0R"),
RS_NULL,
};
static struct route_setting g_capture_voice_dmic1_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "DMic1L"),
RS_ENUM("MUX_VX1", "DMic1R"),
RS_NULL,
};
static struct route_setting g_capture_voice_dmic2_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "DMic2L"),
RS_ENUM("MUX_VX1", "DMic2R"),
RS_NULL,
};
static struct route_setting g_capture_voice_bluetooth_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "BT Left"),
RS_ENUM("MUX_VX1", "BT Right"),
RS_NULL,
};
static struct route_setting g_capture_voice_echo_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "Echo Left"),
RS_ENUM("MUX_VX1", "Echo Right"),
RS_NULL,
};
static struct route_setting g_capture_voice_vxrec_mix[] = {
RS_INT("Voice Capture Mixer Capture", 1),
RS_ENUM("MUX_VX0", "VX Left"),
RS_ENUM("MUX_VX1", "VX Right"),
RS_NULL,
};
static struct route_setting g_capture_be_headsetmic_mix[] = {
RS_INT("AMIC UL Volume", 120),
RS_ENUM("Analog Left Capture Route", "Headset Mic"),
RS_ENUM("Analog Right Capture Route", "Headset Mic"),
RS_INT("Capture Preamplifier Volume", 1),
RS_INT("Capture Volume", 4),
RS_NULL,
};
static struct route_setting g_capture_be_onboardmic_mix[] = {
RS_INT("AMIC UL Volume", 120),
RS_ENUM("Analog Left Capture Route", "Main Mic"),
RS_ENUM("Analog Right Capture Route", "Sub Mic"),
RS_INT("Capture Preamplifier Volume", 1),
RS_INT("Capture Volume", 4),
RS_NULL,
};
static struct route_setting g_capture_be_auxfm_mix[] = {
RS_INT("AMIC UL Volume", 120),
RS_ENUM("Analog Left Capture Route", "Aux/FM Left"),
RS_ENUM("Analog Right Capture Route", "Aux/FM Right"),
RS_INT("Capture Preamplifier Volume", 1),
RS_INT("Capture Volume", 4),
RS_NULL,
};
static struct route_setting g_capture_be_dmic0_mix[] = {
RS_INT("DMIC1 UL Volume", 140),
RS_NULL,
};
static struct route_setting g_capture_be_dmic1_mix[] = {
RS_INT("DMIC2 UL Volume", 140),
RS_NULL,
};
static struct route_setting g_capture_be_dmic2_mix[] = {
RS_INT("DMIC3 UL Volume", 140),
RS_NULL,
};
static struct route_setting g_capture_be_bluetooth_mix[] = {
RS_INT("BT UL Volume", 120),
RS_INT("DL1 BT_VX Switch", 1),
RS_NULL,
};
static struct route_setting g_capture_be_echo_mix[] = {
RS_INT("Echo Mixer DL1", 1),
RS_INT("Echo Mixer DL2", 1),
RS_INT("Echo DL1 Volume", 120),
RS_INT("Echo DL2 Volume", 120),
RS_NULL,
};
static struct route_setting g_capture_be_vxrec_mix[] = {
RS_INT("Capture Mixer Tones", 1),
RS_INT("Capture Mixer Voice Playback", 1),
RS_INT("Capture Mixer Voice Capture", 1),
RS_INT("Capture Mixer Media Playback", 1),
RS_INT("VXREC Media Volume", 120),
RS_INT("VXREC Tones Volume", 120),
RS_INT("VXREC Voice DL Volume", 120),
RS_INT("VXREC Voice UL Volume", 120),
RS_NULL,
};
/* side effects: initializes g_abe_api and g_card_mix_defaults */
static int detect_abe_api(struct audio_tool_mixer_cache *cache)
{
int abe_api = ABE_API_0951;
int has_aux_switch = 0;
int count = 0;
int n;
/* Detect if using 09.56 API */
for (n = 0 ; n < cache->count ; ++n) {
if (0 == strcmp("DL1 PDM_DL2 Switch", cache->ctrls[n].name)) {
abe_api = ABE_API_0956;
break;
}
}
/* Detect if have aux switch */
for (n = 0 ; n < cache->count ; ++n) {
if (0 == strcmp("Aux Left Playback Switch", cache->ctrls[n].name)) {
has_aux_switch = 1;
break;
}
}
count = sizeof(g_defaults_common) / sizeof(g_defaults_common[0]);
if (has_aux_switch) {
count += sizeof(g_defaults_aux_switch) / sizeof(g_defaults_aux_switch[0]);
}
switch (abe_api) {
case ABE_API_0951:
count += sizeof(g_defaults_0951) / sizeof(g_defaults_0951[0]);
break;
case ABE_API_0956:
count += sizeof(g_defaults_0956) / sizeof(g_defaults_0956[0]);
break;
default:
assert(0);
}
g_card_mix_defaults.ctrls = calloc(count, sizeof(struct audio_tool_mixer_control_info));
memcpy(g_card_mix_defaults.ctrls, &g_defaults_common, sizeof(g_defaults_common));
n = sizeof(g_defaults_common) / sizeof(g_defaults_common[0]);
if (has_aux_switch) {
memcpy(g_card_mix_defaults.ctrls + n, &g_defaults_aux_switch,
sizeof(g_defaults_aux_switch));
n += sizeof(g_defaults_aux_switch) / sizeof(g_defaults_aux_switch[0]);
}
switch (abe_api) {
case ABE_API_0951:
memcpy(g_card_mix_defaults.ctrls + n, &g_defaults_0951, sizeof(g_defaults_0951));
break;
case ABE_API_0956:
memcpy(g_card_mix_defaults.ctrls + n, &g_defaults_0956, sizeof(g_defaults_0956));
break;
default:
assert(0);
}
g_card_mix_defaults.count = count;
g_abe_api = abe_api;
/* initialize static id's */
for (n = 0 ; n < g_card_mix_defaults.count ; ++n) {
g_card_mix_defaults.ctrls[n].id = n;
}
/* Set up the routes */
switch (abe_api) {
case ABE_API_0951:
g_playback_multimedia_handsfree_mix = g_playback_multimedia_handsfree_mix_0951;
g_playback_voice_handsfree_mix = g_playback_voice_handsfree_mix_0951;
g_playback_tones_handsfree_mix = g_playback_tones_handsfree_mix_0951;
g_playback_be_earpiece_mix = g_playback_be_earpiece_mix_0951;
g_playback_be_handsfree_mix = g_playback_be_handsfree_mix_0951;
break;
case ABE_API_0956:
g_playback_multimedia_handsfree_mix = g_playback_multimedia_handsfree_mix_0956;
g_playback_voice_handsfree_mix = g_playback_voice_handsfree_mix_0956;
g_playback_tones_handsfree_mix = g_playback_tones_handsfree_mix_0956;
g_playback_be_earpiece_mix = g_playback_be_earpiece_mix_0956;
g_playback_be_handsfree_mix = g_playback_be_handsfree_mix_0956;
break;
default:
assert(0);
}
return 0;
}
static int get_mixer_defaults(struct audio_tool_mixer_cache *cache)
{
struct audio_tool_mixer_cache *defs = &g_card_mix_defaults;
int m, n;
int ret = 0;
if (g_abe_api == ABE_API_NULL)
detect_abe_api(cache);
mixer_cache_reset_touch(defs);
mixer_cache_reset_touch(cache);
for (m = 0 ; m < cache->count ; ++m) {
n = mixer_cache_get_id_by_name(defs,
cache->ctrls[m].name);
if (n < 0) {
fprintf(stderr, "Warning: No default defined for %s\n", cache->ctrls[m].name);
ret = 1;
continue;
}
if (cache->ctrls[m].type != defs->ctrls[n].type) {
fprintf(stderr, "Warning: type mismatch on %s\n", cache->ctrls[m].name);
ret = 1;
continue;
}
memcpy(&cache->ctrls[m].value, &defs->ctrls[n].value,
sizeof(g_defaults_common[0].value));
mixer_cache_touch(cache, m);
mixer_cache_touch(defs, n);
}
ret = mixer_cache_audit_touch(cache, 1) ? 1 : ret;
ret = mixer_cache_audit_touch(defs, 1) ? 1 : ret;
return ret;
}
static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
int enable)
{
struct mixer_ctl *ctl;
unsigned int i, j;
/* Go through the route array and set each value */
i = 0;
while (route[i].ctl_name) {
ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
if (!ctl)
return -EINVAL;
if (route[i].strval) {
if (enable)
mixer_ctl_set_enum_by_string(ctl, route[i].strval);
else
mixer_ctl_set_enum_by_string(ctl, "Off");
} else {
/* This ensures multiple (i.e. stereo) values are set jointly */
for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
if (enable)
mixer_ctl_set_value(ctl, j, route[i].intval);
else
mixer_ctl_set_value(ctl, j, 0);
}
}
i++;
}
return 0;
}
static int get_fe_be_names(int direction, char ***fes, char ***bes)
{
if (direction == AUDIO_DIRECTION_PLAYBACK) {
*fes = g_playback_frontends;
*bes = g_playback_backends;
} else {
assert(direction == AUDIO_DIRECTION_CAPTURE);
*fes = g_capture_frontends;
*bes = g_capture_backends;
}
return 0;
}
#define FE_P_MM 0
#define FE_P_VX 1
#define FE_P_TONES 2
#define FE_P_MMLP 3
#define FE_C_MM 0
#define FE_C_MM2 1
#define FE_C_VX 2
#define BE_P_HS 0
#define BE_P_HF 1
#define BE_P_EP 3
#define BE_P_BT 4
#define BE_C_HSMIC 0
#define BE_C_OBMIC 1
#define BE_C_AUXFM 2
#define BE_C_DMIC0 3
#define BE_C_DMIC1 4
#define BE_C_DMIC2 5
#define BE_C_BT 6
#define BE_C_ECHO 7
#define BE_C_VXREC 8
static int config_playback(struct mixer *mixer, const char* fe,
const char* be, int enable, int *optional_port)
{
int f, b;
int ret = 0;
int port;
if (0 == strcmp(fe, "Multimedia")) {
f = FE_P_MM;
port = 0;
} else if (0 == strcmp(fe, "Voice")) {
f = FE_P_VX;
port = 2;
} else if (0 == strcmp(fe, "Tones")) {
f = FE_P_TONES;
port = 3;
} else if (0 == strcmp(fe, "MultimediaLP")) {
f = FE_P_MMLP;
port = 6;
} else {
return EINVAL;
}
if (optional_port)
*optional_port = port;
if (0 == strcmp(be, "Headset")) {
b = BE_P_HS;
} else if (0 == strcmp(be, "Handsfree")) {
b = BE_P_HF;
} else if (0 == strcmp(be, "Earpiece")) {
b = BE_P_EP;
} else if (0 == strcmp(be, "Bluetooth")) {
b = BE_P_BT;
} else {
return EINVAL;
}
switch (f) {
case FE_P_MM:
case FE_P_MMLP:
if (b == BE_P_HF) {
ret = set_route_by_array(mixer,
g_playback_multimedia_handsfree_mix, enable);
} else {
ret = set_route_by_array(mixer,
g_playback_multimedia_accessory_mix, enable);
}
break;
case FE_P_VX:
if (b == BE_P_HF) {
ret = set_route_by_array(mixer,
g_playback_voice_handsfree_mix, enable);
} else {
ret = set_route_by_array(mixer,
g_playback_voice_accessory_mix, enable);
}
break;
case FE_P_TONES:
if (b == BE_P_HF) {
ret = set_route_by_array(mixer,
g_playback_tones_handsfree_mix, enable);
} else {
ret = set_route_by_array(mixer,
g_playback_tones_accessory_mix, enable);
}
break;
default:
assert(0);
}
if (ret)
return ret;
switch (b) {
case BE_P_HS:
ret = set_route_by_array(mixer,
g_playback_be_headset_mix, enable);
break;
case BE_P_HF:
ret = set_route_by_array(mixer,
g_playback_be_handsfree_mix, enable);
break;
case BE_P_EP:
ret = set_route_by_array(mixer,
g_playback_be_earpiece_mix, enable);
break;
case BE_P_BT:
ret = set_route_by_array(mixer,
g_playback_be_bluetooth_mix, enable);
break;
default:
assert(0);
}
return ret;
}
static int config_capture(struct mixer *mixer, const char* fe,
const char* be, int enable, int *optional_port)
{
int f, b;
int ret = 0;
int port;
if (0 == strcmp(fe, "Multimedia")) {
f = FE_C_MM;
port = 0;
} else if (0 == strcmp(fe, "Multimedia2")) {
f = FE_C_MM2;
port = 1;
} else if (0 == strcmp(fe, "Voice")) {
f = FE_C_VX;
port = 2;
} else {
return EINVAL;
}
if (optional_port)
*optional_port = port;
if (0 == strcmp(be, "HeadsetMic")) {
b = BE_C_HSMIC;
} else if (0 == strcmp(be, "OnboardMic")) {
b = BE_C_OBMIC;
} else if (0 == strcmp(be, "Aux/FM")) {
b = BE_C_AUXFM;
} else if (0 == strcmp(be, "DMic0")) {
b = BE_C_DMIC0;
} else if (0 == strcmp(be, "DMic1")) {
b = BE_C_DMIC1;
} else if (0 == strcmp(be, "DMic2")) {
b = BE_C_DMIC2;
} else if (0 == strcmp(be, "Bluetooth")) {
b = BE_C_BT;
} else if (0 == strcmp(be, "Echo")) {
b = BE_C_ECHO;
} else if (0 == strcmp(be, "VoiceRec")) {
b = BE_C_VXREC;
} else {
return EINVAL;
}
switch (f) {
case FE_C_MM:
switch (b) {
case BE_C_HSMIC:
case BE_C_OBMIC:
case BE_C_AUXFM:
ret = set_route_by_array(mixer,
g_capture_multimedia_amic_mix, enable);
break;
case BE_C_DMIC0:
ret = set_route_by_array(mixer,
g_capture_multimedia_dmic0_mix, enable);
break;
case BE_C_DMIC1:
ret = set_route_by_array(mixer,
g_capture_multimedia_dmic1_mix, enable);
break;
case BE_C_DMIC2:
ret = set_route_by_array(mixer,
g_capture_multimedia_dmic2_mix, enable);
break;
case BE_C_BT:
ret = set_route_by_array(mixer,
g_capture_multimedia_bluetooth_mix, enable);
break;
case BE_C_ECHO:
ret = set_route_by_array(mixer,
g_capture_multimedia_echo_mix, enable);
break;
case BE_C_VXREC:
ret = set_route_by_array(mixer,
g_capture_multimedia_vxrec_mix, enable);
break;
}
break;
case FE_C_MM2:
switch (b) {
case BE_C_HSMIC:
case BE_C_OBMIC:
case BE_C_AUXFM:
ret = set_route_by_array(mixer,
g_capture_multimedia2_amic_mix, enable);
break;
case BE_C_DMIC0:
ret = set_route_by_array(mixer,
g_capture_multimedia2_dmic0_mix, enable);
break;
case BE_C_DMIC1:
ret = set_route_by_array(mixer,
g_capture_multimedia2_dmic1_mix, enable);
break;
case BE_C_DMIC2:
ret = set_route_by_array(mixer,
g_capture_multimedia2_dmic2_mix, enable);
break;
case BE_C_BT:
ret = set_route_by_array(mixer,
g_capture_multimedia2_bluetooth_mix, enable);
break;
case BE_C_ECHO:
ret = set_route_by_array(mixer,
g_capture_multimedia2_echo_mix, enable);
break;
case BE_C_VXREC:
ret = set_route_by_array(mixer,
g_capture_multimedia2_vxrec_mix, enable);
break;
}
break;
case FE_C_VX:
switch (b) {
case BE_C_HSMIC:
case BE_C_OBMIC:
case BE_C_AUXFM:
ret = set_route_by_array(mixer,
g_capture_voice_amic_mix, enable);
break;
case BE_C_DMIC0:
ret = set_route_by_array(mixer,
g_capture_voice_dmic0_mix, enable);
break;
case BE_C_DMIC1:
ret = set_route_by_array(mixer,
g_capture_voice_dmic1_mix, enable);
break;
case BE_C_DMIC2:
ret = set_route_by_array(mixer,
g_capture_voice_dmic2_mix, enable);
break;
case BE_C_BT:
ret = set_route_by_array(mixer,
g_capture_voice_bluetooth_mix, enable);
break;
case BE_C_ECHO:
ret = set_route_by_array(mixer,
g_capture_voice_echo_mix, enable);
break;
case BE_C_VXREC:
ret = set_route_by_array(mixer,
g_capture_voice_vxrec_mix, enable);
break;
}
break;
default:
assert(0);
}
if (ret)
return ret;
switch (b) {
case BE_C_HSMIC:
ret = set_route_by_array(mixer,
g_capture_be_headsetmic_mix, enable);
break;
case BE_C_OBMIC:
ret = set_route_by_array(mixer,
g_capture_be_onboardmic_mix, enable);
break;
case BE_C_AUXFM:
ret = set_route_by_array(mixer,
g_capture_be_auxfm_mix, enable);
break;
case BE_C_DMIC0:
ret = set_route_by_array(mixer,
g_capture_be_dmic0_mix, enable);
break;
case BE_C_DMIC1:
ret = set_route_by_array(mixer,
g_capture_be_dmic1_mix, enable);
break;
case BE_C_DMIC2:
ret = set_route_by_array(mixer,
g_capture_be_dmic2_mix, enable);
break;
case BE_C_BT:
ret = set_route_by_array(mixer,
g_capture_be_bluetooth_mix, enable);
break;
case BE_C_ECHO:
ret = set_route_by_array(mixer,
g_capture_be_echo_mix, enable);
break;
case BE_C_VXREC:
ret = set_route_by_array(mixer,
g_capture_be_vxrec_mix, enable);
break;
default:
assert(0);
}
return ret;
}
static int config(struct mixer *mixer, int direction, const char* fe,
const char* be, int enable, int *optional_port)
{
if (g_abe_api == ABE_API_NULL) {
struct audio_tool_mixer_cache cache;
mixer_cache_init(&cache);
if(mixer_cache_populate(&cache, mixer)) {
fprintf(stderr, "Error: could not populate mixer cache for card\n");
return ENODEV;
}
if(detect_abe_api(&cache)) {
fprintf(stderr, "Error: could not detect ABE version\n");
return ENODEV;
}
mixer_cache_deinit(&cache);
}
if (direction == AUDIO_DIRECTION_PLAYBACK) {
return config_playback(mixer, fe, be, enable, optional_port);
} else {
return config_capture(mixer, fe, be, enable, optional_port);
}
}
/* NULL terminated list: */
static const char* supported_cards[] = {
"OMAP45",
"SDP4430",
"OMAP5",
"OMAP5EVM",
"Tablet44xx",
"Panda",
NULL
};
static int probe(void)
{
int card = -ENODEV;
const char** cardname;
for (cardname = supported_cards ; *cardname ; ++cardname) {
card = ah_card_find_by_name(*cardname);
if (card >= 0)
return 0;
}
return ENODEV;
}
static struct audio_tool_card_module g_omap_abe_mod_template = {
.type = AUDIO_TOOL_MOD_TYPE_CARD,
.name = "",
.probe = probe,
.get_mixer_defaults = get_mixer_defaults,
.get_fe_be_names = get_fe_be_names,
.config = config,
};
static void __init init(void)
{
const char** cardname;
int card;
int ret;
for (cardname = supported_cards ; *cardname ; ++cardname) {
card = ah_card_find_by_name(*cardname);
if (card < 0)
continue;
struct audio_tool_card_module *mod;
mod = malloc(sizeof(struct audio_tool_card_module));
if (!mod) {
fprintf(stderr, "Error: could not allocate memory for module %s\n",
*cardname);
}
*mod = g_omap_abe_mod_template;
mod->name = *cardname;
ret = audio_tool_module_register((struct audio_tool_module*)mod);
if (ret) {
fprintf(stderr, "Error: could not register module %s (%s)\n",
*cardname, strerror(ret));
}
}
}