Files
2026-08-24 10:03:24 +08:00

154 lines
4.8 KiB
C

/*
* Copyright (C) 2019 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* DESCRIPTION:
* to get/set eARC RX/TX latency and Capability Data Structure.
*
*/
#define LOG_TAG "audio_hw_hal_earc"
//#define LOG_NDEBUG 0
#include <earc_utils.h>
#define CDS_VERSION 0x1
#define CDS_MAX 256
static void earc_cds_conf_to_str(char *earc_cds, char *cds_str, int hex, struct aml_arc_hdmi_desc *hdmi_descs)
{
char *cds_blocks;
char *audio_blocks;
char cds_blockid;
int blen = 0, dlen = 0, i, j, n = 0, m, index = 0;
int tag_code = 0;
if (!cds_str || !earc_cds)
return;
cds_str[0] = '\0';
/* bypass version */
cds_blocks = &earc_cds[1];
char cds_str_last[AUDIO_HAL_CHAR_MAX_LEN] = {0};
for (i = 0; i < CDS_MAX - 1;) {
/* block id */
cds_blockid = cds_blocks[i];
if (cds_blockid == 1 || cds_blockid == 2) {
blen = cds_blocks[1 + i]; /* block length */
audio_blocks = &cds_blocks[2 + i];
for (j = 0; j < blen;) {
/* CTA-861-G Audio Data Block */
ALOGI("%s, tagl:%#x\n", __FUNCTION__, audio_blocks[j]);
dlen = audio_blocks[j] & 0x1f; /* length of audio data block */
tag_code = (audio_blocks[j] & 0xe0) >> 5;
/* so far only get Audio Data Block Tag(tag_code = 1) */
for (m = 0; m < dlen && tag_code == 1; m ++) {
/* skip 3 bytes which is for pcm format */
if (m % 3 == 0 && ((audio_blocks[1 + j + m] >> 3) & 0xf) == 0x1) {
m += 2;
continue;
}
if (hex) {
cds_str[index++] = audio_blocks[1 + j + m];
} else {
memcpy(cds_str_last, cds_str, AUDIO_HAL_CHAR_MAX_LEN);
sprintf(cds_str, "%s%d, ", cds_str_last, audio_blocks[1 + j + m]);
}
}
/* Dolby Audio and Dolby Atmos
* over HDMI Specification.
* The audio_hw_profile.c fils also
* has the detail description.
*/
if (tag_code == 0x7) {
if (audio_blocks[j + 1] == 0x11 &&
audio_blocks[j + 2] == 0x46 &&
audio_blocks[j + 3] == 0xD0 &&
audio_blocks[j + 4] == 0x00 &&
audio_blocks[j + 6] == 0x01)
hdmi_descs->mat_fmt.MAT_PCM_48kHz_only = true;
}
if (tag_code == 1)
n += dlen;
j += dlen + 1;
ALOGV("%s, j:%d, cds_str:%s\n", __FUNCTION__, j, cds_str);
}
i += blen + 2;
} else if (cds_blockid == 3) {
/* ignore now */
}
break;
}
if (!hex) {
int length = strlen(cds_str);
cds_str[length - 2] = '\0';
}
ALOGI("%s, bytes:%d, cds_str:%s:end\n", __FUNCTION__, n, cds_str);
}
/*
* CDS Blocks, Now we support only Block Id = 1
*/
void earc_cds_str_to_conf(char *cds_str, char *earc_cds)
{
char *start = cds_str;
char *end;
long int data;
int len = 0;
if (!cds_str || !earc_cds)
return;
/* data for Block ID=1 */
while (start) {
data = strtol(start, &end, 16);
earc_cds[4 + len] = data;
len ++;
start = end;
if (!(*end))
break;
}
ALOGV("%s, cds:%s len:%d\n", __FUNCTION__, cds_str, len);
/* CDS version */
earc_cds[0] = CDS_VERSION;
/* Block ID = 0x1 */
earc_cds[1] = 0x1;
/* Block len */
earc_cds[2] = len + 1;
/* Tag = 1, length of SADs */
earc_cds[3] = (0x1 << 5) | (len & 0x1f);
}
/*
* fetch CDS from eARC_RX, and will update CDS to EDID
* cds_str: CTA short audio descriptor
*/
int earctx_fetch_cds(struct aml_mixer_handle *amixer, char *cds_str, int hex, struct aml_arc_hdmi_desc *hdmi_descs)
{
char earc_cds[CDS_MAX] = {0};
aml_mixer_ctrl_get_array(amixer, AML_MIXER_ID_EARCTX_CDS, earc_cds, CDS_MAX);
earc_cds_conf_to_str(earc_cds, cds_str, hex, hdmi_descs);
return 0;
}