Module Name: src Committed By: tnn Date: Thu Aug 5 19:08:59 UTC 2021
Modified Files: src/sys/dev/spi: ssdfb_spi.c Log Message: ssdfb: support SSD1353 at spi(4) To generate a diff of this commit: cvs rdiff -u -r1.7 -r1.8 src/sys/dev/spi/ssdfb_spi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/spi/ssdfb_spi.c diff -u src/sys/dev/spi/ssdfb_spi.c:1.7 src/sys/dev/spi/ssdfb_spi.c:1.8 --- src/sys/dev/spi/ssdfb_spi.c:1.7 Tue Aug 3 11:30:25 2021 +++ src/sys/dev/spi/ssdfb_spi.c Thu Aug 5 19:08:59 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: ssdfb_spi.c,v 1.7 2021/08/03 11:30:25 tnn Exp $ */ +/* $NetBSD: ssdfb_spi.c,v 1.8 2021/08/05 19:08:59 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.7 2021/08/03 11:30:25 tnn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.8 2021/08/05 19:08:59 tnn Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -70,6 +70,8 @@ static int ssdfb_spi_xfer_rect_3wire_ssd static int ssdfb_spi_cmd_4wire(void *, 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, + uint8_t, uint8_t, uint8_t *, size_t, bool); static void ssdfb_bitstream_init(struct bs_state *, uint8_t *); static void ssdfb_bitstream_append(struct bs_state *, uint8_t, uint8_t); @@ -84,6 +86,8 @@ CFATTACH_DECL_NEW(ssdfb_spi, sizeof(stru static const struct device_compatible_entry compat_data[] = { { .compat = "solomon,ssd1306", .value = SSDFB_PRODUCT_SSD1306_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 }, DEVICE_COMPAT_EOL }; @@ -154,28 +158,32 @@ ssdfb_spi_attach(device_t parent, device sc->sc_3wiremode = true; #endif + sc->sc.sc_cmd = sc->sc_3wiremode + ? ssdfb_spi_cmd_3wire + : ssdfb_spi_cmd_4wire; + switch (flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK) { case SSDFB_PRODUCT_SSD1322_GENERIC: - if (sc->sc_3wiremode) { - sc->sc.sc_transfer_rect = - ssdfb_spi_xfer_rect_3wire_ssd1322; - } else { - sc->sc.sc_transfer_rect = - ssdfb_spi_xfer_rect_4wire_ssd1322; - } + sc->sc.sc_transfer_rect = sc->sc_3wiremode + ? ssdfb_spi_xfer_rect_3wire_ssd1322 + : ssdfb_spi_xfer_rect_4wire_ssd1322; + break; + case SSDFB_PRODUCT_SSD1353_GENERIC: + case SSDFB_PRODUCT_DEP_160128A_RGB: + sc->sc.sc_transfer_rect = sc->sc_3wiremode + ? NULL /* not supported here */ + : ssdfb_spi_xfer_rect_4wire_ssd1353; break; - default: - panic("ssdfb_spi_attach: product not implemented"); } - if (sc->sc_3wiremode) { - sc->sc.sc_cmd = ssdfb_spi_cmd_3wire; - } else { - sc->sc.sc_cmd = ssdfb_spi_cmd_4wire; + + if (!sc->sc.sc_transfer_rect) { + aprint_error(": sc_transfer_rect not implemented\n"); + return; } ssdfb_attach(&sc->sc, flags); - device_printf(sc->sc.sc_dev, "%d-wire SPI interface\n", + aprint_normal_dev(self, "%d-wire SPI interface\n", sc->sc_3wiremode == true ? 3 : 4); } @@ -381,3 +389,79 @@ ssdfb_spi_xfer_rect_4wire_ssd1322(void * return 0; } + +static int +ssdfb_spi_xfer_rect_4wire_ssd1353(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) * 3; + uint8_t bitstream[160 * 3]; + uint8_t *dstp, *srcp, *endp; + 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; + + ssdfb_spi_4wire_set_dc(sc, 0); + cmd = SSD1322_CMD_SET_ROW_ADDRESS; + error = spi_send(sc->sc_sh, sizeof(cmd), &cmd); + if (error) + return error; + ssdfb_spi_4wire_set_dc(sc, 1); + data[0] = fromrow; + data[1] = torow; + if (sc->sc.sc_upsidedown) { + /* fix picture outside frame on 160x128 panel */ + data[0] += 132 - sc->sc.sc_p->p_height; + data[1] += 132 - sc->sc.sc_p->p_height; + } + error = spi_send(sc->sc_sh, sizeof(data), data); + if (error) + return error; + + ssdfb_spi_4wire_set_dc(sc, 0); + cmd = SSD1322_CMD_SET_COLUMN_ADDRESS; + error = spi_send(sc->sc_sh, sizeof(cmd), &cmd); + if (error) + return error; + ssdfb_spi_4wire_set_dc(sc, 1); + data[0] = fromcol; + data[1] = tocol; + error = spi_send(sc->sc_sh, sizeof(data), data); + if (error) + return error; + + ssdfb_spi_4wire_set_dc(sc, 0); + cmd = SSD1322_CMD_WRITE_RAM; + error = spi_send(sc->sc_sh, sizeof(cmd), &cmd); + if (error) + return error; + + ssdfb_spi_4wire_set_dc(sc, 1); + KASSERT(rlen <= sizeof(bitstream)); + for (row = fromrow; row <= torow; row++) { + /* downconvert each row from 32bpp rgba to 18bpp panel format */ + dstp = bitstream; + endp = dstp + rlen; + srcp = p; + while (dstp < endp) { + *dstp++ = (*srcp++) >> 2; + *dstp++ = (*srcp++) >> 2; + *dstp++ = (*srcp++) >> 2; + srcp++; + } + error = spi_send(sc->sc_sh, rlen, bitstream); + if (error) + return error; + p += stride; + } + + return 0; +}