📄 pmic_audio.cpp
字号:
*
* @retval PMIC_SUCCESS If the close request was successful.
* @retval PMIC_PARAMETER_ERROR If the handle is invalid.
*/
PMIC_STATUS PmicAudioClose(const PMIC_AUDIO_HANDLE handle)
{
PMIC_STATUS rc = PMIC_PARAMETER_ERROR;
/* We need a critical section here to maintain a consistent state. */
down_interruptible(mutex);
/* We can now call pmic_audio_close_handle() to actually do the work. */
rc = pmic_audio_close_handle(handle);
/* Exit the critical section. */
up(mutex);
return rc;
}
/*!
* @brief Configure the data bus protocol to be used.
*
* Provide the parameters needed to properly configure the audio data bus
* protocol so that data can be read/written to either the Stereo DAC or
* the Voice CODEC.
*
* @param[in] handle Device handle from pmic_audio_open() call.
* @param[in] busID Select data bus to be used.
* @param[in] protocol Select the data bus protocol.
* @param[in] masterSlave Select the data bus timing mode.
* @param[in] numSlots Define the number of timeslots (only if in
* master mode).
*
* @retval PMIC_SUCCESS If the protocol was successful configured.
* @retval PMIC_PARAMETER_ERROR If the handle or the protocol parameters
* are invalid.
*/
PMIC_STATUS PmicAudioSetProtocol(
const PMIC_AUDIO_HANDLE handle,
const PMIC_AUDIO_DATA_BUS busID,
const PMIC_AUDIO_BUS_PROTOCOL protocol,
const PMIC_AUDIO_BUS_MODE masterSlave,
const PMIC_AUDIO_NUMSLOTS numSlots)
{
PMIC_STATUS rc = PMIC_PARAMETER_ERROR;
const unsigned int ST_DAC_MASK1 = regSTEREO_DAC.STDCSSISEL.mask |
regSTEREO_DAC.STDCSM.mask |
regSTEREO_DAC.STDCCLKEN.mask;
const unsigned int ST_DAC_MASK2 = regSSI_NETWORK.STDCSLOTS.mask;
const unsigned int VCODEC_MASK = regAUDIO_CODEC.CDCSSISEL.mask |
regAUDIO_CODEC.CDCSM.mask |
regAUDIO_CODEC.CDCCLKEN.mask;
unsigned int reg_value = 0;
unsigned int reg_value2 = 0;
/* Enter a critical section so that we can ensure only one
* state change request is completed at a time.
*/
down_interruptible(mutex);
if ((handle == stDAC.handle) &&
(stDAC.handleState == HANDLE_IN_USE))
{
/* Make sure that the MC13783 PMIC supports the requested
* Stereo DAC data bus protocol.
*/
if ((protocol == NETWORK_MODE) &&
!((numSlots == USE_2_TIMESLOTS) ||
(numSlots == USE_4_TIMESLOTS) ||
(numSlots == USE_8_TIMESLOTS)))
{
/* The Stereo DAC only supports 2, 4, or 8 time slots when in
* Network Mode.
*/
DEBUGMSG(ZONE_ERROR,
(_T("%s: Invalid numSlots parameter (Stereo DAC only ")
_T("supports 2,4, or 8 timeslots in Network Mode)\n"),
__FILE__));
rc = PMIC_NOT_SUPPORTED;
}
else if (((protocol == NORMAL_MSB_JUSTIFIED_MODE) ||
(protocol == I2S_MODE)) &&
(numSlots != USE_2_TIMESLOTS))
{
/* The Stereo DAC only supports the use of 2 time slots when in
* Normal Mode or I2S Mode.
*/
DEBUGMSG(ZONE_ERROR,
(_T("%s: Invalid numSlots parameter (Stereo DAC only ")
_T("supports 2 timeslots in Normal or I2S Mode)\n"),
__FILE__));
rc = PMIC_NOT_SUPPORTED;
}
else if ((masterSlave == BUS_MASTER_MODE) &&
((stDAC.clockIn == CLOCK_IN_FSYNC) ||
(stDAC.clockIn == CLOCK_IN_BITCLK)))
{
/* Invalid clock inputs for master mode. */
DEBUGMSG(ZONE_ERROR,
(_T("%s: Invalid Stereo DAC clock selection for ")
_T("Master Mode\n"),
__FILE__));
rc = PMIC_PARAMETER_ERROR;
}
else if ((masterSlave == BUS_SLAVE_MODE) &&
(stDAC.clockIn == CLOCK_IN_DEFAULT))
{
/* Invalid clock inputs for slave mode. */
DEBUGMSG(ZONE_ERROR,
(_T("%s: Invalid Stereo DAC clock selection for ")
_T("Slave Mode\n"),
__FILE__));
rc = PMIC_PARAMETER_ERROR;
}
else if ((vCodec.handleState == HANDLE_IN_USE) &&
(vCodec.busID == busID))
{
/* The requested data bus is already in use by the Voice CODEC. */
DEBUGMSG(ZONE_ERROR,
(_T("%s: Requested data bus already in use by the Voice ")
_T("CODEC\n"), __FILE__));
rc = PMIC_ERROR;
}
else if (protocol == SPD_IF_MODE)
{
/* SPD/IF mode is no longer supported. */
DEBUGMSG(ZONE_ERROR,
(_T("%s: The SPD/IF Stereo DAC mode is no longer ")
_T("supported\n"), __FILE__));
rc = PMIC_NOT_SUPPORTED;
}
else
{
/* The Voice CODEC is not currently being used but we still need
* to switch it to the other data bus so that there is no conflict
* with the Stereo DAC.
*/
if (vCodec.busID == busID)
{
reg_value = SET_BITS(regAUDIO_CODEC, CDCSM, 1);
if (busID == AUDIO_DATA_BUS_1)
{
reg_value |= SET_BITS(regAUDIO_CODEC, CDCSSISEL,
AUDIO_DATA_BUS_2);
}
else
{
reg_value |= SET_BITS(regAUDIO_CODEC, CDCSSISEL,
AUDIO_DATA_BUS_1);
}
/* Note that this update to the AUD_CODEC register also has the
* side effect of disabling the Voice CODEC master mode clock
* outputs (if they are currently enabled) and changing the
* Voice CODEC back to slave mode. We have to do this now
* because we want the Voice CODEC to be in a safe idle state
* when we switch it over to the other data bus.
*/
if (pmic_write_reg(REG_AUDIO_CODEC, reg_value,
VCODEC_MASK) != PMIC_SUCCESS)
{
rc = PMIC_ERROR;
}
else
{
vCodec.busID = (busID == AUDIO_DATA_BUS_1) ?
AUDIO_DATA_BUS_2 : AUDIO_DATA_BUS_1;
}
}
if (rc != PMIC_ERROR)
{
/* We can now proceed with the Stereo DAC configuration. */
reg_value = SET_BITS(regSTEREO_DAC, STDCSSISEL, busID) |
SET_BITS(regSTEREO_DAC, STDCFS, protocol) |
SET_BITS(regSTEREO_DAC, STDCSM, masterSlave);
if (masterSlave == BUS_MASTER_MODE)
{
/* Enable clock outputs when in master mode. */
reg_value |= SET_BITS(regSTEREO_DAC, STDCCLKEN, 1);
}
if (numSlots == USE_2_TIMESLOTS)
{
/* Use 2 time slots (left, right). */
reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 3);
}
else if (numSlots == USE_4_TIMESLOTS)
{
/* Use 4 time slots (left, right, 2 other). */
reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 2);
}
else if ((stDAC.samplingRate == STDAC_RATE_64_KHZ) ||
(stDAC.samplingRate == STDAC_RATE_96_KHZ))
{
/* Use 8 time slots (must use this mode for 64 kHz or
* 96 kHz sampling rates).
*/
reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 0);
}
else
{
/* Use 8 time slots (left, right, 6 other) for all
* sampling rates other than 64 kHz or 96 kHz.
*/
reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 1);
}
if ((pmic_write_reg(REG_STEREO_DAC, reg_value,
ST_DAC_MASK1 | regSTEREO_DAC.STDCFS.mask) ==
PMIC_SUCCESS) &&
(pmic_write_reg(REG_SSI_NETWORK, reg_value2, ST_DAC_MASK2) ==
PMIC_SUCCESS))
{
stDAC.busID = busID;
stDAC.protocol = protocol;
stDAC.masterSlave = masterSlave;
stDAC.numSlots = numSlots;
rc = PMIC_SUCCESS;
}
else
{
rc = PMIC_ERROR;
}
}
}
}
else if ((handle == vCodec.handle) &&
(vCodec.handleState == HANDLE_IN_USE))
{
/* The MC13783 Voice CODEC only supports a network or I2S mode with 4
* timeslots.
*/
if (!((protocol == NETWORK_MODE) || (protocol == I2S_MODE)))
{
DEBUGMSG(ZONE_ERROR,
(_T("%s: Voice CODEC only supports Network or I2S ")
_T("modes\n"), __FILE__));
rc = PMIC_NOT_SUPPORTED;
}
else if (numSlots != USE_4_TIMESLOTS)
{
DEBUGMSG(ZONE_ERROR,
(_T("%s: Voice CODEC only supports using 4 timeslots\n"),
__FILE__));
rc = PMIC_NOT_SUPPORTED;
}
else if ((stDAC.handleState == HANDLE_IN_USE) && (stDAC.busID == busID))
{
/* The requested data bus is already in use by the Stereo DAC. */
DEBUGMSG(ZONE_ERROR,
(_T("%s: Requested data bus already in use by the Stereo ")
_T("DAC\n"), __FILE__));
rc = PMIC_ERROR;
}
else
{
/* The Stereo DAC is not currently being used but we still need
* to switch it to the other data bus so that there is no conflict
* with the Voice CODEC.
*/
if (stDAC.busID == busID)
{
reg_value = SET_BITS(regSTEREO_DAC, STDCSM, 1);
if (busID == AUDIO_DATA_BUS_1)
{
reg_value |= SET_BITS(regSTEREO_DAC, STDCSSISEL,
AUDIO_DATA_BUS_2);
}
else
{
reg_value |= SET_BITS(regSTEREO_DAC, STDCSSISEL,
AUDIO_DATA_BUS_1);
}
/* Note that this update to STEREO_DAC register also has the
* side effect of disabling the Stereo DAC master mode clock
* outputs (if they are currently enabled) and changing the
* Stereo DAC back to slave mode. We have to do this now
* because we want the Stereo DAC to be in a safe idle state
* when we switch it over to the other data bus.
*/
if (pmic_write_reg(REG_STEREO_DAC, reg_value, ST_DAC_MASK1) !=
PMIC_SUCCESS)
{
rc = PMIC_ERROR;
}
else
{
stDAC.busID = (busID == AUDIO_DATA_BUS_1) ?
AUDIO_DATA_BUS_2 : AUDIO_DATA_BUS_1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -