summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2011-08-29 21:05:59 +0000
committerBertrik Sikken <bertrik@sikken.nl>2011-08-29 21:05:59 +0000
commit401edf8b48ea55cb50336c52f6bf7c6f63701f0a (patch)
tree1dc1659054e03a750ee6fd0186b41e2195159a5c /firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
parent152c4fb81993749739bf41890bab6bdbf2825a1b (diff)
downloadrockbox-401edf8b48ea55cb50336c52f6bf7c6f63701f0a.tar.gz
rockbox-401edf8b48ea55cb50336c52f6bf7c6f63701f0a.zip
sansa clipzip: implement more functions in the lcd driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30376 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c')
-rw-r--r--firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c314
1 files changed, 276 insertions, 38 deletions
diff --git a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
index 8efbdf77b9..dd815df05e 100644
--- a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
+++ b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
@@ -26,78 +26,316 @@
#include "system.h"
#include "cpu.h"
-static int display_type;
+#define CLAMP(x,min,max) \
+ if ((x)<(min)) (x)=(min);\
+ if ((x)>(max)) (x)=(max);
+/* the detected lcd type (0 or 1) */
+static int lcd_type;
+
+/* initialises the host lcd hardware, returns the lcd type */
int lcd_hw_init(void)
{
+ /* configure SSP */
bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
+ SSP_CPSR = 8; /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */
+ SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */
+ (1 << 7) | /* SPH, phase = 1 */
+ (1 << 6) | /* SPO, polarity = 1 */
+ (0 << 4) | /* FRF, frame format = motorola SPI */
+ (7 << 0); /* DSS, data size select = 8 bits */
+ SSP_CR1 = (1 << 3) | /* SOD, slave output disable = 1 */
+ (0 << 2) | /* MS, master/slave = master */
+ (1 << 1) | /* SSE, synchronous serial port enabled = true */
+ (0 << 0); /* LBM, loopback mode = normal */
+ SSP_IMSC &= ~0xF; /* disable interrupts */
+ SSP_DMACR &= ~0x3; /* disable DMA */
- SSP_CPSR = AS3525_SSP_PRESCALER; /* OF = 0x10 */
- SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */
- SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */
- SSP_IMSC = 0; /* No interrupts */
-
- /* configure GPIO B2 (display D/C#) as output */
+ /* configure GPIO B2 (lcd D/C#) as output */
GPIOB_DIR |= (1<<2);
- /* configure GPIO B3 (display type detect) as input */
+ /* configure GPIO B3 (lcd type detect) as input */
GPIOB_DIR &= ~(1<<3);
- /* set GPIO A5 (display RESET# ?) */
- GPIOA_DIR |= (1<<5);
- GPIOA_PIN(5) = (1<<5);
+ /* configure GPIO A5 (lcd reset# ?) as output and set low */
+ GPIOA_DIR |= (1 << 5);
+ GPIOA_PIN(5) = 0;
- /* detect display type on GPIO B3 */
+ /* detect lcd type on GPIO B3 */
return GPIOB_PIN(3) ? 1 : 0;
}
-void lcd_write_command(int byte)
+/* writes a command byte to the LCD */
+static void lcd_write_cmd(uint8_t byte)
{
- while(SSP_SR & (1<<4)) /* BSY flag */
- ;
+ /* wait until not busy */
+ while (SSP_SR & (1<<4));
/* LCD command mode */
GPIOB_PIN(2) = 0;
+ /* write data */
SSP_DATA = byte;
- while(SSP_SR & (1<<4)) /* BSY flag */
- ;
+
+ /* wait until not busy */
+ while (SSP_SR & (1<<4));
+
+ /* LCD data mode */
+ GPIOB_PIN(2) = (1 << 2);
}
-void lcd_write_data(const fb_data* p_bytes, int count)
+/* writes a data byte to the LCD */
+static void lcd_write_dat(uint8_t data)
{
- /* LCD data mode */
- GPIOB_PIN(2) = (1<<2);
+ /* wait while transmit FIFO */
+ while (!(SSP_SR & (1<<1)));
- while (count--)
- {
- while(!(SSP_SR & (1<<1))) /* wait until transmit FIFO is not full */
- ;
+ /* write data */
+ SSP_DATA = data;
+}
- SSP_DATA = *p_bytes++;
- }
+/* writes both a command and data value to the lcd */
+static void lcd_write(uint8_t cmd, uint8_t data)
+{
+ lcd_write_cmd(cmd);
+ lcd_write_dat(data);
}
-void lcd_update(void)
+/* delays during lcd initialisation (for type 0 LCDs) */
+static void lcd_delay(int us)
+{
+ udelay(us);
+}
+
+/* initialises lcd type 0 */
+static void lcd_init_type0(void)
{
- /* TODO */
+ lcd_write(0x01, 0x00);
+ lcd_write(0x14, 0x01);
+ lcd_delay(5);
+
+ lcd_write(0x14, 0x00);
+ lcd_delay(5);
+
+ lcd_write(0x0F, 0x41);
+ lcd_write(0xEA, 0x0A);
+ lcd_write(0xEB, 0x42);
+ lcd_write(0x18, 0x08);
+ lcd_write(0x1A, 0x0B);
+ lcd_write(0x48, 0x03);
+
+ /* lcd width/height */
+ lcd_write(0x30, 0x00);
+ lcd_write(0x31, 0x5F);
+ lcd_write(0x32, 0x00);
+ lcd_write(0x33, 0x5F);
+
+ lcd_write(0xE0, 0x10);
+ lcd_write(0xE1, 0x00);
+ lcd_write(0xE5, 0x00);
+ lcd_write(0x0D, 0x00);
+ lcd_write(0x1D, 0x01);
+ lcd_write(0x09, 0x00);
+ lcd_write(0x13, 0x00);
+ lcd_write(0x16, 0x05);
+ lcd_write(0x3A, 0x03);
+ lcd_write(0x3B, 0x03);
+ lcd_write(0x3C, 0x03);
+ lcd_write(0x3D, 0x45);
+ lcd_write(0x3E, 0x45);
+ lcd_write(0x3F, 0x45);
+ lcd_write(0x40, 0x62);
+ lcd_write(0x41, 0x3D);
+ lcd_write(0x42, 0x46);
+}
+
+/* writes a table entry (for type 1 LCDs) */
+static void lcd_write_table(uint8_t val)
+{
+ lcd_write_dat((val >> 4) & 0x07);
+ lcd_write_dat((val >> 0) & 0x0F);
+}
+
+/* initialises lcd type 1 */
+static void lcd_init_type1(void)
+{
+ static const uint8_t curve[256] = {
+ /* 5-bit curve */
+ 0, 5, 10, 15, 20, 25, 30, 35, 39, 43, 47, 51, 55, 59, 63, 67,
+ 71, 75, 79, 83, 87, 91, 95, 99, 103, 105, 109, 113, 117, 121, 123, 127,
+ /* 6-bit curve */
+ 0, 2, 4, 6, 8, 10, 12, 16, 18, 24, 26, 28, 30, 32, 34, 36,
+ 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68,
+ 70, 72, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118, 120, 121, 122, 123, 124, 125, 126, 127,
+ /* 5-bit curve */
+ 0, 5, 10, 15, 20, 25, 30, 35, 39, 43, 47, 51, 55, 59, 63, 67,
+ 71, 75, 79, 83, 87, 91, 93, 97, 101, 105, 109, 113, 117, 121, 124, 127
+ };
+ int i;
+
+ lcd_write_cmd(0x02);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x01);
+
+ lcd_write_cmd(0x03);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x04);
+ lcd_write_dat(0x03);
+
+ lcd_write_cmd(0x05);
+ lcd_write_dat(0x08);
+
+ lcd_write_cmd(0x06);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x07);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x04);
+ lcd_write_dat(0x1F);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x05);
+ lcd_write_dat(0x0F);
+
+ lcd_write_cmd(0x08);
+ lcd_write_dat(0x01);
+
+ lcd_write_cmd(0x09);
+ lcd_write_dat(0x07);
+
+ /* lcd width/height */
+ lcd_write_cmd(0x0A);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x05);
+ lcd_write_dat(0x0F);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x05);
+ lcd_write_dat(0x0F);
+
+ lcd_write_cmd(0x0B);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x0E);
+ lcd_write_dat(0x04);
+ lcd_write_dat(0x02);
+ lcd_write_dat(0x02);
+ lcd_write_dat(0x05);
+ lcd_write_dat(0x03);
+ lcd_write_dat(0x0F);
+
+ lcd_write_cmd(0x0F);
+ lcd_write_dat(0x0A);
+ lcd_write_dat(0x0A);
+ lcd_write_dat(0x0A);
+
+ lcd_write_cmd(0x1C);
+ lcd_write_dat(0x08);
+
+ lcd_write_cmd(0x1D);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x1E);
+ lcd_write_dat(0x05);
+
+ lcd_write_cmd(0x1F);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x30);
+ lcd_write_dat(0x10);
+
+ lcd_write_cmd(0x3A);
+ for (i = 0; i < 256; i++) {
+ lcd_write_table(curve[i]);
+ }
+
+ lcd_write_cmd(0x3C);
+ lcd_write_dat(0x00);
+
+ lcd_write_cmd(0x3D);
+ lcd_write_dat(0x00);
}
+/* initialises the lcd */
void lcd_init_device(void)
{
- /* TODO */
- display_type = lcd_hw_init();
+ lcd_type = lcd_hw_init();
+ if (lcd_type == 0) {
+ lcd_init_type0();
+ }
+ else {
+ lcd_init_type1();
+ }
}
-/* Update a fraction of the display. */
+/* sets up the lcd to receive frame buffer data */
+static void lcd_setup_rect(int x, int x_end, int y, int y_end)
+{
+ if (lcd_type == 0) {
+ lcd_write(0x34, x);
+ lcd_write(0x35, x_end);
+ lcd_write(0x36, y);
+ lcd_write(0x37, y_end);
+ }
+ else {
+ lcd_write_cmd(0x0A);
+ lcd_write_dat((x >> 8) & 0xFF);
+ lcd_write_dat((x >> 0) & 0xFF);
+ lcd_write_dat((x_end >> 8) & 0xFF);
+ lcd_write_dat((x_end >> 0) & 0xFF);
+ lcd_write_dat((y >> 8) & 0xFF);
+ lcd_write_dat((y >> 0) & 0xFF);
+ lcd_write_dat((y_end >> 8) & 0xFF);
+ lcd_write_dat((y_end >> 0) & 0xFF);
+ }
+}
+
+/* Updates 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;
-
- /* TODO not implemented yet, do a full update instead */
- lcd_update();
+ fb_data *ptr;
+ fb_data pixel;
+ int row, col;
+ int x_end = x + width - 1;
+ int y_end = y + height - 1;
+
+ /* check/correct bounds */
+ CLAMP(x, 0, LCD_WIDTH - 1);
+ CLAMP(x_end, 0, LCD_WIDTH - 1);
+ CLAMP(y, 0, LCD_HEIGHT - 1);
+ CLAMP(y_end, 0, LCD_HEIGHT - 1);
+ if ((x > x_end) || (y > y_end)) {
+ return;
+ }
+
+ /* setup GRAM write window */
+ lcd_setup_rect(x, x_end, y, y_end);
+
+ /* write to GRAM */
+ lcd_write_cmd((lcd_type == 0) ? 0x08 : 0x0C);
+ for (row = y; row <= y_end; row++) {
+ ptr = &lcd_framebuffer[row][x];
+ for (col = x; col <= x_end; col++) {
+ pixel = *ptr++;
+ lcd_write_dat((pixel >> 8) & 0xFF);
+ lcd_write_dat((pixel >> 0) & 0xFF);
+ }
+ }
+}
+
+/* updates the entire lcd */
+void lcd_update(void)
+{
+ lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
}