void packets_AudioInfoFrame(u16 baseAddr, audioParams_t *params) { LOG_TRACE(); halFrameComposerAudioInfo_ChannelCount(baseAddr + FC_BASE_ADDR, audioParams_ChannelCount( params)); halFrameComposerAudioInfo_AllocateChannels(baseAddr + FC_BASE_ADDR, audioParams_GetChannelAllocation(params)); halFrameComposerAudioInfo_LevelShiftValue(baseAddr + FC_BASE_ADDR, audioParams_GetLevelShiftValue(params)); halFrameComposerAudioInfo_DownMixInhibit(baseAddr + FC_BASE_ADDR, audioParams_GetDownMixInhibitFlag(params)); if ((audioParams_GetCodingType(params) == ONE_BIT_AUDIO) || (audioParams_GetCodingType(params) == DST)) { /* Audio InfoFrame sample frequency when OBA or DST */ if (audioParams_GetSamplingFrequency(params) == 32000) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 1); } else if (audioParams_GetSamplingFrequency(params) == 44100) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 2); } else if (audioParams_GetSamplingFrequency(params) == 48000) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 3); } else if (audioParams_GetSamplingFrequency(params) == 88200) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 4); } else if (audioParams_GetSamplingFrequency(params) == 96000) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 5); } else if (audioParams_GetSamplingFrequency(params) == 176400) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 6); } else if (audioParams_GetSamplingFrequency(params) == 192000) { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 7); } else { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 0); } } else { halFrameComposerAudioInfo_SampleFreq(baseAddr + FC_BASE_ADDR, 0); /* otherwise refer to stream header (0) */ } halFrameComposerAudioInfo_CodingType(baseAddr + FC_BASE_ADDR, 0); /* for HDMI refer to stream header (0) */ halFrameComposerAudioInfo_SamplingSize(baseAddr + FC_BASE_ADDR, 0); /* for HDMI refer to stream header (0) */ }
int audio_Configure(u16 baseAddr, audioParams_t *params, u16 pixelClk, unsigned int ratioClk) { u16 i = 0; LOG_TRACE(); /* more than 2 channels => layout 1 else layout 0 */ halFrameComposerAudio_PacketLayout(baseAddr + FC_BASE_ADDR, ((audioParams_ChannelCount(params) + 1) > 2) ? 1 : 0); /* iec validity and user bits (IEC 60958-1 */ for (i = 0; i < 4; i++) { /* audioParams_IsChannelEn considers left as 1 channel and * right as another (+1), hence the x2 factor in the following */ /* validity bit is 0 when reliable, which is !IsChannelEn */ halFrameComposerAudio_ValidityRight(baseAddr + FC_BASE_ADDR, !(audioParams_IsChannelEn(params, (2 * i))), i); halFrameComposerAudio_ValidityLeft(baseAddr + FC_BASE_ADDR, !(audioParams_IsChannelEn(params, (2 * i) + 1)), i); halFrameComposerAudio_UserRight(baseAddr + FC_BASE_ADDR, USER_BIT, i); halFrameComposerAudio_UserLeft(baseAddr + FC_BASE_ADDR, USER_BIT, i); } /* IEC - not needed if non-linear PCM */ halFrameComposerAudio_IecCgmsA(baseAddr + FC_BASE_ADDR, audioParams_GetIecCgmsA(params)); halFrameComposerAudio_IecCopyright(baseAddr + FC_BASE_ADDR, audioParams_GetIecCopyright(params) ? 0 : 1); halFrameComposerAudio_IecCategoryCode(baseAddr + FC_BASE_ADDR, audioParams_GetIecCategoryCode(params)); halFrameComposerAudio_IecPcmMode(baseAddr + FC_BASE_ADDR, audioParams_GetIecPcmMode(params)); halFrameComposerAudio_IecSource(baseAddr + FC_BASE_ADDR, audioParams_GetIecSourceNumber(params)); for (i = 0; i < 4; i++) { /* 0, 1, 2, 3 */ halFrameComposerAudio_IecChannelLeft(baseAddr + FC_BASE_ADDR, 2* i + 1, i); /* 1, 3, 5, 7 */ halFrameComposerAudio_IecChannelRight(baseAddr + FC_BASE_ADDR, 2* (i + 1), i); /* 2, 4, 6, 8 */ } halFrameComposerAudio_IecClockAccuracy(baseAddr + FC_BASE_ADDR, audioParams_GetIecClockAccuracy(params)); halFrameComposerAudio_IecSamplingFreq(baseAddr + FC_BASE_ADDR, audioParams_IecSamplingFrequency(params)); halFrameComposerAudio_IecOriginalSamplingFreq(baseAddr + FC_BASE_ADDR, audioParams_IecOriginalSamplingFrequency(params)); halFrameComposerAudio_IecWordLength(baseAddr + FC_BASE_ADDR, audioParams_IecWordLength(params)); halAudioI2s_Select(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, (audioParams_GetInterfaceType(params) == I2S)? 1 : 0); /* * ATTENTION: fixed I2S data enable configuration * is equivalent to 0x1 for 1 or 2 channels * is equivalent to 0x3 for 3 or 4 channels * is equivalent to 0x7 for 5 or 6 channels * is equivalent to 0xF for 7 or 8 channels */ halAudioI2s_DataEnable(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, 0xF); /* ATTENTION: fixed I2S data mode (standard) */ halAudioI2s_DataMode(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, 0); halAudioI2s_DataWidth(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, audioParams_GetSampleSize(params)); halAudioI2s_InterruptMask(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, 3); halAudioI2s_InterruptPolarity(baseAddr + AUD_BASE_ADDR + AUDIO_I2S, 3); halAudioI2s_ResetFifo(baseAddr + AUD_BASE_ADDR + AUDIO_I2S); halAudioSpdif_NonLinearPcm(baseAddr + AUD_BASE_ADDR + AUDIO_SPDIF, audioParams_IsLinearPCM(params)? 0 : 1); halAudioSpdif_DataWidth(baseAddr + AUD_BASE_ADDR + AUDIO_SPDIF, audioParams_GetSampleSize(params)); halAudioSpdif_InterruptMask(baseAddr + AUD_BASE_ADDR + AUDIO_SPDIF, 3); halAudioSpdif_InterruptPolarity(baseAddr + AUD_BASE_ADDR + AUDIO_SPDIF, 3); halAudioSpdif_ResetFifo(baseAddr + AUD_BASE_ADDR + AUDIO_SPDIF); halAudioHbr_Select(baseAddr + AUD_BASE_ADDR + AUDIO_HBR, (audioParams_GetInterfaceType(params) == HBR)? 1 : 0); halAudioHbr_InterruptMask(baseAddr + AUD_BASE_ADDR + AUDIO_HBR, 7); halAudioHbr_InterruptPolarity(baseAddr + AUD_BASE_ADDR + AUDIO_HBR, 7); halAudioHbr_ResetFifo(baseAddr + AUD_BASE_ADDR + AUDIO_HBR); if (audioParams_GetInterfaceType(params) == GPA) { for (i = 0; i < 8; i++) { halAudioGpa_ChannelEnable(baseAddr + AUD_BASE_ADDR + AUDIO_GPA, audioParams_IsChannelEn(params, i), i); } halAudioGpa_HbrEnable(baseAddr + AUD_BASE_ADDR + AUDIO_GPA, audioParams_GetPacketType(params) == HBR_STREAM? 1: 0); halAudioGpa_InterruptMask(baseAddr + AUD_BASE_ADDR + AUDIO_GPA, 3); halAudioGpa_InterruptPolarity(baseAddr + AUD_BASE_ADDR + AUDIO_GPA, 3); halAudioGpa_ResetFifo(baseAddr + AUD_BASE_ADDR + AUDIO_GPA); } halAudioClock_N(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, audio_ComputeN(baseAddr, audioParams_GetSamplingFrequency(params), pixelClk, ratioClk)); /* if NOT GPA interface, use automatic mode, else, compute CTS */ halAudioClock_Cts(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, (audioParams_GetInterfaceType(params) != GPA)? 0: audio_ComputeCts(baseAddr, audioParams_GetSamplingFrequency(params), pixelClk, ratioClk)); if (audioParams_GetInterfaceType(params) != GPA) { switch (audioParams_GetClockFsFactor(params)) { /* This version does not support DRU Bypass - found in controller 1v30a * 0 128Fs I2S- (SPDIF when DRU in bypass) * 1 256Fs I2S- * 2 512Fs I2S-HBR-(SPDIF - when NOT DRU bypass) * 3 1024Fs I2S-(SPDIF - when NOT DRU bypass) * 4 64Fs I2S */ case 64: #if 0 if (audioParams_GetInterfaceType(params) != I2S) { return FALSE; } #endif halAudioClock_F(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, 4); break; case 128: #if 0 if (audioParams_GetInterfaceType(params) != I2S) { return FALSE; } #endif halAudioClock_F(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, 0); break; case 256: #if 0 if (audioParams_GetInterfaceType(params) != I2S) { return FALSE; } #endif halAudioClock_F(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, 1); break; case 512: halAudioClock_F(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, 2); break; case 1024: if (audioParams_GetInterfaceType(params) == HBR) { return FALSE; } halAudioClock_F(baseAddr + AUD_BASE_ADDR + AUDIO_CLOCK, 3); break; default: /* Fs clock factor not supported */ return FALSE; } } #if 0 if (audio_AudioGenerator(baseAddr, params) != TRUE) { return FALSE; } #endif return audio_Mute(baseAddr, 0); }
int audio_AudioGenerator(u16 baseAddr, audioParams_t *params) { /* * audio generator block is not included in real application hardware, * Then the external audio sources are used and this code has no effect */ u32 tmp; LOG_TRACE(); halAudioGenerator_I2sMode(baseAddr + AG_BASE_ADDR, 1); /* should be coherent with I2S config? */ tmp = (1500 * 65535) / audioParams_GetSamplingFrequency(params); /* 1500Hz */ halAudioGenerator_FreqIncrementLeft(baseAddr + AG_BASE_ADDR, (u16) (tmp)); tmp = (3000 * 65535) / audioParams_GetSamplingFrequency(params); /* 3000Hz */ halAudioGenerator_FreqIncrementRight(baseAddr + AG_BASE_ADDR, (u16) (tmp)); halAudioGenerator_IecCgmsA(baseAddr + AG_BASE_ADDR, audioParams_GetIecCgmsA(params)); halAudioGenerator_IecCopyright(baseAddr + AG_BASE_ADDR, audioParams_GetIecCopyright(params) ? 0 : 1); halAudioGenerator_IecCategoryCode(baseAddr + AG_BASE_ADDR, audioParams_GetIecCategoryCode(params)); halAudioGenerator_IecPcmMode(baseAddr + AG_BASE_ADDR, audioParams_GetIecPcmMode(params)); halAudioGenerator_IecSource(baseAddr + AG_BASE_ADDR, audioParams_GetIecSourceNumber(params)); for (tmp = 0; tmp < 4; tmp++) { /* 0 -> iec spec 60958-3 means "do not take into account" */ halAudioGenerator_IecChannelLeft(baseAddr + AG_BASE_ADDR, 0, tmp); halAudioGenerator_IecChannelRight(baseAddr + AG_BASE_ADDR, 0, tmp); /* USER_BIT 0 default by spec */ halAudioGenerator_UserLeft(baseAddr + AG_BASE_ADDR, USER_BIT, tmp); halAudioGenerator_UserRight(baseAddr + AG_BASE_ADDR, USER_BIT, tmp); } halAudioGenerator_IecClockAccuracy(baseAddr + AG_BASE_ADDR, audioParams_GetIecClockAccuracy(params)); halAudioGenerator_IecSamplingFreq(baseAddr + AG_BASE_ADDR, audioParams_IecSamplingFrequency(params)); halAudioGenerator_IecOriginalSamplingFreq(baseAddr + AG_BASE_ADDR, audioParams_IecOriginalSamplingFrequency(params)); halAudioGenerator_IecWordLength(baseAddr + AG_BASE_ADDR, audioParams_IecWordLength(params)); halAudioGenerator_SpdifValidity(baseAddr + AG_BASE_ADDR, VALIDITY_BIT); halAudioGenerator_SpdifEnable(baseAddr + AG_BASE_ADDR, 1); /* enabled by default but usage depends on core selection */ /* HBR is synthesizable but not audible */ halAudioGenerator_HbrDdrEnable(baseAddr + AG_BASE_ADDR, 0); halAudioGenerator_HbrDdrChannel(baseAddr + AG_BASE_ADDR, 0); halAudioGenerator_HbrBurstLength(baseAddr + AG_BASE_ADDR, 0); halAudioGenerator_HbrClockDivider(baseAddr + AG_BASE_ADDR, 128); /* 128 * fs */ halAudioGenerator_HbrEnable(baseAddr + AG_BASE_ADDR, 1); /* GPA */ for (tmp = 0; tmp < 8; tmp++) { halAudioGenerator_GpaSampleValid(baseAddr + AG_BASE_ADDR, !(audioParams_IsChannelEn(params, tmp)), tmp); halAudioGenerator_ChannelSelect(baseAddr + AG_BASE_ADDR, audioParams_IsChannelEn(params, tmp), tmp); } halAudioGenerator_GpaReplyLatency(baseAddr + AG_BASE_ADDR, 0x03); halAudioGenerator_SwReset(baseAddr + AG_BASE_ADDR, 1); return TRUE; }
/** * Check audio parameters against read EDID structure to ensure * compatibility with sink. * @param audio audio parameters data structure */ static int api_CheckParamsAudio(audioParams_t * audio) { unsigned i = 0; int bitSupport = -1; shortAudioDesc_t sad; speakerAllocationDataBlock_t allocation; u8 errorCode = TRUE; int valid = FALSE; /* array to translate from AudioInfoFrame code to EDID Speaker Allocation data block bits */ const u8 sadb[] = { 1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31, 73, 75, 77, 79, 33, 35, 37, 39, 49, 51, 53, 55, 41, 43, 45, 47 }; LOG_TRACE(); if (!api_EdidSupportsBasicAudio()) { error_Set(ERR_SINK_DOES_NOT_SUPPORT_AUDIO); printk("Sink does NOT support audio"); return FALSE; } /* check if audio type supported */ for (i = 0; i < api_EdidSadCount(); i++) { api_EdidSad(i, &sad); if (audioParams_GetCodingType(audio) == shortAudioDesc_GetFormatCode( &sad)) { bitSupport = i; break; } } if (bitSupport >= 0) { api_EdidSad(bitSupport, &sad); /* 192 kHz| 176.4 kHz| 96 kHz| 88.2 kHz| 48 kHz| 44.1 kHz| 32 kHz */ switch (audioParams_GetSamplingFrequency(audio)) { case 32000: valid = shortAudioDesc_Support32k(&sad); break; case 44100: valid = shortAudioDesc_Support44k1(&sad); break; case 48000: valid = shortAudioDesc_Support48k(&sad); break; case 88200: valid = shortAudioDesc_Support88k2(&sad); break; case 96000: valid = shortAudioDesc_Support96k(&sad); break; case 176400: valid = shortAudioDesc_Support176k4(&sad); break; case 192000: valid = shortAudioDesc_Support192k(&sad); break; default: valid = FALSE; break; } if (!valid) { error_Set(ERR_SINK_DOES_NOT_SUPPORT_AUDIO_SAMPLING_FREQ); LOG_WARNING2("Sink does NOT support audio sampling frequency", audioParams_GetSamplingFrequency(audio)); errorCode = FALSE; } if (audioParams_GetCodingType(audio) == PCM) { /* 24 bit| 20 bit| 16 bit */ switch (audioParams_GetSampleSize(audio)) { case 16: valid = shortAudioDesc_Support16bit(&sad); break; case 20: valid = shortAudioDesc_Support20bit(&sad); break; case 24: valid = shortAudioDesc_Support24bit(&sad); break; default: valid = FALSE; break; } if (!valid) { error_Set(ERR_SINK_DOES_NOT_SUPPORT_AUDIO_SAMPLE_SIZE); LOG_WARNING2("Sink does NOT support audio sample size", audioParams_GetSampleSize(audio)); errorCode = FALSE; } } /* check Speaker Allocation */ if (api_EdidSpeakerAllocationDataBlock(&allocation) == TRUE) { LOG_DEBUG2("Audio channel allocation sent", sadb[audioParams_GetChannelAllocation(audio)]); LOG_DEBUG2("Audio channel allocation accepted", speakerAllocationDataBlock_GetSpeakerAllocationByte(&allocation)); valid = (sadb[audioParams_GetChannelAllocation(audio)] & speakerAllocationDataBlock_GetSpeakerAllocationByte( &allocation)) == sadb[audioParams_GetChannelAllocation(audio)]; if (!valid) { error_Set(ERR_SINK_DOES_NOT_SUPPORT_ATTRIBUTED_CHANNELS); printk("Sink does NOT have attributed speakers"); errorCode = FALSE; } } } else { error_Set(ERR_SINK_DOES_NOT_SUPPORT_AUDIO_TYPE); printk("Sink does NOT support audio type"); errorCode = FALSE; } return errorCode; }