rockbox/firmware/target/mips/ingenic_x1000/aic-x1000.h
Aidan MacDonald f63edb52ef x1000: refactor AIC initialization
Have pcm-x1000 handle most work, so target's audiohw code touches
only the relevant settings.

Change-Id: Icf3d1b7ca428ac50a5a16ecec39ed8186ac5ae13
2021-05-30 19:17:50 +00:00

144 lines
4.7 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2021 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __AIC_X1000_H__
#define __AIC_X1000_H__
#include "clk-x1000.h"
#include "x1000/aic.h"
#include <stdbool.h>
#include <stdint.h>
#define AIC_I2S_MASTER_MODE 0
#define AIC_I2S_MASTER_EXCLK_MODE 1
#define AIC_I2S_SLAVE_MODE 2
#define AIC_I2S_LEFT_CHANNEL_FIRST 0
#define AIC_I2S_RIGHT_CHANNEL_FIRST 1
/* Nb. the functions below are intended to serve as "documentation" and make
* target audiohw code clearer, they should normally be called with immediate
* constant arguments so they are inlined to a register read-modify-write. */
/* Enable/disable some kind of big-endian mode. Presumably it refers to
* the endianness of the samples read or written to the FIFO. */
static inline void aic_set_big_endian_format(bool en)
{
jz_writef(AIC_CFG, MSB(en ? 1 : 0));
}
/* Set whether to send the last sample (true) or a zero sample (false)
* if the AIC FIFO underflows during playback. */
static inline void aic_set_play_last_sample(bool en)
{
jz_writef(AIC_CFG, LSMP(en ? 1 : 0));
}
/* Select the use of the internal or external codec. */
static inline void aic_set_external_codec(bool en)
{
jz_writef(AIC_CFG, ICDC(en ? 0 : 1));
}
/* Set I2S interface mode */
static inline void aic_set_i2s_mode(int mode)
{
switch(mode) {
default:
case AIC_I2S_MASTER_MODE:
jz_writef(AIC_CFG, BCKD(1), SYNCD(1));
break;
case AIC_I2S_MASTER_EXCLK_MODE:
jz_writef(AIC_CFG, BCKD(0), SYNCD(1));
break;
case AIC_I2S_SLAVE_MODE:
jz_writef(AIC_CFG, BCKD(0), SYNCD(0));
break;
}
}
/* Select the channel ordering on the I2S interface (playback only). */
static inline void aic_set_i2s_channel_order(int order)
{
switch(order) {
default:
case AIC_I2S_LEFT_CHANNEL_FIRST:
jz_writef(AIC_I2SCR, RFIRST(0));
break;
case AIC_I2S_RIGHT_CHANNEL_FIRST:
jz_writef(AIC_I2SCR, RFIRST(1));
break;
}
}
/* Enable/disable the I2S master clock (also called 'system clock') */
static inline void aic_enable_i2s_master_clock(bool en)
{
jz_writef(AIC_I2SCR, ESCLK(en ? 1 : 0));
}
/* Enable/disable the I2S bit clock */
static inline void aic_enable_i2s_bit_clock(bool en)
{
jz_writef(AIC_I2SCR, STPBK(en ? 0 : 1));
}
/* Select whether I2S mode is used (false) or MSB-justified mode (true). */
static inline void aic_set_msb_justified_mode(bool en)
{
jz_writef(AIC_I2SCR, AMSL(en ? 1 : 0));
}
/* Calculate frequency of I2S clocks.
*
* - 'clksrc' can be one of EXCLK, SCLK_A, or MPLL.
* - 'fs' is the audio sampling frequency in Hz, must be 8 KHz - 192 KHz.
* - The master clock frequency equals 'mult * fs' Hz. Due to hardware
* restrictions, 'mult' must be divisible by 64.
*
* - NOTE: When using EXCLK source, the master clock equals EXCLK and the
* 'mult' parameter is ignored.
*
* This function returns the actual bit clock rate which would be achieved.
* (Note the bit clock is always 64x the effective sampling rate.)
*
* If the exact rate cannot be attained, then this will return the closest
* possible rate to the desired rate. In case of invalid parameters, this
* function will return zero. That also occurs if the chosen PLL is stopped.
*/
extern uint32_t aic_calc_i2s_clock(x1000_clk_t clksrc,
uint32_t fs, uint32_t mult);
/* Set the I2S clock frequency.
*
* Parameters are the same as 'aic_calc_i2s_clock()' except this function
* will set the clocks. If the bit clock is running, it will be automatically
* stopped and restarted properly.
*
* Returns zero on success. If an invalid state occurs (due to bad settings)
* then this function will do nothing and return a nonzero value.
*/
extern int aic_set_i2s_clock(x1000_clk_t clksrc, uint32_t fs, uint32_t mult);
#endif /* __AIC_X1000_H__ */