154 lines
4.8 KiB
C
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;
|
|
}
|