2009-07-13 21:09:39 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Rockbox driver for Sansa View LCDs
|
|
|
|
*
|
|
|
|
* Copyright (c) 2009 Robert Keevil
|
|
|
|
*
|
|
|
|
* 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 <string.h>
|
|
|
|
#include "cpu.h"
|
2014-03-27 22:35:04 +00:00
|
|
|
#include "kernel.h"
|
2009-07-13 21:09:39 +00:00
|
|
|
#include "system.h"
|
|
|
|
#include "backlight-target.h"
|
|
|
|
#include "lcd.h"
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static bool display_on SHAREDBSS_ATTR = true;
|
2009-07-17 20:40:40 +00:00
|
|
|
static int lcd_type;
|
2009-07-13 21:09:39 +00:00
|
|
|
|
|
|
|
#define LCD_DATA_OUT_GPIO GPIOH_OUTPUT_VAL
|
|
|
|
#define LCD_DATA_OUT_PIN 4
|
|
|
|
|
|
|
|
#define LCD_CLOCK_GPIO GPIOH_OUTPUT_VAL
|
|
|
|
#define LCD_CLOCK_PIN 6
|
|
|
|
|
|
|
|
#define LCD_CS_GPIO GPIOH_OUTPUT_VAL
|
|
|
|
#define LCD_CS_PIN 7
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static void lcd_init_gpio(void)
|
|
|
|
{
|
|
|
|
DEV_INIT1 |= 0xfc000000;
|
|
|
|
DEV_INIT3 |= 0xc300000;
|
|
|
|
|
|
|
|
GPIOE_ENABLE = 0;
|
|
|
|
GPIOM_ENABLE &= ~0x3;
|
|
|
|
GPIOF_ENABLE = 0;
|
|
|
|
GPIOJ_ENABLE &= ~0x1a;
|
|
|
|
// reset low
|
|
|
|
GPIOB_ENABLE &= ~0x8;
|
|
|
|
// SPI chip select
|
2009-07-13 21:09:39 +00:00
|
|
|
GPIOH_OUTPUT_VAL |= 0x80;
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIOH_OUTPUT_EN |= 0x80;
|
|
|
|
GPIOH_ENABLE |= 0x80;
|
|
|
|
// SPI clock
|
2009-07-13 21:09:39 +00:00
|
|
|
GPIOH_OUTPUT_VAL |= 0x40;
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIOH_OUTPUT_EN |= 0x40;
|
|
|
|
GPIOH_ENABLE |= 0x40;
|
|
|
|
// unk
|
2009-07-13 21:09:39 +00:00
|
|
|
GPIOH_OUTPUT_VAL |= 0x20;
|
2009-07-17 20:40:40 +00:00
|
|
|
GPIOH_OUTPUT_EN |= 0x20;
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIOH_ENABLE |= 0x20;
|
|
|
|
// SPI data
|
2009-07-13 21:09:39 +00:00
|
|
|
GPIOH_OUTPUT_VAL |= 0x10;
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIOH_OUTPUT_EN |= 0x10;
|
|
|
|
GPIOH_ENABLE |= 0x10;
|
|
|
|
// LCD reset
|
2009-07-13 21:09:39 +00:00
|
|
|
GPIOB_OUTPUT_VAL |= 0x4;
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIOB_ENABLE |= 0x4;
|
|
|
|
GPIOB_OUTPUT_EN |= 0x4;
|
|
|
|
DEV_INIT2 = 0x40000000;
|
|
|
|
// LCD type
|
|
|
|
GPIOG_ENABLE |= 0x8;
|
|
|
|
GPIOG_OUTPUT_EN &= ~0x8;
|
|
|
|
|
|
|
|
if(GPIOG_INPUT_VAL & 0x8)
|
2009-07-17 20:40:40 +00:00
|
|
|
lcd_type = 0;
|
2014-05-05 21:23:50 +00:00
|
|
|
else
|
|
|
|
lcd_type = 1;
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lcd_send_msg(unsigned char count, unsigned int data)
|
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
for(int i = count - 1; i >= 0; i--)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
if(data & (1 << i))
|
|
|
|
GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
|
|
|
|
else
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
udelay(1);
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
udelay(2);
|
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static void lcd_send_cmd(unsigned int cmd)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_send_msg(24, (0x700000 | cmd));
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static void lcd_send_data(unsigned int data)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_send_msg(24, (0x720000 | data));
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lcd_write_reg(unsigned int cmd, unsigned int data)
|
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_send_cmd(cmd);
|
|
|
|
lcd_send_data(data);
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2009-07-17 20:40:40 +00:00
|
|
|
void lcd_reset(void)
|
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
|
2009-07-17 20:40:40 +00:00
|
|
|
udelay(1000);
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
|
2009-07-17 20:40:40 +00:00
|
|
|
udelay(10000);
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
|
2009-07-17 20:40:40 +00:00
|
|
|
udelay(50000);
|
|
|
|
}
|
|
|
|
|
2009-07-13 21:09:39 +00:00
|
|
|
/* Run the powerup sequence for the driver IC */
|
|
|
|
static void lcd_power_on(void)
|
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_init_gpio();
|
2009-07-17 20:40:40 +00:00
|
|
|
lcd_reset();
|
2014-05-05 21:23:50 +00:00
|
|
|
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0xE5, 0x8000);
|
|
|
|
lcd_write_reg(0x0, 0x1);
|
|
|
|
lcd_write_reg(0x1, 0x100);
|
|
|
|
lcd_write_reg(0x2, 0x700);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0x3, 0x5230);
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0x4, 0x0);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0x8, 0x408); /* back porch = 8, front porch = 4 */
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0x9, 0x0);
|
|
|
|
lcd_write_reg(0xa, 0x0);
|
|
|
|
lcd_write_reg(0xd, 0x0);
|
|
|
|
lcd_write_reg(0xf, 0x2);
|
|
|
|
lcd_write_reg(0x10, 0x0);
|
|
|
|
lcd_write_reg(0x11, 0x0);
|
|
|
|
lcd_write_reg(0x12, 0x0);
|
|
|
|
lcd_write_reg(0x13, 0x0);
|
|
|
|
sleep(HZ/5);
|
|
|
|
lcd_write_reg(0x10, 0x17B0);
|
|
|
|
lcd_write_reg(0x11, 0x7);
|
|
|
|
sleep(HZ/20);
|
|
|
|
lcd_write_reg(0x12, 0x13c);
|
|
|
|
sleep(HZ/20);
|
|
|
|
|
2009-07-17 20:40:40 +00:00
|
|
|
if (lcd_type == 0)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
|
|
|
lcd_write_reg(0x13, 0x1700);
|
|
|
|
lcd_write_reg(0x29, 0x10);
|
|
|
|
sleep(HZ/10);
|
|
|
|
lcd_write_reg(0x20, 0x0);
|
|
|
|
lcd_write_reg(0x21, 0x0);
|
|
|
|
|
|
|
|
lcd_write_reg(0x30, 0x7);
|
|
|
|
lcd_write_reg(0x31, 0x403);
|
|
|
|
lcd_write_reg(0x32, 0x400);
|
|
|
|
lcd_write_reg(0x35, 0x3);
|
|
|
|
lcd_write_reg(0x36, 0xF07);
|
2009-07-17 20:40:40 +00:00
|
|
|
lcd_write_reg(0x37, 0x606);
|
|
|
|
lcd_write_reg(0x38, 0x106);
|
|
|
|
lcd_write_reg(0x39, 0x7);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcd_write_reg(0x13, 0x1800);
|
|
|
|
lcd_write_reg(0x29, 0x13);
|
|
|
|
sleep(HZ/10);
|
|
|
|
lcd_write_reg(0x20, 0x0);
|
|
|
|
lcd_write_reg(0x21, 0x0);
|
|
|
|
|
|
|
|
lcd_write_reg(0x30, 0x2);
|
|
|
|
lcd_write_reg(0x31, 0x606);
|
|
|
|
lcd_write_reg(0x32, 0x501);
|
|
|
|
lcd_write_reg(0x35, 0x206);
|
|
|
|
lcd_write_reg(0x36, 0x504);
|
|
|
|
lcd_write_reg(0x37, 0x707);
|
|
|
|
lcd_write_reg(0x38, 0x306);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0x39, 0x7);
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lcd_write_reg(0x3c, 0x700);
|
|
|
|
lcd_write_reg(0x3d, 0x700);
|
|
|
|
|
|
|
|
lcd_write_reg(0x50, 0x0);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0x51, 0xef);
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0x52, 0x0);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0x53, 0x13f);
|
2009-07-13 21:09:39 +00:00
|
|
|
|
|
|
|
lcd_write_reg(0x60, 0x2700);
|
|
|
|
lcd_write_reg(0x61, 0x1);
|
|
|
|
lcd_write_reg(0x6a, 0x0);
|
|
|
|
|
|
|
|
lcd_write_reg(0x80, 0x0);
|
|
|
|
lcd_write_reg(0x81, 0x0);
|
|
|
|
lcd_write_reg(0x82, 0x0);
|
|
|
|
lcd_write_reg(0x83, 0x0);
|
|
|
|
lcd_write_reg(0x84, 0x0);
|
|
|
|
lcd_write_reg(0x85, 0x0);
|
|
|
|
|
|
|
|
lcd_write_reg(0x90, 0x10);
|
|
|
|
lcd_write_reg(0x92, 0x0);
|
|
|
|
lcd_write_reg(0x93, 0x3);
|
|
|
|
lcd_write_reg(0x95, 0x110);
|
|
|
|
lcd_write_reg(0x97, 0x0);
|
|
|
|
lcd_write_reg(0x98, 0x0);
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_write_reg(0xc, 0x000); // SYSTEM mode
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0x7, 0x173);
|
|
|
|
sleep(HZ/10);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_power_on();
|
2009-07-13 21:09:39 +00:00
|
|
|
|
|
|
|
lcd_write_reg(0x7, 0x160);
|
|
|
|
lcd_write_reg(0x10, 0x17B1);
|
|
|
|
}
|
|
|
|
|
2009-07-17 20:40:40 +00:00
|
|
|
void unknown03(bool r0)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2009-07-17 20:40:40 +00:00
|
|
|
if (r0)
|
|
|
|
GPIOJ_ENABLE &= ~0x2;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GPIOJ_ENABLE |= 0x2;
|
|
|
|
GPIOJ_OUTPUT_EN |= 0x2;
|
|
|
|
GPIOJ_OUTPUT_VAL &= ~0x02;
|
|
|
|
}
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
void lcd_init_device(void)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_power_on();
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
#if defined(HAVE_LCD_ENABLE)
|
2009-07-13 21:09:39 +00:00
|
|
|
bool lcd_active(void)
|
|
|
|
{
|
|
|
|
return display_on;
|
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
void lcd_enable(bool on)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
display_on = on;
|
|
|
|
if(on)
|
|
|
|
{
|
|
|
|
lcd_write_reg(0x10, 0x17B0);
|
|
|
|
udelay(100);
|
|
|
|
lcd_write_reg(0x7, 0x173);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcd_write_reg(0x7, 0x160);
|
|
|
|
lcd_write_reg(0x10, 0x17B1);
|
|
|
|
}
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static inline void lcd_send_frame_byte(unsigned char data)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
for(int bit = 0; bit < 8; bit++)
|
|
|
|
{
|
|
|
|
if(data & 0x80)
|
|
|
|
GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
|
|
|
|
else
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
|
|
|
|
data <<= 1;
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
|
|
|
GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
|
|
|
}
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
static void lcd_send_frame(const fb_data *addr, int count)
|
2009-07-13 21:09:39 +00:00
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
|
|
|
|
GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_send_frame_byte(0x72);
|
|
|
|
while(count-- > 0)
|
|
|
|
{
|
|
|
|
lcd_send_frame_byte(*addr >> 8);
|
|
|
|
lcd_send_frame_byte(*addr++ & 0xff);
|
|
|
|
}
|
2009-07-13 21:09:39 +00:00
|
|
|
|
2014-05-05 21:23:50 +00:00
|
|
|
GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcd_update(void)
|
|
|
|
{
|
2014-05-05 21:23:50 +00:00
|
|
|
if(!display_on)
|
|
|
|
return;
|
2009-07-13 21:09:39 +00:00
|
|
|
lcd_write_reg(0x20, 0x0);
|
|
|
|
lcd_write_reg(0x21, 0x0);
|
2014-05-05 21:23:50 +00:00
|
|
|
lcd_send_cmd(0x22);
|
|
|
|
lcd_send_frame(FBADDR(0, 0), LCD_WIDTH * LCD_HEIGHT);
|
2009-07-13 21:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update a fraction of the display. */
|
|
|
|
void lcd_update_rect(int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
(void)x;
|
|
|
|
(void)y;
|
|
|
|
(void)width;
|
|
|
|
(void)height;
|
|
|
|
lcd_update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** hardware configuration ***/
|
|
|
|
|
|
|
|
void lcd_set_contrast(int val)
|
|
|
|
{
|
|
|
|
(void)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcd_set_invert_display(bool yesno)
|
|
|
|
{
|
|
|
|
(void)yesno;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* turn the display upside down (call lcd_update() afterwards) */
|
|
|
|
void lcd_set_flip(bool yesno)
|
|
|
|
{
|
|
|
|
(void)yesno;
|
|
|
|
}
|