blob: 1d1442c731ff6bd5ac5f6f386397fa5c109426cb [file] [log] [blame]
/******************************************************************************
*
* 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 2018 NXP
*
******************************************************************************
*
* API_HDMI_RX_Audio.c
*
******************************************************************************
*/
#include "API_HDMI_RX_Audio.h"
#include "sink_aif_encoder.h"
#include "aif_pckt2smp.h"
#include "address.h"
#include "util.h"
#include "API_General.h"
CDN_API_STATUS CDN_API_RX_AudioAutoConfig(
state_struct *state,
u8 max_ch_num,
u8 i2s_ports_num,
u8 dis_port3,
u8 enc_sample_width,
u8 i2s_sample_width)
{
u32 regread;
u8 num_of_pairs_of_channels_per_port = max_ch_num / (i2s_ports_num * 2);
u8 enc_size_code;
u8 i2s_size_code;
u8 i2s_port3_dis = (dis_port3 != 0 && i2s_ports_num == 4) ? 1 : 0;
u8 times = 0;
/* Valid values: 1/2/4. */
/* 3 ports can be emulated with 'i2s_ports_num = 4' and 'dis_port3 = 1'. */
if (i2s_ports_num == 0 || i2s_ports_num == 3 || i2s_ports_num > 4)
return CDN_ERR;
/* 'dis_port3' makes sense only with 4 ports enabled */
if (dis_port3 != 0 && i2s_ports_num < 4)
return CDN_ERR;
switch (enc_sample_width) {
case 16:
enc_size_code = 0x0;
break;
case 24:
enc_size_code = 0x1;
break;
case 32:
enc_size_code = 0x2;
break;
default:
return CDN_ERR;
}
switch (i2s_sample_width) {
case 16:
i2s_size_code = 0x0;
break;
case 24:
i2s_size_code = 0x1;
break;
case 32:
i2s_size_code = 0x2;
break;
default:
return CDN_ERR;
}
/* Maximum number of channels has to be in range from 2 to 32 */
if (max_ch_num < 2 || max_ch_num > 32)
return CDN_ERR;
/* Maximum number of channels has to be power of 2 */
else if (!(max_ch_num * (max_ch_num - 1)))
return CDN_ERR;
/* Each active port shall carry the same number of sub-channels */
else if (max_ch_num % i2s_ports_num)
return CDN_ERR;
/* Disable ACR during configuration */
if (cdn_apb_write(state, ADDR_AIF_ENCODER + (ACR_CFG << 2), F_ACR_SW_RESET(1)))
return CDN_ERR;
/* Configuring audio FIFO */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + ((0x40 + FIFO_CNTL_ADDR) << 2),
F_CFG_FIFO_SW_RST(0) | F_CFG_INDEX_SYNC_EN(1) |
F_CFG_FIFO_DIR(1) | F_CFG_DIS_PORT3(i2s_port3_dis)))
return CDN_ERR;
/* Configuring audio parameters */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + ((0x40 + AUDIO_SINK_CNFG) << 2),
F_ENC_LOW_INDEX_MSB(0) | F_SINK_AUDIO_CH_NUM(max_ch_num - 1) |
F_ENC_SAMPLE_JUST(0x0) | F_ENC_SMPL_WIDTH(enc_size_code) |
F_I2S_ENC_WL_SIZE(i2s_size_code) | F_CNTL_SMPL_ONLY_EN(1) |
F_CNTL_TYPE_OVRD(0x0) | F_CNTL_TYPE_OVRD_EN(0) |
F_I2S_ENC_PORT_EN((1 << i2s_ports_num) - 1) | F_WS_POLARITY(0)))
return CDN_ERR;
/* Waiting for N value... */
do {
if (cdn_apb_read(state,
ADDR_AIF_ENCODER + (AIF_ACR_N_ST << 2), &regread))
return CDN_ERR;
times++;
udelay(10);
} while (!(regread) && times < 100);
if (times == 100)
return CDN_ERR;
/* Enable ACR */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + (ACR_CFG << 2), F_ACR_SW_RESET(0)))
return CDN_ERR;
/* Important: */
/* Write to AIF_ACR_N_OFST_CFG register is interpreted as new N_CTS value. */
/* The ACR has to be enabled (reset released) to register that event. */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + (AIF_ACR_N_OFST_CFG << 2),
F_ACR_N_OFFSET(regread * (num_of_pairs_of_channels_per_port - 1))))
return CDN_ERR;
/* Enable sample decoder */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + (PKT2SMPL_CNTL << 2), F_PKT2SMPL_EN(1)))
return CDN_ERR;
/* Enable I2S encoder */
if (cdn_apb_write(state,
ADDR_AIF_ENCODER + ((0x40 + AUDIO_SINK_CNTL) << 2), F_I2S_ENC_START(1)))
return CDN_ERR;
return CDN_OK;
}
CDN_API_STATUS CDN_API_RX_AudioAutoConfig_blocking(state_struct *state,
u8 max_ch_num,
u8 i2s_ports_num,
u8 dis_port3,
u8 enc_sample_width,
u8 i2s_sample_width)
{
internal_block_function(&state->mutex,
CDN_API_RX_AudioAutoConfig(state,
max_ch_num,
i2s_ports_num,
dis_port3,
enc_sample_width,
i2s_sample_width));
}