1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "audio_driver_log.h"
10 #include "audio_hdmi_codec_linux.h"
11 #include "audio_sapm.h"
12
13 #define HDF_LOG_TAG HDF_AUDIO_HDMI
14
15 #define HDMI_CODEC_CHMAP_IDX_UNKNOWN (-1)
16
17 #define CARD_ID_INDEX_0 0
18 #define CARD_ID_INDEX_1 1
19 #define CARD_ID_INDEX_2 2
20 #define CARD_ID_INDEX_3 3
21 #define CARD_ID_INDEX_4 4
22 #define CARD_ID_INDEX_5 5
23 #define CARD_ID_INDEX_6 6
24 #define CARD_ID_INDEX_7 7
25 #define CARD_ID_INDEX_8 8
26 #define CARD_ID_INDEX_9 9
27 #define CARD_ID_INDEX_10 0xa
28 #define CARD_ID_INDEX_11 0xb
29 #define CARD_ID_INDEX_12 0xc
30 #define CARD_ID_INDEX_13 0xd
31 #define CARD_ID_INDEX_14 0xe
32 #define CARD_ID_INDEX_15 0xf
33 #define CARD_ID_INDEX_16 0x10
34 #define CARD_ID_INDEX_17 0x11
35 #define CARD_ID_INDEX_18 0x12
36 #define CARD_ID_INDEX_19 0x13
37 #define CARD_ID_INDEX_20 0x14
38 #define CARD_ID_INDEX_21 0x15
39 #define CARD_ID_INDEX_22 0x16
40 #define CARD_ID_INDEX_23 0x17
41 #define CARD_ID_INDEX_24 0x18
42 #define CARD_ID_INDEX_25 0x19
43 #define CARD_ID_INDEX_26 0x1a
44 #define CARD_ID_INDEX_27 0x1b
45 #define CARD_ID_INDEX_28 0x1c
46 #define CARD_ID_INDEX_29 0x1d
47 #define CARD_ID_INDEX_30 0x1e
48 #define CARD_ID_INDEX_31 0x1f
49
50 #define CHANNEL_NUM_2 2
51 #define CHANNEL_NUM_4 4
52 #define CHANNEL_NUM_6 6
53 #define CHANNEL_NUM_8 8
54
55 enum HdmiCodecCeaSpkPlacement {
56 FL = BIT(0), /* Front Left */
57 FC = BIT(1), /* Front Center */
58 FR = BIT(2), /* Front Right */
59 FLC = BIT(3), /* Front Left Center */
60 FRC = BIT(4), /* Front Right Center */
61 RL = BIT(5), /* Rear Left */
62 RC = BIT(6), /* Rear Center */
63 RR = BIT(7), /* Rear Right */
64 RLC = BIT(8), /* Rear Left Center */
65 RRC = BIT(9), /* Rear Right Center */
66 LFE = BIT(10), /* Low Frequency Effect */
67 };
68
69 /*
70 * cea Speaker allocation structure
71 */
72 struct HdmiCodecCeaSpkAlloc {
73 const int32_t cardId;
74 uint32_t channelNum;
75 uint32_t mask;
76 };
77
78 /*
79 * g_hdmiCodecCeaSpkAlloc: speaker configuration available for CEA
80 *
81 * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct
82 * The preceding ones have better chances to be selected by
83 * HdmiCodecGetChAllocTableIdx().
84 */
85 static const struct HdmiCodecCeaSpkAlloc g_hdmiCodecCeaSpkAlloc[] = {
86 {.cardId = CARD_ID_INDEX_0, .channelNum = CHANNEL_NUM_2, .mask = FL | FR },
87 /* 2.1 */
88 {.cardId = CARD_ID_INDEX_1, .channelNum = CHANNEL_NUM_4, .mask = FL | FR | LFE },
89 /* Dolby Surround */
90 {.cardId = CARD_ID_INDEX_2, .channelNum = CHANNEL_NUM_4, .mask = FL | FR | FC },
91 /* surround51 */
92 {.cardId = CARD_ID_INDEX_11, .channelNum = CHANNEL_NUM_6, .mask = FL | FR | LFE | FC | RL | RR },
93 /* surround40 */
94 {.cardId = CARD_ID_INDEX_8, .channelNum = CHANNEL_NUM_6, .mask = FL | FR | RL | RR },
95 /* surround41 */
96 {.cardId = CARD_ID_INDEX_9, .channelNum = CHANNEL_NUM_6, .mask = FL | FR | LFE | RL | RR },
97 /* surround50 */
98 {.cardId = CARD_ID_INDEX_10, .channelNum = CHANNEL_NUM_6, .mask = FL | FR | FC | RL | RR },
99 /* 6.1 */
100 {.cardId = CARD_ID_INDEX_15, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC | RL | RR | RC },
101 /* surround71 */
102 {.cardId = CARD_ID_INDEX_19, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC},
103 /* others */
104 {.cardId = CARD_ID_INDEX_3, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC },
105 {.cardId = CARD_ID_INDEX_4, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RC },
106 {.cardId = CARD_ID_INDEX_5, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RC },
107 {.cardId = CARD_ID_INDEX_6, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FC | RC },
108 {.cardId = CARD_ID_INDEX_7, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC | RC },
109 {.cardId = CARD_ID_INDEX_12, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RC | RL | RR },
110 {.cardId = CARD_ID_INDEX_13, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RL | RR | RC },
111 {.cardId = CARD_ID_INDEX_14, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FC | RL | RR | RC },
112 {.cardId = CARD_ID_INDEX_16, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RL | RR | RLC | RRC },
113 {.cardId = CARD_ID_INDEX_17, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RL | RR | RLC | RRC },
114 {.cardId = CARD_ID_INDEX_18, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FC | RL | RR | RLC | RRC },
115 {.cardId = CARD_ID_INDEX_20, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FLC | FRC },
116 {.cardId = CARD_ID_INDEX_21, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FLC | FRC },
117 {.cardId = CARD_ID_INDEX_22, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FC | FLC | FRC },
118 {.cardId = CARD_ID_INDEX_23, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC | FLC | FRC },
119 {.cardId = CARD_ID_INDEX_24, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RC | FLC | FRC },
120 {.cardId = CARD_ID_INDEX_25, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RC | FLC | FRC },
121 {.cardId = CARD_ID_INDEX_26, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RC | FC | FLC | FRC },
122 {.cardId = CARD_ID_INDEX_27, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RC | FC | FLC | FRC },
123 {.cardId = CARD_ID_INDEX_28, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | RL | RR | FLC | FRC },
124 {.cardId = CARD_ID_INDEX_29, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | RL | RR | FLC | FRC },
125 {.cardId = CARD_ID_INDEX_30, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | FC | RL | RR | FLC | FRC },
126 {.cardId = CARD_ID_INDEX_31, .channelNum = CHANNEL_NUM_8, .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC},
127 };
128
129 static const struct AudioSapmRoute g_audioRoutes[] = {
130 {"SPKL", NULL, "SPKL PGA"},
131 {"HPL", NULL, "HPL PGA" },
132 {"HPR", NULL, "HPR PGA" },
133 {"SPKL PGA", "Speaker1 Switch", "DAC1" },
134 {"HPL PGA", "Headphone1 Switch", "DAC2" },
135 {"HPR PGA", "Headphone2 Switch", "DAC3" },
136
137 {"ADCL", NULL, "LPGA" },
138 {"ADCR", NULL, "RPGA" },
139 {"LPGA", "LPGA MIC Switch", "MIC1" },
140 {"RPGA", "RPGA MIC Switch", "MIC2" },
141 };
142
AudioHdmiCodecDeviceInit(struct AudioCard * audioCard,const struct CodecDevice * device)143 int32_t AudioHdmiCodecDeviceInit(struct AudioCard *audioCard, const struct CodecDevice *device)
144 {
145 if ((audioCard == NULL) || (device == NULL) || device->devData == NULL) {
146 AUDIO_DRIVER_LOG_ERR("input para is NULL.");
147 return HDF_ERR_INVALID_OBJECT;
148 }
149
150 if (AudioAddControls(audioCard, device->devData->controls, device->devData->numControls) != HDF_SUCCESS) {
151 AUDIO_DRIVER_LOG_ERR("add controls failed.");
152 return HDF_FAILURE;
153 }
154
155 if (AudioSapmNewComponents(audioCard, device->devData->sapmComponents, device->devData->numSapmComponent) !=
156 HDF_SUCCESS) {
157 AUDIO_DRIVER_LOG_ERR("new components failed.");
158 return HDF_FAILURE;
159 }
160
161 if (AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes)) != HDF_SUCCESS) {
162 AUDIO_DRIVER_LOG_ERR("add route failed.");
163 return HDF_FAILURE;
164 }
165
166 if (AudioSapmNewControls(audioCard) != HDF_SUCCESS) {
167 AUDIO_DRIVER_LOG_ERR("add sapm controls failed.");
168 return HDF_FAILURE;
169 }
170
171 AUDIO_DRIVER_LOG_DEBUG("success.");
172 return HDF_SUCCESS;
173 }
174
AudioHdmiCodecDaiDeviceInit(struct AudioCard * card,const struct DaiDevice * device)175 int32_t AudioHdmiCodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *device)
176 {
177 struct HdmiCodecPriv *hdmiCodecPriv = NULL;
178
179 hdmiCodecPriv = AudioGetHdmiCodecPriv();
180 if (hdmiCodecPriv == NULL) {
181 AUDIO_DRIVER_LOG_ERR("HdmiCodecPriv is null.");
182 return HDF_FAILURE;
183 }
184
185 (void)card;
186 (void)device;
187
188 mutex_lock(&hdmiCodecPriv->lock);
189 hdmiCodecPriv->busy = false;
190 mutex_unlock(&hdmiCodecPriv->lock);
191
192 AUDIO_DRIVER_LOG_DEBUG("success.");
193 return HDF_SUCCESS;
194 }
195
AudioHdmiCodecDaiStartup(const struct AudioCard * card,const struct DaiDevice * device)196 int32_t AudioHdmiCodecDaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
197 {
198 int32_t ret;
199 struct HdmiCodecPriv *hdmiCodecPriv = NULL;
200
201 hdmiCodecPriv = AudioGetHdmiCodecPriv();
202 if (hdmiCodecPriv == NULL) {
203 AUDIO_DRIVER_LOG_ERR("HdmiCodecPriv is null.");
204 return HDF_FAILURE;
205 }
206
207 (void)card;
208 (void)device;
209 mutex_lock(&hdmiCodecPriv->lock);
210 if (hdmiCodecPriv->busy) {
211 AUDIO_DRIVER_LOG_ERR("Only one simultaneous stream supported!");
212 mutex_unlock(&hdmiCodecPriv->lock);
213 return HDF_FAILURE;
214 }
215
216 if (hdmiCodecPriv->hdmiCodecData.ops == NULL) {
217 mutex_unlock(&hdmiCodecPriv->lock);
218 AUDIO_DRIVER_LOG_ERR("hdmiCodecData.ops is null.");
219 return HDF_FAILURE;
220 }
221 if (hdmiCodecPriv->hdmiCodecData.ops->audio_startup != NULL) {
222 ret = hdmiCodecPriv->hdmiCodecData.ops->audio_startup(hdmiCodecPriv->dev, hdmiCodecPriv->hdmiCodecData.data);
223 if (ret != 0) {
224 mutex_unlock(&hdmiCodecPriv->lock);
225 AUDIO_DRIVER_LOG_ERR("audio_startup is failed.");
226 return ret;
227 }
228 }
229
230 hdmiCodecPriv->busy = true;
231 mutex_unlock(&hdmiCodecPriv->lock);
232
233 AUDIO_DRIVER_LOG_DEBUG("success.");
234 return HDF_SUCCESS;
235 }
236
AudioHdmiCodecDaiShutdown(const struct AudioCard * card,const struct DaiDevice * device)237 int32_t AudioHdmiCodecDaiShutdown(const struct AudioCard *card, const struct DaiDevice *device)
238 {
239 struct HdmiCodecPriv *hdmiCodecPriv = NULL;
240
241 (void)card;
242 (void)device;
243 hdmiCodecPriv = AudioGetHdmiCodecPriv();
244 if (hdmiCodecPriv == NULL) {
245 AUDIO_DRIVER_LOG_ERR("hdmiCodecPriv is null.");
246 return HDF_FAILURE;
247 }
248
249 hdmiCodecPriv->chmapIdx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
250 if (hdmiCodecPriv->hdmiCodecData.ops == NULL || hdmiCodecPriv->hdmiCodecData.ops->audio_shutdown == NULL) {
251 AUDIO_DRIVER_LOG_ERR("hdmiCodecData.ops->audio_shutdown is null.");
252 return HDF_FAILURE;
253 }
254 hdmiCodecPriv->hdmiCodecData.ops->audio_shutdown(hdmiCodecPriv->dev, hdmiCodecPriv->hdmiCodecData.data);
255
256 mutex_lock(&hdmiCodecPriv->lock);
257 hdmiCodecPriv->busy = false;
258 mutex_unlock(&hdmiCodecPriv->lock);
259
260 AUDIO_DRIVER_LOG_DEBUG("success.");
261 return HDF_SUCCESS;
262 }
263
HdmiCodecSpkMaskFromAlloc(uint32_t spkAlloc)264 static unsigned long HdmiCodecSpkMaskFromAlloc(uint32_t spkAlloc)
265 {
266 uint32_t index;
267 uint32_t temp;
268 static const uint32_t hdmiCodecEldSpkAllocBits[] = {
269 FL | FR, LFE, FC, RL | RR, RC, FLC | FRC, RLC | RRC,
270 };
271 uint32_t spkMask = 0;
272
273 for (index = 0; index < HDF_ARRAY_SIZE(hdmiCodecEldSpkAllocBits); index++) {
274 temp = spkAlloc & (1 << index);
275 if (temp != 0) {
276 spkMask |= hdmiCodecEldSpkAllocBits[index];
277 }
278 }
279 return spkMask;
280 }
281
HdmiCodecGetChAllocTableIdx(struct HdmiCodecPriv * hdmiCodecPriv,uint8_t channels,int32_t * index)282 static int32_t HdmiCodecGetChAllocTableIdx(struct HdmiCodecPriv *hdmiCodecPriv, uint8_t channels, int32_t *index)
283 {
284 int32_t item;
285 uint8_t spkAlloc;
286 unsigned long spkMask;
287
288 spkAlloc = drm_eld_get_spk_alloc(hdmiCodecPriv->eld);
289 spkMask = HdmiCodecSpkMaskFromAlloc(spkAlloc);
290
291 for (item = 0; item < HDF_ARRAY_SIZE(g_hdmiCodecCeaSpkAlloc); item++) {
292 if (spkAlloc == 0 && g_hdmiCodecCeaSpkAlloc[item].cardId == 0) {
293 *index = item;
294 return HDF_SUCCESS;
295 }
296 if (g_hdmiCodecCeaSpkAlloc[item].channelNum != channels) {
297 continue;
298 }
299 if (!(g_hdmiCodecCeaSpkAlloc[item].mask == (spkMask & g_hdmiCodecCeaSpkAlloc[item].mask))) {
300 continue;
301 }
302 *index = item;
303 return HDF_SUCCESS;
304 }
305 return HDF_FAILURE;
306 }
307
AudioHdmiCodecDaiHwParams(const struct AudioCard * card,const struct AudioPcmHwParams * param)308 int32_t AudioHdmiCodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
309 {
310 struct HdmiCodecPriv *hdmiCodecPriv = NULL;
311 struct hdmi_codec_daifmt hdmiCodecDaifmt;
312 struct hdmi_codec_params hdmiCodecParams;
313 int32_t ret;
314 int32_t idx = 0;
315
316 (void)card;
317 if (param == NULL) {
318 AUDIO_DRIVER_LOG_ERR("input param is null.");
319 return HDF_FAILURE;
320 }
321
322 hdmiCodecPriv = AudioGetHdmiCodecPriv();
323 if (hdmiCodecPriv == NULL) {
324 AUDIO_DRIVER_LOG_ERR("hdmiCodecPriv is null.");
325 return HDF_FAILURE;
326 }
327
328 (void)memset_s(&hdmiCodecParams, sizeof(struct hdmi_codec_params), 0, sizeof(struct hdmi_codec_params));
329 (void)memset_s(&hdmiCodecDaifmt, sizeof(struct hdmi_codec_daifmt), 0, sizeof(struct hdmi_codec_daifmt));
330 #ifdef CONFIG_DRM_DW_HDMI_I2S_AUDIO
331 hdmi_audio_infoframe_init(&hdmiCodecParams.cea);
332 #endif
333 hdmiCodecParams.cea.channels = param->channels;
334 hdmiCodecParams.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
335 hdmiCodecParams.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
336 hdmiCodecParams.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
337
338 /* Select a channel allocation that matches with ELD and pcm channels */
339 ret = HdmiCodecGetChAllocTableIdx(hdmiCodecPriv, hdmiCodecParams.cea.channels, &idx);
340 if (ret != HDF_SUCCESS) {
341 AUDIO_DRIVER_LOG_ERR("Not able to map channels to speakers", ret);
342 hdmiCodecPriv->chmapIdx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
343 return ret;
344 }
345 hdmiCodecParams.cea.channel_allocation = g_hdmiCodecCeaSpkAlloc[idx].cardId;
346 hdmiCodecPriv->chmapIdx = g_hdmiCodecCeaSpkAlloc[idx].cardId;
347
348 hdmiCodecParams.sample_width = param->format;
349 hdmiCodecParams.sample_rate = param->rate;
350 hdmiCodecParams.channels = param->channels;
351
352 if (hdmiCodecPriv->hdmiCodecData.ops == NULL || hdmiCodecPriv->hdmiCodecData.ops->hw_params == NULL) {
353 AUDIO_DRIVER_LOG_ERR("hdmiCodecData.ops->audio_shutdown is null.");
354 return HDF_FAILURE;
355 }
356 ret = hdmiCodecPriv->hdmiCodecData.ops->hw_params(
357 hdmiCodecPriv->dev, hdmiCodecPriv->hdmiCodecData.data, &hdmiCodecDaifmt, &hdmiCodecParams);
358 if (ret != HDF_SUCCESS) {
359 AUDIO_DRIVER_LOG_ERR("hw_params is failed.");
360 return ret;
361 }
362
363 AUDIO_DRIVER_LOG_DEBUG("success.");
364 return HDF_SUCCESS;
365 }
366
AudioHdmiCodecDaiMuteStream(const struct AudioCard * audioCard,const struct DaiDevice * dai,bool mute,int32_t direction)367 int32_t AudioHdmiCodecDaiMuteStream(
368 const struct AudioCard *audioCard, const struct DaiDevice *dai, bool mute, int32_t direction)
369 {
370 struct HdmiCodecPriv *hdmiCodecPriv = NULL;
371 int32_t ret;
372
373 (void)audioCard;
374 (void)dai;
375 hdmiCodecPriv = AudioGetHdmiCodecPriv();
376 if (hdmiCodecPriv == NULL) {
377 AUDIO_DRIVER_LOG_ERR("hdmiCodecPriv is null.");
378 return HDF_FAILURE;
379 }
380
381 if (hdmiCodecPriv->hdmiCodecData.ops == NULL) {
382 AUDIO_DRIVER_LOG_ERR("hdmiCodecPriv->hdmiCodecData.ops is null.");
383 return HDF_FAILURE;
384 }
385 if (hdmiCodecPriv->hdmiCodecData.ops->mute_stream != NULL &&
386 (direction == AUDIO_RENDER_STREAM_OUT || !hdmiCodecPriv->hdmiCodecData.ops->no_capture_mute)) {
387 ret = hdmiCodecPriv->hdmiCodecData.ops->mute_stream(
388 hdmiCodecPriv->dev, hdmiCodecPriv->hdmiCodecData.data, mute, direction);
389 if (ret != HDF_SUCCESS) {
390 AUDIO_DRIVER_LOG_ERR("mute_stream is failed.");
391 return ret;
392 }
393 }
394 AUDIO_DRIVER_LOG_DEBUG("success.");
395 return HDF_SUCCESS;
396 }
397
AudioHdmiCodecReadReg(const struct CodecDevice * codec,uint32_t reg,uint32_t * val)398 int32_t AudioHdmiCodecReadReg(const struct CodecDevice *codec, uint32_t reg, uint32_t *val)
399 {
400 (void)codec;
401 (void)reg;
402 (void)val;
403
404 AUDIO_DRIVER_LOG_DEBUG("success.");
405 return HDF_SUCCESS;
406 }
407
AudioHdmiCodecWriteReg(const struct CodecDevice * codec,uint32_t reg,uint32_t value)408 int32_t AudioHdmiCodecWriteReg(const struct CodecDevice *codec, uint32_t reg, uint32_t value)
409 {
410 (void)codec;
411 (void)reg;
412 (void)value;
413
414 AUDIO_DRIVER_LOG_DEBUG("success.");
415 return HDF_SUCCESS;
416 }
417
AudioHdmiCodecDaiReadReg(const struct DaiDevice * dai,uint32_t reg,uint32_t * value)418 int32_t AudioHdmiCodecDaiReadReg(const struct DaiDevice *dai, uint32_t reg, uint32_t *value)
419 {
420 (void)dai;
421 (void)reg;
422 (void)value;
423
424 AUDIO_DRIVER_LOG_DEBUG("success.");
425 return HDF_SUCCESS;
426 }
427
AudioHdmiCodecDaiWriteReg(const struct DaiDevice * dai,uint32_t reg,uint32_t value)428 int32_t AudioHdmiCodecDaiWriteReg(const struct DaiDevice *dai, uint32_t reg, uint32_t value)
429 {
430 (void)dai;
431 (void)reg;
432 (void)value;
433
434 AUDIO_DRIVER_LOG_DEBUG("success.");
435 return HDF_SUCCESS;
436 }
437