Глава 10. Прочие устройства

Предыдущая  Содержание  Следующая V*D*V

FM OPL3

FM OPL3 по-прежнему используется во многих чипах (в основном для обратной совместимости). ALSA также имеет хороший уровень управления OPL3 FM. OPL3 API определён в <sound/opl3.h>.

 

Регистры FM могут быть доступны непосредственно через direct-FM API (программный интерфейс прямого доступа к FM), определённый в <sound/asound_fm.h>. В родном режиме ALSA регистры FM доступны через расширенное API аппаратно-зависимого прямого доступа к FM, тогда как в режиме совместимости с OSS регистры FM могут быть доступны с помощью OSS совместимого API прямого доступа к FM в устройстве /dev/dmfmX.

 

Чтобы создать компонент OPL3, у вас есть две функции для вызова. Первая представляет собой конструктор для экземпляра opl3_t.

 

struct snd_opl3 *opl3;

snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,

                integrated, &opl3);

 

Первый аргумент является указателем карты, второй - адресом порта левого канала, а третий - адресом порта правого канала. В большинстве случаев порт правого канала находится по адресу "левый порт + 2".

 

Четвертый аргумент - тип оборудования.

 

Если порты левого и правого канала были уже выделены драйвером карты, в пятом аргументе (integrated) передаётся ненулевое значение. В противном случае, модуль OPL3 будет сам запрашивать указанные порты.

 

Если доступ к оборудованию требует специального метода вместо стандартного доступа ввода/вывода, можно создать экземпляр OPL3 отдельно с помощью snd_opl3_new().

 

struct snd_opl3 *opl3;

snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);

 

Затем укажите command, private_data и private_free для функции доступа к закрытым данным, закрытых данных и деструктора. l_port и r_port устанавливать необязательно. Достаточно правильно установить только command. Вы можете получать данные из поля opl3->private_data. (а откуда тогда берётся поле private_data? каков его размер? деструктор по умолчанию тоже есть?)

 

После создания экземпляра OPL3 через snd_opl3_new(), для инициализации чипа в необходимое состояние вызовите snd_opl3_init(). Обратите внимание, что snd_opl3_create() всегда называет её внутри себя.

 

Затем, если экземпляр OPL3 был создан успешно, для этого OPL3 создаём устройство hwdep.

 

struct snd_hwdep *opl3hwdep;

snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);

 

Первым аргументом является созданный экземпляр opl3_t, а вторым - порядковый номер, как правило, 0.

 

Третий аргумент является индексным смещением для клиента-секвенсора, назначенного этому порту OPL3. Если есть MPU401-UART, укажите здесь 1 (UART всегда получает индекс 0).

Устройства, зависящие от оборудования

Некоторым чипам необходим доступ к пространству пользователя для специального управления или загрузки микро-кода. В таком случае можно создать hwdep (аппаратно-зависимое) устройство. hwdep API определён в <sound/hwdep.h>. Вы можете найти примеры в драйвере opl3 или isa/sb/sb16_csp.c.

 

Создание экземпляра hwdep осуществляется через snd_hwdep_new().

 

struct snd_hwdep *hw;

snd_hwdep_new(card, "My HWDEP", 0, &hw);

 

где третий аргумент является порядковым номером.

 

Затем можно передать любое значения указателя в private_data. Если вы указали закрытые данные, вы также должны определить деструктор. Функция деструктора указывается в поле private_free.

 

struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);

hw->private_data = p;

hw->private_free = mydata_free;

 

а реализацией деструктора было бы:

 

static void mydata_free(struct snd_hwdep *hw)

{

    struct mydata *p = hw->private_data;

    kfree(p);

}

 

Для данного экземпляра  могут быть определены произвольные файловые операции. Файловые операции определены в таблице ops. Например, предположим, что данному чипу необходимо ioctl.

 

hw->ops.open = mydata_open;

hw->ops.ioctl = mydata_ioctl;

hw->ops.release = mydata_release;

 

И реализуйте функции обратного вызова, как вам нравится.

IEC958 (S/PDIF)

Обычно элементы управления для устройств IEC958 реализуются через интерфейс Control. Для формирования строки названия элементов управления IEC958 существует макрос SNDRV_CTL_NAME_IEC958(), определённый в <include/asound.h>.

 

Для статусных битов IEC958 есть несколько стандартных элементов управления. Эти элементы управления используют тип SNDRV_CTL_ELEM_TYPE_IEC958, а размер элемента зафиксирован в виде 4-х байтового массива (value.iec958.status[x]). Для обратного вызова info для этого типа не указывается поле value (однако, поле count должно быть установлено).

 

"IEC958 Playback Con Mask" используется для возвращения битовой маски статусных битов IEC958 потребительского режима (consumer mode). Аналогично, "IEC958 Playback Pro Mask" возвращает битовую маску для профессионального режима (professional mode). Они доступны только для чтения и определяются как элементы управления MIXER (iface = SNDRV_CTL_ELEM_IFACE_MIXER).

 

Для получения и установки используемых в настоящее время битов по умолчанию IEC958 определён элемент управления "IEC958 Playback Default". Обратите внимание, что он обычно определяется как элемент управления PCM (iface = SNDRV_CTL_ELEM_IFACE_PCM), хотя в некоторых местах он определён как элемент управления MIXER.

 

Кроме того, вы можете определить переключатели для включения/выключения или установки нестандартного режима. Реализация будет зависеть от чипа, но элемент управления должен быть назван "IEC958 xxx", желательно с помощью макроса SNDRV_CTL_NAME_IEC958().

 

Разные варианты можно найти, например, в pci/emu10k1, pci/ice1712 или pci/cmipci.c.

 

Предыдущая  Содержание  Следующая