1.packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
private final AudioManager mAudioManager;
private void acceptCall(int flag, boolean retry)
{
if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
Log.d(TAG,"hfp_enable=true");
mAudioManager.setParameters("hfp_enable=true");
}
}
private void processAudioEvent(int state, BluetoothDevice device)
{
switch (state) {
case HeadsetClientHalConstants.AUDIO_STATE_CONNECTED:
mAudioManager.setParameters("hfp_set_sampling_rate=16000");
mAudioManager.setParameters("hfp_enable=true");
mAudioManager.setParameters("hfp_volume=" + hfVol);
transitionTo(mAudioOn);
}
}
2.frameworks/base/media/java/android/media/AudioManager.java
public void setParameters(String keyValuePairs)
{
AudioSystem.setParameters(keyValuePairs);
}
3.frameworks/base/media/java/android/media/AudioSystem.java
public static native int setParameters(String keyValuePairs);
4.frameworks/base/core/jni/android_media_AudioSystem.cpp
static jint
android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
{
int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
}
5.frameworks/av/media/libmedia/AudioSystem.cpp
status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
const sp& af = AudioSystem::get_audio_flinger();
return af->setParameters(ioHandle, keyValuePairs);
}
6.frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs){
audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice
ALOGE("xxx---> %s(), line = %d, devices[%zu] = %s, dev = %p,dev->common.module->name = %s",__FUNCTION__,__LINE__,i,keyValuePairs.string(),dev,dev->common.module->name);
result = dev->set_parameters(dev, keyValuePairs.string());
}
7.hardware/qcom/audio/hal/audio_hw.c
static int adev_open_output_stream()
{
out->stream.common.set_parameters = out_set_parameters;
}
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
audio_extn_set_parameters(adev, parms);
}
8.hardware/qcom/audio/hal/audio_extn/audio_extn.c
void audio_extn_set_parameters(struct audio_device *adev,struct str_parms *parms)
{
audio_extn_set_anc_parameters(adev, parms);
}
9.void audio_extn_set_anc_parameters(struct audio_device *adev, struct str_parms *parms)
{
platform_set_parameters(adev->platform, reply_44_1);
}
10.hardware/qcom/audio/hal/msm8916/platform.c
int platform_set_parameters(void *platform, struct str_parms *parms)
{
ret = set_hd_voice(my_data, state);
}
static int set_hd_voice(struct platform_data *my_data, bool state)
{
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
}
11.external/tinyalsa/mixer.c
int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
{
return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
}
12.kernel/msm-3.18/sound/core/control.c
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
case SNDRV_CTL_IOCTL_ELEM_WRITE:
return snd_ctl_elem_write_user(ctl, argp);
}
static int snd_ctl_elem_write_user(struct snd_ctl_file *file, struct snd_ctl_elem_value __user *_control)
{
result = snd_ctl_elem_write(card, file, control);
copy_to_user(_control, control, sizeof(*control));
return result;
}
//snd_kcontrol结构体分析
struct snd_kcontrol
{
snd_kcontrol_get_t *get;//读Adsp寄存器
snd_kcontrol_put_t *put;//写Adsp寄存器
}
typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
//注册put()和get()回调函数
static int snd_ctl_elem_add()
{
if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED)
kctl.info = snd_ctl_elem_user_enum_info; else kctl.info = snd_ctl_elem_user_info;//获取Adsp信息
if (access & SNDRV_CTL_ELEM_ACCESS_READ)
kctl.get = snd_ctl_elem_user_get;//注册回调,读Adsp寄存器
if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
kctl.put = snd_ctl_elem_user_put;//注册回调,写Adsp寄存器
}
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, void *private_data)
{
kctl.info = ncontrol->info;
kctl.get = ncontrol->get;
kctl.put = ncontrol->put;//这里是从Adsp传过来回调函数
kctl.tlv.p = ncontrol->tlv.p;
kctl.private_value = ncontrol->private_value;
kctl.private_data = private_data;
return snd_ctl_new(&kctl, access);
}
}
static int snd_ctl_elem_write()
{
struct snd_kcontrol *kctl;
result = kctl->put(kctl, control); //这里即是调用snd_ctl_elem_user_put()函数
}
kernel/msm-3.18/include/sound/soc.h
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
.put = snd_soc_put_volsw_range, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = xshift, \
.rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \ //snd_soc_put_volsw();回调函数
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
13.kernel/msm-3.18/sound/soc/soc-core.c
int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
err = snd_soc_component_update_bits(component, reg, val_mask, val);
}
14.kernel/msm-3.18/sound/soc/soc-io.c
static int snd_soc_component_update_bits_legacy(
struct snd_soc_component *component, unsigned int reg,
unsigned int mask, unsigned int val, bool *change)
{
component->write(component, reg, new);//相当于回调了snd_codec_write();写寄存器
}
kernel/msm-3.18/include/sound/soc.h
struct snd_soc_component {
const char *name;
int id;
const char *name_prefix;
struct device *dev;
int (*write)(struct snd_soc_component *, unsigned int, unsigned int);
}
15.kernel/msm-3.18/sound/soc/soc-core.c
int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
codec->component.write = snd_soc_codec_drv_write;
}
static int snd_soc_codec_drv_write(struct snd_soc_component *component,
unsigned int reg, unsigned int val)
{
struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
return codec->driver->write(codec, reg, val);//这里调用的snd_soc_component结构体里的write()
}
<1>.struct snd_soc_codec {
const struct snd_soc_codec_driver *driver;
struct snd_soc_component component;
}
<2>./* codec driver */ codec的write()函数
struct snd_soc_codec_driver {
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
};
//根据平台不同,会调用到当前平台所用的codec,本平台为msm8953用的codec为msm8x16-wcd
kernel/msm-3.18/sound/soc/codecs/msm8x16-wcd.c
static struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
.write = msm8x16_wcd_write,
}
static int msm8x16_wcd_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
int ret;
struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
BUG_ON(reg > MSM8X16_WCD_MAX_REGISTER);
return __msm8x16_wcd_reg_write(codec, reg, (u8)value);
}
static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,
unsigned short reg, u8 val)
{
ret = msm8x16_wcd_ahb_write_device(msm8x16_wcd, reg, &val, 1);
}
static int msm8x16_wcd_ahb_write_device(struct msm8x16_wcd *msm8x16_wcd,
u16 reg, u8 *value, u32 bytes)
{
u32 temp = ((u32)(*value)) & 0x000000FF;
u16 offset = (reg - 0x0200) & 0x03FF;
bool q6_state = false;
q6_state = q6core_is_adsp_ready();
pr_debug("%s: DSP is ready %d\n", __func__, q6_state);
iowrite32(temp, msm8x16_wcd->dig_base + offset);//写入到Adsp寄存器
return 0;
}