ssdfb_spi.c revision 1.8 1 /* $NetBSD: ssdfb_spi.c,v 1.8 2021/08/05 19:08:59 tnn Exp $ */
2
3 /*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tobias Nygren.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.8 2021/08/05 19:08:59 tnn Exp $");
34
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/kernel.h>
38 #include <dev/wscons/wsdisplayvar.h>
39 #include <dev/rasops/rasops.h>
40 #include <dev/spi/spivar.h>
41 #include <dev/ic/ssdfbvar.h>
42 #include "opt_fdt.h"
43 #ifdef FDT
44 #include <dev/fdt/fdtvar.h>
45 #endif
46
47 struct bs_state {
48 uint8_t *base;
49 uint8_t *cur;
50 uint8_t mask;
51 };
52
53 struct ssdfb_spi_softc {
54 struct ssdfb_softc sc;
55 struct spi_handle *sc_sh;
56 #ifdef FDT
57 struct fdtbus_gpio_pin *sc_gpio_dc;
58 struct fdtbus_gpio_pin *sc_gpio_res;
59 #endif
60 bool sc_3wiremode;
61 };
62
63 static int ssdfb_spi_match(device_t, cfdata_t, void *);
64 static void ssdfb_spi_attach(device_t, device_t, void *);
65
66 static int ssdfb_spi_cmd_3wire(void *, uint8_t *, size_t, bool);
67 static int ssdfb_spi_xfer_rect_3wire_ssd1322(void *, uint8_t, uint8_t,
68 uint8_t, uint8_t, uint8_t *, size_t, bool);
69
70 static int ssdfb_spi_cmd_4wire(void *, uint8_t *, size_t, bool);
71 static int ssdfb_spi_xfer_rect_4wire_ssd1322(void *, uint8_t, uint8_t,
72 uint8_t, uint8_t, uint8_t *, size_t, bool);
73 static int ssdfb_spi_xfer_rect_4wire_ssd1353(void *, uint8_t, uint8_t,
74 uint8_t, uint8_t, uint8_t *, size_t, bool);
75
76 static void ssdfb_bitstream_init(struct bs_state *, uint8_t *);
77 static void ssdfb_bitstream_append(struct bs_state *, uint8_t, uint8_t);
78 static void ssdfb_bitstream_append_cmd(struct bs_state *, uint8_t);
79 static void ssdfb_bitstream_append_data(struct bs_state *, uint8_t *,
80 size_t);
81 static void ssdfb_bitstream_final(struct bs_state *);
82
83 CFATTACH_DECL_NEW(ssdfb_spi, sizeof(struct ssdfb_spi_softc),
84 ssdfb_spi_match, ssdfb_spi_attach, NULL, NULL);
85
86 static const struct device_compatible_entry compat_data[] = {
87 { .compat = "solomon,ssd1306", .value = SSDFB_PRODUCT_SSD1306_GENERIC },
88 { .compat = "solomon,ssd1322", .value = SSDFB_PRODUCT_SSD1322_GENERIC },
89 { .compat = "solomon,ssd1353", .value = SSDFB_PRODUCT_SSD1353_GENERIC },
90 { .compat = "dep160128a", .value = SSDFB_PRODUCT_DEP_160128A_RGB },
91 DEVICE_COMPAT_EOL
92 };
93
94 static int
95 ssdfb_spi_match(device_t parent, cfdata_t match, void *aux)
96 {
97 struct spi_attach_args *sa = aux;
98 int res;
99
100 res = spi_compatible_match(sa, match, compat_data);
101 if (!res)
102 return res;
103
104 /*
105 * SSD1306 and SSD1322 data sheets specify 100ns cycle time.
106 */
107 if (spi_configure(sa->sa_handle, SPI_MODE_0, 10000000))
108 res = 0;
109
110 return res;
111 }
112
113 static void
114 ssdfb_spi_attach(device_t parent, device_t self, void *aux)
115 {
116 struct ssdfb_spi_softc *sc = device_private(self);
117 struct cfdata *cf = device_cfdata(self);
118 struct spi_attach_args *sa = aux;
119 int flags = cf->cf_flags;
120
121 sc->sc.sc_dev = self;
122 sc->sc_sh = sa->sa_handle;
123 sc->sc.sc_cookie = (void *)sc;
124 if ((flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK) == SSDFB_PRODUCT_UNKNOWN) {
125 const struct device_compatible_entry *dce =
126 device_compatible_lookup(sa->sa_compat, sa->sa_ncompat, compat_data);
127 if (dce)
128 flags |= (int)dce->value;
129 else
130 flags |= SSDFB_PRODUCT_SSD1322_GENERIC;
131 }
132 /*
133 * Note on interface modes.
134 *
135 * 3 wire mode sends 9 bit sequences over the MOSI, MSB contains
136 * the bit that determines if the lower 8 bits are command or data.
137 *
138 * 4 wire mode sends 8 bit sequences and requires an auxiliary GPIO
139 * pin for the command/data bit.
140 */
141 #ifdef FDT
142 const int phandle = sa->sa_cookie;
143 sc->sc_gpio_dc =
144 fdtbus_gpio_acquire(phandle, "dc-gpio", GPIO_PIN_OUTPUT);
145 if (!sc->sc_gpio_dc)
146 sc->sc_gpio_dc =
147 fdtbus_gpio_acquire(phandle, "cd-gpio", GPIO_PIN_OUTPUT);
148 sc->sc_3wiremode = (sc->sc_gpio_dc == NULL);
149 sc->sc_gpio_res =
150 fdtbus_gpio_acquire(phandle, "res-gpio", GPIO_PIN_OUTPUT);
151 if (sc->sc_gpio_res) {
152 fdtbus_gpio_write_raw(sc->sc_gpio_res, 0);
153 DELAY(100);
154 fdtbus_gpio_write_raw(sc->sc_gpio_res, 1);
155 DELAY(100);
156 }
157 #else
158 sc->sc_3wiremode = true;
159 #endif
160
161 sc->sc.sc_cmd = sc->sc_3wiremode
162 ? ssdfb_spi_cmd_3wire
163 : ssdfb_spi_cmd_4wire;
164
165 switch (flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK) {
166 case SSDFB_PRODUCT_SSD1322_GENERIC:
167 sc->sc.sc_transfer_rect = sc->sc_3wiremode
168 ? ssdfb_spi_xfer_rect_3wire_ssd1322
169 : ssdfb_spi_xfer_rect_4wire_ssd1322;
170 break;
171 case SSDFB_PRODUCT_SSD1353_GENERIC:
172 case SSDFB_PRODUCT_DEP_160128A_RGB:
173 sc->sc.sc_transfer_rect = sc->sc_3wiremode
174 ? NULL /* not supported here */
175 : ssdfb_spi_xfer_rect_4wire_ssd1353;
176 break;
177 }
178
179 if (!sc->sc.sc_transfer_rect) {
180 aprint_error(": sc_transfer_rect not implemented\n");
181 return;
182 }
183
184 ssdfb_attach(&sc->sc, flags);
185
186 aprint_normal_dev(self, "%d-wire SPI interface\n",
187 sc->sc_3wiremode == true ? 3 : 4);
188 }
189
190 static int
191 ssdfb_spi_cmd_3wire(void *cookie, uint8_t *cmd, size_t len, bool usepoll)
192 {
193 struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
194 uint8_t bitstream[16 * 9 / 8];
195 struct bs_state s;
196
197 KASSERT(len > 0 && len <= 16);
198 ssdfb_bitstream_init(&s, bitstream);
199 ssdfb_bitstream_append_cmd(&s, *cmd);
200 cmd++;
201 len--;
202 ssdfb_bitstream_append_data(&s, cmd, len);
203 ssdfb_bitstream_final(&s);
204
205 return spi_send(sc->sc_sh, s.cur - s.base, bitstream);
206 }
207
208 static int
209 ssdfb_spi_xfer_rect_3wire_ssd1322(void *cookie, uint8_t fromcol, uint8_t tocol,
210 uint8_t fromrow, uint8_t torow, uint8_t *p, size_t stride, bool usepoll)
211 {
212 struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
213 uint8_t bitstream[128 * 9 / 8];
214 struct bs_state s;
215 uint8_t row;
216 size_t rlen = (tocol + 1 - fromcol) * 2;
217 int error;
218
219 /*
220 * Unlike iic(4), there is no way to force spi(4) to use polling.
221 */
222 if (usepoll && !cold)
223 return 0;
224
225 ssdfb_bitstream_init(&s, bitstream);
226 ssdfb_bitstream_append_cmd(&s, SSD1322_CMD_SET_ROW_ADDRESS);
227 ssdfb_bitstream_append_data(&s, &fromrow, 1);
228 ssdfb_bitstream_append_data(&s, &torow, 1);
229 ssdfb_bitstream_append_cmd(&s, SSD1322_CMD_SET_COLUMN_ADDRESS);
230 ssdfb_bitstream_append_data(&s, &fromcol, 1);
231 ssdfb_bitstream_append_data(&s, &tocol, 1);
232 ssdfb_bitstream_append_cmd(&s, SSD1322_CMD_WRITE_RAM);
233 ssdfb_bitstream_final(&s);
234 error = spi_send(sc->sc_sh, s.cur - s.base, bitstream);
235 if (error)
236 return error;
237
238 KASSERT(rlen <= 128);
239 for (row = fromrow; row <= torow; row++) {
240 ssdfb_bitstream_init(&s, bitstream);
241 ssdfb_bitstream_append_data(&s, p, rlen);
242 ssdfb_bitstream_final(&s);
243 error = spi_send(sc->sc_sh, s.cur - s.base, bitstream);
244 if (error)
245 return error;
246 p += stride;
247 }
248
249 return 0;
250 }
251
252 static void
253 ssdfb_bitstream_init(struct bs_state *s, uint8_t *dst)
254 {
255 s->base = s->cur = dst;
256 s->mask = 0x80;
257 }
258
259 static void
260 ssdfb_bitstream_append(struct bs_state *s, uint8_t b, uint8_t srcmask)
261 {
262 while(srcmask) {
263 if (b & srcmask)
264 *s->cur |= s->mask;
265 else
266 *s->cur &= ~s->mask;
267 srcmask >>= 1;
268 s->mask >>= 1;
269 if (!s->mask) {
270 s->mask = 0x80;
271 s->cur++;
272 }
273 }
274 }
275
276 static void
277 ssdfb_bitstream_append_cmd(struct bs_state *s, uint8_t cmd)
278 {
279 ssdfb_bitstream_append(s, 0, 1);
280 ssdfb_bitstream_append(s, cmd, 0x80);
281 }
282
283 static void
284 ssdfb_bitstream_append_data(struct bs_state *s, uint8_t *data, size_t len)
285 {
286 while(len--) {
287 ssdfb_bitstream_append(s, 1, 1);
288 ssdfb_bitstream_append(s, *data++, 0x80);
289 }
290 }
291
292 static void
293 ssdfb_bitstream_final(struct bs_state *s)
294 {
295 uint8_t padding_cmd = SSD1322_CMD_WRITE_RAM;
296 /* padding_cmd = SSDFB_NOP_CMD; */
297
298 while (s->mask != 0x80) {
299 ssdfb_bitstream_append_cmd(s, padding_cmd);
300 }
301 }
302
303 static void
304 ssdfb_spi_4wire_set_dc(struct ssdfb_spi_softc *sc, int value)
305 {
306 #ifdef FDT
307 fdtbus_gpio_write_raw(sc->sc_gpio_dc, value);
308 #else
309 panic("ssdfb_spi_4wire_set_dc");
310 #endif
311 }
312
313 static int
314 ssdfb_spi_cmd_4wire(void *cookie, uint8_t *cmd, size_t len, bool usepoll)
315 {
316 struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
317 int error;
318
319 ssdfb_spi_4wire_set_dc(sc, 0);
320 error = spi_send(sc->sc_sh, 1, cmd);
321 if (error)
322 return error;
323 if (len > 1) {
324 ssdfb_spi_4wire_set_dc(sc, 1);
325 len--;
326 cmd++;
327 error = spi_send(sc->sc_sh, len, cmd);
328 if (error)
329 return error;
330 }
331
332 return 0;
333 }
334
335 static int
336 ssdfb_spi_xfer_rect_4wire_ssd1322(void *cookie, uint8_t fromcol, uint8_t tocol,
337 uint8_t fromrow, uint8_t torow, uint8_t *p, size_t stride, bool usepoll)
338 {
339 struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
340 uint8_t row;
341 size_t rlen = (tocol + 1 - fromcol) * 2;
342 int error;
343 uint8_t cmd;
344 uint8_t data[2];
345
346 /*
347 * Unlike iic(4), there is no way to force spi(4) to use polling.
348 */
349 if (usepoll && !cold)
350 return 0;
351
352 ssdfb_spi_4wire_set_dc(sc, 0);
353 cmd = SSD1322_CMD_SET_ROW_ADDRESS;
354 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
355 if (error)
356 return error;
357 ssdfb_spi_4wire_set_dc(sc, 1);
358 data[0] = fromrow;
359 data[1] = torow;
360 error = spi_send(sc->sc_sh, sizeof(data), data);
361 if (error)
362 return error;
363
364 ssdfb_spi_4wire_set_dc(sc, 0);
365 cmd = SSD1322_CMD_SET_COLUMN_ADDRESS;
366 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
367 if (error)
368 return error;
369 ssdfb_spi_4wire_set_dc(sc, 1);
370 data[0] = fromcol;
371 data[1] = tocol;
372 error = spi_send(sc->sc_sh, sizeof(data), data);
373 if (error)
374 return error;
375
376 ssdfb_spi_4wire_set_dc(sc, 0);
377 cmd = SSD1322_CMD_WRITE_RAM;
378 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
379 if (error)
380 return error;
381
382 ssdfb_spi_4wire_set_dc(sc, 1);
383 for (row = fromrow; row <= torow; row++) {
384 error = spi_send(sc->sc_sh, rlen, p);
385 if (error)
386 return error;
387 p += stride;
388 }
389
390 return 0;
391 }
392
393 static int
394 ssdfb_spi_xfer_rect_4wire_ssd1353(void *cookie, uint8_t fromcol, uint8_t tocol,
395 uint8_t fromrow, uint8_t torow, uint8_t *p, size_t stride, bool usepoll)
396 {
397 struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
398 uint8_t row;
399 size_t rlen = (tocol + 1 - fromcol) * 3;
400 uint8_t bitstream[160 * 3];
401 uint8_t *dstp, *srcp, *endp;
402 int error;
403 uint8_t cmd;
404 uint8_t data[2];
405
406 /*
407 * Unlike iic(4), there is no way to force spi(4) to use polling.
408 */
409 if (usepoll && !cold)
410 return 0;
411
412 ssdfb_spi_4wire_set_dc(sc, 0);
413 cmd = SSD1322_CMD_SET_ROW_ADDRESS;
414 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
415 if (error)
416 return error;
417 ssdfb_spi_4wire_set_dc(sc, 1);
418 data[0] = fromrow;
419 data[1] = torow;
420 if (sc->sc.sc_upsidedown) {
421 /* fix picture outside frame on 160x128 panel */
422 data[0] += 132 - sc->sc.sc_p->p_height;
423 data[1] += 132 - sc->sc.sc_p->p_height;
424 }
425 error = spi_send(sc->sc_sh, sizeof(data), data);
426 if (error)
427 return error;
428
429 ssdfb_spi_4wire_set_dc(sc, 0);
430 cmd = SSD1322_CMD_SET_COLUMN_ADDRESS;
431 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
432 if (error)
433 return error;
434 ssdfb_spi_4wire_set_dc(sc, 1);
435 data[0] = fromcol;
436 data[1] = tocol;
437 error = spi_send(sc->sc_sh, sizeof(data), data);
438 if (error)
439 return error;
440
441 ssdfb_spi_4wire_set_dc(sc, 0);
442 cmd = SSD1322_CMD_WRITE_RAM;
443 error = spi_send(sc->sc_sh, sizeof(cmd), &cmd);
444 if (error)
445 return error;
446
447 ssdfb_spi_4wire_set_dc(sc, 1);
448 KASSERT(rlen <= sizeof(bitstream));
449 for (row = fromrow; row <= torow; row++) {
450 /* downconvert each row from 32bpp rgba to 18bpp panel format */
451 dstp = bitstream;
452 endp = dstp + rlen;
453 srcp = p;
454 while (dstp < endp) {
455 *dstp++ = (*srcp++) >> 2;
456 *dstp++ = (*srcp++) >> 2;
457 *dstp++ = (*srcp++) >> 2;
458 srcp++;
459 }
460 error = spi_send(sc->sc_sh, rlen, bitstream);
461 if (error)
462 return error;
463 p += stride;
464 }
465
466 return 0;
467 }
468