summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/fb
diff options
context:
space:
mode:
authorSteve Markgraf <steve@steve-m.de>2012-01-30 18:18:56 +0100
committerHarald Welte <laforge@gnumonks.org>2012-02-03 23:59:36 +0100
commit533d5e6dc40946375b7582c08e56b6f8f1c839b6 (patch)
treeddeee517915789c652f4fcbd587f6b64d43c539e /src/target/firmware/fb
parent4284a90a2a8dc8220fb15a15fd8793e4ae1a2121 (diff)
firmware/fb: add framebuffer driver for J100i display
Signed-off-by: Steve Markgraf <steve@steve-m.de>
Diffstat (limited to 'src/target/firmware/fb')
-rw-r--r--src/target/firmware/fb/fb_ssd1963.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/target/firmware/fb/fb_ssd1963.c b/src/target/firmware/fb/fb_ssd1963.c
new file mode 100644
index 00000000..361434e4
--- /dev/null
+++ b/src/target/firmware/fb/fb_ssd1963.c
@@ -0,0 +1,196 @@
+/* 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;