audio wip, PIO beep but no DMA

This commit is contained in:
shinyquagsire23 2024-06-06 00:47:37 -06:00
parent 9e1b2ee573
commit 1cf55e2225
17 changed files with 1303 additions and 9 deletions

View file

@ -31,6 +31,7 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
# Hardware.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
rt5639.o ahub.o \
bpmp.o ccplex.o clock.o di.o i2c.o irq.o timer.o \
mc.o sdram.o minerva.o \
gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \

276
bdk/audio/ahub.c Normal file
View file

@ -0,0 +1,276 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2024 shinyquagsire23
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utils/types.h>
#include <audio/ahub.h>
#include <soc/timer.h>
#include <soc/bpmp.h>
#include <stdio.h>
#include <stdlib.h>
//#include <avpc.h>
#include <malloc.h>
#include <string.h>
#define OUT_BUF_SIZE 0x80000
#define IN_BUF_SIZE 0x8000
s16 *output_buf;
s16 *input_buf;
u32 ahub_get_cif(int is_receive, u32 channels, u32 bits_per_sample, u32 fifo_threshold)
{
u32 audio_bits = (bits_per_sample >> 2) - 1;
return (channels - 1) << 20 |
(channels - 1) << 16 |
audio_bits << 12 |
audio_bits << 8 |
(fifo_threshold - 1) << 24;
//(is_receive ? 1 << 2 : 0);
}
void ahub_init(void)
{
output_buf = memalign(0x1000, OUT_BUF_SIZE);
input_buf = memalign(0x1000, IN_BUF_SIZE);
memset(output_buf, 0, OUT_BUF_SIZE);
memset(input_buf, 0, IN_BUF_SIZE);
u32 fifo_threshold = 4;
u8 bits_per_sample = 16;
ADMAIF_GLOBAL_ENABLE_0 = 1;
ADMA_GLOBAL_CMD_0 = 1;
I2S_CG_0(1) = 0;
I2S_CTRL_0(1) = 0x400;
for (int i = 0; i < 5; i++)
{
if (!I2S_SOFT_RESET_0(1) & 1) break;
usleep(10);
}
I2S_SOFT_RESET_0(1) = 0;
I2S_ENABLE_0(1) = 1;
// Timing stuff, currently "set" for 46.84KHz.
// Heavily dependent on CAR I2S + AUD_MCLK (EXTPERIPH1) clocks
I2S_CTRL_0(1) = I2S_CTRL_FRAME_FORMAT_BASIC | I2S_CTRL_BIT_CNT_16 | I2S_CTRL_LRCK_POLARITY_LOW
| I2S_FSYNC_WIDTH(bits_per_sample) | I2S_CTRL_EDGE_CTRL_POS_EDGE | I2S_CTRL_MASTER;
I2S_TIMING_0(1) = 31;
// Set I2S (spkrs) AXBAR settings for what data it should expect
I2S_AXBAR_TX_CTRL_0(1) = I2S_RXTX_DATA_OFFSET(1) | I2S_NOHIGHZ;
I2S_SLOT_CTRL_0(1) = 0;
I2S_AXBAR_TX_SLOT_CTRL_0(1) = 0;
I2S_AXBAR_TX_CIF_CTRL_0(1) = ahub_get_cif(1, 2, bits_per_sample, fifo_threshold);
// Set I2S (mic) AXBAR settings for what data it should be sending
I2S_AXBAR_RX_CTRL_0(1) = I2S_RXTX_DATA_OFFSET(1) | I2S_NOHIGHZ;
I2S_AXBAR_RX_SLOT_CTRL_0(1) = 0;
I2S_AXBAR_RX_CIF_CTRL_0(1) = ahub_get_cif(1, 2, bits_per_sample, fifo_threshold);
// Set up ADMAIF TX0 and RX0 settings, set I2S (spkr) to receive from ADMAIF TX1 and ADMAIF RX1 to receive from I2S (mic)
ADMAIF_AXBAR_TX0_CIF_CTRL_0 = ahub_get_cif(1, 2, bits_per_sample, fifo_threshold) | CIF_UNPACK16;
ADMAIF_AXBAR_RX0_CIF_CTRL_0 = ahub_get_cif(1, 2, bits_per_sample, fifo_threshold) | CIF_UNPACK16;
ADMAIF_AXBAR_TX0_FIFO_CTRL_0 |= BIT(31); // PIO, for manual driving w/ FIFO_WRITE
ADMAIF_AXBAR_RX0_FIFO_CTRL_0 |= BIT(31);
//ADMAIF_AXBAR_TX0_FIFO_CTRL_0 &= ~BIT(31); // DMA
//ADMAIF_AXBAR_RX0_FIFO_CTRL_0 &= ~BIT(31);
AXBAR_PART_0_I2S1_RX1_0 = ADMAIF_TX1;
AXBAR_PART_0_ADMAIF_RX0_0 = I2S1_TX1;
// Enable AXBAR + I2S TX
ADMAIF_AXBAR_TX0_ENABLE_0 = 1; // added
I2S_AXBAR_RX_ENABLE_0(1) = 1; // added
// Enable AXBAR + I2S RX (mic)
ADMAIF_AXBAR_RX0_ENABLE_0 = 1; // added for mic
I2S_AXBAR_TX_ENABLE_0(1) = 1; //added for mic
// Final pipeline is
// ADMA -> AXBAR TX0 -> I2S
// I2S -> AXBAR RX0 -> ADMA
}
void ahub_shutdown(void)
{
adma_stop(0);
}
void adma_init_out(int channel, bool loop)
{
if (channel >= ADMA_NUM_CHANNELS) return;
// Reset DMA channel
ADMA_CHn_SOFT_RESET_0(channel) = 1;
for (int i = 0; i < 5; i++)
{
if (!ADMA_CHn_SOFT_RESET_0(channel) & 1) break;
usleep(10);
}
ADMA_CHn_SOFT_RESET_0(channel) = 0;
// Configured to output to TX1
ADMA_CHn_CTRL_0(channel) = ADMA_FLOWCTRL_ENABLE | (loop ? ADMA_TRANSFER_MODE_CONTINUOUS : ADMA_TRANSFER_MODE_ONCE) | ADMA_TRANSFER_DIRECTION_MEMORY_TO_AHUB | ADMA_TX_REQUEST_SELECT(1);
ADMA_CHn_CONFIG_0(channel) = ADMA_TARGET_ADDR_WRAP_ON_1_WORD | ADMA_BURST_SIZE_WORDS_16;
}
void adma_init_in(int channel, bool loop)
{
if (channel >= ADMA_NUM_CHANNELS) return;
// Reset DMA channel
ADMA_CHn_SOFT_RESET_0(channel) = 1;
for (int i = 0; i < 5; i++)
{
if (!ADMA_CHn_SOFT_RESET_0(channel) & 1) break;
usleep(10);
}
ADMA_CHn_SOFT_RESET_0(channel) = 0;
// Configured to read from RX0
ADMA_CHn_CTRL_0(channel) = ADMA_FLOWCTRL_ENABLE | (loop ? ADMA_TRANSFER_MODE_CONTINUOUS : ADMA_TRANSFER_MODE_ONCE) | ADMA_TRANSFER_DIRECTION_AHUB_TO_MEMORY | ADMA_RX_REQUEST_SELECT(1);
ADMA_CHn_CONFIG_0(channel) = ADMA_SOURCE_ADDR_WRAP_ON_1_WORD | ADMA_BURST_SIZE_WORDS_16;
}
void adma_set_source(int channel, void* addr, u32 size)
{
ADMA_CHn_LOWER_SOURCE_ADDR_0(channel) = (intptr_t)addr;
ADMA_CHn_TC_0(channel) = size;
}
void adma_set_target(int channel, void* addr, u32 size)
{
ADMA_CHn_LOWER_TARGET_ADDR_0(channel) = (intptr_t)addr;
ADMA_CHn_TC_0(channel) = size;
}
void adma_wait(int channel)
{
while (ADMA_CHn_STATUS_0(channel) & ADMA_TRANSFER_ENABLED);
}
void adma_start(int channel)
{
ADMA_CHn_CMD_0(channel) = ADMA_TRANSFER_ENABLE;
}
void adma_stop(int channel)
{
ADMA_CHn_CMD_0(channel) = ADMA_TRANSFER_DISABLE;
}
void ahub_tx_test(void)
{
// mic in
//adma_init_in(1, false);
//adma_set_target(1, input_buf, IN_BUF_SIZE);
#if 1
// Waveform generation
int index = 0;
int amt = 80;
int vol = 0x10;
u32 buf_slice = 0x1C000/8;
while (index + 2 < buf_slice / sizeof(s16))
{
for (int i = 0; i < amt/2; i++)
{
// Left/Right
output_buf[index++] = vol;
output_buf[index++] = vol;
}
if (index + 2 >= buf_slice / sizeof(s16)) break;
for (int i = 0; i < amt/2; i++)
{
output_buf[index++] = -vol;
output_buf[index++] = -vol;
}
}
// Flush to DRAM
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
/*adma_stop(0);
adma_init_out(0, false);
adma_set_source(0, output_buf, buf_slice);
adma_start(0);*/
//adma_wait(0);
for (int i = 0; i < buf_slice; i++)
{
while(ADMAIF_GLOBAL_TX_ACIF_FIFO_FULL_STATUS_0 & BIT(0));
//u16 val = (i >> 3) & 1 ? 0x7FFF : 0x8000;
ADMAIF_AXBAR_TX0_FIFO_WRITE_0 = output_buf[i];
//usleep(1);
}
/*for (int i = 0; i < 1000; i++)
{
adma_wait(0);
adma_start(0);
msleep(1);
}*/
#endif
#if 0
// WAV read
vfile_t file = { 0 };
off_t read = 0;
vfile_open(&file, "sdmc:/apple_startup.wav", FA_READ);
vfile_read(&file, 0, output_buf, 0x2C, &read);
vfile_read(&file, 0, output_buf, 0x72E84-0x2C, &read);
vfile_close(&file);
vfile_open(&file, "sdmc:/apple_logo.bin", FA_READ);
vfile_read(&file, 0, (void*)0xC0000000+0x100000, 1280*768*4, &read);
vfile_close(&file);
fb_framebuffer((void*)0xC0000000+0x100000, false);
adma_start(0);
while (1);
#endif
// Non-continuous
/*for (int i = 0; i < 1000; i++)
{
adma_wait(0);
adma_start(0);
}*/
// Continuous
//adma_start(0);
//adma_start(1); // mic
// Direct feeding
/*for (int i = 0; i < 3000000; i++)
{
u16 val = (i >> 3) & 1 ? 0x7FFF : 0x8000;
ADMAIF_AXBAR_TX0_FIFO_WRITE_0 = val;
usleep(1);
}*/
}

192
bdk/audio/ahub.h Normal file
View file

@ -0,0 +1,192 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2024 shinyquagsire23
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AHUB_H_
#define _AHUB_H_
#include <utils/types.h>
#include <soc/t210.h>
#include <audio/i2s.h>
//#define AHUB_BASE ((void*)0x702d0000)
#define ADMAIF_BASE ((void*)0x702d0000)
//#define ADMA_BASE ((void*)0x702e2000)
//#define AXBAR_BASE ((void*)0x702d0800)
#define ADMA_CH_SIZE (0x80)
#define ADMA_NUM_CHANNELS (22)
#define ADMA_CHn_CMD_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x000))
#define ADMA_CHn_SOFT_RESET_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x004))
#define ADMA_CHn_STATUS_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x00C))
#define ADMA_CHn_INT_STATUS_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x010))
#define ADMA_CHn_INT_SET_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x018))
#define ADMA_CHn_INT_CLEAR_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x01C))
#define ADMA_CHn_CTRL_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x024))
#define ADMA_CHn_CONFIG_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x028))
#define ADMA_CHn_AHUB_FIFO_CTRL_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x02C))
#define ADMA_CHn_TC_STATUS_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x030))
#define ADMA_CHn_LOWER_SOURCE_ADDR_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x034))
#define ADMA_CHn_LOWER_TARGET_ADDR_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x03C))
#define ADMA_CHn_TC_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x044))
#define ADMA_CHn_LOWER_DESC_ADDR_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x048))
#define ADMA_CHn_TRANSFER_STATUS_0(n) (*(vu32*)(ADMA_BASE + (n * ADMA_CH_SIZE) + 0x054))
#define ADMA_GLOBAL_CMD_0 (*(vu32*)(ADMA_BASE + 0xC00))
#define ADMA_GLOBAL_SOFT_RESET_0 (*(vu32*)(ADMA_BASE + 0xC04))
#define ADMA_GLOBAL_CG_0 (*(vu32*)(ADMA_BASE + 0xC08))
#define ADMA_GLOBAL_STATUS_0 (*(vu32*)(ADMA_BASE + 0xC10))
#define ADMA_GLOBAL_INT_STATUS_0 (*(vu32*)(ADMA_BASE + 0xC14))
#define ADMA_GLOBAL_INT_MASK_0 (*(vu32*)(ADMA_BASE + 0xC18))
#define ADMA_GLOBAL_INT_SET_0 (*(vu32*)(ADMA_BASE + 0xC1C))
#define ADMA_GLOBAL_INT_CLEAR_0 (*(vu32*)(ADMA_BASE + 0xC20))
#define ADMA_GLOBAL_CTRL_0 (*(vu32*)(ADMA_BASE + 0xC24))
#define ADMA_GLOBAL_CH_INT_STATUS_0 (*(vu32*)(ADMA_BASE + 0xC28))
#define ADMA_GLOBAL_CH_ENABLE_STATUS_0 (*(vu32*)(ADMA_BASE + 0xC2C))
#define ADMA_GLOBAL_TX_REQUESTORS_0 (*(vu32*)(ADMA_BASE + 0xC30))
#define ADMA_GLOBAL_RX_REQUESTORS_0 (*(vu32*)(ADMA_BASE + 0xC34))
#define ADMA_GLOBAL_GLOBAL_TRIGGERS_0 (*(vu32*)(ADMA_BASE + 0xC38))
#define ADMA_GLOBAL_TRANSFER_ERROR_LOG_0 (*(vu32*)(ADMA_BASE + 0xC3C))
// ADMA_CHn_CTRL
#define ADMA_TX_REQUEST_SELECT(n) (n << 28)
#define ADMA_RX_REQUEST_SELECT(n) (n << 24)
#define ADMA_TRANSFER_DIRECTION_MEMORY_TO_MEMORY (1 << 12)
#define ADMA_TRANSFER_DIRECTION_AHUB_TO_MEMORY (2 << 12)
#define ADMA_TRANSFER_DIRECTION_MEMORY_TO_AHUB (4 << 12)
#define ADMA_TRANSFER_DIRECTION_AHUB_TO_AHUB (7 << 12)
#define ADMA_TRANSFER_MODE_ONCE (1 << 8)
#define ADMA_TRANSFER_MODE_CONTINUOUS (2 << 8)
#define ADMA_TRANSFER_MODE_LINKED_LIST (4 << 8)
#define ADMA_FLOWCTRL_ENABLE BIT(1)
#define ADMA_TRANSFER_PAUSE BIT(0)
// ADMA_CHn_CONFIG
#define ADMA_TARGET_ADDR_WRAP_NONE (0)
#define ADMA_TARGET_ADDR_WRAP_ON_1_WORD (1)
#define ADMA_SOURCE_ADDR_WRAP_NONE (0 << 16)
#define ADMA_SOURCE_ADDR_WRAP_ON_1_WORD (1 << 16)
#define ADMA_BURST_SIZE_WORDS_1 (1 << 20)
#define ADMA_BURST_SIZE_WORDS_2 (2 << 20)
#define ADMA_BURST_SIZE_WORDS_4 (3 << 20)
#define ADMA_BURST_SIZE_WORDS_8 (4 << 20)
#define ADMA_BURST_SIZE_WORDS_16 (5 << 20)
// ADMA_CHn_CMD
#define ADMA_TRANSFER_DISABLE (0)
#define ADMA_TRANSFER_ENABLE (1)
// ADMA_CHn_STATUS
#define ADMA_TRANSFER_ENABLED (1)
#define ADMAIF_AXBAR_RX0_ENABLE_0 (*(vu32*)(ADMAIF_BASE + 0x000))
#define ADMAIF_AXBAR_RX0_SOFT_RESET_0 (*(vu32*)(ADMAIF_BASE + 0x004))
#define ADMAIF_AXBAR_RX0_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x00c))
#define ADMAIF_AXBAR_RX0_INT_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x010))
#define ADMAIF_AXBAR_RX0_INT_MASK_0 (*(vu32*)(ADMAIF_BASE + 0x014))
#define ADMAIF_AXBAR_RX0_INT_SET_0 (*(vu32*)(ADMAIF_BASE + 0x018))
#define ADMAIF_AXBAR_RX0_INT_CLEAR_0 (*(vu32*)(ADMAIF_BASE + 0x01c))
#define ADMAIF_AXBAR_RX0_CIF_CTRL_0 (*(vu32*)(ADMAIF_BASE + 0x020))
#define ADMAIF_AXBAR_RX0_FIFO_CTRL_0 (*(vu32*)(ADMAIF_BASE + 0x028))
#define ADMAIF_AXBAR_RX0_FIFO_READ_0 (*(vu32*)(ADMAIF_BASE + 0x02c))
#define ADMAIF_AXBAR_TX0_ENABLE_0 (*(vu32*)(ADMAIF_BASE + 0x300))
#define ADMAIF_AXBAR_TX0_SOFT_RESET_0 (*(vu32*)(ADMAIF_BASE + 0x304))
#define ADMAIF_AXBAR_TX0_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x30c))
#define ADMAIF_AXBAR_TX0_INT_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x310))
#define ADMAIF_AXBAR_TX0_INT_MASK_0 (*(vu32*)(ADMAIF_BASE + 0x314))
#define ADMAIF_AXBAR_TX0_INT_SET_0 (*(vu32*)(ADMAIF_BASE + 0x318))
#define ADMAIF_AXBAR_TX0_INT_CLEAR_0 (*(vu32*)(ADMAIF_BASE + 0x31c))
#define ADMAIF_AXBAR_TX0_CIF_CTRL_0 (*(vu32*)(ADMAIF_BASE + 0x320))
#define ADMAIF_AXBAR_TX0_FIFO_CTRL_0 (*(vu32*)(ADMAIF_BASE + 0x328))
#define ADMAIF_AXBAR_TX0_FIFO_WRITE_0 (*(vu32*)(ADMAIF_BASE + 0x32c))
#define ADMAIF_GLOBAL_ENABLE_0 (*(vu32*)(ADMAIF_BASE + 0x700))
#define ADMAIF_GLOBAL_SOFT_RESET_0 (*(vu32*)(ADMAIF_BASE + 0x704))
#define ADMAIF_GLOBAL_CG_0 (*(vu32*)(ADMAIF_BASE + 0x708))
#define ADMAIF_GLOBAL_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x710))
#define ADMAIF_GLOBAL_RX_ENABLE_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x720))
#define ADMAIF_GLOBAL_TX_ENABLE_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x724))
#define ADMAIF_GLOBAL_RX_DMA_FIFO_EMPTY_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x728))
#define ADMAIF_GLOBAL_RX_DMA_FIFO_FULL_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x72c))
#define ADMAIF_GLOBAL_TX_DMA_FIFO_EMPTY_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x730))
#define ADMAIF_GLOBAL_TX_DMA_FIFO_FULL_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x734))
#define ADMAIF_GLOBAL_RX_ACIF_FIFO_EMPTY_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x738))
#define ADMAIF_GLOBAL_RX_ACIF_FIFO_FULL_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x73c))
#define ADMAIF_GLOBAL_TX_ACIF_FIFO_EMPTY_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x740))
#define ADMAIF_GLOBAL_TX_ACIF_FIFO_FULL_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x744))
#define ADMAIF_GLOBAL_RX_DMA_OVERRUN_INT_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x748))
#define ADMAIF_GLOBAL_TX_DMA_UNDERRUN_INT_STATUS_0 (*(vu32*)(ADMAIF_BASE + 0x74c))
#define AXBAR_PART_0_ADMAIF_RX0_0 (*(vu32*)(AXBAR_BASE + 0x000))
#define AXBAR_PART_0_ADMAIF_RX1_0 (*(vu32*)(AXBAR_BASE + 0x004))
#define AXBAR_PART_0_ADMAIF_RX2_0 (*(vu32*)(AXBAR_BASE + 0x008))
#define AXBAR_PART_0_ADMAIF_RX3_0 (*(vu32*)(AXBAR_BASE + 0x00C))
#define AXBAR_PART_0_I2S1_RX1_0 (*(vu32*)(AXBAR_BASE + 0x040))
#define AXBAR_PART_0_I2S2_RX1_0 (*(vu32*)(AXBAR_BASE + 0x044))
#define AXBAR_PART_0_I2S3_RX1_0 (*(vu32*)(AXBAR_BASE + 0x048))
#define AXBAR_PART_0_I2S4_RX1_0 (*(vu32*)(AXBAR_BASE + 0x04C))
#define AXBAR_PART_0_I2S5_RX1_0 (*(vu32*)(AXBAR_BASE + 0x050))
#define AXBAR_PART_0_SFC1_RX1_0 (*(vu32*)(AXBAR_BASE + 0x060))
#define AXBAR_PART_0_SFC2_RX1_0 (*(vu32*)(AXBAR_BASE + 0x064))
#define AXBAR_PART_0_SFC3_RX1_0 (*(vu32*)(AXBAR_BASE + 0x068))
#define AXBAR_PART_0_SFC4_RX1_0 (*(vu32*)(AXBAR_BASE + 0x06C))
#define AXBAR_PART_0_MIXER1_RX0_0 (*(vu32*)(AXBAR_BASE + 0x080))
#define AXBAR_PART_0_MIXER1_RX1_0 (*(vu32*)(AXBAR_BASE + 0x084))
#define AXBAR_PART_0_MIXER1_RX2_0 (*(vu32*)(AXBAR_BASE + 0x088))
#define AXBAR_PART_0_MIXER1_RX3_0 (*(vu32*)(AXBAR_BASE + 0x08C))
#define AXBAR_PART_0_MIXER1_RX4_0 (*(vu32*)(AXBAR_BASE + 0x090))
#define AXBAR_PART_0_MIXER1_RX5_0 (*(vu32*)(AXBAR_BASE + 0x094))
#define AXBAR_PART_0_MIXER1_RX6_0 (*(vu32*)(AXBAR_BASE + 0x098))
#define AXBAR_PART_0_MIXER1_RX7_0 (*(vu32*)(AXBAR_BASE + 0x09C))
#define AXBAR_PART_0_MIXER1_RX8_0 (*(vu32*)(AXBAR_BASE + 0x0A0))
#define AXBAR_PART_0_MIXER1_RX9_0 (*(vu32*)(AXBAR_BASE + 0x0A4))
// AXBAR bits
#define SFC4_TX1 BIT(27)
#define SFC3_TX1 BIT(26)
#define SFC2_TX1 BIT(25)
#define SFC1_TX1 BIT(24)
#define I2S5_TX1 BIT(20)
#define I2S4_TX1 BIT(19)
#define I2S3_TX1 BIT(18)
#define I2S2_TX1 BIT(17)
#define I2S1_TX1 BIT(16)
#define ADMAIF_TX10 BIT(9)
#define ADMAIF_TX9 BIT(8)
#define ADMAIF_TX8 BIT(7)
#define ADMAIF_TX7 BIT(6)
#define ADMAIF_TX6 BIT(5)
#define ADMAIF_TX5 BIT(4)
#define ADMAIF_TX4 BIT(3)
#define ADMAIF_TX3 BIT(2)
#define ADMAIF_TX2 BIT(1)
#define ADMAIF_TX1 BIT(0)
#define CIF_UNPACK16 BIT(30)
void ahub_init(void);
void ahub_shutdown(void);
void adma_init_out(int channel, bool loop);
void adma_init_in(int channel, bool loop);
void adma_set_source(int channel, void* addr, u32 size);
void adma_set_target(int channel, void* addr, u32 size);
void adma_wait(int channel);
void adma_start(int channel);
void adma_stop(int channel);
void ahub_tx_test(void);
#endif // _AHUB_H_

99
bdk/audio/i2s.h Normal file
View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2024 shinyquagsire23
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _I2S_H_
#define _I2S_H_
#include <utils/types.h>
#define I2S1_BASE ((void*)0x702D1000)
#define I2S2_BASE ((void*)0x702D1100)
#define I2S3_BASE ((void*)0x702D1200)
#define I2S4_BASE ((void*)0x702D1300)
#define I2S5_BASE ((void*)0x702D1400)
#define I2S_BASE(n) (((n) == 1) ? I2S1_BASE : \
((n) == 2) ? I2S2_BASE : \
((n) == 3) ? I2S3_BASE : \
((n) == 4) ? I2S4_BASE : \
((n) == 5) ? I2S5_BASE : \
NULL)
#define I2S_AXBAR_RX_ENABLE_0(n) (*(vu32*)(I2S_BASE(n) + 0x000))
#define I2S_AXBAR_RX_SOFT_RESET_0(n) (*(vu32*)(I2S_BASE(n) + 0x004))
#define I2S_AXBAR_RX_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x00c))
#define I2S_AXBAR_RX_INT_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x010))
#define I2S_AXBAR_RX_INT_MASK_0(n) (*(vu32*)(I2S_BASE(n) + 0x014))
#define I2S_AXBAR_RX_INT_SET_0(n) (*(vu32*)(I2S_BASE(n) + 0x018))
#define I2S_AXBAR_RX_INT_CLEAR_0(n) (*(vu32*)(I2S_BASE(n) + 0x01c))
#define I2S_AXBAR_RX_CIF_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x020))
#define I2S_AXBAR_RX_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x024))
#define I2S_AXBAR_RX_SLOT_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x028))
#define I2S_AXBAR_RX_CLK_TRIM_0(n) (*(vu32*)(I2S_BASE(n) + 0x02c))
#define I2S_AXBAR_TX_ENABLE_0(n) (*(vu32*)(I2S_BASE(n) + 0x040))
#define I2S_AXBAR_TX_SOFT_RESET_0(n) (*(vu32*)(I2S_BASE(n) + 0x044))
#define I2S_AXBAR_TX_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x04c))
#define I2S_AXBAR_TX_INT_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x050))
#define I2S_AXBAR_TX_INT_MASK_0(n) (*(vu32*)(I2S_BASE(n) + 0x054))
#define I2S_AXBAR_TX_INT_SET_0(n) (*(vu32*)(I2S_BASE(n) + 0x058))
#define I2S_AXBAR_TX_INT_CLEAR_0(n) (*(vu32*)(I2S_BASE(n) + 0x05c))
#define I2S_AXBAR_TX_CIF_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x060))
#define I2S_AXBAR_TX_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x064))
#define I2S_AXBAR_TX_SLOT_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x068))
#define I2S_AXBAR_TX_CLK_TRIM_0(n) (*(vu32*)(I2S_BASE(n) + 0x06c))
#define I2S_ENABLE_0(n) (*(vu32*)(I2S_BASE(n) + 0x080))
#define I2S_SOFT_RESET_0(n) (*(vu32*)(I2S_BASE(n) + 0x084))
#define I2S_CG_0(n) (*(vu32*)(I2S_BASE(n) + 0x088))
#define I2S_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x08c))
#define I2S_INT_STATUS_0(n) (*(vu32*)(I2S_BASE(n) + 0x090))
#define I2S_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x0a0))
#define I2S_TIMING_0(n) (*(vu32*)(I2S_BASE(n) + 0x0a4))
#define I2S_SLOT_CTRL_0(n) (*(vu32*)(I2S_BASE(n) + 0x0a8))
#define I2S_CLK_TRIM_0(n) (*(vu32*)(I2S_BASE(n) + 0x0ac))
// I2S_AXBAR_RX_CTRL_0 / I2S_AXBAR_TX_CTRL_0
#define I2S_RXTX_DATA_OFFSET(n) ((n << 8) & 0x3F0)
#define I2S_NOHIGHZ (0 << 1)
#define I2S_HIGHZ (1 << 1)
#define I2S_HIGHZ_ON_HALF_BIT_CLK (2 << 1)
// I2S_CTRL_0
#define I2S_CTRL_BIT_CNT_8 (1)
#define I2S_CTRL_BIT_CNT_12 (2)
#define I2S_CTRL_BIT_CNT_16 (3)
#define I2S_CTRL_BIT_CNT_20 (4)
#define I2S_CTRL_BIT_CNT_24 (5)
#define I2S_CTRL_BIT_CNT_28 (6)
#define I2S_CTRL_BIT_CNT_32 (7)
#define I2S_CTRL_LOOPBACK BIT(8)
#define I2S_CTRL_LRCK_POLARITY_LOW (0)
#define I2S_CTRL_LRCK_POLARITY_HIGH BIT(9)
#define I2S_CTRL_SLAVE (0)
#define I2S_CTRL_MASTER BIT(10)
#define I2S_CTRL_FRAME_FORMAT_BASIC (0)
#define I2S_CTRL_FRAME_FORMAT_LJM (0)
#define I2S_CTRL_FRAME_FORMAT_RJM (0)
#define I2S_CTRL_FRAME_FORMAT_DSP BIT(12)
#define I2S_CTRL_FRAME_FORMAT_PCM BIT(12)
#define I2S_CTRL_FRAME_FORMAT_NW BIT(12)
#define I2S_CTRL_FRAME_FORMAT_TDM BIT(12)
#define I2S_CTRL_EDGE_CTRL_NEG_EDGE BIT(20)
#define I2S_CTRL_EDGE_CTRL_POS_EDGE (0)
#define I2S_FSYNC_WIDTH(n) ((n << 24) & 0xFF000000)
#endif // _I2S_H_

337
bdk/audio/rt5639.c Normal file
View file

@ -0,0 +1,337 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2024 shinyquagsire23
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rt5639.h"
#include <utils/types.h>
#include <soc/clock.h>
#include <soc/gpio.h>
#include <soc/i2c.h>
#include <soc/pinmux.h>
#include <soc/timer.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <power/max7762x.h>
#include <audio/ahub.h>
#include <stdio.h>
u16 rt5639_read16(u8 reg);
void rt5639_reset(void)
{
i2c_send_buf_small(I2C_1, RT5639_I2C_ADDR, RT5639_RESET, (u8[2]){0,0}, 2);
}
void rt5639_write16(u8 reg, u16 val)
{
u16 val_flip = byte_swap_16(val); // le -> be
i2c_send_buf_small(I2C_1, RT5639_I2C_ADDR, reg, (u8*)&val_flip, 2);
}
u16 rt5639_read16(u8 reg)
{
u16 val;
i2c_recv_buf_small((u8*)&val, 2, I2C_1, RT5639_I2C_ADDR, reg);
return byte_swap_16(val); // be -> le
}
void rt5639_pr_write16(u16 preg, u16 val)
{
rt5639_write16(RT5639_PRIV_INDEX, preg);
rt5639_write16(RT5639_PRIV_DATA, val);
}
u16 rt5639_pr_read16(u16 preg)
{
rt5639_write16(RT5639_PRIV_INDEX, preg);
return rt5639_read16(RT5639_PRIV_DATA);
}
void rt5639_setbits(u8 reg, u16 bits)
{
rt5639_write16(reg, rt5639_read16(reg) | bits);
}
void rt5639_maskbits(u8 reg, u16 bits)
{
rt5639_write16(reg, rt5639_read16(reg) & bits);
}
// TODO maybe just abstract this into clock.c
#define SET_CLK_ENB_APE (BIT(6))
#define CLR_APE_RST (BIT(6))
#define SET_CLK_ENB_APB2APE (BIT(11))
#define CLR_APB2APE_RST (BIT(11))
#define SET_APE_RST (BIT(6))
#define CLR_APE_RST (BIT(6))
void nx_ape_init(void)
{
pmc_enable_partition(POWER_RAIL_AUD, 1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = SET_CLK_ENB_APB2APE; // TODO clock_enable_apb2ape()
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = SET_CLK_ENB_APE; // TODO clock_enable_ape()
usleep(2);
pmc_unclamp_partition(POWER_RAIL_AUD);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = CLR_APB2APE_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = CLR_APE_RST;
clock_enable_audio();
}
void nx_ape_fini(void)
{
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = SET_APE_RST;
}
void misc_audio_init()
{
PINMUX_AUX(PINMUX_AUX_AUD_MCLK) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_DAP1_FS) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_DAP1_DIN) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_DAP1_DOUT) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_DAP1_SCLK) = PINMUX_INPUT_ENABLE;
PMC(APBDEV_PMC_PWR_DET) |= (PMC_PWR_DET_AUDIO_HV);
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_AUDIO_HV); // 1.8v
usleep(130);
// AUDIO
PMC(APBDEV_PMC_DPD_SAMPLE) = 1;
PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF | BIT(17) /*AUDIO*/;
PMC(APBDEV_PMC_IO_DPD_OFF_MASK) &= ~BIT(17);
usleep(250);
PMC(APBDEV_PMC_DPD_SAMPLE) = 0;
// AUDIO
PMC(APBDEV_PMC_DPD_SAMPLE) = 1;
PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF | BIT(29) /*AUDIO_HV*/;
PMC(APBDEV_PMC_IO_DPD2_OFF_MASK) &= ~BIT(29);
usleep(250);
PMC(APBDEV_PMC_DPD_SAMPLE) = 0;
PINMUX_AUX(PINMUX_AUX_AUD_MCLK) = 0;
PINMUX_AUX(PINMUX_AUX_DAP1_FS) = 0;//PINMUX_INPUT;
PINMUX_AUX(PINMUX_AUX_DAP1_DIN) = 0;//PINMUX_INPUT;
PINMUX_AUX(PINMUX_AUX_DAP1_DOUT) = 0;//PINMUX_INPUT;
PINMUX_AUX(PINMUX_AUX_DAP1_SCLK) = 0;//PINMUX_INPUT;
// Accessing i2s registers (or any registers in the APE block)
// will hang unless it is powered on.
nx_ape_init();
}
void rt5639_init(void)
{
misc_audio_init();
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_AUDIO_HV;
gpio_config(GPIO_PORT_BB, GPIO_PIN_0, GPIO_MODE_SPIO); // TODO what was this, i2s?
gpio_config(GPIO_PORT_B, GPIO_PIN_0, GPIO_MODE_SPIO); // TODO what was this, i2s?
gpio_config(GPIO_PORT_B, GPIO_PIN_1, GPIO_MODE_SPIO); // TODO what was this, i2s?
gpio_config(GPIO_PORT_B, GPIO_PIN_2, GPIO_MODE_SPIO); // TODO what was this, i2s?
gpio_config(GPIO_PORT_B, GPIO_PIN_3, GPIO_MODE_SPIO); // TODO what was this, i2s?
APB_MISC(APB_MISC_GP_AUD_MCLK_CFGPADCTRL) = (0x10 << 20) | (0x10 << 12);
APB_MISC(APB_MISC_DAS_DAP_CTRL_SEL) = BIT(31);
APB_MISC(APB_MISC_DAS_DAC_INPUT_DATA_CLK_SEL) = 0;
PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN;
//clock_enable_i2s_controller();
clock_enable_i2s(0);
/*max7762x_regulator_enable(REGULATOR_LDO0, true);
max7762x_regulator_enable(REGULATOR_LDO1, true);
max7762x_regulator_enable(REGULATOR_LDO2, true);
max7762x_regulator_enable(REGULATOR_LDO3, true);
max7762x_regulator_enable(REGULATOR_LDO4, true);
max7762x_regulator_enable(REGULATOR_LDO5, true);
max7762x_regulator_enable(REGULATOR_LDO6, true);
max7762x_regulator_enable(REGULATOR_LDO7, true);
max7762x_regulator_enable(REGULATOR_LDO8, true);*/
pinmux_config_audio_codec();
gpio_direction_output(GPIO_PORT_Z, GPIO_PIN_4, 1); // deassert codec reset
gpio_direction_input(GPIO_PORT_BB, GPIO_PIN_4); // IRQ/alert, probably headphone removal
msleep(20);
rt5639_reset();
msleep(200);
// HOS init
rt5639_write16(RT5639_HP_DCC_INT1, 0x9f00);
rt5639_write16(RT5639_PWR_ANLG1, 0xA810);
usleep(50000);
rt5639_write16(RT5639_PWR_ANLG1, 0xE818);
usleep(10000);
rt5639_pr_write16(0x1B, 0x200); // unk priv
rt5639_write16(RT5639_DUMMY1, 0x3E01);
//rt5639_write16(RT5639_ADDA_CLK1, 0x8814);
rt5639_write16(RT5639_ADDA_CLK1, 0x1114); // 16-bit
rt5639_pr_write16(0x1D, 0x347); // unk priv
rt5639_pr_write16(RT5639_CHOP_DAC_ADC, 0x3600);
rt5639_pr_write16(RT5639_BIAS_CUR1, 0xAA8);
rt5639_pr_write16(RT5639_BIAS_CUR3, 0x8AAA);
rt5639_pr_write16(0x20, 0x6110); // unk priv
rt5639_pr_write16(0x23, 0x804); // unk priv
rt5639_write16(RT5639_I2S1_SDP, 0x8000);
rt5639_write16(RT5639_I2S2_SDP, 0x8000);
rt5639_write16(RT5639_IRQ_CTRL1, 0x4000);
rt5639_write16(RT5639_IRQ_CTRL2, 0x8000);
rt5639_write16(RT5639_GPIO_CTRL1, 0x8400);
rt5639_write16(RT5639_GPIO_CTRL3, 4);
rt5639_write16(RT5639_JD_CTRL, 0);
rt5639_write16(RT5639_DUMMY2, 0);
rt5639_write16(RT5639_CLS_D_OUT, 0xA800);
rt5639_write16(RT5639_CLS_D_OVCD, 0x328);
rt5639_write16(RT5639_SPK_L_MIXER, 0x36);
rt5639_write16(RT5639_SPK_R_MIXER, 0x36);
rt5639_write16(RT5639_SPK_VOL, 0x8484);
rt5639_write16(RT5639_SPO_CLSD_RATIO, 4);
rt5639_write16(RT5639_SPO_L_MIXER, 0xE800);
rt5639_write16(RT5639_SPO_R_MIXER, 0x2800);
rt5639_write16(RT5639_DAC1_DIG_VOL, 0);
rt5639_write16(RT5639_OUT_L2_MIXER, 0);
rt5639_write16(RT5639_OUT_R2_MIXER, 0);
rt5639_write16(RT5639_OUT_L3_MIXER, 0x1FE);
rt5639_write16(RT5639_OUT_R3_MIXER, 0x1FE);
rt5639_write16(RT5639_HP_VOL, 0x1111);
rt5639_write16(RT5639_HPO_MIXER, 0xC000);
rt5639_write16(RT5639_STO_DAC_MIXER, 0x1414);
rt5639_pr_write16(RT5639_DEPOP_M3, 0x2000);
rt5639_pr_write16(RT5639_CHARGE_PUMP, 0x1000);
rt5639_write16(RT5639_DEPOP_M2, 0x1100);
rt5639_write16(RT5639_DEPOP_M3, 0x646);
rt5639_pr_write16(RT5639_MAMP_INT_REG2, 0xFC00);
rt5639_write16(RT5639_CHARGE_PUMP, 0xC00);
rt5639_write16(RT5639_IN1_IN2, 0x5000);
rt5639_write16(RT5639_IN3_IN4, 0);
rt5639_write16(RT5639_REC_L2_MIXER, 0x7F);
rt5639_write16(RT5639_REC_R2_MIXER, 0x7F);
rt5639_write16(RT5639_STO_ADC_MIXER, 0x3060);
rt5639_write16(RT5639_MICBIAS, 0x3800);
rt5639_write16(RT5639_DIG_INF_DATA, 0x2000);
rt5639_write16(RT5639_ADC_DIG_VOL, 0x2F80);
rt5639_write16(RT5639_PWR_DIG1, 0x8001);
rt5639_write16(RT5639_PWR_DIG2, 0);
rt5639_write16(RT5639_PWR_ANLG2, 0);
rt5639_write16(RT5639_PWR_MIXER, 0x3000);
rt5639_write16(RT5639_PWR_VOL, 0xC000);
rt5639_setbits(RT5639_PWR_DIG1, 0x1800);
usleep(10000);
rt5639_maskbits(RT5639_SPK_VOL, 0x7F7F);
bool headphones = false;
// Activate speakers
if (!headphones)
{
rt5639_write16(RT5639_DEPOP_M3, 0x646);
rt5639_pr_write16(0x37, 0xFC00);
rt5639_setbits(RT5639_DEPOP_M1, 0x4);
rt5639_setbits(RT5639_DEPOP_M1, 0x20);
rt5639_maskbits(RT5639_DEPOP_M1, 0xFCDF);
rt5639_setbits(RT5639_DEPOP_M1, 0x300);
rt5639_setbits(RT5639_HP_VOL, 0x8080);
usleep(30000);
rt5639_maskbits(RT5639_DEPOP_M1, 0x7CFF);
rt5639_write16(RT5639_CHARGE_PUMP, 0xC00);
rt5639_pr_write16(0xA0, 0xED87);
rt5639_pr_write16(0xA1, 0);
rt5639_pr_write16(RT5639_EQ_CTRL1, 0x1FB4);
rt5639_pr_write16(RT5639_EQ_CTRL2, 0x4B);
rt5639_pr_write16(0xB2, 0x1FB4);
rt5639_pr_write16(0xB3, 0x800);
rt5639_pr_write16(RT5639_DRC_AGC_1, 0x800);
rt5639_write16(RT5639_EQ_CTRL2, 0xC1);
rt5639_write16(RT5639_EQ_CTRL1, 0x6041);
rt5639_write16(RT5639_DRC_AGC_2, 0x1F80);
rt5639_write16(RT5639_DRC_AGC_3, 0x480);
rt5639_write16(RT5639_DRC_AGC_1, 0x6B30);
rt5639_maskbits(RT5639_PWR_MIXER, 0x3FFF);
rt5639_maskbits(RT5639_PWR_VOL, 0xF3FF);
rt5639_maskbits(RT5639_PWR_ANLG1, 0xFF1F);
rt5639_maskbits(RT5639_DEPOP_M1, 0xFF66);
rt5639_setbits(RT5639_DEPOP_M1, 0x80);
rt5639_write16(RT5639_DEPOP_M2, 0x1100);
rt5639_setbits(RT5639_PWR_DIG1, 1);
rt5639_setbits(RT5639_PWR_MIXER, 0x3000);
rt5639_setbits(RT5639_PWR_VOL, 0xC000);
rt5639_maskbits(RT5639_SPK_VOL, 0x7F7F);
rt5639_write16(RT5639_SPK_VOL, 0x0404); // 6dB gain left/right
}
else
{
// Activate headphones
rt5639_setbits(RT5639_SPK_VOL, 0x8080);// mute sporp/spolp
rt5639_maskbits(RT5639_PWR_DIG1, 0xFFFE);
rt5639_maskbits(RT5639_PWR_MIXER, 0xCFFF);
rt5639_maskbits(RT5639_PWR_VOL, 0x3FFF);
rt5639_write16(RT5639_DEPOP_M2, 0x3100);
rt5639_write16(RT5639_DEPOP_M1, 0x9);
rt5639_setbits(RT5639_PWR_ANLG1, 0xE0);
rt5639_setbits(RT5639_DEPOP_M1, 0x14);
rt5639_setbits(RT5639_PWR_MIXER, 0xC000);
rt5639_setbits(RT5639_PWR_VOL, 0xC00);
rt5639_write16(RT5639_CHARGE_PUMP, 0xE00);
rt5639_write16(RT5639_EQ_CTRL2, 0);
rt5639_write16(RT5639_EQ_CTRL1, 0x6000);
rt5639_write16(RT5639_DRC_AGC_1, 0x2206);
rt5639_write16(RT5639_DEPOP_M3, 0x737);
rt5639_write16(RT5639_PRIV_INDEX, 0x37);
rt5639_write16(RT5639_PRIV_DATA, 0xFC00);
rt5639_setbits(RT5639_DEPOP_M1, 0x8000);
rt5639_setbits(RT5639_DEPOP_M1, 0x40);
rt5639_maskbits(RT5639_DEPOP_M1, 0xFCBF);
rt5639_setbits(RT5639_DEPOP_M1, 0x300);
rt5639_maskbits(RT5639_HP_VOL, 0x7F7F);
usleep(100000);
rt5639_maskbits(RT5639_DEPOP_M1, 0xFCFB);
rt5639_write16(RT5639_HP_VOL, 0x0000);
}
rt5639_write16(RT5639_DAC1_DIG_VOL, 0x7F7F); // 0dB attenuation left/right
#if 0
// Enable mic
rt5639_write16(RT5639_PWR_DIG2, 0x8000); // stereo adc digital filter power control
rt5639_write16(RT5639_PWR_ANLG2, 0x8800); // mic bst1, micbias1
rt5639_setbits(RT5639_PWR_DIG1, 4); // analog adcl control
rt5639_setbits(RT5639_PWR_MIXER, 0x800); // RECMIXL power
rt5639_setbits(RT5639_PWR_ANLG1, 4); // LDO2 power
rt5639_maskbits(RT5639_REC_L2_MIXER, 0xFFFD);
rt5639_write16(RT5639_ADC_DIG_VOL, 0x2f80);
#endif
ahub_init();
ahub_tx_test();
}

222
bdk/audio/rt5639.h Normal file
View file

@ -0,0 +1,222 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2024 shinyquagsire23
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _RT5639_H_
#define _RT5639_H_
/* Info */
#define RT5639_RESET 0x00
#define RT5639_VENDOR_ID 0xfd
#define RT5639_VENDOR_ID1 0xfe
#define RT5639_VENDOR_ID2 0xff
/* I/O - Output */
#define RT5639_SPK_VOL 0x01
#define RT5639_HP_VOL 0x02
#define RT5639_OUTPUT 0x03
#define RT5639_MONO_OUT 0x04
/* I/O - Input */
#define RT5639_IN1_IN2 0x0d
#define RT5639_IN3_IN4 0x0e
#define RT5639_INL_INR_VOL 0x0f
/* I/O - ADC/DAC/DMIC */
#define RT5639_DAC1_DIG_VOL 0x19
#define RT5639_DAC2_DIG_VOL 0x1a
#define RT5639_DAC2_CTRL 0x1b
#define RT5639_ADC_DIG_VOL 0x1c
#define RT5639_ADC_DATA 0x1d
#define RT5639_ADC_BST_VOL 0x1e
/* Mixer - D-D */
#define RT5639_STO_ADC_MIXER 0x27
#define RT5639_MONO_ADC_MIXER 0x28
#define RT5639_AD_DA_MIXER 0x29
#define RT5639_STO_DAC_MIXER 0x2a
#define RT5639_MONO_DAC_MIXER 0x2b
#define RT5639_DIG_MIXER 0x2c
#define RT5639_DSP_PATH1 0x2d
#define RT5639_DSP_PATH2 0x2e
#define RT5639_DIG_INF_DATA 0x2f
/* Mixer - ADC */
#define RT5639_REC_L1_MIXER 0x3b
#define RT5639_REC_L2_MIXER 0x3c
#define RT5639_REC_R1_MIXER 0x3d
#define RT5639_REC_R2_MIXER 0x3e
/* Mixer - DAC */
#define RT5639_HPO_MIXER 0x45
#define RT5639_SPK_L_MIXER 0x46
#define RT5639_SPK_R_MIXER 0x47
#define RT5639_SPO_L_MIXER 0x48
#define RT5639_SPO_R_MIXER 0x49
#define RT5639_SPO_CLSD_RATIO 0x4a
#define RT5639_MONO_MIXER 0x4c
#define RT5639_OUT_L1_MIXER 0x4d
#define RT5639_OUT_L2_MIXER 0x4e
#define RT5639_OUT_L3_MIXER 0x4f
#define RT5639_OUT_R1_MIXER 0x50
#define RT5639_OUT_R2_MIXER 0x51
#define RT5639_OUT_R3_MIXER 0x52
#define RT5639_LOUT_MIXER 0x53
/* Power */
#define RT5639_PWR_DIG1 0x61
#define RT5639_PWR_DIG2 0x62
#define RT5639_PWR_ANLG1 0x63
#define RT5639_PWR_ANLG2 0x64
#define RT5639_PWR_MIXER 0x65
#define RT5639_PWR_VOL 0x66
/* Private Register Control */
#define RT5639_PRIV_INDEX 0x6a
#define RT5639_PRIV_DATA 0x6c
/* Format - ADC/DAC */
#define RT5639_I2S1_SDP 0x70
#define RT5639_I2S2_SDP 0x71
#define RT5639_ADDA_CLK1 0x73
#define RT5639_ADDA_CLK2 0x74
#define RT5639_DMIC 0x75
/* Function - Analog */
#define RT5639_GLB_CLK 0x80
#define RT5639_PLL_CTRL1 0x81
#define RT5639_PLL_CTRL2 0x82
#define RT5639_ASRC_1 0x83
#define RT5639_ASRC_2 0x84
#define RT5639_ASRC_3 0x85
#define RT5639_ASRC_4 0x89
#define RT5639_ASRC_5 0x8a
#define RT5639_HP_OVCD 0x8b
#define RT5639_CLS_D_OVCD 0x8c
#define RT5639_CLS_D_OUT 0x8d
#define RT5639_DEPOP_M1 0x8e
#define RT5639_DEPOP_M2 0x8f
#define RT5639_DEPOP_M3 0x90
#define RT5639_CHARGE_PUMP 0x91
#define RT5639_PV_DET_SPK_G 0x92
#define RT5639_MICBIAS 0x93
/* Function - Digital */
#define RT5639_EQ_CTRL1 0xb0
#define RT5639_EQ_CTRL2 0xb1
#define RT5639_WIND_FILTER 0xb2
#define RT5639_DRC_AGC_1 0xb4
#define RT5639_DRC_AGC_2 0xb5
#define RT5639_DRC_AGC_3 0xb6
#define RT5639_SVOL_ZC 0xb7
#define RT5639_ANC_CTRL1 0xb8
#define RT5639_ANC_CTRL2 0xb9
#define RT5639_ANC_CTRL3 0xba
#define RT5639_JD_CTRL 0xbb
#define RT5639_ANC_JD 0xbc
#define RT5639_IRQ_CTRL1 0xbd
#define RT5639_IRQ_CTRL2 0xbe
#define RT5639_INT_IRQ_ST 0xbf
#define RT5639_GPIO_CTRL1 0xc0
#define RT5639_GPIO_CTRL2 0xc1
#define RT5639_GPIO_CTRL3 0xc2
#define RT5639_DSP_CTRL1 0xc4
#define RT5639_DSP_CTRL2 0xc5
#define RT5639_DSP_CTRL3 0xc6
#define RT5639_DSP_CTRL4 0xc7
#define RT5639_PGM_REG_ARR1 0xc8
#define RT5639_PGM_REG_ARR2 0xc9
#define RT5639_PGM_REG_ARR3 0xca
#define RT5639_PGM_REG_ARR4 0xcb
#define RT5639_PGM_REG_ARR5 0xcc
#define RT5639_SCB_FUNC 0xcd
#define RT5639_SCB_CTRL 0xce
#define RT5639_BASE_BACK 0xcf
#define RT5639_MP3_PLUS1 0xd0
#define RT5639_MP3_PLUS2 0xd1
#define RT5639_3D_HP 0xd2
#define RT5639_ADJ_HPF 0xd3
#define RT5639_HP_CALIB_AMP_DET 0xd6
#define RT5639_HP_CALIB2 0xd7
#define RT5639_SV_ZCD1 0xd9
#define RT5639_SV_ZCD2 0xda
/* Dummy Register */
#define RT5639_DUMMY1 0xfa
#define RT5639_DUMMY2 0xfb
#define RT5639_DUMMY3 0xfc
/* Index of Codec Private Register definition */
#define RT5639_BIAS_CUR1 0x12
#define RT5639_BIAS_CUR3 0x14
#define RT5639_BIAS_CUR4 0x15
#define RT5639_CHPUMP_INT_REG1 0x24
#define RT5639_MAMP_INT_REG2 0x37
#define RT5639_CHOP_DAC_ADC 0x3d
#define RT5639_3D_SPK 0x63
#define RT5639_WND_1 0x6c
#define RT5639_WND_2 0x6d
#define RT5639_WND_3 0x6e
#define RT5639_WND_4 0x6f
#define RT5639_WND_5 0x70
#define RT5639_WND_8 0x73
#define RT5639_DIP_SPK_INF 0x75
#define RT5639_HP_DCC_INT1 0x77
#define RT5639_EQ_BW_LOP 0xa0
#define RT5639_EQ_GN_LOP 0xa1
#define RT5639_EQ_FC_BP1 0xa2
#define RT5639_EQ_BW_BP1 0xa3
#define RT5639_EQ_GN_BP1 0xa4
#define RT5639_EQ_FC_BP2 0xa5
#define RT5639_EQ_BW_BP2 0xa6
#define RT5639_EQ_GN_BP2 0xa7
#define RT5639_EQ_FC_BP3 0xa8
#define RT5639_EQ_BW_BP3 0xa9
#define RT5639_EQ_GN_BP3 0xaa
#define RT5639_EQ_FC_BP4 0xab
#define RT5639_EQ_BW_BP4 0xac
#define RT5639_EQ_GN_BP4 0xad
#define RT5639_EQ_FC_HIP1 0xae
#define RT5639_EQ_GN_HIP1 0xaf
#define RT5639_EQ_FC_HIP2 0xb0
#define RT5639_EQ_BW_HIP2 0xb1
#define RT5639_EQ_GN_HIP2 0xb2
#define RT5639_EQ_PRE_VOL 0xb3
#define RT5639_EQ_PST_VOL 0xb4
/* SPOMIX bits */
#define RT5639_HPOMIX_MUTE_DAC1 BIT(14)
#define RT5639_HPOMIX_MUTE_HPOVOL BIT(13)
/* SPOLMIX bits */
#define RT5639_SPOLMIX_MUTE_DACR1 BIT(15)
#define RT5639_SPOLMIX_MUTE_DACL1 BIT(14)
#define RT5639_SPOLMIX_MUTE_SPKVOLR BIT(13)
#define RT5639_SPOLMIX_MUTE_SPKVOLL BIT(12)
#define RT5639_SPOLMIX_MUTE_BST1 BIT(11)
/* SPORMIX bits */
#define RT5639_SPORMIX_MUTE_DACR1 BIT(13)
#define RT5639_SPORMIX_MUTE_SPKVOLR BIT(12)
#define RT5639_SPORMIX_MUTE_BST1 BIT(11)
#define RT5639_I2C_ADDR 0x1C
void rt5639_init(void);
void rt5639_init_2(void);
#endif // _RT5639_H_

View file

@ -19,6 +19,7 @@
#include <memory_map.h>
#include <audio/rt5639.h>
#include <display/di.h>
#include <display/vic.h>
#include <input/als.h>

View file

@ -59,6 +59,22 @@ static const clk_rst_t _clock_i2c[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, CLK_SRC_DIV(10.5) } //20.4MHz -> 100KHz
};
static const clk_rst_t _clock_i2s[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2S1, CLK_L_I2S1, 0, CLK_SRC_DIV(80) }, // PLLA_out0 (120MHz) / 9 -> 1.5MHz
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2S2, CLK_L_I2S2, 0, CLK_SRC_DIV(80) }, // PLLA_out0 (120MHz) / 9 -> 1.5MHz
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2S3, CLK_L_I2S3, 0, CLK_SRC_DIV(80) }, // PLLA_out0 (120MHz) / 9 -> 1.5MHz
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2S4, CLK_V_I2S4, 0, CLK_SRC_DIV(80) }, // PLLA_out0 (120MHz) / 9 -> 1.5MHz
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2S5, CLK_V_I2S5, 0, CLK_SRC_DIV(80) }, // PLLA_out0 (120MHz) / 9 -> 1.5MHz
};
static const clk_rst_t _clock_audio_sync_clk_i2s[] = {
{ CLK_NOT_USED, CLK_NOT_USED, CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S1, CLK_NOT_USED, 0, CLK_SRC_DIV(9) }, // PLLA_out0 (120MHz) / 9 -> 13.33MHz
{ CLK_NOT_USED, CLK_NOT_USED, CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S2, CLK_NOT_USED, 0, CLK_SRC_DIV(9) }, // PLLA_out0 (120MHz) / 9 -> 13.33MHz
{ CLK_NOT_USED, CLK_NOT_USED, CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S3, CLK_NOT_USED, 0, CLK_SRC_DIV(9) }, // PLLA_out0 (120MHz) / 9 -> 13.33MHz
{ CLK_NOT_USED, CLK_NOT_USED, CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S4, CLK_NOT_USED, 0, CLK_SRC_DIV(9) }, // PLLA_out0 (120MHz) / 9 -> 13.33MHz
{ CLK_NOT_USED, CLK_NOT_USED, CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S5, CLK_NOT_USED, 0, CLK_SRC_DIV(9) }, // PLLA_out0 (120MHz) / 9 -> 13.33MHz
};
static clk_rst_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, CLK_SRC_DIV(1) // 408MHz. Default: 408MHz. Max: 627.2 MHz.
};
@ -114,7 +130,7 @@ static clk_rst_t _clock_actmon = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, CLK_SRC_DIV(1) // 19.2MHz.
};
static clk_rst_t _clock_extperiph1 = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, CLK_SRC_DIV(1)
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 2, CLK_SRC_DIV(17) // 24MHz
};
static clk_rst_t _clock_extperiph2 = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, CLK_SRC_DIV(102) // 4.0MHz
@ -123,26 +139,32 @@ static clk_rst_t _clock_extperiph2 = {
void clock_enable(const clk_rst_t *clk)
{
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
if (clk->reset)
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
// Disable.
CLOCK(clk->enable) &= ~BIT(clk->index);
if (clk->enable)
CLOCK(clk->enable) &= ~BIT(clk->index);
// Configure clock source if required.
if (clk->source)
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29u);
// Enable.
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index);
if (clk->enable)
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index);
usleep(2);
// Take clock off reset.
CLOCK(clk->reset) &= ~BIT(clk->index);
if (clk->reset)
CLOCK(clk->reset) &= ~BIT(clk->index);
}
void clock_disable(const clk_rst_t *clk)
{
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
if (clk->reset)
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
// Disable.
CLOCK(clk->enable) &= ~BIT(clk->index);
if (clk->enable)
CLOCK(clk->enable) &= ~BIT(clk->index);
}
void clock_enable_fuse(bool enable)
@ -191,6 +213,73 @@ void clock_disable_i2c(u32 idx)
clock_disable(&_clock_i2c[idx]);
}
void clock_enable_i2s(u32 idx)
{
clock_enable(&_clock_i2s[idx]);
//clock_enable(&_clock_audio_sync_clk_i2s[idx]);
}
void clock_disable_i2s(u32 idx)
{
clock_disable(&_clock_i2s[idx]);
//clock_disable(&_clock_audio_sync_clk_i2s[idx]);
}
// TODO
/* AHUB clock sources */
#define AHUB_SRC_PLLA_OUT0 (0 << 29)
#define AHUB_SRC_PLLP_OUT0 (4 << 29)
#define SET_CLK_ENB_I2S1 (BIT(30))
#define SET_CLK_ENB_I2S3 (BIT(18))
#define SET_CLK_ENB_I2S2 (BIT(11))
#define SET_CLK_ENB_SPDIF (BIT(10))
#define CLR_I2S1_RST (BIT(30))
#define CLR_I2S3_RST (BIT(18))
#define CLR_I2S2_RST (BIT(11))
#define CLR_SPDIF_RST (BIT(10))
#define SET_CLK_ENB_EXTPERIPH1 (BIT(24))
#define SET_CLK_ENB_APB2APE (BIT(11))
#define SET_CLK_ENB_AHUB (BIT(10))
#define SET_CLK_ENB_I2S5 (BIT(6))
#define SET_CLK_ENB_I2S4 (BIT(5))
#define CLR_EXTPERIPH1_RST (BIT(24))
#define CLR_APB2APE_RST (BIT(11))
#define CLR_AHUB_RST (BIT(10))
#define CLR_I2S5_RST (BIT(6))
#define CLR_I2S4_RST (BIT(5))
#define EXTPERIPH1_SRC_PLLA_OUT0 (0 << 29)
#define EXTPERIPH1_SRC_PLLP_OUT0 (2 << 29)
void clock_enable_audio()
{
clock_enable_plla();
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_AHUB) = AHUB_SRC_PLLP_OUT0 | CLK_SRC_DIV(34); // AHUB @ 12MHz
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HDA2CODEC_2X) = 0x8000001e;
//CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1) = EXTPERIPH1_SRC_PLLP_OUT0 | (((408/24)-1) * 2); // RT5677 MCLK @ 24MHz from 408MHz PLLP
clock_enable_extperiph1();
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HDA) = 0xe;
// ?
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(13);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(13);
// From https://github.com/coreboot/coreboot/blob/master/src/soc/nvidia/tegra210/clock.c#L787:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = SET_CLK_ENB_I2S1 | SET_CLK_ENB_I2S3 | SET_CLK_ENB_I2S2 | SET_CLK_ENB_SPDIF;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(28) /*HDA*/ | SET_CLK_ENB_EXTPERIPH1 | SET_CLK_ENB_APB2APE | SET_CLK_ENB_AHUB | SET_CLK_ENB_I2S5 | SET_CLK_ENB_I2S4;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = CLR_I2S1_RST | CLR_I2S3_RST | CLR_I2S2_RST | CLR_SPDIF_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(28) /*HDA*/ | CLR_EXTPERIPH1_RST | CLR_APB2APE_RST | CLR_AHUB_RST | CLR_I2S5_RST | CLR_I2S4_RST;
}
void clock_enable_se()
{
clock_enable(&_clock_se);
@ -389,6 +478,19 @@ void clock_disable_extperiph2()
clock_disable(&_clock_extperiph2);
}
void clock_enable_plla()
{
u32 divp = 1;
u32 divn = 200;
u32 plla_div = (divp << 20) | (divn << 11) | 8;
// PLLA @ 120MHz
CLOCK(CLK_RST_CONTROLLER_PLLA_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plla_div; //p << 20, n << 8, m
CLOCK(CLK_RST_CONTROLLER_PLLA_OUT) = 0x3 | 2 << 8; // divide by an extra 2
CLOCK(CLK_RST_CONTROLLER_PLLA_MISC1) = 0x0000f000; // TODO what is this
CLOCK(CLK_RST_CONTROLLER_PLLA_MISC) = 0x12000000; // TODO what is this
}
void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210)
{
u32 plld_div = (divp << 20) | (divn << 11) | 1;

View file

@ -64,6 +64,7 @@
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 0x100
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S3 0x104
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
@ -116,13 +117,17 @@
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC 0x3A0
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S4 0x3BC
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S5 0x3C0
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4
#define CLK_RST_CONTROLLER_CLK_SOURCE_AHUB 0x3D0
#define CLK_RST_CONTROLLER_CLK_SOURCE_HDA2CODEC_2X 0x3E4
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON 0x3E8
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 0x3F0
#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
#define CLK_RST_CONTROLLER_CLK_SOURCE_HDA 0x428
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
#define CLK_RST_CONTROLLER_RST_DEV_V_SET 0x430
#define CLK_RST_CONTROLLER_RST_DEV_V_CLR 0x434
@ -138,7 +143,11 @@
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG1 0x484
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488
#define CLK_RST_CONTROLLER_PLLE_AUX 0x48C
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S1 0x4A0
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S2 0x4A4
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S3 0x4A8
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S4 0x4AC
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S5 0x4B0
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG3 0x4C0
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
#define CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0 0x52C
@ -743,6 +752,11 @@ void clock_disable_uart(u32 idx);
int clock_uart_use_src_div(u32 idx, u32 baud);
void clock_enable_i2c(u32 idx);
void clock_disable_i2c(u32 idx);
void clock_enable_i2s_controller();
void clock_disable_i2s_controller();
void clock_enable_i2s(u32 idx);
void clock_disable_i2s(u32 idx);
void clock_enable_audio();
void clock_enable_se();
void clock_enable_tzram();
void clock_enable_host1x();
@ -780,6 +794,7 @@ void clock_disable_extperiph1();
void clock_enable_extperiph2();
void clock_disable_extperiph2();
void clock_enable_plla();
void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210);
void clock_enable_pllx();
void clock_enable_pllc(u32 divn);

View file

@ -18,6 +18,7 @@
#include <string.h>
#include <soc/hw_init.h>
#include <audio/rt5639.h>
#include <display/di.h>
#include <display/vic.h>
#include <input/joycon.h>
@ -413,6 +414,8 @@ void hw_init()
// Enable HOST1X used by every display module (DC, VIC, NVDEC, NVENC, TSEC, etc).
clock_enable_host1x();
rt5639_init();
}
void hw_reinit_workaround(bool coreboot, u32 bl_magic)

View file

@ -30,3 +30,8 @@ void pinmux_config_i2c(u32 idx)
PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE;
}
void pinmux_config_audio_codec(void)
{
PINMUX_AUX(PINMUX_AUX_AUDIO_CODEC_RST) = (3 & PINMUX_FUNC_MASK) | PINMUX_PULL_DOWN; // codec RST
}

View file

@ -46,10 +46,17 @@
#define PINMUX_AUX_CAM_I2C_SDA 0xD8
#define PINMUX_AUX_UART2_TX 0xF4
#define PINMUX_AUX_UART3_TX 0x104
#define PINMUX_AUX_DAP1_FS 0x124
#define PINMUX_AUX_DAP1_DIN 0x128
#define PINMUX_AUX_DAP1_DOUT 0x12C
#define PINMUX_AUX_DAP1_SCLK 0x130
#define PINMUX_AUX_DAP4_DIN 0x148
#define PINMUX_AUX_DAP4_DOUT 0x14C
#define PINMUX_AUX_DAP4_SCLK 0x150
#define PINMUX_AUX_CLK_32K_OUT 0x164
#define PINMUX_AUX_AUD_MCLK 0x180
#define PINMUX_AUX_DVFS_PWM 0x184
#define PINMUX_AUX_DVFS_CLK 0x188
#define PINMUX_AUX_GPIO_X1_AUD 0x18C
#define PINMUX_AUX_GPIO_X3_AUD 0x190
#define PINMUX_AUX_SPDIF_IN 0x1A4
@ -81,6 +88,9 @@
#define PINMUX_AUX_GPIO_PK3 0x260
#define PINMUX_AUX_GPIO_PK7 0x270
#define PINMUX_AUX_GPIO_PZ1 0x280
#define PINMUX_AUX_GPIO_PZ3 0x288
#define PINMUX_AUX_GPIO_PZ4 0x28C
#define PINMUX_AUX_AUDIO_CODEC_RST PINMUX_AUX_GPIO_PZ4
/* Only in T210B01 */
#define PINMUX_AUX_SDMMC2_DAT0 0x294
#define PINMUX_AUX_SDMMC2_DAT1 0x298
@ -130,5 +140,6 @@
void pinmux_config_uart(u32 idx);
void pinmux_config_i2c(u32 idx);
void pinmux_config_audio_codec(void);
#endif

View file

@ -131,3 +131,19 @@ int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
return 1;
}
bool pmc_get_partition_clamped(pmc_power_rail_t part)
{
return PMC(APBDEV_PMC_CLAMP_STATUS) & BIT(part);
}
void pmc_unclamp_partition(pmc_power_rail_t part)
{
u32 part_mask = BIT(part);
if (!pmc_get_partition_clamped(part)) return;
PMC(APBDEV_PMC_REMOVE_CLAMPING_CMD) = part_mask;
while (pmc_get_partition_clamped(part));
}

View file

@ -36,7 +36,10 @@
#define PMC_CNTRL_FUSE_OVERRIDE BIT(18)
#define PMC_CNTRL_SHUTDOWN_OE BIT(22)
#define APBDEV_PMC_SEC_DISABLE 0x4
#define APBDEV_PMC_DPD_SAMPLE 0x20
#define APBDEV_PMC_CLAMP_STATUS 0x2C
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
#define APBDEV_PMC_REMOVE_CLAMPING_CMD 0x034
#define APBDEV_PMC_PWRGATE_STATUS 0x38
#define APBDEV_PMC_NO_IOPOWER 0x44
#define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12)
@ -53,6 +56,7 @@
PMC_SCRATCH0_MODE_BOOTLOADER | \
PMC_SCRATCH0_MODE_PAYLOAD)
#define APBDEV_PMC_BLINK_TIMER 0x40
#define APBDEV_PMC_PWR_DET 0x48
#define PMC_BLINK_ON(n) ((n & 0x7FFF))
#define PMC_BLINK_FORCE BIT(15)
#define PMC_BLINK_OFF(n) ((u32)(n & 0xFFFF) << 16)
@ -99,7 +103,9 @@
#define PMC_RST_STATUS_LP0 4
#define PMC_RST_STATUS_AOTAG 5
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
#define PMC_IO_DPD_REQ_DPD_IDLE 0
#define PMC_IO_DPD_REQ_DPD_OFF (1 << 30)
#define PMC_IO_DPD_REQ_DPD_ON (2 << 30)
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
#define APBDEV_PMC_VDDP_SEL 0x1CC
#define APBDEV_PMC_DDR_CFG 0x1D0
@ -132,11 +138,13 @@
#define PMC_CNTRL2_SYSCLK_ORRIDE BIT(10)
#define PMC_CNTRL2_HOLD_CKE_LOW_EN BIT(12)
#define PMC_CNTRL2_ALLOW_PULSE_WAKE BIT(14)
#define APBDEV_PMC_IO_DPD_OFF_MASK 0x444
#define APBDEV_PMC_FUSE_CONTROL 0x450
#define PMC_FUSE_CONTROL_PS18_LATCH_SET BIT(8)
#define PMC_FUSE_CONTROL_PS18_LATCH_CLR BIT(9)
#define APBDEV_PMC_IO_DPD3_REQ 0x45C
#define APBDEV_PMC_IO_DPD4_REQ 0x464
#define APBDEV_PMC_IO_DPD2_OFF_MASK 0x480
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4
#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC
#define APBDEV_PMC_DDR_CNTRL 0x4E4
@ -246,5 +254,7 @@ typedef enum _pmc_power_rail_t
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
bool pmc_get_partition_clamped(pmc_power_rail_t part);
void pmc_unclamp_partition(pmc_power_rail_t part);
#endif

View file

@ -240,6 +240,8 @@
#define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
#define APB_MISC_DAS_DAP_CTRL_SEL 0xC00
#define APB_MISC_DAS_DAC_INPUT_DATA_CLK_SEL 0xC40
/*! Secure boot registers. */
#define SB_CSR 0x0

View file

@ -16,6 +16,7 @@ SECTIONS {
}
. = ALIGN(0x10);
__ipl_end = .;
__end__ = .;
.bss : {
__bss_start = .;
*(COMMON)

View file

@ -15,6 +15,7 @@ SECTIONS {
}
. = ALIGN(0x10);
__ipl_end = .;
__end__ = .;
.bss : {
__bss_start = .;
*(COMMON)