197 lines
5.6 KiB
C
197 lines
5.6 KiB
C
/* Framebuffer implementation - SSD1963 (S1D15G14 clone) LCD driver for J100i */
|
|
/* Based on ssd1963.c by Steve Markgraf and Harald Welte */
|
|
|
|
/* (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
|
|
* (C) 2012 by Steve Markgraf <steve@steve-m.de>
|
|
*
|
|
* All Rights Reserved
|
|
*
|
|
* 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 program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
#include <fb/framebuffer.h>
|
|
#include <fb/fb_rgb332.h>
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <delay.h>
|
|
#include <uwire.h>
|
|
#include <calypso/clock.h>
|
|
|
|
#define SSD1963_WIDTH 96
|
|
#define SSD1963_HEIGHT 64
|
|
#define SSD1963_UWIRE_BITLEN 9
|
|
#define SSD1963_DEV_ID 0
|
|
|
|
static uint8_t fb_ssd1963_mem[SSD1963_WIDTH * SSD1963_HEIGHT];
|
|
|
|
enum ssd1963_cmdflag { CMD, DATA, END };
|
|
|
|
struct ssd1963_cmdlist {
|
|
enum ssd1963_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */
|
|
uint8_t data; /* 8 bit to send to LC display */
|
|
} __attribute__((packed));
|
|
|
|
static const struct ssd1963_cmdlist
|
|
ssd1963_initdata[] = {
|
|
{ CMD, 0xb6 }, /* CMD Display Control, set panel parameters */
|
|
{ DATA, 0x4b },
|
|
{ DATA, 0xf1 },
|
|
{ DATA, 0x40 },
|
|
{ DATA, 0x40 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x8c },
|
|
{ DATA, 0x00 },
|
|
{ CMD, 0x3a }, /* CMD Set pixel format */
|
|
{ DATA, 0x02 }, /* DATA: 8 bit per pixel */
|
|
{ CMD, 0x2d }, /* Colour set, RGB332 -> RGB 565 mapping */
|
|
{ DATA, 0x00 }, /* DATA red 000 */
|
|
{ DATA, 0x04 }, /* DATA red 001 */
|
|
{ DATA, 0x09 }, /* DATA red 010 */
|
|
{ DATA, 0x0d }, /* DATA red 011 */
|
|
{ DATA, 0x12 }, /* DATA red 100 */
|
|
{ DATA, 0x16 }, /* DATA red 101 */
|
|
{ DATA, 0x1b }, /* DATA red 110 */
|
|
{ DATA, 0x1f }, /* DATA red 111 */
|
|
{ DATA, 0x00 }, /* Those bytes are probably a second palette */
|
|
{ DATA, 0x00 }, /* for an unused powersaving mode with reduced colors */
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 }, /* DATA green 000 */
|
|
{ DATA, 0x09 }, /* DATA green 001 */
|
|
{ DATA, 0x12 }, /* DATA green 010 */
|
|
{ DATA, 0x1b }, /* DATA green 011 */
|
|
{ DATA, 0x24 }, /* DATA green 100 */
|
|
{ DATA, 0x2d }, /* DATA green 101 */
|
|
{ DATA, 0x36 }, /* DATA green 110 */
|
|
{ DATA, 0x3f }, /* DATA green 111 */
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 }, /* DATA blue 00 */
|
|
{ DATA, 0x0a }, /* DATA blue 01 */
|
|
{ DATA, 0x15 }, /* DATA blue 10 */
|
|
{ DATA, 0x1f }, /* DATA blue 11 */
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ DATA, 0x00 },
|
|
{ CMD, 0x11 }, /* CMD Exit sleep mode*/
|
|
{ CMD, 0xba }, /* CMD Set contrast/Electronic Volume Control */
|
|
{ DATA, 0x5b }, /* DATA: */
|
|
{ DATA, 0x84 }, /* DATA: */
|
|
{ CMD, 0x36 }, /* CMD Memory access control */
|
|
{ DATA, 0x00 }, /* DATA: */
|
|
{ CMD, 0x13 }, /* CMD Enter normal mode */
|
|
{ CMD, 0x29 }, /* CMD Set display on */
|
|
{ END, 0x00 }, /* MARKER: end of list */
|
|
};
|
|
|
|
static void
|
|
fb_ssd1963_send_cmdlist(const struct ssd1963_cmdlist *p) {
|
|
int i=0;
|
|
while(p->is_cmd != END){
|
|
uint16_t sendcmd = p->data;
|
|
if(p->is_cmd == DATA)
|
|
sendcmd |= 0x0100; /* 9th bit is cmd/data flag */
|
|
uwire_xfer(SSD1963_DEV_ID, SSD1963_UWIRE_BITLEN, &sendcmd, NULL);
|
|
p++;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fb_ssd1963_init(void){
|
|
printf("%s: initializing LCD.\n",__FUNCTION__);
|
|
calypso_reset_set(RESET_EXT, 0);
|
|
delay_ms(5);
|
|
uwire_init();
|
|
delay_ms(5);
|
|
fb_ssd1963_send_cmdlist(ssd1963_initdata);
|
|
}
|
|
|
|
static void
|
|
fb_ssd1963_flush(void){
|
|
int x,y;
|
|
uint8_t *p;
|
|
struct ssd1963_cmdlist prepare_disp_write_cmds[] = {
|
|
{ CMD, 0x2a }, /* set column address */
|
|
{ DATA, fb_rgb332->damage_x1 },
|
|
{ DATA, fb_rgb332->damage_x2-1 },
|
|
{ CMD, 0x2b }, /* set page address (Y) */
|
|
{ DATA, fb_rgb332->damage_y1 },
|
|
{ DATA, fb_rgb332->damage_y2-1 },
|
|
{ CMD, 0x2c }, /* enter write display ram mode */
|
|
{ END, 0x00 }
|
|
};
|
|
struct ssd1963_cmdlist nop[] = {
|
|
{ CMD, 0x00 }, // NOP command
|
|
{ END, 0x00 }
|
|
};
|
|
|
|
/* If everything's clean, just return */
|
|
if(fb_rgb332->damage_x1 == fb_rgb332->damage_x2 ||
|
|
fb_rgb332->damage_y1 == fb_rgb332->damage_y2) {
|
|
printf("%s: no damage\n",__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
fb_ssd1963_send_cmdlist(prepare_disp_write_cmds);
|
|
|
|
for(y=fb_rgb332->damage_y1;y<fb_rgb332->damage_y2;y++) {
|
|
p = & fb_rgb332->mem[y * framebuffer->width]; // start of line
|
|
p += fb_rgb332->damage_x1; // start of damage area
|
|
|
|
for(x=fb_rgb332->damage_x1;x<fb_rgb332->damage_x2;x++) {
|
|
uint16_t data = 0x0100 | *p++;
|
|
uwire_xfer(SSD1963_DEV_ID, SSD1963_UWIRE_BITLEN,
|
|
&data, NULL);
|
|
}
|
|
}
|
|
fb_ssd1963_send_cmdlist(nop);
|
|
|
|
fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
|
|
fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
|
|
}
|
|
|
|
static struct framebuffer fb_ssd1963_framebuffer = {
|
|
.name = "ssd1963",
|
|
.init = fb_ssd1963_init,
|
|
.clear = fb_rgb332_clear,
|
|
.boxto = fb_rgb332_boxto,
|
|
.lineto = fb_rgb332_lineto,
|
|
.putstr = fb_rgb332_putstr,
|
|
.flush = fb_ssd1963_flush,
|
|
.width = SSD1963_WIDTH,
|
|
.height = SSD1963_HEIGHT
|
|
};
|
|
|
|
static struct fb_rgb332 fb_ssd1963_rgb332 = {
|
|
.mem = fb_ssd1963_mem
|
|
};
|
|
|
|
struct framebuffer *framebuffer = &fb_ssd1963_framebuffer;
|
|
struct fb_rgb332 *fb_rgb332 = &fb_ssd1963_rgb332;
|