summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/fb/fb_s6b33b1x.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/firmware/fb/fb_s6b33b1x.c')
-rw-r--r--src/target/firmware/fb/fb_s6b33b1x.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/target/firmware/fb/fb_s6b33b1x.c b/src/target/firmware/fb/fb_s6b33b1x.c
new file mode 100644
index 00000000..3629a101
--- /dev/null
+++ b/src/target/firmware/fb/fb_s6b33b1x.c
@@ -0,0 +1,193 @@
+/* Framebuffer implementation - combined Sunplus SPCA552E and
+ * Samsung S6B33B1X LCD driver - as used in the Pirelli DP-L10 */
+
+/* (C) 2012 by Steve Markgraf <steve@steve-m.de>
+ *
+ * based on fb_ssd1783.c:
+ * (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
+ *
+ * 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 <memory.h>
+
+#define S6B33B1X_WIDTH 128
+#define S6B33B1X_HEIGHT 128
+#define LCD_INVIS_X_PIXELS 4
+
+#define ARMIO_LATCH_OUT 0xfffe4802
+#define nCS4_ADDR 0x02800000
+
+static uint8_t fb_s6b33b1x_mem[S6B33B1X_WIDTH * S6B33B1X_HEIGHT];
+
+enum s6b33b1x_cmdflag { CMD, DATA, END };
+
+struct s6b33b1x_cmdlist {
+ enum s6b33b1x_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 s6b33b1x_cmdlist
+s6b33b1x_initdata[] = {
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x00 }, /* DATA: everything off */
+ { CMD, 0x02 }, /* CMD Oscillation Mode Set */
+ { DATA, 0x00 }, /* DATA: oscillator off */
+ { CMD, 0x2c }, /* CMD Standby Mode off */
+ { CMD, 0x50 }, /* CMD Display off */
+ { CMD, 0x02 }, /* CMD Oscillation Mode Set */
+ { DATA, 0x01 }, /* DATA: oscillator on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x01 }, /* DATA: Booster 1 on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x09 }, /* DATA: Booster 1 on, OP-AMP on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x0b }, /* DATA: Booster 1 + 2 on, OP-AMP on */
+ { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */
+ { DATA, 0x0f }, /* DATA: Booster 1 + 2 + 3 on, OP-AMP on */
+ { CMD, 0x20 }, /* CMD DC-DC Select */
+ { DATA, 0x01 }, /* DATA: step up x1.5 */
+ { CMD, 0x24 }, /* CMD DCDC Clock Division Set */
+ { DATA, 0x0a }, /* DATA: fPCK = fOSC/6 */
+ { CMD, 0x2a }, /* CMD Contrast Control */
+ { DATA, 0x2d }, /* DATA: default contrast */
+ { CMD, 0x30 }, /* CMD Adressing mode set */
+ { DATA, 0x0b }, /* DATA: 65536 color mode */
+ { CMD, 0x10 }, /* CMD Driver output mode set */
+ { DATA, 0x03 }, /* DATA: Display duty: 1/132 */
+ { CMD, 0x34 }, /* CMD N-line inversion set */
+ { DATA, 0x88 }, /* DATA: inversion on, one frame, every 8 blocks */
+ { CMD, 0x40 }, /* CMD Entry mode set */
+ { DATA, 0x00 }, /* DATA: Y address counter mode */
+ { CMD, 0x28 }, /* CMD Temperature Compensation set */
+ { DATA, 0x01 }, /* DATA: slope -0.05%/degC */
+ { CMD, 0x32 }, /* CMD ROW vector mode set */
+ { DATA, 0x01 }, /* DATA: every 2 subgroup */
+ { CMD, 0x51 }, /* CMD Display on */
+ { END, 0x00 }, /* MARKER: end of list */
+};
+
+static void fb_s6b33b1x_send_cmdlist(const struct s6b33b1x_cmdlist *p)
+{
+ while(p->is_cmd != END){
+ writew(p->data, nCS4_ADDR);
+ p++;
+ }
+}
+
+static void fb_spca_write(uint16_t addr, uint16_t val)
+{
+ writew(addr, nCS4_ADDR);
+ writew(val , nCS4_ADDR | 2);
+}
+
+static void fb_spca_init(void)
+{
+ uint16_t reg;
+
+ /* Initialize Sunplus SPCA552E Media Controller for bypass mode */
+ fb_spca_write(0x7e, 0x00); /* internal register access */
+ delay_ms(10);
+ fb_spca_write(0x7a, 0x00); /* keep CPU in reset state */
+ delay_ms(10);
+ fb_spca_write(0x7f, 0x00); /* select main page */
+ delay_ms(5);
+ fb_spca_write(0x72, 0x07); /* don't reshape timing, 16 bit mode */
+ fb_spca_write(0x14, 0x03);
+ fb_spca_write(0x7f, 0x00); /* select main page */
+ delay_ms(5);
+ fb_spca_write(0x06, 0xff);
+ fb_spca_write(0x7f, 0x09);
+ fb_spca_write(0x19, 0x08); /* backlight: 0x08 is on, 0x0c is off */
+ fb_spca_write(0x23, 0x18);
+
+ /* enable bypass mode */
+ reg = readw(ARMIO_LATCH_OUT);
+ reg |= (1 << 7);
+ writew(reg, ARMIO_LATCH_OUT);
+}
+
+static void fb_s6b33b1x_init(void)
+{
+ printf("%s: initializing LCD.\n",__FUNCTION__);
+
+ fb_spca_init();
+ fb_s6b33b1x_send_cmdlist(s6b33b1x_initdata);
+}
+
+static void fb_s6b33b1x_flush(void)
+{
+ int x,y;
+ uint8_t *p;
+ struct s6b33b1x_cmdlist prepare_disp_write_cmds[] = {
+ { CMD, 0x42 }, /* set column address */
+ { DATA, fb_rgb332->damage_x1 + LCD_INVIS_X_PIXELS },
+ { DATA, fb_rgb332->damage_x2 + LCD_INVIS_X_PIXELS - 1 },
+ { CMD, 0x43 }, /* set page address (Y) */
+ { DATA, fb_rgb332->damage_y1 },
+ { DATA, fb_rgb332->damage_y2 - 1 },
+ { 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_s6b33b1x_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 = rgb332_to_565(*p++);
+ writew(data , nCS4_ADDR | 2);
+ }
+ }
+
+ fb_rgb332->damage_x1 = fb_rgb332->damage_x2 = 0;
+ fb_rgb332->damage_y1 = fb_rgb332->damage_y2 = 0;
+}
+
+static struct framebuffer fb_s6b33b1x_framebuffer = {
+ .name = "s6b33b1x",
+ .init = fb_s6b33b1x_init,
+ .clear = fb_rgb332_clear,
+ .boxto = fb_rgb332_boxto,
+ .lineto = fb_rgb332_lineto,
+ .putstr = fb_rgb332_putstr,
+ .flush = fb_s6b33b1x_flush,
+ .width = S6B33B1X_WIDTH,
+ .height = S6B33B1X_HEIGHT
+};
+
+static struct fb_rgb332 fb_s6b33b1x_rgb332 = {
+ .mem = fb_s6b33b1x_mem
+};
+
+struct framebuffer *framebuffer = &fb_s6b33b1x_framebuffer;
+struct fb_rgb332 *fb_rgb332 = &fb_s6b33b1x_rgb332;