From 1deab739803ee768e393bba41446450a792b6410 Mon Sep 17 00:00:00 2001 From: Lorenzo Miori Date: Fri, 15 Nov 2013 22:05:40 +0100 Subject: Initial commit for the YP-Z5 port The port uses the imx233 soc, it's a STMP3650 based Samsung player Change-Id: I50b6d7e77fd292fab5ed26de87853cd5aaf9eaa4 Reviewed-on: http://gerrit.rockbox.org/490 Reviewed-by: Amaury Pouly --- firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c | 294 +++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c (limited to 'firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c') diff --git a/firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c b/firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c new file mode 100644 index 0000000000..4f7d9b88b5 --- /dev/null +++ b/firmware/target/arm/imx233/samsung-ypz5/lcd-ypz5.c @@ -0,0 +1,294 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (c) 2013 by Lorenzo Miori + * + * 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 /* off_t */ +#include +#include "cpu.h" +#include "system.h" +#include "backlight-target.h" +#include "lcd.h" +#include "lcdif-imx233.h" +#include "clkctrl-imx233.h" +#include "pinctrl-imx233.h" +#include "dcp-imx233.h" +#include "logf.h" +#ifndef BOOTLOADER +#include "button.h" +#include "font.h" +#include "action.h" +#endif +#include "dma-imx233.h" + +#include "regs/regs-lcdif.h" + +/** + * NOTE + * We don't know exact LCD models nor we have datasheets for them + * Register function are partly guessed from the values, others are guessed from other LCD + * drivers and others have been confirmed studying their values + */ + +static enum lcd_type_t +{ + LCD_TYPE_ZERO = 0, + LCD_TYPE_ONE = 1 +} lcd_type = LCD_TYPE_ZERO; + +static void lcd_write_reg(uint16_t reg, uint16_t data) +{ + imx233_lcdif_pio_send(false, 1, ®); + if(reg != 0x22) + imx233_lcdif_pio_send(true, 1, &data); +} + +/* + * The two LCD types require different initialization sequences + */ +void lcd_init_seq(void) +{ + switch (lcd_type) + { + case LCD_TYPE_ZERO: + { + lcd_write_reg(0x11, 0x1f1e); + lcd_write_reg(0x38, 0xf0f); + lcd_write_reg(0x12, 0x1101); + lcd_write_reg(0x13, 0x808); + lcd_write_reg(0x14, 0x3119); + lcd_write_reg(0x10, 0x1a10); + udelay(0xc350); + lcd_write_reg(0x13, 0x83b); + udelay(0x30d40); + lcd_write_reg(1, 0x90c); /* Display mode */ + lcd_write_reg(2, 0x200); + lcd_write_reg(3, 0x1030); + lcd_write_reg(7, 5); + lcd_write_reg(8, 0x503); + lcd_write_reg(11, 0); + lcd_write_reg(12, 0); + /* Gamma control */ + lcd_write_reg(0x30, 0x606); + lcd_write_reg(0x31, 0x606); + lcd_write_reg(0x32, 0x305); + lcd_write_reg(0x33, 2); + lcd_write_reg(0x34, 0x503); + lcd_write_reg(0x35, 0x606); + lcd_write_reg(0x36, 0x606); + lcd_write_reg(0x37, 0x200); + + lcd_write_reg(0x11, 0x1f1e); + lcd_write_reg(0x38, 0xf0f); + /* Set initial LCD limits and RAM settings */ + lcd_write_reg(0x40, 0); //BPP ? + lcd_write_reg(0x42, 0x9f00); + lcd_write_reg(0x43, 0); + lcd_write_reg(0x44, 0x7f00); /* Horizontal initial refresh zone [0 - 127] */ + lcd_write_reg(0x45, 0x9f00); /* Vertical initial refresh zone [0 - 159] */ + + lcd_write_reg(14, 0x13); + lcd_write_reg(0xa9, 0x14); + lcd_write_reg(0xa7, 0x30); + lcd_write_reg(0xa8, 0x124); + lcd_write_reg(0x6f, 0x1d00); + lcd_write_reg(0x70, 3); + lcd_write_reg(7, 1); + lcd_write_reg(0x10, 0x1a10); + udelay(0x9c40); + lcd_write_reg(7, 0x21); + lcd_write_reg(7, 0x23); + udelay(0x9c40); + lcd_write_reg(7, 0x37); /* Seems to be "power on" */ + break; + } + case LCD_TYPE_ONE: + { + lcd_write_reg(0, 1); + udelay(0x2710); + lcd_write_reg(0x11, 0x171b); + lcd_write_reg(0x12, 0); + lcd_write_reg(0x13, 0x80d); + lcd_write_reg(0x14, 0x18); + lcd_write_reg(0x10, 0x1a10); + udelay(0xc350); + lcd_write_reg(0x13, 0x81d); + udelay(0xc350); + lcd_write_reg(1, 0x90c); /* Display mode */ + lcd_write_reg(2, 0x200); + lcd_write_reg(3, 0x1030); + lcd_write_reg(7, 5); + lcd_write_reg(8, 0x30a); + lcd_write_reg(11, 4); + lcd_write_reg(12, 0); + /* Gamma control */ + lcd_write_reg(0x30, 0x300); + lcd_write_reg(0x31, 0); + lcd_write_reg(0x32, 0); + lcd_write_reg(0x33, 0x404); + lcd_write_reg(0x34, 0x707); + lcd_write_reg(0x35, 0x700); + lcd_write_reg(0x36, 0x703); + lcd_write_reg(0x37, 4); + + lcd_write_reg(0x38, 0); + /* Set initial LCD limits and RAM settings */ + lcd_write_reg(0x40, 0); + lcd_write_reg(0x42, 0x9f00); /* LCD Display Start Address Register 0 */ + lcd_write_reg(0x43, 0); /* LCD Display Start Address Register 1 */ + lcd_write_reg(0x44, 0x7f00); /* Horizontal initial refresh zone [0 - 127] */ + lcd_write_reg(0x45, 0x9f00); /* Vertical initial refresh zone [0 - 159] */ + + lcd_write_reg(7, 1); + udelay(0x2710); + lcd_write_reg(7, 0x21); + lcd_write_reg(7, 0x23); + udelay(0x2710); + lcd_write_reg(7, 0x1037); + udelay(0x2710); + lcd_write_reg(7, 0x35); + lcd_write_reg(7, 0x36); + lcd_write_reg(7, 0x37); + udelay(10000); + break; + } + default: + break; + } +} + +static void send_update_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h) +{ + /* Set horizontal refresh zone */ + lcd_write_reg(0x44, (x | (y + w - 1) << 0x8)); + /* Set vertical refresh zone */ + lcd_write_reg(0x45, (y | (y + h - 1) << 0x8)); + lcd_write_reg(0x21, x | y << 8); + /* Set register index to 0x22 to write screen data. 0 is mock value */ + lcd_write_reg(0x22, 0); +} + +static void setup_lcd_pins(void) +{ + imx233_lcdif_setup_system_pins(16); + /* lcd_rd */ + imx233_pinctrl_acquire(0, 9, "lcd rd"); + imx233_pinctrl_set_function(0, 9, PINCTRL_FUNCTION_GPIO); + imx233_pinctrl_set_gpio(0, 9, false); + /* + * This pin is important to know the LCD type + * There are two types that require two different initialization sequences + */ + /* lcd_tp */ + imx233_pinctrl_acquire(3, 12, "lcd type"); + imx233_pinctrl_set_function(3, 12, PINCTRL_FUNCTION_GPIO); + imx233_pinctrl_enable_gpio(3, 12, false); + /* Sense LCD Type */ + lcd_type = imx233_pinctrl_get_gpio(3, 12) ? LCD_TYPE_ONE : LCD_TYPE_ZERO; +} + +static void setup_parameters(void) +{ + imx233_lcdif_init(); + imx233_lcdif_enable(true); + imx233_lcdif_set_word_length(16); + imx233_lcdif_set_data_swizzle(false); + imx233_lcdif_set_timings(2, 1, 1, 1); + BF_WR_V(LCDIF_CTRL, MODE86, 8080_MODE); + + imx233_lcdif_reset_lcd(true); + udelay(50); + imx233_lcdif_reset_lcd(false); + udelay(10); + imx233_lcdif_reset_lcd(true); +} + +void lcd_init_device(void) +{ + /* Setup interface pins */ + setup_lcd_pins(); + /* Set LCD parameters */ + setup_parameters(); + /* Send initialization sequence to LCD */ + lcd_init_seq(); +} + +struct lcdif_cmd_t +{ + struct apb_dma_command_t dma; + uint32_t ctrl0; + uint32_t pad[4]; +} __attribute__((packed)) CACHEALIGN_ATTR; + +struct lcdif_cmd_t lcdif_dma; +void lcd_update(void) +{ + unsigned size = LCD_WIDTH * LCD_HEIGHT * sizeof(fb_data); + + send_update_rect(0,0,LCD_WIDTH,LCD_HEIGHT); + /* We can safely do the transfer in a single shot, since 160 * 128 * 2 < 65k, + * the maximum transfer size! + */ + lcdif_dma.dma.cmd |= BF_OR3(APB_CHx_CMD, CMDWORDS(1), XFER_COUNT(size), COMMAND(2)); + lcdif_dma.ctrl0 = HW_LCDIF_CTRL & ~BM_LCDIF_CTRL_COUNT; + lcdif_dma.ctrl0 |= BF_OR2(LCDIF_CTRL, COUNT(size/2), DATA_SELECT(1)); + lcdif_dma.dma.buffer = FBADDR(0,0); + lcdif_dma.dma.cmd |= BM_APB_CHx_CMD_SEMAPHORE; + + imx233_dma_start_command(APB_LCDIF, &lcdif_dma.dma); + imx233_dma_wait_completion(APB_LCDIF, HZ); +} + +void lcd_update_rect(int x, int y, int w, int h) +{ + (void)x; + (void)y; + (void)w; + (void)h; + lcd_update(); +} + +#ifndef BOOTLOADER +bool lcd_debug_screen(void) +{ + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + int button = get_action(CONTEXT_STD, HZ / 10); + switch(button) + { + case ACTION_STD_NEXT: + case ACTION_STD_PREV: + case ACTION_STD_OK: + case ACTION_STD_MENU: + lcd_setfont(FONT_UI); + return true; + case ACTION_STD_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + lcd_putsf(0, 0, "LCD type: %d", lcd_type); + lcd_update(); + yield(); + } + + return true; +} +#endif -- cgit v1.2.3