osmocom-bb/src/target/firmware/fb/fb_st7558.c

130 lines
3.5 KiB
C

/* Framebuffer implementation - ST1783 LCD driver for C123 */
/* Based on st7558.c by Harald Welte */
/* (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.
*
*/
#include <fb/framebuffer.h>
#include <fb/fb_bw8.h>
#include <i2c.h>
#include <calypso/clock.h>
#include <delay.h>
#include <stdio.h>
/* Sitronix ST7558 LCD Driver for OSMOCOM framebuffer interface. */
/* (c) 2010 Christian Vogel <vogelchr@vogel.cx> */
/* Based on the initial LCD driver by Harald Welte */
#define CONTROL_RS_CMD
#define ST7558_SLAVE_ADDR 0x3c
#define ST7558_CMD_ADDR 0x00
#define ST7558_RAM_ADDR 0x40
#define ST7558_WIDTH 96 /* in pixels */
#define ST7558_HEIGHT 65
#define I2C_MAX_TRANSFER 16
static uint8_t
fb_st7558_mem[ST7558_WIDTH * ((ST7558_HEIGHT+7)/8)];
/* setup as initially proposed by Harald in st7558.c */
static const uint8_t st7558_setup[] = {
0x2e, /* ext. display control, set mirror X, set mirror Y*/
0x21, /* function set, enable extended instruction mode */
0x12, /* bias system BS[2,1,0] = [0,1,0] */
0xc0, /* set V_OP (V_OP6 = 1, V_OP[5:0] = 0) */
0x0b, /* booster stages PC1=1, PC0=1 */
0x20, /* function set, disable extended instruction mode */
0x11, /* V_LCD L/H select, PRS=1 */
0x00, /* NOP */
0x0c, /* normal video mode */
0x40, /* set X address to 0 */
0x80 /* set Y address to 0 */
};
static void
fb_st7558_init(){
calypso_reset_set(RESET_EXT, 0);
i2c_init(0,0);
/* initialize controller */
i2c_write(ST7558_SLAVE_ADDR,ST7558_CMD_ADDR,1,
st7558_setup,sizeof(st7558_setup));
}
static void
fb_st7558_flush(){
uint16_t x;
int page,chunksize,nbytes;
uint8_t *p;
uint8_t cmd[2];
if(fb_bw8->damage_y1 == fb_bw8->damage_y2 ||
fb_bw8->damage_x1 == fb_bw8->damage_x2)
return; /* nothing to update */
/* update display in stripes of 8 rows, called "pages" */
for(page=fb_bw8->damage_y1 >> 3;page <= fb_bw8->damage_y2>>3;page++){
/* base offset in RAM framebuffer */
x = fb_bw8->damage_x1;
nbytes = fb_bw8->damage_x2 - fb_bw8->damage_x1;
p = fb_bw8->mem + (page * framebuffer->width + x);
/* i2c fifo can only handle a maximum of 16 bytes */
while(nbytes){
cmd[0]=0x40 | page; /* Set Y address of RAM. */
cmd[1]=0x80 | x;
chunksize = nbytes > I2C_MAX_TRANSFER ? I2C_MAX_TRANSFER : nbytes;
i2c_write(ST7558_SLAVE_ADDR,ST7558_CMD_ADDR,1,cmd,sizeof(cmd));
i2c_write(ST7558_SLAVE_ADDR,ST7558_RAM_ADDR,1,p,chunksize);
nbytes -= chunksize;
p+=I2C_MAX_TRANSFER;
x+=I2C_MAX_TRANSFER;
}
}
/* mark current buffer as unmodified! */
fb_bw8->damage_x1 = fb_bw8->damage_x2 = 0;
fb_bw8->damage_y1 = fb_bw8->damage_y2 = 0;
}
static struct framebuffer fb_st7558_framebuffer = {
.name = "st7558",
.init = fb_st7558_init,
.clear = fb_bw8_clear,
.boxto = fb_bw8_boxto,
.lineto = fb_bw8_lineto,
.set_p = fb_bw8_set_p,
.putstr = fb_bw8_putstr,
.flush = fb_st7558_flush,
.width = ST7558_WIDTH,
.height = ST7558_HEIGHT
};
static struct fb_bw8 fb_st7558_bw8 = {
.mem = fb_st7558_mem
};
struct framebuffer *framebuffer = &fb_st7558_framebuffer;
struct fb_bw8 *fb_bw8 = &fb_st7558_bw8;