]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/fbtft/fb_uc1701.c
Merge tag 'pm+acpi-4.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / fbtft / fb_uc1701.c
CommitLineData
5741ecd6
TP
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 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/init.h>
27#include <linux/gpio.h>
28#include <linux/spi/spi.h>
29#include <linux/delay.h>
30
31#include "fbtft.h"
32
33#define DRVNAME "fb_uc1701"
34#define WIDTH 102
35#define HEIGHT 64
36#define PAGES (HEIGHT/8)
37
38/* 1: Display on/off */
39#define LCD_DISPLAY_ENABLE 0xAE
40/* 2: display start line set */
41#define LCD_START_LINE 0x40
42/* 3: Page address set (lower 4 bits select one of the pages) */
43#define LCD_PAGE_ADDRESS 0xB0
44/* 4: column address */
45#define LCD_COL_ADDRESS 0x10
46/* 8: select orientation */
47#define LCD_BOTTOMVIEW 0xA0
48/* 9: inverted display */
49#define LCD_DISPLAY_INVERT 0xA6
50/* 10: show memory content or switch all pixels on */
51#define LCD_ALL_PIXEL 0xA4
52/* 11: lcd bias set */
53#define LCD_BIAS 0xA2
54/* 14: Reset Controller */
55#define LCD_RESET_CMD 0xE2
56/* 15: output mode select (turns display upside-down) */
57#define LCD_SCAN_DIR 0xC0
58/* 16: power control set */
59#define LCD_POWER_CONTROL 0x28
60/* 17: voltage regulator resistor ratio set */
61#define LCD_VOLTAGE 0x20
62/* 18: Volume mode set */
63#define LCD_VOLUME_MODE 0x81
64/* 22: NOP command */
65#define LCD_NO_OP 0xE3
66/* 25: advanced program control */
67#define LCD_ADV_PROG_CTRL 0xFA
68/* 25: advanced program control2 */
69#define LCD_ADV_PROG_CTRL2 0x10
70#define LCD_TEMPCOMP_HIGH 0x80
71/* column offset for normal orientation */
72#define SHIFT_ADDR_NORMAL 0
73/* column offset for bottom view orientation */
74#define SHIFT_ADDR_TOPVIEW 30
75
76
77static int init_display(struct fbtft_par *par)
78{
79 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
80
81 par->fbtftops.reset(par);
82
83 /* softreset of LCD */
84 write_reg(par, LCD_RESET_CMD);
85 mdelay(10);
86
87 /* set startpoint */
88 /* LCD_START_LINE | (pos & 0x3F) */
89 write_reg(par, LCD_START_LINE);
90
91 /* select orientation BOTTOMVIEW */
92 write_reg(par, LCD_BOTTOMVIEW | 1);
93 /* output mode select (turns display upside-down) */
94 write_reg(par, LCD_SCAN_DIR | 0x00);
95
96 /* Normal Pixel mode */
97 write_reg(par, LCD_ALL_PIXEL | 0);
98
99 /* positive display */
100 write_reg(par, LCD_DISPLAY_INVERT | 0);
101
102 /* bias 1/9 */
103 write_reg(par, LCD_BIAS | 0);
104
105 /* power control mode: all features on */
106 /* LCD_POWER_CONTROL | (val&0x07) */
107 write_reg(par, LCD_POWER_CONTROL | 0x07);
108
109 /* set voltage regulator R/R */
110 /* LCD_VOLTAGE | (val&0x07) */
111 write_reg(par, LCD_VOLTAGE | 0x07);
112
113 /* volume mode set */
114 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
115 write_reg(par, LCD_VOLUME_MODE);
116 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
117 write_reg(par, 0x09);
118 /* ???? */
119 /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */
120 write_reg(par, LCD_NO_OP);
121
122 /* advanced program control */
123 write_reg(par, LCD_ADV_PROG_CTRL);
124 write_reg(par, LCD_ADV_PROG_CTRL2|LCD_TEMPCOMP_HIGH);
125
126 /* enable display */
127 write_reg(par, LCD_DISPLAY_ENABLE | 1);
128
129 return 0;
130}
131
132static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
133{
134 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
135
136 /* goto 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, LCD_PAGE_ADDRESS);
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, 0x00);
145 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
146 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
147 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
148 write_reg(par, LCD_COL_ADDRESS);
149}
150
151static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
152{
153 u16 *vmem16 = (u16 *)par->info->screen_base;
154 u8 *buf = par->txbuf.buf;
155 int x, y, i;
156 int ret = 0;
157
158 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__);
159
160 for (y = 0; y < PAGES; y++) {
161 buf = par->txbuf.buf;
162 for (x = 0; x < WIDTH; x++) {
163 *buf = 0x00;
164 for (i = 0; i < 8; i++)
165 *buf |= (vmem16[((y*8*WIDTH)+(i*WIDTH))+x] ? 1 : 0) << i;
166 buf++;
167 }
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, LCD_PAGE_ADDRESS|(u8)y);
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, 0x00);
176 /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
177 (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
178 LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
179 write_reg(par, LCD_COL_ADDRESS);
180 gpio_set_value(par->gpio.dc, 1);
181 ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
182 gpio_set_value(par->gpio.dc, 0);
183 }
184
185 if (ret < 0)
aed1c72e
HM
186 dev_err(par->info->device, "write failed and returned: %d\n",
187 ret);
5741ecd6
TP
188
189 return ret;
190}
191
192
193static struct fbtft_display display = {
194 .regwidth = 8,
195 .width = WIDTH,
196 .height = HEIGHT,
197 .fbtftops = {
198 .init_display = init_display,
199 .set_addr_win = set_addr_win,
200 .write_vmem = write_vmem,
201 },
202 .backlight = 1,
203};
204FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display);
205
206MODULE_ALIAS("spi:" DRVNAME);
207MODULE_ALIAS("spi:uc1701");
208
209MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller");
210MODULE_AUTHOR("Juergen Holzmann");
211MODULE_LICENSE("GPL");