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