123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- /*
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2019 NXP
- * Copyright (c) 2021 hpmicro
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
- #include <stdio.h>
- #include "hpm_sgtl5000.h"
- /*******************************************************************************
- * Definitations
- ******************************************************************************/
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*******************************************************************************
- * Code
- ******************************************************************************/
- hpm_stat_t sgtl_init(sgtl_context_t *context, sgtl_config_t *config)
- {
- assert(context != NULL);
- assert(config != NULL);
- if (sgtl_write_reg(context, CHIP_ANA_POWER, 0x6AFF) != status_success)
- {
- return status_fail;
- }
- /* Set the data route */
- if (sgtl_set_data_route(context, config->route) != status_success)
- {
- return status_fail;
- }
- /* Set sgtl5000 to master or slave */
- sgtl_set_master_mode(context, config->master);
- /* Input Volume Control
- Configure ADC left and right analog volume to desired default.
- Example shows volume of 0dB. */
- if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0000U) != status_success)
- {
- return status_fail;
- }
- /* Volume and Mute Control
- Configure HP_OUT left and right volume to minimum, unmute.
- HP_OUT and ramp the volume up to desired volume.*/
- if (sgtl_write_reg(context, CHIP_ANA_HP_CTRL, 0x1818U) != status_success)
- {
- return status_fail;
- }
- if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFEFU, 0x0000U) != status_success)
- {
- return status_fail;
- }
- /* LINEOUT and DAC volume control */
- if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFEFFU, 0x0000U) != status_success)
- {
- return status_fail;
- }
- /* Configure DAC left and right digital volume */
- if (sgtl_write_reg(context, CHIP_DAC_VOL, 0x5C5CU) != status_success)
- {
- return status_fail;
- }
- /* Configure ADC volume, reduce 6db. */
- if (sgtl_write_reg(context, CHIP_ANA_ADC_CTRL, 0x0100U) != status_success)
- {
- return status_fail;
- }
- /* Unmute DAC */
- if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFFBU, 0x0000U) != status_success)
- {
- return status_fail;
- }
- if (sgtl_modify_reg(context, CHIP_ADCDAC_CTRL, 0xFFF7U, 0x0000U) != status_success)
- {
- return status_fail;
- }
- /* Unmute ADC */
- if (sgtl_modify_reg(context, CHIP_ANA_CTRL, 0xFFFEU, 0x0000U) != status_success)
- {
- return status_fail;
- }
- /* Set the audio format */
- if (sgtl_set_protocol(context, config->bus) != status_success)
- {
- return status_fail;
- }
- if (sgtl_config_data_format(context, config->format.mclk_hz, config->format.sample_rate, config->format.bit_width) !=
- status_success)
- {
- return status_fail;
- }
- /* sclk valid edge */
- if (config->format.sclk_edge == sgtl_sclk_valid_edge_rising)
- {
- if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE) !=
- status_success)
- {
- return status_fail;
- }
- }
- else
- {
- if (sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE) !=
- status_success)
- {
- return status_fail;
- }
- }
- return status_success;
- }
- hpm_stat_t sgtl_deinit(sgtl_context_t *context)
- {
- hpm_stat_t stat = status_success;
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_adc));
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dac));
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_dap));
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sin));
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_i2sout));
- HPM_CHECK_RET(sgtl_disable_module(context, sgtl_module_lineout));
- return stat;
- }
- void sgtl_set_master_mode(sgtl_context_t *context, bool master)
- {
- if (master == true)
- {
- (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_MASTER);
- }
- else
- {
- (void)sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MS_CLR_MASK, SGTL5000_I2S_SLAVE);
- }
- }
- hpm_stat_t sgtl_enable_module(sgtl_context_t *context, sgtl_module_t module)
- {
- hpm_stat_t stat = status_success;
- switch (module)
- {
- case sgtl_module_adc:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
- ((uint16_t)1U << SGTL5000_ADC_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
- ((uint16_t)1U << SGTL5000_ADC_POWERUP_SHIFT)));
- break;
- case sgtl_module_dac:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
- ((uint16_t)1U << SGTL5000_DAC_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
- ((uint16_t)1U << SGTL5000_DAC_POWERUP_SHIFT)));
- break;
- case sgtl_module_dap:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
- ((uint16_t)1U << SGTL5000_DAP_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
- ((uint16_t)1U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
- break;
- case sgtl_module_i2sin:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
- ((uint16_t)1U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
- break;
- case sgtl_module_i2sout:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
- ((uint16_t)1U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
- break;
- case sgtl_module_hp:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
- ((uint16_t)1U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
- break;
- case sgtl_module_lineout:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
- ((uint16_t)1U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_disable_module(sgtl_context_t *context, sgtl_module_t module)
- {
- hpm_stat_t stat = status_success;
- switch (module)
- {
- case sgtl_module_adc:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_ADC_ENABLE_CLR_MASK,
- ((uint16_t)0U << SGTL5000_ADC_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_ADC_POWERUP_CLR_MASK,
- ((uint16_t)0U << SGTL5000_ADC_POWERUP_SHIFT)));
- break;
- case sgtl_module_dac:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAC_ENABLE_CLR_MASK,
- ((uint16_t)0U << SGTL5000_DAC_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_DAC_POWERUP_CLR_MASK,
- ((uint16_t)0U << SGTL5000_DAC_POWERUP_SHIFT)));
- break;
- case sgtl_module_dap:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_DAP_ENABLE_CLR_MASK,
- ((uint16_t)0U << SGTL5000_DAP_ENABLE_SHIFT)));
- HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK,
- ((uint16_t)0U << SGTL5000_DAP_CONTROL_DAP_EN_SHIFT)));
- break;
- case sgtl_module_i2sin:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_IN_ENABLE_CLR_MASK,
- ((uint16_t)0U << SGTL5000_I2S_IN_ENABLE_SHIFT)));
- break;
- case sgtl_module_i2sout:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_DIG_POWER, SGTL5000_I2S_OUT_ENABLE_CLR_MASK,
- ((uint16_t)0U << SGTL5000_I2S_OUT_ENABLE_SHIFT)));
- break;
- case sgtl_module_hp:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_HEADPHONE_POWERUP_CLR_MASK,
- ((uint16_t)0U << SGTL5000_HEADPHONE_POWERUP_SHIFT)));
- break;
- case sgtl_module_lineout:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_POWER, SGTL5000_LINEOUT_POWERUP_CLR_MASK,
- ((uint16_t)0U << SGTL5000_LINEOUT_POWERUP_SHIFT)));
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_set_data_route(sgtl_context_t *context, sgtl_route_t route)
- {
- hpm_stat_t stat = status_success;
- switch (route)
- {
- case sgtl_route_bypass:
- /* Bypass means from line-in to HP*/
- HPM_CHECK_RET(sgtl_write_reg(context, CHIP_DIG_POWER, 0x0000));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_LINEIN));
- break;
- case sgtl_route_playback:
- /* Data route I2S_IN-> DAC-> HP */
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
- break;
- case sgtl_route_playback_record:
- /* I2S IN->DAC->HP LINE_IN->ADC->I2S_OUT */
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_I2S_IN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
- break;
- case sgtl_route_playback_with_dap:
- /* I2S_IN->DAP->DAC->HP */
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
- break;
- case sgtl_route_playback_with_dap_record:
- /* I2S_IN->DAP->DAC->HP, LINE_IN->ADC->I2S_OUT */
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_hp));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dac));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sin));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_dap));
- HPM_CHECK_RET(sgtl_modify_reg(context, SGTL5000_DAP_CONTROL, SGTL5000_DAP_CONTROL_DAP_EN_CLR_MASK, 0x0001));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAP_SEL_CLR_MASK, SGTL5000_DAP_SEL_I2S_IN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_DAC_SEL_CLR_MASK, SGTL5000_DAC_SEL_DAP));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_HP_CLR_MASK, SGTL5000_SEL_HP_DAC));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
- break;
- case sgtl_route_record:
- /* LINE_IN->ADC->I2S_OUT */
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_i2sout));
- HPM_CHECK_RET(sgtl_enable_module(context, sgtl_module_adc));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_SEL_ADC_CLR_MASK, SGTL5000_SEL_ADC_LINEIN));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_SSS_CTRL, SGTL5000_I2S_OUT_SEL_CLR_MASK, SGTL5000_I2S_OUT_SEL_ADC));
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_set_protocol(sgtl_context_t *context, sgtl_protocol_t protocol)
- {
- hpm_stat_t stat = status_success;
- switch (protocol)
- {
- case sgtl_bus_i2s:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
- break;
- case sgtl_bus_left_justified:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_I2S_LJ));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
- break;
- case sgtl_bus_right_justified:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_RJ));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_RISING_EDGE));
- break;
- case sgtl_bus_pcma:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_ONE_BIT_DELAY));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
- break;
- case sgtl_bus_pcmb:
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_MODE_CLR_MASK, SGTL5000_I2S_MODE_PCM));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_LRALIGN_CLR_MASK, SGTL5000_I2S_NO_DELAY));
- HPM_CHECK_RET(sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_SCLK_INV_CLR_MASK, SGTL5000_I2S_VAILD_FALLING_EDGE));
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_set_volume(sgtl_context_t *context, sgtl_module_t module, uint32_t volume)
- {
- uint16_t vol = 0;
- hpm_stat_t stat = status_success;
- switch (module)
- {
- case sgtl_module_adc:
- if (volume > SGTL5000_ADC_MAX_VOLUME_VALUE)
- {
- return status_invalid_argument;
- }
- vol = (uint16_t)(volume | (volume << 4U));
- stat = sgtl_modify_reg(context, CHIP_ANA_ADC_CTRL,
- SGTL5000_ADC_VOL_LEFT_CLR_MASK & SGTL5000_ADC_VOL_RIGHT_CLR_MASK, vol);
- break;
- case sgtl_module_dac:
- if ((volume > SGTL5000_DAC_MAX_VOLUME_VALUE) || (volume < SGTL5000_DAC_MIN_VOLUME_VALUE))
- {
- return status_invalid_argument;
- }
- vol = (uint16_t)(volume | (volume << 8U));
- stat = sgtl_write_reg(context, CHIP_DAC_VOL, vol);
- break;
- case sgtl_module_hp:
- if (volume > SGTL5000_HEADPHONE_MAX_VOLUME_VALUE)
- {
- return status_invalid_argument;
- }
- vol = (uint16_t)(volume | (volume << 8U));
- stat = sgtl_write_reg(context, CHIP_ANA_HP_CTRL, vol);
- break;
- case sgtl_module_lineout:
- if (volume > SGTL5000_LINE_OUT_MAX_VOLUME_VALUE)
- {
- return status_invalid_argument;
- }
- vol = (uint16_t)(volume | (volume << 8U));
- stat = sgtl_write_reg(context, CHIP_LINE_OUT_VOL, vol);
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- uint32_t sgtl_get_volume(sgtl_context_t *context, sgtl_module_t module)
- {
- uint16_t vol = 0;
- hpm_stat_t stat = status_success;
- switch (module)
- {
- case sgtl_module_adc:
- stat = sgtl_read_reg(context, CHIP_ANA_ADC_CTRL, &vol);
- vol = (vol & (uint16_t)SGTL5000_ADC_VOL_LEFT_GET_MASK) >> SGTL5000_ADC_VOL_LEFT_SHIFT;
- break;
- case sgtl_module_dac:
- stat = sgtl_read_reg(context, CHIP_DAC_VOL, &vol);
- vol = (vol & (uint16_t)SGTL5000_DAC_VOL_LEFT_GET_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
- break;
- case sgtl_module_hp:
- stat = sgtl_read_reg(context, CHIP_ANA_HP_CTRL, &vol);
- vol = (vol & (uint16_t)SGTL5000_HP_VOL_LEFT_GET_MASK) >> SGTL5000_HP_VOL_LEFT_SHIFT;
- break;
- case sgtl_module_lineout:
- stat = sgtl_read_reg(context, CHIP_LINE_OUT_VOL, &vol);
- vol = (vol & (uint16_t)SGTL5000_LINE_OUT_VOL_LEFT_GET_MASK) >> SGTL5000_LINE_OUT_VOL_LEFT_SHIFT;
- break;
- default:
- vol = 0;
- break;
- }
- return stat == status_success ? vol : 0U;
- }
- hpm_stat_t sgtl_set_mute(sgtl_context_t *context, sgtl_module_t module, bool mute)
- {
- hpm_stat_t stat = status_success;
- switch (module)
- {
- case sgtl_module_adc:
- stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_ADC_CLR_MASK, mute ? 1U : 0U);
- break;
- case sgtl_module_dac:
- if (mute)
- {
- stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
- SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x000C);
- }
- else
- {
- stat = sgtl_modify_reg(context, CHIP_ADCDAC_CTRL,
- SGTL5000_DAC_MUTE_LEFT_CLR_MASK & SGTL5000_DAC_MUTE_RIGHT_CLR_MASK, 0x0000);
- }
- break;
- case sgtl_module_hp:
- stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_HP_CLR_MASK,
- ((uint16_t)mute << SGTL5000_MUTE_HP_SHIFT));
- break;
- case sgtl_module_lineout:
- stat = sgtl_modify_reg(context, CHIP_ANA_CTRL, SGTL5000_MUTE_LO_CLR_MASK,
- ((uint16_t)mute << SGTL5000_MUTE_LO_SHIFT));
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_config_data_format(sgtl_context_t *context, uint32_t mclk, uint32_t sample_rate, uint32_t bits)
- {
- uint16_t val = 0;
- uint16_t regVal = 0;
- uint16_t mul_clk = 0U;
- uint32_t sysFs = 0U;
- hpm_stat_t stat = status_success;
- /* Over sample rate can only up to 512, the least to 8k */
- if ((mclk / (MIN(sample_rate * 6U, 96000U)) > 512U) || (mclk / sample_rate < 256U))
- {
- return status_invalid_argument;
- }
- /* Configure the sample rate */
- switch (sample_rate)
- {
- case 8000:
- if (mclk > 32000U * 512U)
- {
- val = 0x0038;
- sysFs = 48000;
- }
- else
- {
- val = 0x0020;
- sysFs = 32000;
- }
- break;
- case 11025:
- val = 0x0024;
- sysFs = 44100;
- break;
- case 12000:
- val = 0x0028;
- sysFs = 48000;
- break;
- case 16000:
- if (mclk > 32000U * 512U)
- {
- val = 0x003C;
- sysFs = 96000;
- }
- else
- {
- val = 0x0010;
- sysFs = 32000;
- }
- break;
- case 22050:
- val = 0x0014;
- sysFs = 44100;
- break;
- case 24000:
- if (mclk > 48000U * 512U)
- {
- val = 0x002C;
- sysFs = 96000;
- }
- else
- {
- val = 0x0018;
- sysFs = 48000;
- }
- break;
- case 32000:
- val = 0x0000;
- sysFs = 32000;
- break;
- case 44100:
- val = 0x0004;
- sysFs = 44100;
- break;
- case 48000:
- if (mclk > 48000U * 512U)
- {
- val = 0x001C;
- sysFs = 96000;
- }
- else
- {
- val = 0x0008;
- sysFs = 48000;
- }
- break;
- case 96000:
- val = 0x000C;
- sysFs = 96000;
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- if (stat != status_success)
- {
- return stat;
- }
- if (sgtl_read_reg(context, CHIP_I2S_CTRL, ®Val) != status_success)
- {
- return status_fail;
- }
- /* While as slave, Fs is input */
- if ((regVal & SGTL5000_I2S_MS_GET_MASK) == 0U)
- {
- sysFs = sample_rate;
- }
- mul_clk = (uint16_t)(mclk / sysFs);
- /* Configure the mul_clk. Sgtl-5000 only support 256, 384 and 512 oversample rate */
- if ((mul_clk / 128U - 2U) > 2U)
- {
- return status_invalid_argument;
- }
- else
- {
- val |= (mul_clk / 128U - 2U);
- }
- if (sgtl_write_reg(context, CHIP_CLK_CTRL, val) != status_success)
- {
- return status_fail;
- }
- /* Data bits configure,sgtl supports 16bit, 20bit 24bit, 32bit */
- if (sgtl_modify_reg(context, CHIP_I2S_CTRL, 0xFEFF, SGTL5000_I2S_SCLKFREQ_64FS) != status_success)
- {
- return status_fail;
- }
- switch (bits)
- {
- case 16:
- stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_16);
- break;
- case 20:
- stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_20);
- break;
- case 24:
- stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_24);
- break;
- case 32:
- stat = sgtl_modify_reg(context, CHIP_I2S_CTRL, SGTL5000_I2S_DLEN_CLR_MASK, SGTL5000_I2S_DLEN_32);
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- return stat;
- }
- hpm_stat_t sgtl_set_play(sgtl_context_t *context, uint32_t playSource)
- {
- uint16_t regValue = 0U, regBitMask = 0x40U;
- /* headphone source form PGA */
- if (playSource == (uint32_t)sgtl_play_source_linein)
- {
- regValue = 0x40U;
- }
- /* headphone source from DAC */
- else
- {
- regValue = 0U;
- }
- return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
- }
- hpm_stat_t sgtl_set_record(sgtl_context_t *context, uint32_t recordSource)
- {
- uint16_t regValue = 0U, regBitMask = 0x4U;
- /* ADC source form LINEIN */
- if (recordSource == (uint32_t)sgtl_record_source_linein)
- {
- regValue = 0x4U;
- }
- /* ADC source from MIC */
- else
- {
- regValue = 0U;
- }
- return sgtl_modify_reg(context, CHIP_ANA_CTRL, regBitMask, regValue);
- }
- hpm_stat_t sgtl_write_reg(sgtl_context_t *context, uint16_t reg, uint16_t val)
- {
- rt_size_t size;
- rt_uint8_t data[4];
- data[0] = reg >> 8;
- data[1] = reg & 0xFF;
- data[2] = (uint8_t) (val>>8);
- data[3] = (uint8_t) (val & 0xFF);
- size = rt_i2c_master_send(context->i2c_bus, context->slave_address, RT_I2C_WR, data, 4U);
- if (size != 4) {
- return status_fail;
- }
- return status_success;
- }
- hpm_stat_t sgtl_read_reg(sgtl_context_t *context, uint16_t reg, uint16_t *val)
- {
- rt_size_t size;
- rt_uint8_t r[2];
- uint8_t d[2];
- r[0] = reg >> 8;
- r[1] = reg & 0xFF;
- size = rt_i2c_master_send(context->i2c_bus, context->slave_address, RT_I2C_WR, r, 2U);
- if (size != 2) {
- return status_fail;
- }
- size = rt_i2c_master_recv(context->i2c_bus, context->slave_address, RT_I2C_RD, d, 2U);
- if (size != 2) {
- return status_fail;
- }
- *val = (uint16_t)((d[0] << 8) | d[1]);
- return status_success;
- }
- hpm_stat_t sgtl_modify_reg(sgtl_context_t *context, uint16_t reg, uint16_t clr_mask, uint16_t val)
- {
- hpm_stat_t retval = 0;
- uint16_t reg_val;
- /* Read the register value out */
- retval = sgtl_read_reg(context, reg, ®_val);
- if (retval != status_success)
- {
- return status_fail;
- }
- /* Modify the value */
- reg_val &= clr_mask;
- reg_val |= val;
- /* Write the data to register */
- retval = sgtl_write_reg(context, reg, reg_val);
- if (retval != status_success)
- {
- return status_fail;
- }
- return status_success;
- }
|