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 static int init_display(struct fbtft_par *par) 73 { 74 par->fbtftops.reset(par); 75 76 /* softreset of LCD */ 77 write_reg(par, LCD_RESET_CMD); 78 mdelay(10); 79 80 /* set startpoint */ 81 write_reg(par, LCD_START_LINE); 82 83 /* select orientation BOTTOMVIEW */ 84 write_reg(par, LCD_BOTTOMVIEW | 1); 85 86 /* output mode select (turns display upside-down) */ 87 write_reg(par, LCD_SCAN_DIR | 0x00); 88 89 /* Normal Pixel mode */ 90 write_reg(par, LCD_ALL_PIXEL | 0); 91 92 /* positive display */ 93 write_reg(par, LCD_DISPLAY_INVERT | 0); 94 95 /* bias 1/9 */ 96 write_reg(par, LCD_BIAS | 0); 97 98 /* power control mode: all features on */ 99 write_reg(par, LCD_POWER_CONTROL | 0x07); 100 101 /* set voltage regulator R/R */ 102 write_reg(par, LCD_VOLTAGE | 0x07); 103 104 /* volume mode set */ 105 write_reg(par, LCD_VOLUME_MODE); 106 write_reg(par, 0x09); 107 write_reg(par, LCD_NO_OP); 108 109 /* advanced program control */ 110 write_reg(par, LCD_ADV_PROG_CTRL); 111 write_reg(par, LCD_ADV_PROG_CTRL2 | LCD_TEMPCOMP_HIGH); 112 113 /* enable display */ 114 write_reg(par, LCD_DISPLAY_ENABLE | 1); 115 116 return 0; 117 } 118 119 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) 120 { 121 /* goto address */ 122 write_reg(par, LCD_PAGE_ADDRESS); 123 write_reg(par, 0x00); 124 write_reg(par, LCD_COL_ADDRESS); 125 } 126 127 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) 128 { 129 u16 *vmem16 = (u16 *)par->info->screen_buffer; 130 u8 *buf = par->txbuf.buf; 131 int x, y, i; 132 int ret = 0; 133 134 for (y = 0; y < PAGES; y++) { 135 buf = par->txbuf.buf; 136 for (x = 0; x < WIDTH; x++) { 137 *buf = 0x00; 138 for (i = 0; i < 8; i++) 139 *buf |= (vmem16[((y * 8 * WIDTH) + 140 (i * WIDTH)) + x] ? 141 1 : 0) << i; 142 buf++; 143 } 144 145 write_reg(par, LCD_PAGE_ADDRESS | (u8)y); 146 write_reg(par, 0x00); 147 write_reg(par, LCD_COL_ADDRESS); 148 gpio_set_value(par->gpio.dc, 1); 149 ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); 150 gpio_set_value(par->gpio.dc, 0); 151 } 152 153 if (ret < 0) 154 dev_err(par->info->device, "write failed and returned: %d\n", 155 ret); 156 157 return ret; 158 } 159 160 static struct fbtft_display display = { 161 .regwidth = 8, 162 .width = WIDTH, 163 .height = HEIGHT, 164 .fbtftops = { 165 .init_display = init_display, 166 .set_addr_win = set_addr_win, 167 .write_vmem = write_vmem, 168 }, 169 .backlight = 1, 170 }; 171 172 FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display); 173 174 MODULE_ALIAS("spi:" DRVNAME); 175 MODULE_ALIAS("spi:uc1701"); 176 177 MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller"); 178 MODULE_AUTHOR("Juergen Holzmann"); 179 MODULE_LICENSE("GPL"); 180