Звук. Программная реализация.: различия между версиями
Нет описания правки |
Zombah (обсуждение | вклад) м (fix links) |
||
Строка 8: | Строка 8: | ||
===Процесс инициализации=== | ===Процесс инициализации=== | ||
В файле [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5623.c alc5632.c] описаны процедуры инициализации ядерного модуля для нашей звуковухи. Метод [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1177 alc5632_modinit] вызывается первым при инициализации модуля. Этот метод регистрирует структуру типа [ | В файле [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5623.c alc5632.c] описаны процедуры инициализации ядерного модуля для нашей звуковухи. Метод [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1177 alc5632_modinit] вызывается первым при инициализации модуля. Этот метод регистрирует структуру типа [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1167 i2c_dirver] (в этой струкруре содержатся указатели на методы добавления/удаления устройства). | ||
После регистрации зовется метод [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1079 alc5632_i2c_probe] (он зарегистрирован как метод probe в структуре [ | После регистрации зовется метод [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1079 alc5632_i2c_probe] (он зарегистрирован как метод probe в структуре [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1167 i2c_driver]). В начале этого метода в dmesd плюется дебажное сообщение '''"in i2c probe"'''. Потом считывается vid1 и vid2 (vendor id), чтобы определить, действительно ли позвали инициализацию для нужного устройства, а именно звуковой карты. Если все хорошо, то в dmesg пишется сообщение '''"Found codec: ALC5632 (ID: 5c)"'''. Последний байт vid2 должен быть равен 0x5с (это значение выводится как ID), иначе дальше возвращается ошибка. Далее зовется функция регистрации кодека - [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-core.c#line3641 snd_soc_register_codec], в которую передаются структуры [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line1062 soc_codec_device_alc5632] (содержит указатели на методы инициализации/деинициализации, управления питанием и т.п.) и [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line855 alc5632_dai] (dai = digital audio interface, содержит общие методы инициализации/деинициализации и т.п., а также параметры для воспроизведения и записи). | ||
При регистрации кодека зовется функция инициализации [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line984 alc5632_probe] (именно она пишет в dmesg "'''in codec probe''' ..."). В этой функции происходит инициализация устройства - запись в регистры для сброса состояния, установка регистров питания в нужное значение, перевод в slave режим, ... | При регистрации кодека зовется функция инициализации [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line984 alc5632_probe] (именно она пишет в dmesg "'''in codec probe''' ..."). В этой функции происходит инициализация устройства - запись в регистры для сброса состояния, установка регистров питания в нужное значение, перевод в slave режим, ... | ||
Часть настройка производится вызовом функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line923 androids_init], часть вызовами функция для добавления "контролов". | Часть настройка производится вызовом функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line923 androids_init], часть вызовами функция для добавления "контролов". | ||
Строка 22: | Строка 22: | ||
</pre> | </pre> | ||
Они появляются из функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-dapm.c#line489 dapm_new_mux] (в нее ошибка приходит от [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/core/control.c#line326 snd_ctl_add]). Интересно то, что на '''SpeakerOut N Mux''' ругани нет ([https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line238 список mux'ов]). | Они появляются из функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-dapm.c#line489 dapm_new_mux] (в нее ошибка приходит от [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/core/control.c#line326 snd_ctl_add]). Интересно то, что на '''SpeakerOut N Mux''' ругани нет ([https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/codecs/alc5632.c#line238 список mux'ов]). | ||
Вот здесь определяется дефайн инициализации, которую используют для контролов: [ | Вот здесь определяется дефайн инициализации, которую используют для контролов: [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/include/sound/soc-dapm.h#line93 SND_SOC_DAPM_MUX] | ||
[ | [http://www.alsa-project.org/main/index.php/DAPM DAPM] - Dynamic Audio Power Management, используется для включения/выключения аудиоустройств для экономии энергии на портативных девайсах. | ||
Сигнатура SND_SOC_DAPM_MUX: | Сигнатура SND_SOC_DAPM_MUX: | ||
<pre> | <pre> | ||
Строка 34: | Строка 34: | ||
</pre> | </pre> | ||
Код ошибки 16: '''EBUSY''' /* Device or resource busy */, ошибка выпадает в этой проверке: [ | Код ошибки 16: '''EBUSY''' /* Device or resource busy */, ошибка выпадает в этой проверке: [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/core/control.c#line338 sound/core/control.c#line338] | ||
<pre> | <pre> | ||
if (snd_ctl_find_id(card, &id)) { | if (snd_ctl_find_id(card, &id)) { | ||
Строка 57: | Строка 57: | ||
Файл [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c paz00.c] описывает процесс инициализации звука на платформе ''paz00''. Принцип регистрации драйвера и вызова основной probe функции аналогичен остальным модулям (более детально описано выше). | Файл [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c paz00.c] описывает процесс инициализации звука на платформе ''paz00''. Принцип регистрации драйвера и вызова основной probe функции аналогичен остальным модулям (более детально описано выше). | ||
В качестве основной probe функции выступает [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line251 tegra_snd_paz00_probe]. В этой функции происходит проверка платформы. Далее получаются значения различных "клоков" - [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/tegra_asoc_utils.c#line106 tegra_asoc_utils_init]. Потом идет какая-то внутренняя магия и затем регистрация звуковой карты функцией [ | В качестве основной probe функции выступает [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line251 tegra_snd_paz00_probe]. В этой функции происходит проверка платформы. Далее получаются значения различных "клоков" - [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/tegra_asoc_utils.c#line106 tegra_asoc_utils_init]. Потом идет какая-то внутренняя магия и затем регистрация звуковой карты функцией [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-core.c#line3287 snd_soc_register_card]. | ||
В какой именно последовательности дальше вызываются функции я пока не понял. В структуре, описывающей карту ([ | В какой именно последовательности дальше вызываются функции я пока не понял. В структуре, описывающей карту ([http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line245 snd_soc_paz00]) содержится указатель на структуру [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line234 paz00_alc5632_dai], которая в свою очередь содержит указатель на функцию инициализации ([http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line170 paz00_asoc_init]) и на структуру с функциями операций - [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line103 paz00_asoc_ops] (в нашем случае заполнено только одно поле '''hw_params''', которое указывает на [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line39 paz00_asoc_hw_params]). | ||
[ | [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line170 paz00_asoc_init] - добавляет контролы и пины. | ||
[https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line39 paz00_asoc_hw_params] - получает '''srate''', на его основе рассчитывает '''mclk''' затем на основе этих значений зовет [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/tegra_asoc_utils.c#line30 tegra_asoc_ustils_set_rate]. Затем выставляются форматы. В конце, если '''mclk''' отличается от того, что был по умолчанию зовется [ | [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/paz00.c#line39 paz00_asoc_hw_params] - получает '''srate''', на его основе рассчитывает '''mclk''' затем на основе этих значений зовет [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/tegra/tegra_asoc_utils.c#line30 tegra_asoc_ustils_set_rate]. Затем выставляются форматы. В конце, если '''mclk''' отличается от того, что был по умолчанию зовется [http://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-core.c#line3090 snd_soc_dai_set_sysclk] | ||
Интеграция paz00 и alc5632 судя по всему происходит в функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-core.c#line2079 soc_new_pcm]. Из нее в dmesg попадает сообщение '''"asoc: alc5632-hifi <-> tegra-i2s.0 mapping ok"'''. | Интеграция paz00 и alc5632 судя по всему происходит в функции [https://gitorious.org/%7Emarvin24/ac100/marvin24s-kernel/blobs/chromeos-ac100-2.6.38/sound/soc/soc-core.c#line2079 soc_new_pcm]. Из нее в dmesg попадает сообщение '''"asoc: alc5632-hifi <-> tegra-i2s.0 mapping ok"'''. |
Текущая версия от 16:23, 16 января 2015
Как устроен звук на тоше в плане железа, можно посмотреть на странице Звук
Исходники ядра, связанные со звуком:
- sound/soc/codecs (alc5632.c и alc5632.h)
- sound/soc/tegra (интересно все кроме harmony.c и seabord.c)
- arch/arm/mach-tegra/pinmux.c
- arch/arm/mach-tegra/pinmux-t2-tables.c
Процесс инициализации
В файле 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 слышны щелчки в наушниках.