1 /* 2 * FB driver for the UC1701 LCD Controller 3 * 4 * The display is monochrome and the video memory is RGB565. 5 * Any pixel value except 0 turns the pixel on. 6 * 7 * Copyright (C) 2014 Juergen Holzmann 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20 #include <linux/module.h> 21 #include <linux/kernel.h> 22 #include <linux/init.h> 23 #include <linux/gpio.h> 24 #include <linux/spi/spi.h> 25 #include <linux/delay.h> 26 27 #include "fbtft.h" 28 29 #define DRVNAME "fb_uc1701" 30 #define WIDTH 102 31 #define HEIGHT 64 32 #define PAGES (HEIGHT/8) 33 34 /* 1: Display on/off */ 35 #define LCD_DISPLAY_ENABLE 0xAE 36 /* 2: display start line set */ 37 #define LCD_START_LINE 0x40 38 /* 3: Page address set (lower 4 bits select one of the pages) */ 39 #define LCD_PAGE_ADDRESS 0xB0 40 /* 4: column address */ 41 #define LCD_COL_ADDRESS 0x10 42 /* 8: select orientation */ 43 #define LCD_BOTTOMVIEW 0xA0 44 /* 9: inverted display */ 45 #define LCD_DISPLAY_INVERT 0xA6 46 /* 10: show memory content or switch all pixels on */ 47 #define LCD_ALL_PIXEL 0xA4 48 /* 11: lcd bias set */ 49 #define LCD_BIAS 0xA2 50 /* 14: Reset Controller */ 51 #define LCD_RESET_CMD 0xE2 52 /* 15: output mode select (turns display upside-down) */ 53 #define LCD_SCAN_DIR 0xC0 54 /* 16: power control set */ 55 #define LCD_POWER_CONTROL 0x28 56 /* 17: voltage regulator resistor ratio set */ 57 #define LCD_VOLTAGE 0x20 58 /* 18: Volume mode set */ 59 #define LCD_VOLUME_MODE 0x81 60 /* 22: NOP command */ 61 #define LCD_NO_OP 0xE3 62 /* 25: advanced program control */ 63 #define LCD_ADV_PROG_CTRL 0xFA 64 /* 25: advanced program control2 */ 65 #define LCD_ADV_PROG_CTRL2 0x10 66 #define LCD_TEMPCOMP_HIGH 0x80 67 /* column offset for normal orientation */ 68 #define SHIFT_ADDR_NORMAL 0 69 /* column offset for bottom view orientation */ 70 #define SHIFT_ADDR_TOPVIEW 30 71 72 73 static int init_display(struct fbtft_par *par) 74 { 75 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); 76 77 par->fbtftops.reset(par); 78 79 /* softreset of LCD */ 80 write_reg(par, LCD_RESET_CMD); 81 mdelay(10); 82 83 /* set startpoint */ 84 /* LCD_START_LINE | (pos & 0x3F) */ 85 write_reg(par, LCD_START_LINE); 86 87 /* select orientation BOTTOMVIEW */ 88 write_reg(par, LCD_BOTTOMVIEW | 1); 89 /* output mode select (turns display upside-down) */ 90 write_reg(par, LCD_SCAN_DIR | 0x00); 91 92 /* Normal Pixel mode */ 93 write_reg(par, LCD_ALL_PIXEL | 0); 94 95 /* positive display */ 96 write_reg(par, LCD_DISPLAY_INVERT | 0); 97 98 /* bias 1/9 */ 99 write_reg(par, LCD_BIAS | 0); 100 101 /* power control mode: all features on */ 102 /* LCD_POWER_CONTROL | (val&0x07) */ 103 write_reg(par, LCD_POWER_CONTROL | 0x07); 104 105 /* set voltage regulator R/R */ 106 /* LCD_VOLTAGE | (val&0x07) */ 107 write_reg(par, LCD_VOLTAGE | 0x07); 108 109 /* volume mode set */ 110 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ 111 write_reg(par, LCD_VOLUME_MODE); 112 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ 113 write_reg(par, 0x09); 114 /* ???? */ 115 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ 116 write_reg(par, LCD_NO_OP); 117 118 /* advanced program control */ 119 write_reg(par, LCD_ADV_PROG_CTRL); 120 write_reg(par, LCD_ADV_PROG_CTRL2|LCD_TEMPCOMP_HIGH); 121 122 /* enable display */ 123 write_reg(par, LCD_DISPLAY_ENABLE | 1); 124 125 return 0; 126 } 127 128 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) 129 { 130 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); 131 132 /* goto address */ 133 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 134 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 135 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 136 write_reg(par, LCD_PAGE_ADDRESS); 137 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 138 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 139 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 140 write_reg(par, 0x00); 141 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 142 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 143 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 144 write_reg(par, LCD_COL_ADDRESS); 145 } 146 147 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) 148 { 149 u16 *vmem16 = (u16 *)par->info->screen_base; 150 u8 *buf = par->txbuf.buf; 151 int x, y, i; 152 int ret = 0; 153 154 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); 155 156 for (y = 0; y < PAGES; y++) { 157 buf = par->txbuf.buf; 158 for (x = 0; x < WIDTH; x++) { 159 *buf = 0x00; 160 for (i = 0; i < 8; i++) 161 *buf |= (vmem16[((y*8*WIDTH)+(i*WIDTH))+x] ? 1 : 0) << i; 162 buf++; 163 } 164 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 165 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 166 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 167 write_reg(par, LCD_PAGE_ADDRESS|(u8)y); 168 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 169 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 170 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 171 write_reg(par, 0x00); 172 /* LCD_PAGE_ADDRESS | ((page) & 0x1F), 173 (((col)+SHIFT_ADDR_NORMAL) & 0x0F), 174 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ 175 write_reg(par, LCD_COL_ADDRESS); 176 gpio_set_value(par->gpio.dc, 1); 177 ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); 178 gpio_set_value(par->gpio.dc, 0); 179 } 180 181 if (ret < 0) 182 dev_err(par->info->device, "write failed and returned: %d\n", 183 ret); 184 185 return ret; 186 } 187 188 189 static struct fbtft_display display = { 190 .regwidth = 8, 191 .width = WIDTH, 192 .height = HEIGHT, 193 .fbtftops = { 194 .init_display = init_display, 195 .set_addr_win = set_addr_win, 196 .write_vmem = write_vmem, 197 }, 198 .backlight = 1, 199 }; 200 FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display); 201 202 MODULE_ALIAS("spi:" DRVNAME); 203 MODULE_ALIAS("spi:uc1701"); 204 205 MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller"); 206 MODULE_AUTHOR("Juergen Holzmann"); 207 MODULE_LICENSE("GPL"); 208