rk27xx: keep the LCD bus timing at the boosted clock

The LCD controller's CSn/WEn/RDn strobes count bus clocks, set once for
1-4-1 clocks: a 120 ns write cycle at the 50 MHz bus clock, but 60 ns
when the CPU is boosted and the bus runs at 100 MHz. That is too fast
for the Samsung YP-CP3's panel: with the CPU boosted it showed stray
pixels, and partial updates left tearing behind moving things - the
boot logo too, as the firmware boosts before lcd_init().

Double the clocks while boosted, 2-8-2, which keeps the write cycle at
120 ns: set_cpu_frequency() switches them before raising the clock and
after lowering it, and lcd init picks them for the clock it runs at -
the bootloader stays at crt0's CPUFREQ_MAX.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I482073c16af39c6b1856a0e18d19a747c78975f0
This commit is contained in:
Marcin Bukat 2026-10-02 10:30:58 +02:00
parent 3fa27091f3
commit 69af17695d
3 changed files with 27 additions and 1 deletions

View file

@ -95,6 +95,19 @@ static void lcdctrl_buff_setup(int width, int height)
LINE3_UVADDR = LINE3_YADDR + 1; LINE3_UVADDR = LINE3_YADDR + 1;
} }
/* CSn/WEn/RDn timings in MCU mode, in AHB clocks: csrw (bits 9-7), rwpw
* (6-3), rwcs (2-0). csrw 1, rwpw 4, rwcs 1 makes a 120 ns write cycle at
* the 50 MHz bus clock, but 60 ns at the boosted 100 MHz - too fast for
* the panel: stray pixels, and partial updates landing in the wrong place.
* Twice the clocks keep it 120 ns there. */
#define LCD_TIMING_50MHZ ((1<<7) | (4<<3) | 1)
#define LCD_TIMING_100MHZ ((2<<7) | (8<<3) | 2)
void lcdif_set_bus_timing(bool boosted)
{
VERT_PERIOD = boosted ? LCD_TIMING_100MHZ : LCD_TIMING_50MHZ;
}
static void lcdctrl_init(void) static void lcdctrl_init(void)
{ {
int i; int i;
@ -107,7 +120,9 @@ static void lcdctrl_init(void)
LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B; LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS; MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
VERT_PERIOD = (1<<7)|(1<<5)|1; /* CSn/WEn/RDn signal timings */ /* for the clock running now: the firmware boosts before lcd_init(),
* and the bootloader runs at crt0's, which is CPUFREQ_MAX */
lcdif_set_bus_timing(cpu_frequency == CPUFREQ_MAX);
lcd_display_init(); lcd_display_init();
lcdctrl_bypass(0); lcdctrl_bypass(0);

View file

@ -1,6 +1,8 @@
#ifndef _LCDIF_RK27XX_H #ifndef _LCDIF_RK27XX_H
#define _LCDIF_RK27XX_H #define _LCDIF_RK27XX_H
#include <stdbool.h>
#define LCDIF_16BIT 16 #define LCDIF_16BIT 16
#define LCDIF_18BIT 18 #define LCDIF_18BIT 18
@ -12,4 +14,7 @@ void lcd_display_init(void);
void lcd_set_gram_area(int x_start, int y_start, int x_end, int y_end); void lcd_set_gram_area(int x_start, int y_start, int x_end, int y_end);
/* LCD bus timing for the bus clock: set before it rises, after it falls */
void lcdif_set_bus_timing(bool boosted);
#endif /* _LCDIF_RK27XX_H */ #endif /* _LCDIF_RK27XX_H */

View file

@ -23,6 +23,7 @@
#include "panic.h" #include "panic.h"
#include "button.h" #include "button.h"
#include "system-target.h" #include "system-target.h"
#include "lcdif-rk27xx.h"
#define default_interrupt(name) \ #define default_interrupt(name) \
extern __attribute__((weak,alias("UIRQ"))) void name (void) extern __attribute__((weak,alias("UIRQ"))) void name (void)
@ -249,6 +250,9 @@ void set_cpu_frequency(long frequency)
if (frequency == CPUFREQ_MAX) if (frequency == CPUFREQ_MAX)
{ {
/* the LCD strobes take twice the clocks at twice the clock */
lcdif_set_bus_timing(true);
/* PLL set to 200 Mhz /* PLL set to 200 Mhz
* PLL:ARM = 1:1 * PLL:ARM = 1:1
* ARM:AHB = 2:1 * ARM:AHB = 2:1
@ -282,6 +286,8 @@ void set_cpu_frequency(long frequency)
SCU_DIVCON1 &= ~1; SCU_DIVCON1 &= ~1;
set_sdram_timing(CPUFREQ_NORMAL); set_sdram_timing(CPUFREQ_NORMAL);
lcdif_set_bus_timing(false);
} }
cpu_frequency = frequency; cpu_frequency = frequency;