Friday, June 26, 2009

Gotcha !!! (LCD pixel clock problem fixed)

This is what I've done: I built a program with the SDK that runs on the original firmware and that writes all the registers and stuff to a log file. I booted the original firmware with and without dual boot and compared the log files.

And man, this "bug" is so exotic I have to explain it (warning: your head may explode):

This is a summary of events related to clocks and LCD that happen from reset:
  1. The SPL initializes the PLL and all system clocks.
  2. The system loader initializes the LCD and shows the Dingoo Digital splash screen.
  3. Either the system loader or the ccpmp.bin program that it loads initialize again the system clocks.
The initialization of the system clocks has one funny detail: you program the PLL for a certain frequency (say 336MHz) and you configure it to output either that frequency or half that frequency. The different peripheals (including the LCD) generate their clocks by dividing the PLL output.

This is what happens in the original firmware:
  1. The SPL code initializes system clocks: PLL 336MHz, PLL output 336/2=168MHz.
  2. The system loader initializes the LCD clock generator. It programs the divider to obtain 16.8MHz. It accounts for the "divide by two" configuration and thus the required divider for the LCD is 10 (168MHz / 10 = 16.8MHz).
  3. The system loader (or ccpmp.bin) initializes again the system clocks. As the configuration of the system clocks is the same set in step (1), nothing changes, in particular the LCD clock.
This is what happens with dual boot:
  1. The dual boot SPL initializes system clocks: PLL 336MHz, PLL output 336MHz (not divided by two !!!).
  2. The system loader initializes the LCD clock generator. It programs the divider to obtain 16.8MHz. As the PLL output is not divided by two, the required divider for the LCD is 21 (336MHz / 21 = 16MHz, which is the best possible approximation to 16.8MHz).
  3. The system loader (or ccpmp.bin) initializes again the system clocks, but now, something changes: the PLL output is programmed to be divided by two. As the LCD clock divider remains unchanged, the net result is that the LCD clock is divided by two, resulting in 8MHz.
As you see, this is actually a bug in the original firmware !!!. Either you must initialize the LCD after the system clocks or you must recalculate the LCD clock after a change in the system clocks configuration.

IMPORTANT: something similar was happening with the USB clock. That might explain the effect of plugging the USB cable that some users notices, though I can't think of what is actually happening. Also, I can't explain why some users hardly notice the slowdown while others say it's unbearable.

Not sure if this was the only thing that needed to be fixed. I'm still investigating in the GPIO differences I noticed.

I have already fixed it and plan to repackage it all again and make another release. However, there's an interesting dilemma here: some users are extremely happy because the reduced LCD pixel clock seems to fix tearing in some games/emulators. I all for fixing it because:
  • I don't have time to play. I'm too busy coding :-)
  • The whole idea is to leave the original firmware unchanged.
  • It is not ok for some users. We need something that works for everybody.
There is an easy solution: just as there is an application to overclock the A320, it is very easy to program an application to change the LCD pixel clock. I'm a bit swamped so I beg your pardon but I won't program such application. If someone wants to, here's the code you need (from this file):

/* Timing setting */
__cpm_stop_lcd();

pclk = 16800000; /* Pixclk */

pll_div = (REG_CPM_CPCCR & CPM_CPCCR_PCS); /* clock source,0:pllout/2 1: pllout */
pll_div = pll_div ? 1 : 2 ;

val = (__cpm_get_pllout() / pll_div) / pclk;
val--;
if (val > 0x1ff)
val = 0x1ff;

__cpm_set_pixdiv(val);

REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* Update divide */

__cpm_start_lcd();

3 comments:

  1. Are you a sort of genius, booboo? Wonderful job! I'm still stucked in simple coding with the S2DSDK while in the meantime you did all this! You deserve respect, man!

    ReplyDelete
  2. Awesome job you sir are one hard worker

    ReplyDelete