kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Pi Firmware: refactor so changing PLLA/C/D is easier
Change-Id: I11dcb5d4994ebbb371af3e4fd30ececd6400034epull/105/head
rodzic
0e671ea107
commit
cba658095c
18
src/defs.h
18
src/defs.h
|
@ -96,11 +96,6 @@
|
|||
|
||||
#define BIT_BOTH_BUFFERS (BIT_DRAW_BUFFER | BIT_DISP_BUFFER)
|
||||
|
||||
// Define the pixel clock for sampling
|
||||
#define PLL_PER_DIVIDER 4 // This gives a default PLLA_PER clock of 600MHz
|
||||
#define GPCLK_SOURCE 4 // PLLA_PER used as source
|
||||
#define DEFAULT_GPCLK_DIVISOR 6 // 600MHz / 6 = 100MHz
|
||||
|
||||
// Pi 2/3 Multicore options
|
||||
#if defined(RPI2) || defined(RPI3)
|
||||
|
||||
|
@ -290,10 +285,21 @@ typedef struct {
|
|||
#define PIXELVALVE2_VERTA (volatile uint32_t *)(PERIPHERAL_BASE + 0x807014)
|
||||
#define PIXELVALVE2_VERTB (volatile uint32_t *)(PERIPHERAL_BASE + 0x807018)
|
||||
|
||||
|
||||
#define PM_RSTC (volatile uint32_t *)(PERIPHERAL_BASE + 0x10001c)
|
||||
#define PM_WDOG (volatile uint32_t *)(PERIPHERAL_BASE + 0x100024)
|
||||
#define PM_PASSWORD 0x5a000000
|
||||
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
|
||||
|
||||
#define CM_PASSWORD 0x5a000000
|
||||
#define CM_PLLA_LOADCORE (1 << 4)
|
||||
#define CM_PLLA_HOLDCORE (1 << 5)
|
||||
#define CM_PLLA_LOADPER (1 << 6)
|
||||
#define CM_PLLA_HOLDPER (1 << 7)
|
||||
#define A2W_PLL_CHANNEL_DISABLE (1 << 8)
|
||||
#define GZ_CLK_BUSY (1 << 7)
|
||||
#define GZ_CLK_ENA (1 << 4)
|
||||
#define GP_CLK1_CTL (volatile uint32_t *)(PERIPHERAL_BASE + 0x101078)
|
||||
#define GP_CLK1_DIV (volatile uint32_t *)(PERIPHERAL_BASE + 0x10107C)
|
||||
#define CM_PLLA (volatile uint32_t *)(0x20101104)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,17 +28,68 @@
|
|||
|
||||
typedef void (*func_ptr)();
|
||||
|
||||
#define CM_PASSWORD 0x5a000000
|
||||
#define CM_PLLA_LOADCORE (1 << 4)
|
||||
#define CM_PLLA_HOLDCORE (1 << 5)
|
||||
#define CM_PLLA_LOADPER (1 << 6)
|
||||
#define CM_PLLA_HOLDPER (1 << 7)
|
||||
#define A2W_PLL_CHANNEL_DISABLE (1 << 8)
|
||||
#define GZ_CLK_BUSY (1 << 7)
|
||||
#define GZ_CLK_ENA (1 << 4)
|
||||
#define GP_CLK1_CTL (volatile uint32_t *)(PERIPHERAL_BASE + 0x101078)
|
||||
#define GP_CLK1_DIV (volatile uint32_t *)(PERIPHERAL_BASE + 0x10107C)
|
||||
#define CM_PLLA (volatile uint32_t *)(0x20101104)
|
||||
// =============================================================
|
||||
// Define the PLL to be used for the sampling clock
|
||||
// =============================================================
|
||||
//
|
||||
// Choose between PLLA, PLLC and PLLD
|
||||
//
|
||||
// PLLA - not otherwise used
|
||||
// PLLC - used for the Core Clock
|
||||
// PLLD - possibly used for the SDRAM Clock, so might overclock it by 20%
|
||||
//
|
||||
// TODO: PLLA doesn't currently start on the Pi2/Pi3
|
||||
//
|
||||
// Power-on defaults are values for the Pi Zero
|
||||
|
||||
// SYS_CLK_DIVIDER is the ratio between PLLC and the Core Clock
|
||||
// This is typically 3 or 4, depending on the Pi Model. We need
|
||||
// to know this to correct serial speed when PLLC used.
|
||||
|
||||
#if defined(RPI3)
|
||||
#define USE_PLLC
|
||||
#define SYS_CLK_DIVIDER 3
|
||||
#elif defined(RPI2)
|
||||
#define USE_PLLC
|
||||
#define SYS_CLK_DIVIDER 4
|
||||
#else
|
||||
#define USE_PLLA
|
||||
#define SYS_CLK_DIVIDER 3
|
||||
#endif
|
||||
|
||||
#ifdef USE_PLLA
|
||||
#define PLL_NAME "PLLA" // power-on default = off
|
||||
#define GPCLK_SOURCE 4 // PLLA_PER used as source
|
||||
#define DEFAULT_GPCLK_DIVISOR 6 // 600MHz / 6 = 100MHz
|
||||
#define PLL_CTRL PLLA_CTRL
|
||||
#define PLL_FRAC PLLA_FRAC
|
||||
#define PLL_SCALE 2
|
||||
#define MIN_PLL_FREQ 800000000 // PLLA_PER = 400MHz
|
||||
#define MAX_PLL_FREQ 1200000000 // PLLA_PER = 600MHz
|
||||
#endif
|
||||
|
||||
#ifdef USE_PLLC
|
||||
#define PLL_NAME "PLLC" // power-on default = 1200MHz
|
||||
#define GPCLK_SOURCE 5 // PLLC_PER used as source
|
||||
#define DEFAULT_GPCLK_DIVISOR 12 // 1200MHz / 12 = 100MHz
|
||||
#define PLL_CTRL PLLC_CTRL
|
||||
#define PLL_FRAC PLLC_FRAC
|
||||
#define PLL_SCALE 1
|
||||
#define MIN_PLL_FREQ 900000000 // PLLC_PER = 900MHz
|
||||
#define MAX_PLL_FREQ 1200000000 // PLLC_PER = 1200MHz
|
||||
#endif
|
||||
|
||||
#ifdef USE_PLLD
|
||||
#define PLL_NAME "PLLD" // power-on default = 500MHz
|
||||
#define GPCLK_SOURCE 6 // PLLD_PER used as source
|
||||
#define DEFAULT_GPCLK_DIVISOR 5 // 500MHz / 5 = 100MHz
|
||||
#define PLL_CTRL PLLD_CTRL
|
||||
#define PLL_FRAC PLLD_FRAC
|
||||
#define PLL_SCALE 2
|
||||
#define MIN_PLL_FREQ 800000000 // PLLD_PER = 400MHz
|
||||
#define MAX_PLL_FREQ 1200000000 // PLLD_PER = 600MHz
|
||||
#endif
|
||||
|
||||
|
||||
// =============================================================
|
||||
// Forward declarations
|
||||
|
@ -535,9 +586,9 @@ static int calibrate_sampling_clock() {
|
|||
log_info(" Error adjusted clock = %d Hz", adjusted_clock);
|
||||
|
||||
// Pick the best value for pll_freq and gpclk_divisor
|
||||
int pll_scale = PLL_PER_DIVIDER / 2; // This comes from the value in PLL_PER (4)
|
||||
int min_pll_freq = 800000000; // This gives a GPCLK soource of 400MHz
|
||||
int max_pll_freq = 1200000000; // This gives a GPCLK souurce of 600MHz
|
||||
int pll_scale = PLL_SCALE; // defined at the top
|
||||
int min_pll_freq = MIN_PLL_FREQ; // defined at the top
|
||||
int max_pll_freq = MAX_PLL_FREQ; // defined at the top
|
||||
int gpclk_divisor = max_pll_freq / pll_scale / new_clock;
|
||||
int pll_freq = new_clock * pll_scale * gpclk_divisor ;
|
||||
log_info(" GPCLK Divisor = %d", gpclk_divisor);
|
||||
|
@ -555,15 +606,20 @@ static int calibrate_sampling_clock() {
|
|||
|
||||
// If the clock has changed from it's previous value, then actually change it
|
||||
if (pll_freq != old_pll_freq) {
|
||||
set_pll_frequency(((double) pll_freq) / 1e6, PLLA_CTRL, PLLA_FRAC);
|
||||
set_pll_frequency(((double) pll_freq) / 1e6, PLL_CTRL, PLL_FRAC);
|
||||
|
||||
#ifdef USE_PLLC
|
||||
// Reinitialize the UART as the Core Clock has changed
|
||||
RPI_AuxMiniUartInit_With_Freq(115200, 8, pll_freq / SYS_CLK_DIVIDER);
|
||||
#endif
|
||||
|
||||
// And remember for next time
|
||||
old_pll_freq = pll_freq;
|
||||
}
|
||||
|
||||
// TODO: this should be superfluous (as the GPU is not changing the core clock)
|
||||
// However, if we remove it, the next osd_update_palette() call hangs
|
||||
int core_clock = get_clock_rate(CORE_CLK_ID);
|
||||
log_info(" Core clock freq = %d Hz", core_clock);
|
||||
get_clock_rate(CORE_CLK_ID);
|
||||
|
||||
// Finally, set the new divisor
|
||||
log_debug("Setting up divisor");
|
||||
|
@ -847,7 +903,6 @@ int recalculate_hdmi_clock_line_locked_update(int force) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Configure PLLA so we can use it as a sampling clock source
|
||||
//
|
||||
// The logic to configure PLLA conmes from the Linux Kernel clk-bcm2835
|
||||
|
@ -856,7 +911,7 @@ int recalculate_hdmi_clock_line_locked_update(int force) {
|
|||
// - bcm2835_pll_divider_set_rate
|
||||
// - bcm2835_pll_divider_on
|
||||
// https://elixir.bootlin.com/linux/v4.4.70/source/drivers/clk/bcm/clk-bcm2835.c
|
||||
|
||||
#ifdef USE_PLLA
|
||||
static void configure_plla(int divider) {
|
||||
|
||||
// Log the before register values
|
||||
|
@ -882,6 +937,7 @@ static void configure_plla(int divider) {
|
|||
// Log the before register values
|
||||
log_plla();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_hardware() {
|
||||
int i;
|
||||
|
@ -922,8 +978,19 @@ static void init_hardware() {
|
|||
// Configure the GPCLK pin as a GPCLK
|
||||
RPI_SetGpioPinFunction(GPCLK_PIN, FS_ALT5);
|
||||
|
||||
log_info("Using %s as the sampling clock", PLL_NAME);
|
||||
|
||||
// Log all the PLL values
|
||||
log_plla();
|
||||
log_pllb();
|
||||
log_pllc();
|
||||
log_plld();
|
||||
log_pllh();
|
||||
|
||||
#ifdef USE_PLLA
|
||||
// Enable the PLLA_PER divider
|
||||
configure_plla(PLL_PER_DIVIDER);
|
||||
configure_plla(4);
|
||||
#endif
|
||||
|
||||
// The divisor us now the same for both modes
|
||||
log_debug("Setting up divisor");
|
||||
|
|
Ładowanie…
Reference in New Issue