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
init_display(struct fbtft_par * par)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 /* LCD_START_LINE | (pos & 0x3F) */
82 write_reg(par, LCD_START_LINE);
83
84 /* select orientation BOTTOMVIEW */
85 write_reg(par, LCD_BOTTOMVIEW | 1);
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 /* LCD_POWER_CONTROL | (val&0x07) */
100 write_reg(par, LCD_POWER_CONTROL | 0x07);
101
102 /* set voltage regulator R/R */
103 /* LCD_VOLTAGE | (val&0x07) */
104 write_reg(par, LCD_VOLTAGE | 0x07);
105
106 /* volume mode set */
107 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
108 write_reg(par, LCD_VOLUME_MODE);
109 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
110 write_reg(par, 0x09);
111 /* ???? */
112 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
113 write_reg(par, LCD_NO_OP);
114
115 /* advanced program control */
116 write_reg(par, LCD_ADV_PROG_CTRL);
117 write_reg(par, LCD_ADV_PROG_CTRL2 | LCD_TEMPCOMP_HIGH);
118
119 /* enable display */
120 write_reg(par, LCD_DISPLAY_ENABLE | 1);
121
122 return 0;
123 }
124
set_addr_win(struct fbtft_par * par,int xs,int ys,int xe,int ye)125 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
126 {
127 /* goto address */
128 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
129 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
130 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
131 write_reg(par, LCD_PAGE_ADDRESS);
132 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
133 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
134 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
135 write_reg(par, 0x00);
136 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
137 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
138 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
139 write_reg(par, LCD_COL_ADDRESS);
140 }
141
write_vmem(struct fbtft_par * par,size_t offset,size_t len)142 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
143 {
144 u16 *vmem16 = (u16 *)par->info->screen_buffer;
145 u8 *buf = par->txbuf.buf;
146 int x, y, i;
147 int ret = 0;
148
149 for (y = 0; y < PAGES; y++) {
150 buf = par->txbuf.buf;
151 for (x = 0; x < WIDTH; x++) {
152 *buf = 0x00;
153 for (i = 0; i < 8; i++)
154 *buf |= (vmem16[((y * 8 * WIDTH) +
155 (i * WIDTH)) + x] ?
156 1 : 0) << i;
157 buf++;
158 }
159 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
160 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
161 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
162 write_reg(par, LCD_PAGE_ADDRESS | (u8)y);
163 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
164 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
165 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
166 write_reg(par, 0x00);
167 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
168 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
169 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
170 write_reg(par, LCD_COL_ADDRESS);
171 gpio_set_value(par->gpio.dc, 1);
172 ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
173 gpio_set_value(par->gpio.dc, 0);
174 }
175
176 if (ret < 0)
177 dev_err(par->info->device, "write failed and returned: %d\n",
178 ret);
179
180 return ret;
181 }
182
183 static struct fbtft_display display = {
184 .regwidth = 8,
185 .width = WIDTH,
186 .height = HEIGHT,
187 .fbtftops = {
188 .init_display = init_display,
189 .set_addr_win = set_addr_win,
190 .write_vmem = write_vmem,
191 },
192 .backlight = 1,
193 };
194
195 FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display);
196
197 MODULE_ALIAS("spi:" DRVNAME);
198 MODULE_ALIAS("spi:uc1701");
199
200 MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller");
201 MODULE_AUTHOR("Juergen Holzmann");
202 MODULE_LICENSE("GPL");
203