[pulseaudio-discuss] [RFC] Dynamically created PCM devices for HDMI/DisplayPort

Raymond Yau superquad.vortex2 at gmail.com
Tue Jun 30 19:07:06 PDT 2015


>>
>> It looks like in the future the ALSA drivers for some Intel hardware
>> will dynamically create a new PCM device when a DisplayPort monitor is
>> plugged in. This is being discussed in this thread (part of the thread
>> is also cross-posted to pulseaudio-discuss):
>>
http://thread.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/62703/focus=63002
>>
>
> No objections to the plan below, but some nitpicks.
>
>
>>
>> PulseAudio doesn't currently support dynamic PCM devices, so work is
>> needed to add that support. I may work on that, or it may be someone
>> else from Intel. I'll describe here what code changes I think we should
>> make. That serves two purposes: to get feedback about the plan before
>> any code gets written, and to help with the implementation work if
>> someone else than me is going to write the code.
>>
>> This is a long mail, but I'm sure I still didn't think of every issue
>> that will arise when implementing this...
>>
>>
>> Event: monitor gets plugged in
>> ------------------------------
>>
>> The first thing that happens should be that PulseAudio gets a wakeup
>> from the alsa mixer, when a new ELD control for the monitor is added.
>> This is important, because the mixer should be ready when PulseAudio
>> starts to use the new PCM device. It's up to the driver developer to do
>> this right. This wakeup can be ignored, so no code changes are needed in
>> PulseAudio to handle this.
>>
>> The second thing that happens is that udev notifies PulseAudio about a
>> new PCM device. Interfacing with udev is done in
>> src/modules/module-udev-detect.c. Currently PulseAudio only cares about
>> new and removed cards, so module-udev-detect has to be modified to also
>> keep track of what PCM devices each card has, so that new devices can be
>> noticed.
>
>
> I am not sure whether this "wakeup from alsa mixer first, from udev
second" ordering is something that can be relied on. But a "ELD control
exists when udev notifies us" requirement looks sensible.
>
>
>>
>> When module-udev-detect sees a new PCM device, it needs to notify
>> module-alsa-card about it. module-udev-detect's only interface with
>> module-alsa-card is pa_module, which is not useful for adding the
>> notification. I think we should move the bulk of the code in
>> module-alsa-card.c to a new class: pa_alsa_card. module-udev-detect
>> would then create pa_alsa_card objects instead of loading
>> module-alsa-card instances. module-alsa-card would still exist as a
>> wrapper around pa_alsa_card, but the module would not be used by
>> module-udev-detect. With pa_alsa_card in place, we can add a
>> pa_alsa_card_pcm_added() function to its API.
>
>
> OK.
>
>
>> pa_alsa_card should be defined in src/modules/alsa/alsa-card.[ch] and
>> included in the libalsa-util.la helper library.
>>
>> When moving the code from module-alsa-card to pa_alsa_card, some changes
>> to the sink and source error handling is needed. Currently, if something
>> fails in the IO thread of an alsa sink or source, the sink/source
>> unloads the module that owns the sink/source (see the end of
>> thread_func() in alsa-sink.c and alsa-source.c). Now the owner module of
>> alsa sinks and sources becomes module-udev-detect, and we certainly
>> don't want to unload that if a single sink or source fails. The
>> sink/source should notify the pa_alsa_card object of the failure (new
>> functions pa_alsa_card_sink_failed() and pa_alsa_card_source_failed()),
>> and pa_alsa_card should free the failed pa_alsa_sink or pa_alsa_source
>> object.
>
>
> The case of manually-loaded module-alsa-sink is not described here, but
should be.
>
>
>> Let's get back to the pa_alsa_card_pcm_added() function. What should it
>> do? We shouldn't support dynamic PCMs for arbitrary hw PCMs, because
>> that's not compatible with relying on logical device names like "front",
>> "surround51" etc. At this point we only need to support dynamic PCMs
>> that are dedicated to hotplugged HDMI/DisplayPort/Thunderbolt devices.
>> The current proposal to detect such PCMs is to add a new HDMI class to
>> snd_pcm_class_t, which can be queried with snd_pcm_info_get_class().
>>
>> Currently when opening HDMI devices, we use "hdmi:x,y" as the device
>> string, where x is the card index and y is the device index. The device
>> index may be different than the hw device index, but the mapping between
>> "hdmi:x,y" to "hw:x,z" is static. The mapping can be different with
>> different drivers, AFAIK. We currently blindly try all device indexes
>> from 0 to 7 when probing the card. Takashi Iwai told that such behaviour
>> won't be compatible with drivers that create dynamic PCMs for HDMI. I
>> guess the reason is that the dynamically allocated hw device indexes can
>> (and usually do) fall outside the index range that is used in "hdmi:x,y".
>>
>> Since the new HDMI PCM class is new, old kernels and old alsa-lib won't
>> use that class even with PCMs that are actually dedicated to HDMI. We
>> need to tell apart drivers that use the new HDMI PCM class and drivers
>> that don't. With drivers that never use the HDMI class, we should keep
>> using the "hdmi:x,y" device strings. With drivers that use the HDMI
>> class, we should use "hdmi:CARD=x,SYSDEV=z", where z is the hw device
>> index (the SYSDEV parameter doesn't currently exist, so alsa-lib needs
>> to be updated to support it). How do we tell the two kinds of drivers
>> apart? The current proposal is to add a version field to the PCM info.
>> Version 0 would mean that the driver is unaware of the HDMI PCM class,
>> and version 1 would mean that the driver will set the PCM class to HDMI
>> when appropriate.
>>
>> I assume that the PCM info version will be provided separately for each
>> PCM device, but I expect the version to be always the same for every
>> device that belongs to the same card. We definitely need to make the
>> decision between the two models at the card level in any case, because
>> we can't really mix the "hdmi:x,y" model with the "hdmi:CARD=x,SYSDEV=z"
>> model within the same card. When probing a new card, we should check the
>> PCM info version of the first device that we probe, and choose the HDMI
>> model for the card based on that. If the first device has PCM info
>> version 0, then we won't support dynamic HDMI devices for that card,
>> even if subsequent devices would somehow have version 1.
>>
>> The "mapping" concept in our alsa-mixer code corresponds to the PCM
>> devices. What mappings exist is configured in
>> src/modules/alsa/mixer/profile-sets/default.conf. We have many HDMI
>> entries, here are a couple of examples:
>>
>> [Mapping hdmi-stereo]
>> description = Digital Stereo (HDMI)
>> device-strings = hdmi:%f
>> paths-output = hdmi-output-0
>> channel-map = left,right
>> priority = 4
>> direction = output
>>
>> [Mapping hdmi-stereo-extra1]
>> description = Digital Stereo (HDMI 2)
>> device-strings = hdmi:%f,1
>> paths-output = hdmi-output-1
>> channel-map = left,right
>> priority = 2
>> direction = output
>>
>> The "device-strings" option doesn't suit the HDMI case very well, if we
>> sometimes have to use "hdmi:x,y" and sometimes "hdmi:CARD=x,SYSDEV=z".
>> Also, the path configuration files assume a particular mapping from
>> "hdmi:x,y" to "hw:x,z" when dealing with ELD information and jack
>> detection, and that assumed mapping is incorrect with dynamic HDMI
>> devices. (This assumption probably also means that our HDMI ELD and jack
>> detection functionality is currently broken on non-HDA cards.)
>>
>> I propose that we add a new boolean option for mappings, which would
>> indicate that the mapping represents more than one PCM device, and that
>> the PCM and mixer handling is performed according to the complex HDMI
>> specific rules that I've explained above. The option name could be e.g.
>> "dynamic-hdmi". When "dynamic-hdmi" is be set for a mapping, the
>> "description", "device-strings", "paths-output" and "direction" options
>> in the configuration file would be ignored, and the appropriate values
>> for those would be hardcoded. That would allow us to shorten
>> default.conf quite a bit, and also remove all the hdmi-output-N.conf
>> path files (the generated paths would be hardcoded too).
>>
>> All that hardcoding isn't nice from flexibility point of view, but I
>> don't think the lost flexibility is very important in this case. I
>> believe that any alternative solution that would keep everything in the
>> configuration files would introduce a significant amount of complexity
>> to deal with the variance in the "hdmi:x,y" -> "hw:x,z" mapping (and I'm
>> not sure it's even possible to have non-HDA-specific ELD information and
>> jack detection support with the old-style "hdmi:x,y" device strings,
>> since we don't have a reliable method to figure out what hw PCM device
>> index y corresponds to).
>>
>> In case of dynamic HDMI mappings, the HDMI profiles need to become
>> dynamic too. So, if a profile definition in a configuration file
>> references a mapping that has the "dynamic-hdmi" flag set, that profile
>> definition will then represent multiple profiles, one for each HDMI
>> device. I'm not sure how to deal with the "description" option. Should
>> it be ignored, or should we append a number to the description when
>> there are multiple HDMI devices? When profiles are autogenerated (which
>> is the common case), then the existing profile description logic should
>> work fine.
>>
>> So, when pa_alsa_card_pcm_added() sees that a new HDMI PCM device
>> appeared, it should create a new mapping for the device, a new path for
>> the mapping, and a new profile containing the mapping. Then
>> pa_alsa_card_pcm_added() needs to call pa_card_add_profile(), and
>> hopefully it will just work.
>>
>>
>> Event: monitor gets unplugged
>> -----------------------------
>>
>> When a monitor gets unplugged, module-udev-detect gets a notified, and
>> it should figure out that a PCM device has disappeared. It should then
>> call pa_alsa_card_pcm_removed(), which is a new function that needs to
>> be implemented.
>
>
> Again, the case of manually loaded module-alsa-sink is not considered.
>
>
>>
>> pa_alsa_card_pcm_removed() should mirror pa_alsa_card_pcm_added(), just
>> undoing the things that _added() did, in reverse order. So, first it
>> should call pa_card_remove_profile(). That function doesn't exist
>> currently, so it needs to be implemented. Next
>> pa_alsa_card_pcm_removed() should free the pa_alsa_profile,
>> pa_alsa_mapping and pa_alsa_path objects corresponding to the removed
>> device. I think that's it for pa_alsa_card_pcm_removed().
>>
>> If the profile that is being removed is active, pa_card_remove_profile()
>> should change the card profile to something else. I suppose it should
>> use the same logic as what pa_card_new() uses when choosing the default
>> profile.
>>
>
> What else is missing is the big picture of the available multi-monitor
use cases.
>
> Currently, if one has a card with multiple HDMI outputs, one can use
audio from one monitor at a time, using profiles. I.e. there are no
profiles like "HDMI Digital Stereo Output + HDMI 3 Digital Surround Output"
(with the possibility to move individual streams between monitors),
presumably due to the combinatorial explosion. Will this limitation be
lifted?

>
> Also, AFAIR, there was a discussion of a possibility to send the same PCM
stream to two monitors. How would that work?

http://www.intel.com/support/graphics/sb/CS-031040.htm

The multi display monitors can be configured by graphic driver in clone
mode or extended display mode

Are there hardware limitation (e.g. bandwidth ) which limit the highest
sample rate and 32bits cannot be used by multi monitors at same time ?

Are there any different in primary display , second display and third
display ?

Will th power off/on of the monitor in the middle of dasiy chain affect the
other displays of the dasiy chain ?

http://www.intel.com/support/graphics/sb/CS-033714.htm

How do pulseaudio/driver know multi displays are in clone node or
independent display mode ?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/pulseaudio-discuss/attachments/20150701/efdf3974/attachment.html>


More information about the pulseaudio-discuss mailing list