Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / fbtft / fb_uc1701.c
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
77 static 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
132 static 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
151 static 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)
186                 dev_err(par->info->device, "write failed and returned: %d\n",
187                         ret);
188
189         return ret;
190 }
191
192
193 static 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 };
204 FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display);
205
206 MODULE_ALIAS("spi:" DRVNAME);
207 MODULE_ALIAS("spi:uc1701");
208
209 MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller");
210 MODULE_AUTHOR("Juergen Holzmann");
211 MODULE_LICENSE("GPL");