1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/init.h>
5 #include <linux/gpio/consumer.h>
6 #include <linux/spi/spi.h>
7 #include <linux/delay.h>
11 #define DRVNAME "fb_ssd1331"
16 #define DEFAULT_GAMMA "0 2 2 2 2 2 2 2 " \
25 static int init_display(struct fbtft_par *par)
27 par
->fbtftops
.reset(par
);
29 write_reg(par
, 0xae); /* Display Off */
31 /* Set Column Address Mapping, COM Scan Direction and Colour Depth */
32 if (par
->info
->var
.rotate
== 180)
33 write_reg(par
, 0xa0, 0x60 | (par
->bgr
<< 2));
35 write_reg(par
, 0xa0, 0x72 | (par
->bgr
<< 2));
37 write_reg(par
, 0x72); /* RGB colour */
38 write_reg(par
, 0xa1, 0x00); /* Set Display Start Line */
39 write_reg(par
, 0xa2, 0x00); /* Set Display Offset */
40 write_reg(par
, 0xa4); /* NORMALDISPLAY */
41 write_reg(par
, 0xa8, 0x3f); /* Set multiplex */
42 write_reg(par
, 0xad, 0x8e); /* Set master */
43 /* write_reg(par, 0xb0, 0x0b); Set power mode */
44 write_reg(par
, 0xb1, 0x31); /* Precharge */
45 write_reg(par
, 0xb3, 0xf0); /* Clock div */
46 write_reg(par
, 0x8a, 0x64); /* Precharge A */
47 write_reg(par
, 0x8b, 0x78); /* Precharge B */
48 write_reg(par
, 0x8c, 0x64); /* Precharge C */
49 write_reg(par
, 0xbb, 0x3a); /* Precharge level */
50 write_reg(par
, 0xbe, 0x3e); /* vcomh */
51 write_reg(par
, 0x87, 0x06); /* Master current */
52 write_reg(par
, 0x81, 0x91); /* Contrast A */
53 write_reg(par
, 0x82, 0x50); /* Contrast B */
54 write_reg(par
, 0x83, 0x7d); /* Contrast C */
55 write_reg(par
, 0xaf); /* Set Sleep Mode Display On */
60 static void set_addr_win(struct fbtft_par
*par
, int xs
, int ys
, int xe
, int ye
)
62 write_reg(par
, 0x15, xs
, xe
);
63 write_reg(par
, 0x75, ys
, ye
);
66 static void write_reg8_bus8(struct fbtft_par
*par
, int len
, ...)
72 if (unlikely(par
->debug
& DEBUG_WRITE_REGISTER
)) {
74 for (i
= 0; i
< len
; i
++)
75 buf
[i
] = (u8
)va_arg(args
, unsigned int);
77 fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER
, par
, par
->info
->device
,
78 u8
, buf
, len
, "%s: ", __func__
);
83 *buf
= (u8
)va_arg(args
, unsigned int);
84 gpiod_set_value(par
->gpio
.dc
, 0);
85 ret
= par
->fbtftops
.write(par
, par
->buf
, sizeof(u8
));
88 dev_err(par
->info
->device
,
89 "write() failed and returned %d\n", ret
);
97 *buf
++ = (u8
)va_arg(args
, unsigned int);
98 ret
= par
->fbtftops
.write(par
, par
->buf
, len
* (sizeof(u8
)));
101 dev_err(par
->info
->device
,
102 "write() failed and returned %d\n", ret
);
106 gpiod_set_value(par
->gpio
.dc
, 1);
111 * Grayscale Lookup Table
113 * The driver Gamma curve contains the relative values between the entries
114 * in the Lookup table.
117 * 8.8 Gray Scale Decoder
119 * there are total 180 Gamma Settings (Setting 0 to Setting 180)
120 * available for the Gray Scale table.
122 * The gray scale is defined in incremental way, with reference
123 * to the length of previous table entry:
124 * Setting of GS1 has to be >= 0
125 * Setting of GS2 has to be > Setting of GS1 +1
126 * Setting of GS3 has to be > Setting of GS2 +1
128 * Setting of GS63 has to be > Setting of GS62 +1
131 static int set_gamma(struct fbtft_par
*par
, u32
*curves
)
133 unsigned long tmp
[GAMMA_NUM
* GAMMA_LEN
];
136 for (i
= 0; i
< 63; i
++) {
137 if (i
> 0 && curves
[i
] < 2) {
138 dev_err(par
->info
->device
,
139 "Illegal value in Grayscale Lookup Table at index %d. Must be greater than 1\n",
146 dev_err(par
->info
->device
,
147 "Illegal value(s) in Grayscale Lookup Table. At index=%d, the accumulated value has exceeded 180\n",
154 tmp
[0], tmp
[1], tmp
[2], tmp
[3], tmp
[4], tmp
[5], tmp
[6],
155 tmp
[7], tmp
[8], tmp
[9], tmp
[10], tmp
[11], tmp
[12], tmp
[13],
156 tmp
[14], tmp
[15], tmp
[16], tmp
[17], tmp
[18], tmp
[19], tmp
[20],
157 tmp
[21], tmp
[22], tmp
[23], tmp
[24], tmp
[25], tmp
[26], tmp
[27],
158 tmp
[28], tmp
[29], tmp
[30], tmp
[31], tmp
[32], tmp
[33], tmp
[34],
159 tmp
[35], tmp
[36], tmp
[37], tmp
[38], tmp
[39], tmp
[40], tmp
[41],
160 tmp
[42], tmp
[43], tmp
[44], tmp
[45], tmp
[46], tmp
[47], tmp
[48],
161 tmp
[49], tmp
[50], tmp
[51], tmp
[52], tmp
[53], tmp
[54], tmp
[55],
162 tmp
[56], tmp
[57], tmp
[58], tmp
[59], tmp
[60], tmp
[61],
168 static int blank(struct fbtft_par
*par
, bool on
)
171 write_reg(par
, 0xAE);
173 write_reg(par
, 0xAF);
177 static struct fbtft_display display
= {
181 .gamma_num
= GAMMA_NUM
,
182 .gamma_len
= GAMMA_LEN
,
183 .gamma
= DEFAULT_GAMMA
,
185 .write_register
= write_reg8_bus8
,
186 .init_display
= init_display
,
187 .set_addr_win
= set_addr_win
,
188 .set_gamma
= set_gamma
,
193 FBTFT_REGISTER_DRIVER(DRVNAME
, "solomon,ssd1331", &display
);
195 MODULE_ALIAS("spi:" DRVNAME
);
196 MODULE_ALIAS("platform:" DRVNAME
);
197 MODULE_ALIAS("spi:ssd1331");
198 MODULE_ALIAS("platform:ssd1331");
200 MODULE_DESCRIPTION("SSD1331 OLED Driver");
201 MODULE_AUTHOR("Alec Smecher (adapted from SSD1351 by James Davies)");
202 MODULE_LICENSE("GPL");