Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/spi ssdfb: add support for SSD1306 and SH1106 at spi...
details: https://anonhg.NetBSD.org/src/rev/08f27070cf36
branches: trunk
changeset: 1023021:08f27070cf36
user: tnn <tnn%NetBSD.org@localhost>
date: Thu Aug 19 17:50:18 2021 +0000
description:
ssdfb: add support for SSD1306 and SH1106 at spi attachment
Only support the 4-wire mode for now. Support for 3-wire mode is
theoretically possible but most (all?) modules in circulation have the
BS0 / IM0 3-wire config pin internally grounded within the flat-flex
assembly so it is not easy to enable & test.
diffstat:
sys/dev/spi/ssdfb_spi.c | 112 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 98 insertions(+), 14 deletions(-)
diffs (221 lines):
diff -r 8f72b772c67a -r 08f27070cf36 sys/dev/spi/ssdfb_spi.c
--- a/sys/dev/spi/ssdfb_spi.c Thu Aug 19 16:29:41 2021 +0000
+++ b/sys/dev/spi/ssdfb_spi.c Thu Aug 19 17:50:18 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ssdfb_spi.c,v 1.10 2021/08/19 11:04:21 tnn Exp $ */
+/* $NetBSD: ssdfb_spi.c,v 1.11 2021/08/19 17:50:18 tnn Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.10 2021/08/19 11:04:21 tnn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.11 2021/08/19 17:50:18 tnn Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -70,6 +70,10 @@
uint8_t, uint8_t, uint8_t *, size_t, bool);
static int ssdfb_spi_cmd_4wire(void *, uint8_t *, size_t, bool);
+static int ssdfb_spi_xfer_rect_4wire_sh1106(void *, uint8_t, uint8_t,
+ uint8_t, uint8_t, uint8_t *, size_t, bool);
+static int ssdfb_spi_xfer_rect_4wire_ssd1306(void *, uint8_t, uint8_t,
+ uint8_t, uint8_t, uint8_t *, size_t, bool);
static int ssdfb_spi_xfer_rect_4wire_ssd1322(void *, uint8_t, uint8_t,
uint8_t, uint8_t, uint8_t *, size_t, bool);
static int ssdfb_spi_xfer_rect_4wire_ssd1353(void *, uint8_t, uint8_t,
@@ -87,6 +91,7 @@
static const struct device_compatible_entry compat_data[] = {
{ .compat = "solomon,ssd1306", .value = SSDFB_PRODUCT_SSD1306_GENERIC },
+ { .compat = "sino,sh1106", .value = SSDFB_PRODUCT_SH1106_GENERIC },
{ .compat = "solomon,ssd1322", .value = SSDFB_PRODUCT_SSD1322_GENERIC },
{ .compat = "solomon,ssd1353", .value = SSDFB_PRODUCT_SSD1353_GENERIC },
{ .compat = "dep160128a", .value = SSDFB_PRODUCT_DEP_160128A_RGB },
@@ -165,6 +170,20 @@
: ssdfb_spi_cmd_4wire;
switch (flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK) {
+ case SSDFB_PRODUCT_SH1106_GENERIC:
+ sc->sc.sc_transfer_rect = sc->sc_3wiremode
+ ? NULL
+ : ssdfb_spi_xfer_rect_4wire_sh1106;
+ sc->sc_padding_cmd = SSDFB_CMD_NOP;
+ sc->sc_late_dc_deassert = true;
+ break;
+ case SSDFB_PRODUCT_SSD1306_GENERIC:
+ sc->sc.sc_transfer_rect = sc->sc_3wiremode
+ ? NULL
+ : ssdfb_spi_xfer_rect_4wire_ssd1306;
+ sc->sc_padding_cmd = SSDFB_CMD_NOP;
+ sc->sc_late_dc_deassert = true;
+ break;
case SSDFB_PRODUCT_SSD1322_GENERIC:
sc->sc.sc_transfer_rect = sc->sc_3wiremode
? ssdfb_spi_xfer_rect_3wire_ssd1322
@@ -215,7 +234,6 @@
struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
uint8_t bitstream[128 * 9 / 8];
struct bs_state s;
- uint8_t row;
size_t rlen = (tocol + 1 - fromcol) * 2;
int error;
@@ -239,13 +257,14 @@
return error;
KASSERT(rlen <= 128);
- for (row = fromrow; row <= torow; row++) {
+ while (fromrow <= torow) {
ssdfb_bitstream_init(&s, bitstream);
ssdfb_bitstream_append_data(&s, p, rlen);
ssdfb_bitstream_final(&s, sc->sc_padding_cmd);
error = spi_send(sc->sc_sh, s.cur - s.base, bitstream);
if (error)
return error;
+ fromrow++;
p += stride;
}
@@ -334,19 +353,86 @@
}
static int
+ssdfb_spi_xfer_rect_4wire_sh1106(void *cookie, uint8_t fromcol, uint8_t tocol,
+ uint8_t frompage, uint8_t topage, uint8_t *p, size_t stride, bool usepoll)
+{
+ struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
+ size_t rlen = tocol + 1 - fromcol;
+ int error;
+ uint8_t cmd[] = {
+ SSDFB_CMD_SET_PAGE_START_ADDRESS_BASE + frompage,
+ SSDFB_CMD_SET_HIGHER_COLUMN_START_ADDRESS_BASE + (fromcol >> 4),
+ SSDFB_CMD_SET_LOWER_COLUMN_START_ADDRESS_BASE + (fromcol & 0xf)
+ };
+
+ if (usepoll && !cold)
+ return 0;
+
+ while (frompage <= topage) {
+ cmd[0] = SSDFB_CMD_SET_PAGE_START_ADDRESS_BASE + frompage;
+ ssdfb_spi_4wire_set_dc(sc, 0);
+ error = spi_send(sc->sc_sh, sizeof(cmd), cmd);
+ if (error)
+ return error;
+ ssdfb_spi_4wire_set_dc(sc, 1);
+ error = spi_send(sc->sc_sh, rlen, p);
+ if (error)
+ return error;
+ frompage++;
+ p += stride;
+ }
+
+ return 0;
+}
+
+static int
+ssdfb_spi_xfer_rect_4wire_ssd1306(void *cookie, uint8_t fromcol, uint8_t tocol,
+ uint8_t frompage, uint8_t topage, uint8_t *p, size_t stride, bool usepoll)
+{
+ struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
+ size_t rlen = tocol + 1 - fromcol;
+ int error;
+ uint8_t cmd[] = {
+ SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE,
+ SSD1306_MEMORY_ADDRESSING_MODE_HORIZONTAL,
+ SSD1306_CMD_SET_COLUMN_ADDRESS,
+ fromcol,
+ tocol,
+ SSD1306_CMD_SET_PAGE_ADDRESS,
+ frompage,
+ topage
+ };
+
+ if (usepoll && !cold)
+ return 0;
+
+ ssdfb_spi_4wire_set_dc(sc, 0);
+ error = spi_send(sc->sc_sh, sizeof(cmd), cmd);
+ if (error)
+ return error;
+ ssdfb_spi_4wire_set_dc(sc, 1);
+
+ while (frompage <= topage) {
+ error = spi_send(sc->sc_sh, rlen, p);
+ if (error)
+ return error;
+ frompage++;
+ p += stride;
+ }
+
+ return 0;
+}
+
+static int
ssdfb_spi_xfer_rect_4wire_ssd1322(void *cookie, uint8_t fromcol, uint8_t tocol,
uint8_t fromrow, uint8_t torow, uint8_t *p, size_t stride, bool usepoll)
{
struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
- uint8_t row;
size_t rlen = (tocol + 1 - fromcol) * 2;
int error;
uint8_t cmd;
uint8_t data[2];
- /*
- * Unlike iic(4), there is no way to force spi(4) to use polling.
- */
if (usepoll && !cold)
return 0;
@@ -381,10 +467,11 @@
return error;
ssdfb_spi_4wire_set_dc(sc, 1);
- for (row = fromrow; row <= torow; row++) {
+ while (fromrow <= torow) {
error = spi_send(sc->sc_sh, rlen, p);
if (error)
return error;
+ fromrow++;
p += stride;
}
@@ -396,7 +483,6 @@
uint8_t fromrow, uint8_t torow, uint8_t *p, size_t stride, bool usepoll)
{
struct ssdfb_spi_softc *sc = (struct ssdfb_spi_softc *)cookie;
- uint8_t row;
size_t rlen = (tocol + 1 - fromcol) * 3;
uint8_t bitstream[160 * 3];
uint8_t *dstp, *srcp, *endp;
@@ -404,9 +490,6 @@
uint8_t cmd;
uint8_t data[2];
- /*
- * Unlike iic(4), there is no way to force spi(4) to use polling.
- */
if (usepoll && !cold)
return 0;
@@ -447,7 +530,7 @@
ssdfb_spi_4wire_set_dc(sc, 1);
KASSERT(rlen <= sizeof(bitstream));
- for (row = fromrow; row <= torow; row++) {
+ while (fromrow <= torow) {
/* downconvert each row from 32bpp rgba to 18bpp panel format */
dstp = bitstream;
endp = dstp + rlen;
@@ -461,6 +544,7 @@
error = spi_send(sc->sc_sh, rlen, bitstream);
if (error)
return error;
+ fromrow++;
p += stride;
}
Home |
Main Index |
Thread Index |
Old Index