162306a36Sopenharmony_ci============================ 262306a36Sopenharmony_ciALSA PCM channel-mapping API 362306a36Sopenharmony_ci============================ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciTakashi Iwai <tiwai@suse.de> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciGeneral 862306a36Sopenharmony_ci======= 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciThe channel mapping API allows user to query the possible channel maps 1162306a36Sopenharmony_ciand the current channel map, also optionally to modify the channel map 1262306a36Sopenharmony_ciof the current stream. 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciA channel map is an array of position for each PCM channel. 1562306a36Sopenharmony_ciTypically, a stereo PCM stream has a channel map of 1662306a36Sopenharmony_ci``{ front_left, front_right }`` 1762306a36Sopenharmony_ciwhile a 4.0 surround PCM stream has a channel map of 1862306a36Sopenharmony_ci``{ front left, front right, rear left, rear right }.`` 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciThe problem, so far, was that we had no standard channel map 2162306a36Sopenharmony_ciexplicitly, and applications had no way to know which channel 2262306a36Sopenharmony_cicorresponds to which (speaker) position. Thus, applications applied 2362306a36Sopenharmony_ciwrong channels for 5.1 outputs, and you hear suddenly strange sound 2462306a36Sopenharmony_cifrom rear. Or, some devices secretly assume that center/LFE is the 2562306a36Sopenharmony_cithird/fourth channels while others that C/LFE as 5th/6th channels. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ciAlso, some devices such as HDMI are configurable for different speaker 2862306a36Sopenharmony_cipositions even with the same number of total channels. However, there 2962306a36Sopenharmony_ciwas no way to specify this because of lack of channel map 3062306a36Sopenharmony_cispecification. These are the main motivations for the new channel 3162306a36Sopenharmony_cimapping API. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciDesign 3562306a36Sopenharmony_ci====== 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciActually, "the channel mapping API" doesn't introduce anything new in 3862306a36Sopenharmony_cithe kernel/user-space ABI perspective. It uses only the existing 3962306a36Sopenharmony_cicontrol element features. 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciAs a ground design, each PCM substream may contain a control element 4262306a36Sopenharmony_ciproviding the channel mapping information and configuration. This 4362306a36Sopenharmony_cielement is specified by: 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci* iface = SNDRV_CTL_ELEM_IFACE_PCM 4662306a36Sopenharmony_ci* name = "Playback Channel Map" or "Capture Channel Map" 4762306a36Sopenharmony_ci* device = the same device number for the assigned PCM substream 4862306a36Sopenharmony_ci* index = the same index number for the assigned PCM substream 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciNote the name is different depending on the PCM substream direction. 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciEach control element provides at least the TLV read operation and the 5362306a36Sopenharmony_ciread operation. Optionally, the write operation can be provided to 5462306a36Sopenharmony_ciallow user to change the channel map dynamically. 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciTLV 5762306a36Sopenharmony_ci--- 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciThe TLV operation gives the list of available channel 6062306a36Sopenharmony_cimaps. A list item of a channel map is usually a TLV of 6162306a36Sopenharmony_ci``type data-bytes ch0 ch1 ch2...`` 6262306a36Sopenharmony_ciwhere type is the TLV type value, the second argument is the total 6362306a36Sopenharmony_cibytes (not the numbers) of channel values, and the rest are the 6462306a36Sopenharmony_ciposition value for each channel. 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciAs a TLV type, either ``SNDRV_CTL_TLVT_CHMAP_FIXED``, 6762306a36Sopenharmony_ci``SNDRV_CTL_TLV_CHMAP_VAR`` or ``SNDRV_CTL_TLVT_CHMAP_PAIRED`` can be used. 6862306a36Sopenharmony_ciThe ``_FIXED`` type is for a channel map with the fixed channel position 6962306a36Sopenharmony_ciwhile the latter two are for flexible channel positions. ``_VAR`` type is 7062306a36Sopenharmony_cifor a channel map where all channels are freely swappable and ``_PAIRED`` 7162306a36Sopenharmony_citype is where pair-wise channels are swappable. For example, when you 7262306a36Sopenharmony_cihave {FL/FR/RL/RR} channel map, ``_PAIRED`` type would allow you to swap 7362306a36Sopenharmony_cionly {RL/RR/FL/FR} while ``_VAR`` type would allow even swapping FL and 7462306a36Sopenharmony_ciRR. 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciThese new TLV types are defined in ``sound/tlv.h``. 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciThe available channel position values are defined in ``sound/asound.h``, 7962306a36Sopenharmony_cihere is a cut: 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci:: 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* channel positions */ 8462306a36Sopenharmony_ci enum { 8562306a36Sopenharmony_ci SNDRV_CHMAP_UNKNOWN = 0, 8662306a36Sopenharmony_ci SNDRV_CHMAP_NA, /* N/A, silent */ 8762306a36Sopenharmony_ci SNDRV_CHMAP_MONO, /* mono stream */ 8862306a36Sopenharmony_ci /* this follows the alsa-lib mixer channel value + 3 */ 8962306a36Sopenharmony_ci SNDRV_CHMAP_FL, /* front left */ 9062306a36Sopenharmony_ci SNDRV_CHMAP_FR, /* front right */ 9162306a36Sopenharmony_ci SNDRV_CHMAP_RL, /* rear left */ 9262306a36Sopenharmony_ci SNDRV_CHMAP_RR, /* rear right */ 9362306a36Sopenharmony_ci SNDRV_CHMAP_FC, /* front center */ 9462306a36Sopenharmony_ci SNDRV_CHMAP_LFE, /* LFE */ 9562306a36Sopenharmony_ci SNDRV_CHMAP_SL, /* side left */ 9662306a36Sopenharmony_ci SNDRV_CHMAP_SR, /* side right */ 9762306a36Sopenharmony_ci SNDRV_CHMAP_RC, /* rear center */ 9862306a36Sopenharmony_ci /* new definitions */ 9962306a36Sopenharmony_ci SNDRV_CHMAP_FLC, /* front left center */ 10062306a36Sopenharmony_ci SNDRV_CHMAP_FRC, /* front right center */ 10162306a36Sopenharmony_ci SNDRV_CHMAP_RLC, /* rear left center */ 10262306a36Sopenharmony_ci SNDRV_CHMAP_RRC, /* rear right center */ 10362306a36Sopenharmony_ci SNDRV_CHMAP_FLW, /* front left wide */ 10462306a36Sopenharmony_ci SNDRV_CHMAP_FRW, /* front right wide */ 10562306a36Sopenharmony_ci SNDRV_CHMAP_FLH, /* front left high */ 10662306a36Sopenharmony_ci SNDRV_CHMAP_FCH, /* front center high */ 10762306a36Sopenharmony_ci SNDRV_CHMAP_FRH, /* front right high */ 10862306a36Sopenharmony_ci SNDRV_CHMAP_TC, /* top center */ 10962306a36Sopenharmony_ci SNDRV_CHMAP_TFL, /* top front left */ 11062306a36Sopenharmony_ci SNDRV_CHMAP_TFR, /* top front right */ 11162306a36Sopenharmony_ci SNDRV_CHMAP_TFC, /* top front center */ 11262306a36Sopenharmony_ci SNDRV_CHMAP_TRL, /* top rear left */ 11362306a36Sopenharmony_ci SNDRV_CHMAP_TRR, /* top rear right */ 11462306a36Sopenharmony_ci SNDRV_CHMAP_TRC, /* top rear center */ 11562306a36Sopenharmony_ci SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC, 11662306a36Sopenharmony_ci }; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciWhen a PCM stream can provide more than one channel map, you can 11962306a36Sopenharmony_ciprovide multiple channel maps in a TLV container type. The TLV data 12062306a36Sopenharmony_cito be returned will contain such as: 12162306a36Sopenharmony_ci:: 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci SNDRV_CTL_TLVT_CONTAINER 96 12462306a36Sopenharmony_ci SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC 12562306a36Sopenharmony_ci SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR 12662306a36Sopenharmony_ci SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \ 12762306a36Sopenharmony_ci SNDRV_CHMAP_RL SNDRV_CHMAP_RR 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciThe channel position is provided in LSB 16bits. The upper bits are 13062306a36Sopenharmony_ciused for bit flags. 13162306a36Sopenharmony_ci:: 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci #define SNDRV_CHMAP_POSITION_MASK 0xffff 13462306a36Sopenharmony_ci #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) 13562306a36Sopenharmony_ci #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci``SNDRV_CHMAP_PHASE_INVERSE`` indicates the channel is phase inverted, 13862306a36Sopenharmony_ci(thus summing left and right channels would result in almost silence). 13962306a36Sopenharmony_ciSome digital mic devices have this. 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciWhen ``SNDRV_CHMAP_DRIVER_SPEC`` is set, all the channel position values 14262306a36Sopenharmony_cidon't follow the standard definition above but driver-specific. 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciRead Operation 14562306a36Sopenharmony_ci-------------- 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ciThe control read operation is for providing the current channel map of 14862306a36Sopenharmony_cithe given stream. The control element returns an integer array 14962306a36Sopenharmony_cicontaining the position of each channel. 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciWhen this is performed before the number of the channel is specified 15262306a36Sopenharmony_ci(i.e. hw_params is set), it should return all channels set to 15362306a36Sopenharmony_ci``UNKNOWN``. 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ciWrite Operation 15662306a36Sopenharmony_ci--------------- 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciThe control write operation is optional, and only for devices that can 15962306a36Sopenharmony_cichange the channel configuration on the fly, such as HDMI. User needs 16062306a36Sopenharmony_cito pass an integer value containing the valid channel positions for 16162306a36Sopenharmony_ciall channels of the assigned PCM substream. 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciThis operation is allowed only at PCM PREPARED state. When called in 16462306a36Sopenharmony_ciother states, it shall return an error. 165