1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "audio_hw_primary" 18 19 #include <stdlib.h> 20 #include <stdio.h> 21 22 #include <cutils/log.h> 23 24 /* 25 * This is the sysfs path for the HDMI audio data block 26 */ 27 #define AUDIO_DATA_BLOCK_PATH "/sys/class/graphics/fb1/audio_data_block" 28 29 /* 30 * This file will have a maximum of 38 bytes: 31 * 32 * 4 bytes: number of audio blocks 33 * 4 bytes: total length of Short Audio Descriptor (SAD) blocks 34 * Maximum 10 * 3 bytes: SAD blocks 35 */ 36 #define MAX_SAD_BLOCKS 10 37 #define SAD_BLOCK_SIZE 3 38 39 /* EDID format ID for LPCM audio */ 40 #define EDID_FORMAT_LPCM 1 41 42 struct audio_block_header 43 { 44 int reserved; 45 int length; 46 }; 47 48 int edid_get_max_channels(void) 49 { 50 FILE *file; 51 struct audio_block_header header; 52 char block[MAX_SAD_BLOCKS * SAD_BLOCK_SIZE]; 53 char *sad = block; 54 int num_audio_blocks; 55 int channel_count; 56 int max_channels = 0; 57 int i; 58 59 file = fopen(AUDIO_DATA_BLOCK_PATH, "rb"); 60 if (file == NULL) { 61 ALOGE("Unable to open '%s'", AUDIO_DATA_BLOCK_PATH); 62 return 0; 63 } 64 65 /* Read audio block header */ 66 fread(&header, 1, sizeof(header), file); 67 68 /* Read SAD blocks, clamping the maximum size for safety */ 69 if (header.length > (int)sizeof(block)) 70 header.length = (int)sizeof(block); 71 fread(&block, header.length, 1, file); 72 73 fclose(file); 74 75 /* Calculate the number of SAD blocks */ 76 num_audio_blocks = header.length / SAD_BLOCK_SIZE; 77 78 for (i = 0; i < num_audio_blocks; i++) { 79 /* Only consider LPCM blocks */ 80 if ((sad[0] >> 3) != EDID_FORMAT_LPCM) 81 continue; 82 83 channel_count = (sad[0] & 0x7) + 1; 84 if (channel_count > max_channels) 85 max_channels = channel_count; 86 87 /* Advance to next block */ 88 sad += 3; 89 } 90 91 return max_channels; 92 } 93 94