Звук. Программная реализация.

Материал из Toshiba AC100 wiki
Версия от 08:15, 15 октября 2014; Unknown user (обсуждение)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску

Как устроен звук на тоше в плане железа, можно посмотреть на странице Звук

Исходники ядра, связанные со звуком:

Процесс инициализации

В файле alc5632.c описаны процедуры инициализации ядерного модуля для нашей звуковухи. Метод alc5632_modinit вызывается первым при инициализации модуля. Этот метод регистрирует структуру типа i2c_dirver (в этой струкруре содержатся указатели на методы добавления/удаления устройства). После регистрации зовется метод alc5632_i2c_probe (он зарегистрирован как метод probe в структуре i2c_driver). В начале этого метода в dmesd плюется дебажное сообщение "in i2c probe". Потом считывается vid1 и vid2 (vendor id), чтобы определить, действительно ли позвали инициализацию для нужного устройства, а именно звуковой карты. Если все хорошо, то в dmesg пишется сообщение "Found codec: ALC5632 (ID: 5c)". Последний байт vid2 должен быть равен 0x5с (это значение выводится как ID), иначе дальше возвращается ошибка. Далее зовется функция регистрации кодека - snd_soc_register_codec, в которую передаются структуры soc_codec_device_alc5632 (содержит указатели на методы инициализации/деинициализации, управления питанием и т.п.) и alc5632_dai (dai = digital audio interface, содержит общие методы инициализации/деинициализации и т.п., а также параметры для воспроизведения и записи). При регистрации кодека зовется функция инициализации alc5632_probe (именно она пишет в dmesg "in codec probe ..."). В этой функции происходит инициализация устройства - запись в регистры для сброса состояния, установка регистров питания в нужное значение, перевод в slave режим, ... Часть настройка производится вызовом функции androids_init, часть вызовами функция для добавления "контролов". При ошибке добавления "контрола" в dmesg должно появляться сообщение вида <range type="comment" id="85502">"%s: Failed to add %s: %d"</range id="85502"> (%s - строка, %d - число).

Сейчас в dmesg есть сообщения:

[ 8.151320] alc5632 0-001e: asoc: failed to add kcontrol Right Headphone Mux
[ 8.157220] alc5632 0-001e: asoc: failed to add kcontrol Left Headphone Mux
[ 8.162891] alc5632 0-001e: asoc: failed to add kcontrol SpeakerOut Mux
[ 8.168566] alc5632 0-001e: asoc: failed to add kcontrol AuxOut Mux

Они появляются из функции dapm_new_mux (в нее ошибка приходит от snd_ctl_add). Интересно то, что на SpeakerOut N Mux ругани нет (список mux'ов). Вот здесь определяется дефайн инициализации, которую используют для контролов: SND_SOC_DAPM_MUX DAPM - Dynamic Audio Power Management, используется для включения/выключения аудиоустройств для экономии энергии на портативных девайсах. Сигнатура SND_SOC_DAPM_MUX:

SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
wname const char* Name to give to the widget.
wreg unsigned int Register to modify when turning the DAC on or off
wshift unsigned int Bit in register to modify when turning the DAC on or off
winvert unsigned int Is the control inverted? If set to 1, setting the bit turns the DAC off
wcontrols ???

Код ошибки 16: EBUSY /* Device or resource busy */, ошибка выпадает в этой проверке: sound/core/control.c#line338

if (snd_ctl_find_id(card, &id)) {
    up_write(&card->controls_rwsem);
    snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n",
              id.iface,
              id.device,
              id.subdevice,
              id.name,
              id.index);
    err = -EBUSY;
    goto error;
}

Видимо, устройства уже инициализированы до этого. Если так, то нужно найти, где они инициализируются и проверить, все ли в порядке.

[ 40.211708] spk event: 2
[ 46.076741] spk event: 4

Эти два сообщения выводятся из функции paz00_event_int_spk, которая на данный момент ничего не делает (за исключением вывода сообщения :) ) Очень похоже, что это события для обработки драйвером включения/выключения спикера.

Файл paz00.c описывает процесс инициализации звука на платформе paz00. Принцип регистрации драйвера и вызова основной probe функции аналогичен остальным модулям (более детально описано выше). В качестве основной probe функции выступает tegra_snd_paz00_probe. В этой функции происходит проверка платформы. Далее получаются значения различных "клоков" - tegra_asoc_utils_init. Потом идет какая-то внутренняя магия и затем регистрация звуковой карты функцией snd_soc_register_card. В какой именно последовательности дальше вызываются функции я пока не понял. В структуре, описывающей карту (snd_soc_paz00) содержится указатель на структуру paz00_alc5632_dai, которая в свою очередь содержит указатель на функцию инициализации (paz00_asoc_init) и на структуру с функциями операций - paz00_asoc_ops (в нашем случае заполнено только одно поле hw_params, которое указывает на paz00_asoc_hw_params). paz00_asoc_init - добавляет контролы и пины. paz00_asoc_hw_params - получает srate, на его основе рассчитывает mclk затем на основе этих значений зовет tegra_asoc_ustils_set_rate. Затем выставляются форматы. В конце, если mclk отличается от того, что был по умолчанию зовется snd_soc_dai_set_sysclk

Интеграция paz00 и alc5632 судя по всему происходит в функции soc_new_pcm. Из нее в dmesg попадает сообщение "asoc: alc5632-hifi <-> tegra-i2s.0 mapping ok".

dmesg с дебажными сообщениями - music_dmesg_debug.txt

[ 20.853311] snd_ctl_add: add control Route
[ 20.857859] snd_ctl_add, card - id: , shortname: , longname: driver:
[ 20.862657] control 2:0:0:Route:0 is already present (snd_ctrl_find_id ret db313480, Route)
[ 20.867439] alc5632 0-001e: asoc: ac100-dbg: failed to add kcontrol Right Headphone Mux, err: -16

после Route не добавляются контролы. я пытаюсь понять почему.


SND_SOC_DAPM_PGA задает, к какому регистру/биту какой id соответствует. Согласно даташиту в регистре 3e (ALC5632_PWR_MANAG_ADD3 - дополнительный регистр питания 3):

SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3, 12, 0, NULL, 0),

Контролы

В алсамиксере звук встроенных колонок и наушников регулируется итемами Line (изначально я полагал, что за громкость динамиков отвечают итемы "Speaker...") и Headphone. Эти итемы добавляются в функции alc5632_probe и описаны массивом alc5632_vol_snd_controls в файле alc5632.c.

... продолжение следует


Наблюдения

alsamixer

При включении/выключении итемов HPR Mix ADC2HP_R и .._L слышны щелчки в наушниках.