From 4c60bc9e681865fcfc149775a1ed7ccd2613d5bf Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 23 May 2021 17:30:58 +0100 Subject: New port: Shanling Q1 native - Audio playback works - Touchscreen and buttons work - Bootloader works and is capable of dual boot - Plugins are working - Cabbiev2 theme has been ported - Stable for general usage Thanks to Marc Aarts for porting Cabbiev2 and plugin bitmaps. There's a few minor known issues: - Bootloader must be installed manually using 'usbboot' as there is no support in jztool yet. - Keymaps may be lacking, need further testing and feedback. - Some plugins may not be fully adapted to the screen size and could benefit from further tweaking. - LCD shows abnormal effects under some circumstances: for example, after viewing a mostly black screen an afterimage appears briefly when going back to a brightly-lit screen. Sudden power-off without proper shutdown of the backlight causes a "dissolving" effect. - CW2015 battery reporting driver is buggy, and disabled for now. Battery reporting is currently voltage-based using the AXP192. Change-Id: I635e83f02a880192c5a82cb0861ad3a61c137c3a --- .../mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c | 399 +++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c (limited to 'firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c') diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c new file mode 100644 index 0000000000..532a149185 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c @@ -0,0 +1,399 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * 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 "system.h" +#include "lcd-x1000.h" +#include "gpio-x1000.h" + +/* LCD controller is probably an RM68090. + */ + +static const uint32_t q1_lcd_cmd_enable[] = { + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0xbe, + LCD_INSTR_DAT, 0xc3, + LCD_INSTR_DAT, 0x29, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x01, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x04, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x02, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x03, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x10, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x05, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x06, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x07, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x08, + LCD_INSTR_DAT, 0x03, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x0d, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x10, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0xc1, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x11, + LCD_INSTR_DAT, 0xb1, + LCD_INSTR_DAT, 0x08, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x12, + LCD_INSTR_DAT, 0xb1, + LCD_INSTR_DAT, 0x08, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x13, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x0f, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x14, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x14, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x15, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x04, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x16, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x22, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x23, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x30, + LCD_INSTR_DAT, 0x7c, + LCD_INSTR_DAT, 0x3f, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x32, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x70, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x91, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0xe0, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0xe1, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x61, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x00, + LCD_INSTR_DAT, 0x10, + LCD_INSTR_DAT, 0x30, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x01, + LCD_INSTR_DAT, 0xf6, + LCD_INSTR_DAT, 0x3f, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x02, + LCD_INSTR_DAT, 0x50, + LCD_INSTR_DAT, 0x1f, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x03, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x30, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x08, + LCD_INSTR_DAT, 0x03, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x11, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x35, + LCD_INSTR_DAT, 0x76, + LCD_INSTR_DAT, 0x66, + + LCD_INSTR_CMD, 0x01, + LCD_INSTR_CMD, 0x39, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x26, + + LCD_INSTR_CMD, 0x04, + LCD_INSTR_CMD, 0x00, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0xc7, + + LCD_INSTR_CMD, 0x04, + LCD_INSTR_CMD, 0x01, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x06, + LCD_INSTR_CMD, 0x06, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x00, + LCD_INSTR_DAT, 0x0d, + LCD_INSTR_DAT, 0x0e, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x01, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x02, + LCD_INSTR_DAT, 0x08, + LCD_INSTR_DAT, 0x08, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x03, + LCD_INSTR_DAT, 0x02, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x04, + LCD_INSTR_DAT, 0x03, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x05, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x04, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x06, + LCD_INSTR_DAT, 0x1b, + LCD_INSTR_DAT, 0x21, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x07, + LCD_INSTR_DAT, 0x0f, + LCD_INSTR_DAT, 0x0e, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x08, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x04, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x09, + LCD_INSTR_DAT, 0x08, + LCD_INSTR_DAT, 0x08, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x0a, + LCD_INSTR_DAT, 0x02, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x0b, + LCD_INSTR_DAT, 0x03, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x0c, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x03, + LCD_INSTR_CMD, 0x0d, + LCD_INSTR_DAT, 0x31, + LCD_INSTR_DAT, 0x34, + + /* X start */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x10, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x1e, /* 30 */ + + /* X end */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x11, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x85, /* 389 */ + + /* Y start */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x12, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, /* 0 */ + + /* Y end */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x13, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x8f, /* 399 */ + + /* RAM write start X? */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x00, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x1e, + + /* RAM write start Y? */ + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x01, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x00, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x03, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x30, + + LCD_INSTR_CMD, 0x02, + LCD_INSTR_CMD, 0x02, + LCD_INSTR_END, +}; + +/* NOTE this sleep mode may not be saving power, but it gets rid of the + * ghost image that would otherwise remain on the display */ +static const uint32_t q1_lcd_cmd_sleep[] = { + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x10, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x07, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x01, + + LCD_INSTR_END, +}; + +static const uint32_t q1_lcd_cmd_wake[] = { + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x07, + LCD_INSTR_DAT, 0x01, + LCD_INSTR_DAT, 0x03, + + LCD_INSTR_CMD, 0x00, + LCD_INSTR_CMD, 0x10, + LCD_INSTR_DAT, 0x00, + LCD_INSTR_DAT, 0xc1, + + LCD_INSTR_END, +}; + +static const uint8_t __attribute__((aligned(64))) + q1_lcd_dma_wr_cmd[] = {0x02, 0x02, 0x02, 0x02}; + +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, + .big_endian = 1, + .dma_wr_cmd_buf = &q1_lcd_dma_wr_cmd, + .dma_wr_cmd_size = sizeof(q1_lcd_dma_wr_cmd), +}; + +void lcd_tgt_enable(bool enable) +{ + if(enable) { + /* power on the panel */ + gpio_set_level(GPIO_LCD_PWR, 1); + gpio_set_level(GPIO_LCD_RST, 1); + gpio_set_level(GPIO_LCD_CE, 1); + gpio_set_level(GPIO_LCD_RD, 1); + mdelay(50); + gpio_set_level(GPIO_LCD_RST, 0); + mdelay(100); + gpio_set_level(GPIO_LCD_RST, 1); + mdelay(50); + gpio_set_level(GPIO_LCD_CE, 0); + + /* Start the controller */ + lcd_set_clock(X1000_CLK_MPLL, 50000000); + lcd_exec_commands(q1_lcd_cmd_enable); + } else { + /* FIXME: Shanling Q1 LCD power down sequence + * not important because we don't use it but it'd be nice to know */ + } +} + +void lcd_tgt_sleep(bool sleep) +{ + if(sleep) + lcd_exec_commands(q1_lcd_cmd_sleep); + else + lcd_exec_commands(q1_lcd_cmd_wake); +} -- cgit v1.2.3