mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
ata-creativezen looks like a legit memory-trashing bug, the rtc fixes are bitwise inversion of a bool, and the remaining are just unused static variables. Change-Id: I1a818d4839cd3a54ca6e85f26feb743a4a9d29dc
366 lines
11 KiB
C
366 lines
11 KiB
C
/***************************************************************************
|
||
* __________ __ ___.
|
||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||
* \/ \/ \/ \/ \/
|
||
* $Id$
|
||
*
|
||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License
|
||
* as published by the Free Software Foundation; either version 2
|
||
* of the License, or (at your option) any later version.
|
||
*
|
||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||
* KIND, either express or implied.
|
||
*
|
||
****************************************************************************/
|
||
|
||
#include "lcd.h"
|
||
#include "kernel.h"
|
||
#include "lcd-x1000.h"
|
||
#include "gpio-x1000.h"
|
||
#include "system.h"
|
||
#include "devicedata.h"
|
||
|
||
/* for reference on these command/data hex values, see the mipi dcs lcd spec. *
|
||
* Not everything here is there, but all the standard stuff is. */
|
||
|
||
|
||
/* New Display Eroq 2.1 / Hifiwalker 1.7+ / Surfans v3.2, unknown Controller *
|
||
* (partially GC9A01 register compatible) *
|
||
* https://espruino.microcosm.app/api/v1/files/ \ *
|
||
* 9dc1b976d621a2ab3854312cce862c4a9a50dc1b.html#GC9A01 , *
|
||
* https://www.buydisplay.com/download/ic/GC9A01A.pdf , *
|
||
* https://lcddisplay.co/wp-content/uploads/2023/02/GC9A01.pdf *
|
||
* Init sequence From 'EROS Q (c口)_V2.1_20231209固件.zip' *
|
||
* update.upt/.iso -> In 'uboot.bin' at 0x52da0-0x5305f *
|
||
* http://www.eroshifi.com/download/firmware/122.html */
|
||
#if !defined(BOOTLOADER) || (EROSQN_VER >= 3)
|
||
static const uint32_t erosqnative_lcd_cmd_enable_v3[] = {
|
||
|
||
/* Unlock EXTC? */
|
||
LCD_INSTR_CMD, 0xfe, // Inter Register Enable1
|
||
LCD_INSTR_CMD, 0xef, // Inter Register Enable2
|
||
|
||
LCD_INSTR_CMD, 0x36, // Memory Access Control
|
||
/* Bit7 1:vertical flip 0:no vertical flip
|
||
Bit6 1:horizontal flip 0:no horizontal flip
|
||
Bit3 1:BGR 0:RGB */
|
||
LCD_INSTR_DAT, 0x90,
|
||
/* Pixel Format Set */
|
||
LCD_INSTR_CMD, 0x3a,
|
||
LCD_INSTR_DAT, 0x55, /* Rockbox uses 16pp, OF specified 18 bpp */
|
||
|
||
LCD_INSTR_CMD, 0x84, // ?? (undocumented)
|
||
LCD_INSTR_DAT, 0x04,
|
||
LCD_INSTR_CMD, 0x86, // ??
|
||
LCD_INSTR_DAT, 0xfb,
|
||
LCD_INSTR_CMD, 0x87, // ??
|
||
LCD_INSTR_DAT, 0x79,
|
||
LCD_INSTR_CMD, 0x89, // ??
|
||
LCD_INSTR_DAT, 0x0b,
|
||
LCD_INSTR_CMD, 0x8a, // ??
|
||
LCD_INSTR_DAT, 0x20,
|
||
LCD_INSTR_CMD, 0x8b, // ??
|
||
LCD_INSTR_DAT, 0x80,
|
||
LCD_INSTR_CMD, 0x8d, // ??
|
||
LCD_INSTR_DAT, 0x3b,
|
||
LCD_INSTR_CMD, 0x8e, // ??
|
||
LCD_INSTR_DAT, 0xcf,
|
||
|
||
LCD_INSTR_CMD, 0xec, // Charge Pump Frequent Control
|
||
LCD_INSTR_DAT, 0x33,
|
||
LCD_INSTR_DAT, 0x02,
|
||
LCD_INSTR_DAT, 0x4c,
|
||
|
||
LCD_INSTR_CMD, 0x98, // ?? (undocumented)
|
||
LCD_INSTR_DAT, 0x3e,
|
||
LCD_INSTR_CMD, 0x9c, // ??
|
||
LCD_INSTR_DAT, 0x4b,
|
||
LCD_INSTR_CMD, 0x99, // ??
|
||
LCD_INSTR_DAT, 0x3e,
|
||
LCD_INSTR_CMD, 0x9d, // ??
|
||
LCD_INSTR_DAT, 0x4b,
|
||
LCD_INSTR_CMD, 0x9b, // ??
|
||
LCD_INSTR_DAT, 0x55,
|
||
|
||
LCD_INSTR_CMD, 0xe8, // Frame Rate
|
||
LCD_INSTR_DAT, 0x11,
|
||
LCD_INSTR_DAT, 0x00,
|
||
|
||
LCD_INSTR_CMD, 0xff, // ?? (Adafruit & Co lib. C:0xFF, D:0x60, D:0x01, D:0x04)
|
||
LCD_INSTR_DAT, 0x62, // LCD_INSTR_DAT, 0x01, LCD_INSTR_DAT, 0x04,
|
||
LCD_INSTR_CMD, 0xc3, // Vreg1a voltage Control
|
||
LCD_INSTR_DAT, 0x20,
|
||
LCD_INSTR_CMD, 0xc4, // Vreg1b voltage Control
|
||
LCD_INSTR_DAT, 0x03,
|
||
LCD_INSTR_CMD, 0xc9, // Vreg2a voltage Control
|
||
LCD_INSTR_DAT, 0x2a,
|
||
|
||
LCD_INSTR_CMD, 0xf0, // SET_GAMMA1
|
||
LCD_INSTR_DAT, 0x4a,
|
||
LCD_INSTR_DAT, 0x10,
|
||
LCD_INSTR_DAT, 0x0a,
|
||
LCD_INSTR_DAT, 0x0a,
|
||
LCD_INSTR_DAT, 0x26,
|
||
LCD_INSTR_DAT, 0x39,
|
||
|
||
LCD_INSTR_CMD, 0xf2, // SET_GAMMA3
|
||
LCD_INSTR_DAT, 0x4a,
|
||
LCD_INSTR_DAT, 0x10,
|
||
LCD_INSTR_DAT, 0x0a,
|
||
LCD_INSTR_DAT, 0x0a,
|
||
LCD_INSTR_DAT, 0x26,
|
||
LCD_INSTR_DAT, 0x39,
|
||
|
||
LCD_INSTR_CMD, 0xf1, // SET_GAMMA2
|
||
LCD_INSTR_DAT, 0x50,
|
||
LCD_INSTR_DAT, 0x8f,
|
||
LCD_INSTR_DAT, 0xaf,
|
||
LCD_INSTR_DAT, 0x3b,
|
||
LCD_INSTR_DAT, 0x3f,
|
||
LCD_INSTR_DAT, 0x7f,
|
||
|
||
LCD_INSTR_CMD, 0xf3, // SET_GAMMA4
|
||
LCD_INSTR_DAT, 0x50,
|
||
LCD_INSTR_DAT, 0x8f,
|
||
LCD_INSTR_DAT, 0xaf,
|
||
LCD_INSTR_DAT, 0x3b,
|
||
LCD_INSTR_DAT, 0x3f,
|
||
LCD_INSTR_DAT, 0x7f,
|
||
|
||
LCD_INSTR_CMD, 0xba, // TE Control
|
||
LCD_INSTR_DAT, 0x0a,
|
||
|
||
#ifdef BOOTLOADER
|
||
LCD_INSTR_CMD, 0x35, // Tearing Effect Line ON
|
||
LCD_INSTR_DAT, 0x00,
|
||
#endif
|
||
|
||
LCD_INSTR_CMD, 0x21, /* Invert */
|
||
|
||
/* Lock EXTC? */
|
||
LCD_INSTR_CMD, 0xfe, // Inter Register Enable1
|
||
LCD_INSTR_CMD, 0xee,
|
||
|
||
/* Exit Sleep */
|
||
LCD_INSTR_CMD, 0x11,
|
||
LCD_INSTR_UDELAY, 120000,
|
||
/* Display On */
|
||
LCD_INSTR_CMD, 0x29,
|
||
LCD_INSTR_UDELAY, 20000,
|
||
LCD_INSTR_END,
|
||
};
|
||
#endif
|
||
|
||
#if !defined(BOOTLOADER) || (EROSQN_VER < 3)
|
||
/* Original Display / Hifiwalker -1.5 / Surfans -2.7 */
|
||
static const uint32_t erosqnative_lcd_cmd_enable_v1[] = {
|
||
/* Set EXTC? */
|
||
LCD_INSTR_CMD, 0xc8,
|
||
LCD_INSTR_DAT, 0xff,
|
||
LCD_INSTR_DAT, 0x93,
|
||
LCD_INSTR_DAT, 0x42,
|
||
/* Set Address Mode */
|
||
LCD_INSTR_CMD, 0x36,
|
||
LCD_INSTR_DAT, 0xd8,
|
||
/* Pixel Format Set */
|
||
LCD_INSTR_CMD, 0x3a,
|
||
//LCD_INSTR_DAT, 0x66, /* OF specified 18 bpp */
|
||
LCD_INSTR_DAT, 0x05, /* RB seems to be happier dealing with 16 bits/pixel */
|
||
/* Power Control 1? */
|
||
LCD_INSTR_CMD, 0xc0,
|
||
LCD_INSTR_DAT, 0x15,
|
||
LCD_INSTR_DAT, 0x15,
|
||
/* Power Control 2? */
|
||
LCD_INSTR_CMD, 0xc1,
|
||
LCD_INSTR_DAT, 0x01,
|
||
/* VCOM? */
|
||
LCD_INSTR_CMD, 0xc5,
|
||
LCD_INSTR_DAT, 0xda,
|
||
/* ?? */
|
||
LCD_INSTR_CMD, 0xb1,
|
||
LCD_INSTR_DAT, 0x00,
|
||
LCD_INSTR_DAT, 0x1b,
|
||
/* ?? */
|
||
LCD_INSTR_CMD, 0xb4,
|
||
LCD_INSTR_DAT, 0x02,
|
||
/* Positive gamma correction? */
|
||
LCD_INSTR_CMD, 0xe0,
|
||
LCD_INSTR_DAT, 0x0f,
|
||
LCD_INSTR_DAT, 0x13,
|
||
LCD_INSTR_DAT, 0x17,
|
||
LCD_INSTR_DAT, 0x04,
|
||
LCD_INSTR_DAT, 0x13,
|
||
LCD_INSTR_DAT, 0x07,
|
||
LCD_INSTR_DAT, 0x40,
|
||
LCD_INSTR_DAT, 0x39,
|
||
LCD_INSTR_DAT, 0x4f,
|
||
LCD_INSTR_DAT, 0x06,
|
||
LCD_INSTR_DAT, 0x0d,
|
||
LCD_INSTR_DAT, 0x0a,
|
||
LCD_INSTR_DAT, 0x1f,
|
||
LCD_INSTR_DAT, 0x22,
|
||
LCD_INSTR_DAT, 0x00,
|
||
/* Negative gamma correction? */
|
||
LCD_INSTR_CMD, 0xe1,
|
||
LCD_INSTR_DAT, 0x00,
|
||
LCD_INSTR_DAT, 0x21,
|
||
LCD_INSTR_DAT, 0x24,
|
||
LCD_INSTR_DAT, 0x03,
|
||
LCD_INSTR_DAT, 0x0f,
|
||
LCD_INSTR_DAT, 0x05,
|
||
LCD_INSTR_DAT, 0x38,
|
||
LCD_INSTR_DAT, 0x32,
|
||
LCD_INSTR_DAT, 0x49,
|
||
LCD_INSTR_DAT, 0x00,
|
||
LCD_INSTR_DAT, 0x09,
|
||
LCD_INSTR_DAT, 0x08,
|
||
LCD_INSTR_DAT, 0x32,
|
||
LCD_INSTR_DAT, 0x35,
|
||
LCD_INSTR_DAT, 0x0f,
|
||
/* Exit Sleep */
|
||
LCD_INSTR_CMD, 0x11,
|
||
LCD_INSTR_UDELAY, 120000,
|
||
/* Display On */
|
||
LCD_INSTR_CMD, 0x29,
|
||
LCD_INSTR_UDELAY, 20000,
|
||
LCD_INSTR_END,
|
||
};
|
||
#endif
|
||
|
||
static const uint32_t erosqnative_lcd_of_compat_cmd[] = {
|
||
/* Pixel Format Set */
|
||
LCD_INSTR_CMD, 0x3a,
|
||
LCD_INSTR_DAT, 0x66, /* 18 bpp */
|
||
/* Exit Sleep */
|
||
LCD_INSTR_CMD, 0x11,
|
||
LCD_INSTR_UDELAY, 120000,
|
||
/* Display On */
|
||
LCD_INSTR_CMD, 0x29,
|
||
LCD_INSTR_UDELAY, 20000,
|
||
LCD_INSTR_END,
|
||
};
|
||
|
||
/* sleep and wake copied directly from m3k */
|
||
static const uint32_t erosqnative_lcd_cmd_sleep[] = {
|
||
/* Display OFF */
|
||
LCD_INSTR_CMD, 0x28,
|
||
/* Sleep IN */
|
||
LCD_INSTR_CMD, 0x10,
|
||
LCD_INSTR_UDELAY, 5000,
|
||
LCD_INSTR_END,
|
||
};
|
||
|
||
static const uint32_t erosqnative_lcd_cmd_wake[] = {
|
||
/* Sleep OUT */
|
||
LCD_INSTR_CMD, 0x11,
|
||
LCD_INSTR_UDELAY, 5000,
|
||
/* Display ON */
|
||
LCD_INSTR_CMD, 0x29,
|
||
LCD_INSTR_END,
|
||
};
|
||
|
||
/* As far as I can tell, this is a sequence of commands sent before each
|
||
* DMA set. Original in OF was:
|
||
* {0x2c, 0x2c, 0x2c, 0x2c}
|
||
* But this set from the m3k seems to work the same, and makes more sense
|
||
* to me:
|
||
* {0x00, 0x00, 0x00, 0x2c}
|
||
* This command is more than likely going to be the same
|
||
* for any old mipi lcd on the market, maybe. I really don't think we need
|
||
* to send "write_memory_start four times in a row. */
|
||
static const uint8_t __attribute__((aligned(64)))
|
||
erosqnative_lcd_dma_wr_cmd[] = {0x2c, 0x2c, 0x2c, 0x2c};
|
||
|
||
const struct lcd_tgt_config lcd_tgt_config = {
|
||
.bus_width = 8,
|
||
.cmd_width = 8,
|
||
.use_6800_mode = 0,
|
||
.use_serial = 0,
|
||
.clk_polarity = 0,
|
||
.dc_polarity = 0,
|
||
.wr_polarity = 1,
|
||
.te_enable = 0, /* OF had TE enabled (1) */
|
||
.te_polarity = 1,
|
||
.te_narrow = 0,
|
||
.dma_wr_cmd_buf = &erosqnative_lcd_dma_wr_cmd,
|
||
.dma_wr_cmd_size = sizeof(erosqnative_lcd_dma_wr_cmd),
|
||
};
|
||
|
||
void lcd_tgt_enable(bool enable)
|
||
{
|
||
if(enable) {
|
||
/* power up the panel */
|
||
#ifdef BOOTLOADER
|
||
# if EROSQN_VER <= 3
|
||
gpio_set_level(GPIO_LCD_PWR_HW1, 1);
|
||
# endif
|
||
#else
|
||
if (device_data.hw_rev <= 3)
|
||
{
|
||
gpio_set_level(GPIO_LCD_PWR_HW1, 1);
|
||
}
|
||
#endif
|
||
mdelay(20);
|
||
gpio_set_level(GPIO_LCD_RESET, 1);
|
||
mdelay(12);
|
||
|
||
/* set the clock */
|
||
lcd_set_clock(X1000_CLK_SCLK_A, 20000000);
|
||
|
||
/* toggle chip select low (active) */
|
||
gpio_set_level(GPIO_LCD_RD, 1);
|
||
gpio_set_level(GPIO_LCD_CE, 1);
|
||
mdelay(5);
|
||
gpio_set_level(GPIO_LCD_CE, 0);
|
||
|
||
#ifdef BOOTLOADER
|
||
# if EROSQN_VER >= 3
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]);
|
||
# else
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_enable_v1[0]);
|
||
# endif
|
||
#else
|
||
if (device_data.hw_rev >= 3)
|
||
{
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]);
|
||
}
|
||
else
|
||
{
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_enable_v1[0]);
|
||
}
|
||
#endif
|
||
} else {
|
||
/* doesn't flash white if we don't do anything... */
|
||
#if 0
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
|
||
|
||
mdelay(115); // copied from m3k
|
||
|
||
gpio_set_level(GPIO_LCD_PWR, 0);
|
||
gpio_set_level(GPIO_LCD_RESET, 0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
void lcd_tgt_enable_of(bool enable)
|
||
{
|
||
/* silence the unused parameter warning */
|
||
if (enable)
|
||
{}
|
||
|
||
lcd_exec_commands(&erosqnative_lcd_of_compat_cmd[0]);
|
||
}
|
||
|
||
void lcd_tgt_sleep(bool sleep)
|
||
{
|
||
if(sleep)
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
|
||
else
|
||
lcd_exec_commands(&erosqnative_lcd_cmd_wake[0]);
|
||
}
|