433 lines
12 KiB
C
433 lines
12 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2016-2017 Cadence Design Systems, Inc.
|
|
* All rights reserved worldwide.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Copyright 2017 NXP
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* API_Audio.c
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
#include "address.h"
|
|
#include "aif_pckt2smp.h"
|
|
#include "API_Audio.h"
|
|
#include "API_DPTX.h"
|
|
#include "API_General.h"
|
|
#include "clock_meters.h"
|
|
#include "dptx_stream.h"
|
|
#include "dptx_framer.h"
|
|
#include "source_aif_decoder.h"
|
|
#include "source_aif_smpl2pckt.h"
|
|
#include "source_car.h"
|
|
#include "util.h"
|
|
|
|
CDN_API_STATUS CDN_API_AudioMute(state_struct *state, AUDIO_MUTE_MODE mode)
|
|
{
|
|
return (CDN_API_General_Write_Field
|
|
(state, ADDR_DPTX_STREAM + (DP_VB_ID << 2), 4, 1,
|
|
(1 - mode) << 4));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioMute_blocking(state_struct *state,
|
|
AUDIO_MUTE_MODE mode)
|
|
{
|
|
internal_block_function(&state->mutex, CDN_API_AudioMute(state, mode));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioMode(state_struct *state, AUDIO_MODE mode)
|
|
{
|
|
return (CDN_API_General_Write_Register
|
|
(state, ADDR_DPTX_FRAMER + (AUDIO_PACK_CONTROL << 2),
|
|
F_AUDIO_PACK_EN(mode)));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioMode_blocking(state_struct *state, AUDIO_MODE mode)
|
|
{
|
|
internal_block_function(&state->mutex, CDN_API_AudioMode(state, mode));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioConfigCore(state_struct *state,
|
|
AUDIO_TYPE audioType, int numOfChannels,
|
|
AUDIO_FREQ freq, int lanes,
|
|
AUDIO_WIDTH width)
|
|
{
|
|
int i;
|
|
int lanesParam;
|
|
u32 I2S_DEC_PORT_EN_Val;
|
|
|
|
if (numOfChannels == 2) {
|
|
if (lanes == 1)
|
|
lanesParam = 1;
|
|
else
|
|
lanesParam = 3;
|
|
} else
|
|
lanesParam = 0;
|
|
|
|
if (audioType == AUDIO_TYPE_I2S) {
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNFG << 2),
|
|
0x20000);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (FIFO_CNTL << 2), 2);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNFG << 2),
|
|
F_MAX_NUM_CH(numOfChannels - 1) |
|
|
F_NUM_OF_I2S_PORTS_S((numOfChannels / 2) - 1) |
|
|
(1 << 8) | (lanesParam << 11));
|
|
|
|
if (numOfChannels == 2)
|
|
I2S_DEC_PORT_EN_Val = 1;
|
|
else if (numOfChannels == 4)
|
|
I2S_DEC_PORT_EN_Val = 3;
|
|
else
|
|
I2S_DEC_PORT_EN_Val = 0xF;
|
|
|
|
/* 24 bit configuration + number of channels according to config */
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNFG << 2),
|
|
0x01000 | F_AUDIO_SAMPLE_WIDTH(width) |
|
|
F_AUDIO_CH_NUM(numOfChannels - 1) |
|
|
F_I2S_DEC_PORT_EN(I2S_DEC_PORT_EN_Val));
|
|
|
|
for (i = 0; i < (numOfChannels + 1) / 2; i++) {
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
((STTS_BIT_CH01 + i) << 2),
|
|
F_WORD_LENGTH_CH0(0x2) |
|
|
F_WORD_LENGTH_CH1(0x2) |
|
|
F_CHANNEL_NUM_CH0(i * 2) |
|
|
F_CHANNEL_NUM_CH1((i * 2) + 1));
|
|
}
|
|
|
|
/*set ch status bits */
|
|
switch (freq) {
|
|
|
|
case AUDIO_FREQ_32:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0x3) |
|
|
F_ORIGINAL_SAMP_FREQ(0xC));
|
|
break;
|
|
case AUDIO_FREQ_192:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0xE) |
|
|
F_ORIGINAL_SAMP_FREQ(0x1));
|
|
break;
|
|
|
|
case AUDIO_FREQ_48:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0x2) |
|
|
F_ORIGINAL_SAMP_FREQ(0xD));
|
|
break;
|
|
case AUDIO_FREQ_96:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0xA) |
|
|
F_ORIGINAL_SAMP_FREQ(0x5));
|
|
break;
|
|
case AUDIO_FREQ_44_1:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0x0) |
|
|
F_ORIGINAL_SAMP_FREQ(0xF));
|
|
break;
|
|
case AUDIO_FREQ_88_2:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0x8) |
|
|
F_ORIGINAL_SAMP_FREQ(0x7));
|
|
break;
|
|
case AUDIO_FREQ_176_4:
|
|
cdn_apb_write(state, ADDR_SOURCE_AIF_DECODER +
|
|
(COM_CH_STTS_BITS << 2),
|
|
4 | F_SAMPLING_FREQ(0xC) |
|
|
F_ORIGINAL_SAMP_FREQ(0x3));
|
|
break;
|
|
}
|
|
|
|
/* Enable I2S encoder */
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNTL << 2), 2);
|
|
/* Enable smpl2pkt */
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNTL << 2), 2);
|
|
} else {
|
|
|
|
/* set spidif 2c en */
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (SPDIF_CTRL_ADDR << 2),
|
|
0x1F0707);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (FIFO_CNTL << 2), 2);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNFG << 2),
|
|
0x101 | (lanesParam << 11));
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNTL << 2), 2);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (SPDIF_CTRL_ADDR << 2),
|
|
0x3F0707);
|
|
}
|
|
return CDN_OK;
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioConfigCore_blocking(state_struct *state,
|
|
AUDIO_TYPE audioType,
|
|
int numOfChannels,
|
|
AUDIO_FREQ freq, int lanes,
|
|
AUDIO_WIDTH width)
|
|
{
|
|
internal_block_function(&state->mutex, CDN_API_AudioConfigCore
|
|
(state, audioType, numOfChannels, freq, lanes,
|
|
width));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioAutoConfig(state_struct *state,
|
|
AUDIO_TYPE audioType, int numOfChannels,
|
|
AUDIO_FREQ freq, int lanes,
|
|
AUDIO_WIDTH width,
|
|
CDN_PROTOCOL_TYPE protocol, int ncts,
|
|
AUDIO_MUTE_MODE mode)
|
|
{
|
|
|
|
CDN_API_STATUS ret = CDN_BSY;
|
|
u32 REF_CYC_Val;
|
|
|
|
switch (state->tmp) {
|
|
case 0:
|
|
if (protocol == CDN_DPTX) {
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_DPTX_FRAMER +
|
|
(AUDIO_PACK_STATUS <<
|
|
2), 0x11 << 16);
|
|
} else {
|
|
ret = CDN_OK;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
if (protocol == CDN_DPTX) {
|
|
REF_CYC_Val = 0x8000;
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_CLOCK_METERS +
|
|
(CM_LANE_CTRL << 2),
|
|
REF_CYC_Val);
|
|
} else {
|
|
/* hdmi mode */
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_CLOCK_METERS +
|
|
(CM_CTRL << 2), 8);
|
|
|
|
}
|
|
break;
|
|
case 2:
|
|
if ((protocol == CDN_HDMITX_TYPHOON)
|
|
|| (protocol == CDN_HDMITX_KIRAN)) {
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_CLOCK_METERS +
|
|
(CM_I2S_CTRL << 2),
|
|
ncts | 0x4000000);
|
|
} else {
|
|
ret = CDN_OK;
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
if ((protocol == CDN_HDMITX_TYPHOON)
|
|
|| (protocol == CDN_HDMITX_KIRAN)) {
|
|
ret = CDN_OK;
|
|
} else {
|
|
/* in dptx set audio on in dp framer */
|
|
ret = CDN_API_AudioMode(state, 1);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
/* set car audio on _not reset */
|
|
if (protocol == CDN_DPTX) {
|
|
/* TODO DK: try to merge case 3 and 4 */
|
|
ret = CDN_OK;
|
|
} else {
|
|
ret = CDN_OK;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if ((protocol == CDN_DPTX) && (audioType != AUDIO_TYPE_I2S)) {
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_SOURCE_CAR +
|
|
(SOURCE_AIF_CAR <<
|
|
2), 0xff);
|
|
} else {
|
|
ret = CDN_OK;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (protocol == CDN_DPTX) {
|
|
ret =
|
|
CDN_API_General_Write_Register(state,
|
|
ADDR_CLOCK_METERS +
|
|
(CM_CTRL << 2), 0);
|
|
} else {
|
|
ret = CDN_OK;
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
ret =
|
|
CDN_API_AudioConfigCore(state, audioType, numOfChannels,
|
|
freq, lanes, width);
|
|
break;
|
|
}
|
|
if (!state->tmp && ret == CDN_STARTED)
|
|
return CDN_STARTED;
|
|
switch (ret) {
|
|
case CDN_OK:
|
|
state->tmp++;
|
|
break;
|
|
case CDN_STARTED:
|
|
return CDN_BSY;
|
|
break;
|
|
default:
|
|
return ret;
|
|
}
|
|
if (state->tmp == 8) {
|
|
state->tmp = 0;
|
|
return CDN_OK;
|
|
}
|
|
return CDN_BSY;
|
|
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioAutoConfig_blocking(state_struct *state,
|
|
AUDIO_TYPE audioType,
|
|
int numOfChannels,
|
|
AUDIO_FREQ freq, int lanes,
|
|
AUDIO_WIDTH width,
|
|
CDN_PROTOCOL_TYPE protocol,
|
|
int ncts, AUDIO_MUTE_MODE mode)
|
|
{
|
|
internal_block_function(&state->mutex, CDN_API_AudioAutoConfig
|
|
(state, audioType, numOfChannels, freq, lanes,
|
|
width, protocol, ncts, mode));
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioOff(state_struct *state, AUDIO_TYPE audioType)
|
|
{
|
|
CDN_API_STATUS ret = CDN_BSY;
|
|
|
|
switch (state->tmp) {
|
|
case 0:
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (SPDIF_CTRL_ADDR << 2),
|
|
0x1F0707);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNTL << 2),
|
|
0);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNFG << 2),
|
|
0);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNTL << 2),
|
|
1);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_DECODER + (AUDIO_SRC_CNTL << 2),
|
|
0);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNTL << 2),
|
|
0);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNTL << 2),
|
|
1);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (SMPL2PKT_CNTL << 2),
|
|
0);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (FIFO_CNTL << 2), 1);
|
|
cdn_apb_write(state,
|
|
ADDR_SOURCE_AIF_SMPL2PCKT + (FIFO_CNTL << 2), 0);
|
|
ret = CDN_OK;
|
|
|
|
break;
|
|
case 1:
|
|
ret =
|
|
CDN_API_General_Write_Register(state, ADDR_SOURCE_CAR +
|
|
(SOURCE_AIF_CAR << 2), 0x5f);
|
|
break;
|
|
case 2:
|
|
ret =
|
|
CDN_API_General_Write_Register(state, ADDR_SOURCE_CAR +
|
|
(SOURCE_AIF_CAR << 2), 0x0f);
|
|
break;
|
|
case 3:
|
|
ret = CDN_OK;
|
|
break;
|
|
}
|
|
|
|
if (!state->tmp && ret == CDN_STARTED)
|
|
return CDN_STARTED;
|
|
switch (ret) {
|
|
case CDN_OK:
|
|
state->tmp++;
|
|
break;
|
|
case CDN_STARTED:
|
|
return CDN_BSY;
|
|
break;
|
|
default:
|
|
return ret;
|
|
}
|
|
if (state->tmp == 4) {
|
|
state->tmp = 0;
|
|
return CDN_OK;
|
|
}
|
|
return CDN_BSY;
|
|
}
|
|
|
|
CDN_API_STATUS CDN_API_AudioOff_blocking(state_struct *state,
|
|
AUDIO_TYPE audioType)
|
|
{
|
|
internal_block_function(&state->mutex, CDN_API_AudioOff(state, audioType));
|
|
}
|