]>
Commit | Line | Data |
---|---|---|
be84bbcc TI |
1 | ALSA PCM channel-mapping API |
2 | ============================ | |
3 | Takashi Iwai <tiwai@suse.de> | |
4 | ||
5 | GENERAL | |
6 | ------- | |
7 | ||
8 | The channel mapping API allows user to query the possible channel maps | |
9 | and the current channel map, also optionally to modify the channel map | |
10 | of the current stream. | |
11 | ||
12 | A channel map is an array of position for each PCM channel. | |
13 | Typically, a stereo PCM stream has a channel map of | |
14 | { front_left, front_right } | |
15 | while a 4.0 surround PCM stream has a channel map of | |
16 | { front left, front right, rear left, rear right }. | |
17 | ||
18 | The problem, so far, was that we had no standard channel map | |
19 | explicitly, and applications had no way to know which channel | |
20 | corresponds to which (speaker) position. Thus, applications applied | |
21 | wrong channels for 5.1 outputs, and you hear suddenly strange sound | |
22 | from rear. Or, some devices secretly assume that center/LFE is the | |
23 | third/fourth channels while others that C/LFE as 5th/6th channels. | |
24 | ||
25 | Also, some devices such as HDMI are configurable for different speaker | |
26 | positions even with the same number of total channels. However, there | |
27 | was no way to specify this because of lack of channel map | |
28 | specification. These are the main motivations for the new channel | |
29 | mapping API. | |
30 | ||
31 | ||
32 | DESIGN | |
33 | ------ | |
34 | ||
35 | Actually, "the channel mapping API" doesn't introduce anything new in | |
36 | the kernel/user-space ABI perspective. It uses only the existing | |
37 | control element features. | |
38 | ||
39 | As a ground design, each PCM substream may contain a control element | |
40 | providing the channel mapping information and configuration. This | |
41 | element is specified by: | |
42 | iface = SNDRV_CTL_ELEM_IFACE_PCM | |
43 | name = "Playback Channel Map" or "Capture Channel Map" | |
44 | device = the same device number for the assigned PCM substream | |
45 | index = the same index number for the assigned PCM substream | |
46 | ||
47 | Note the name is different depending on the PCM substream direction. | |
48 | ||
49 | Each control element provides at least the TLV read operation and the | |
50 | read operation. Optionally, the write operation can be provided to | |
51 | allow user to change the channel map dynamically. | |
52 | ||
53 | * TLV | |
54 | ||
55 | The TLV operation gives the list of available channel | |
56 | maps. A list item of a channel map is usually a TLV of | |
57 | type data-bytes ch0 ch1 ch2... | |
58 | where type is the TLV type value, the second argument is the total | |
59 | bytes (not the numbers) of channel values, and the rest are the | |
60 | position value for each channel. | |
61 | ||
62 | As a TLV type, either SNDRV_CTL_TLVT_CHMAP_FIXED, | |
63 | SNDRV_CTL_TLV_CHMAP_VAR or SNDRV_CTL_TLVT_CHMAP_PAIRED can be used. | |
64 | The _FIXED type is for a channel map with the fixed channel position | |
65 | while the latter two are for flexible channel positions. _VAR type is | |
66 | for a channel map where all channels are freely swappable and _PAIRED | |
67 | type is where pair-wise channels are swappable. For example, when you | |
68 | have {FL/FR/RL/RR} channel map, _PAIRED type would allow you to swap | |
69 | only {RL/RR/FL/FR} while _VAR type would allow even swapping FL and | |
70 | RR. | |
71 | ||
72 | These new TLV types are defined in sound/tlv.h. | |
73 | ||
74 | The available channel position values are defined in sound/asound.h, | |
75 | here is a cut: | |
76 | ||
77 | /* channel positions */ | |
78 | enum { | |
79 | SNDRV_CHMAP_UNKNOWN = 0, | |
7b31d009 TI |
80 | SNDRV_CHMAP_NA, /* N/A, silent */ |
81 | SNDRV_CHMAP_MONO, /* mono stream */ | |
82 | /* this follows the alsa-lib mixer channel value + 3 */ | |
be84bbcc | 83 | SNDRV_CHMAP_FL, /* front left */ |
be84bbcc | 84 | SNDRV_CHMAP_FR, /* front right */ |
be84bbcc | 85 | SNDRV_CHMAP_RL, /* rear left */ |
be84bbcc | 86 | SNDRV_CHMAP_RR, /* rear right */ |
080108c4 TI |
87 | SNDRV_CHMAP_FC, /* front center */ |
88 | SNDRV_CHMAP_LFE, /* LFE */ | |
be84bbcc TI |
89 | SNDRV_CHMAP_SL, /* side left */ |
90 | SNDRV_CHMAP_SR, /* side right */ | |
080108c4 TI |
91 | SNDRV_CHMAP_RC, /* rear center */ |
92 | /* new definitions */ | |
93 | SNDRV_CHMAP_FLC, /* front left center */ | |
94 | SNDRV_CHMAP_FRC, /* front right center */ | |
95 | SNDRV_CHMAP_RLC, /* rear left center */ | |
96 | SNDRV_CHMAP_RRC, /* rear right center */ | |
be84bbcc TI |
97 | SNDRV_CHMAP_FLW, /* front left wide */ |
98 | SNDRV_CHMAP_FRW, /* front right wide */ | |
99 | SNDRV_CHMAP_FLH, /* front left high */ | |
100 | SNDRV_CHMAP_FCH, /* front center high */ | |
101 | SNDRV_CHMAP_FRH, /* front right high */ | |
102 | SNDRV_CHMAP_TC, /* top center */ | |
7b31d009 TI |
103 | SNDRV_CHMAP_TFL, /* top front left */ |
104 | SNDRV_CHMAP_TFR, /* top front right */ | |
105 | SNDRV_CHMAP_TFC, /* top front center */ | |
106 | SNDRV_CHMAP_TRL, /* top rear left */ | |
107 | SNDRV_CHMAP_TRR, /* top rear right */ | |
108 | SNDRV_CHMAP_TRC, /* top rear center */ | |
109 | SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC, | |
be84bbcc TI |
110 | }; |
111 | ||
112 | When a PCM stream can provide more than one channel map, you can | |
113 | provide multiple channel maps in a TLV container type. The TLV data | |
114 | to be returned will contain such as: | |
115 | SNDRV_CTL_TLVT_CONTAINER 96 | |
116 | SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC | |
117 | SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR | |
118 | SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \ | |
119 | SNDRV_CHMAP_RL SNDRV_CHMAP_RR | |
120 | ||
121 | The channel position is provided in LSB 16bits. The upper bits are | |
122 | used for bit flags. | |
123 | ||
124 | #define SNDRV_CHMAP_POSITION_MASK 0xffff | |
125 | #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) | |
126 | #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) | |
127 | ||
128 | SNDRV_CHMAP_PHASE_INVERSE indicates the channel is phase inverted, | |
129 | (thus summing left and right channels would result in almost silence). | |
130 | Some digital mic devices have this. | |
131 | ||
132 | When SNDRV_CHMAP_DRIVER_SPEC is set, all the channel position values | |
133 | don't follow the standard definition above but driver-specific. | |
134 | ||
135 | * READ OPERATION | |
136 | ||
137 | The control read operation is for providing the current channel map of | |
138 | the given stream. The control element returns an integer array | |
139 | containing the position of each channel. | |
140 | ||
141 | When this is performed before the number of the channel is specified | |
142 | (i.e. hw_params is set), it should return all channels set to | |
143 | UNKNOWN. | |
144 | ||
145 | * WRITE OPERATION | |
146 | ||
147 | The control write operation is optional, and only for devices that can | |
148 | change the channel configuration on the fly, such as HDMI. User needs | |
149 | to pass an integer value containing the valid channel positions for | |
150 | all channels of the assigned PCM substream. | |
151 | ||
152 | This operation is allowed only at PCM PREPARED state. When called in | |
153 | other states, it shall return an error. |