From d15f52d220cbd7355e67b94f91d0ac12ed4ef0cf Mon Sep 17 00:00:00 2001 From: tnn Date: Thu, 19 Aug 2021 11:04:21 +0000 Subject: [PATCH] ssdfb_spi: fix issues with command xfers needed for SSD1306 & SH1106 These controllers require D/C# to be deasserted for the entire duration of the command, contrary to docs and how newer controllers like SSD1353 behave. Probably this is needed for all controllers that do not have the WRITE_RAM (0x5c) command. Also support using alternate padding commands for 3-wire mode when WRITE_RAM is not available. --- sys/dev/spi/ssdfb_spi.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sys/dev/spi/ssdfb_spi.c b/sys/dev/spi/ssdfb_spi.c index c8c7a6c87f1a..e17bbaefd7cb 100644 --- a/sys/dev/spi/ssdfb_spi.c +++ b/sys/dev/spi/ssdfb_spi.c @@ -1,4 +1,4 @@ -/* $NetBSD: ssdfb_spi.c,v 1.9 2021/08/05 19:17:22 tnn Exp $ */ +/* $NetBSD: ssdfb_spi.c,v 1.10 2021/08/19 11:04:21 tnn Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.9 2021/08/05 19:17:22 tnn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.10 2021/08/19 11:04:21 tnn Exp $"); #include #include @@ -58,6 +58,8 @@ struct ssdfb_spi_softc { struct fdtbus_gpio_pin *sc_gpio_res; #endif bool sc_3wiremode; + bool sc_late_dc_deassert; + uint8_t sc_padding_cmd; }; static int ssdfb_spi_match(device_t, cfdata_t, void *); @@ -78,7 +80,7 @@ static void ssdfb_bitstream_append(struct bs_state *, uint8_t, uint8_t); static void ssdfb_bitstream_append_cmd(struct bs_state *, uint8_t); static void ssdfb_bitstream_append_data(struct bs_state *, uint8_t *, size_t); -static void ssdfb_bitstream_final(struct bs_state *); +static void ssdfb_bitstream_final(struct bs_state *, uint8_t); CFATTACH_DECL_NEW(ssdfb_spi, sizeof(struct ssdfb_spi_softc), ssdfb_spi_match, ssdfb_spi_attach, NULL, NULL); @@ -167,6 +169,7 @@ ssdfb_spi_attach(device_t parent, device_t self, void *aux) sc->sc.sc_transfer_rect = sc->sc_3wiremode ? ssdfb_spi_xfer_rect_3wire_ssd1322 : ssdfb_spi_xfer_rect_4wire_ssd1322; + sc->sc_padding_cmd = SSD1322_CMD_WRITE_RAM; break; case SSDFB_PRODUCT_SSD1353_GENERIC: case SSDFB_PRODUCT_DEP_160128A_RGB: @@ -200,7 +203,7 @@ ssdfb_spi_cmd_3wire(void *cookie, uint8_t *cmd, size_t len, bool usepoll) cmd++; len--; ssdfb_bitstream_append_data(&s, cmd, len); - ssdfb_bitstream_final(&s); + ssdfb_bitstream_final(&s, sc->sc_padding_cmd); return spi_send(sc->sc_sh, s.cur - s.base, bitstream); } @@ -230,7 +233,7 @@ ssdfb_spi_xfer_rect_3wire_ssd1322(void *cookie, uint8_t fromcol, uint8_t tocol, ssdfb_bitstream_append_data(&s, &fromcol, 1); ssdfb_bitstream_append_data(&s, &tocol, 1); ssdfb_bitstream_append_cmd(&s, SSD1322_CMD_WRITE_RAM); - ssdfb_bitstream_final(&s); + ssdfb_bitstream_final(&s, sc->sc_padding_cmd); error = spi_send(sc->sc_sh, s.cur - s.base, bitstream); if (error) return error; @@ -239,7 +242,7 @@ ssdfb_spi_xfer_rect_3wire_ssd1322(void *cookie, uint8_t fromcol, uint8_t tocol, for (row = fromrow; row <= torow; row++) { ssdfb_bitstream_init(&s, bitstream); ssdfb_bitstream_append_data(&s, p, rlen); - ssdfb_bitstream_final(&s); + ssdfb_bitstream_final(&s, sc->sc_padding_cmd); error = spi_send(sc->sc_sh, s.cur - s.base, bitstream); if (error) return error; @@ -290,11 +293,8 @@ ssdfb_bitstream_append_data(struct bs_state *s, uint8_t *data, size_t len) } static void -ssdfb_bitstream_final(struct bs_state *s) +ssdfb_bitstream_final(struct bs_state *s, uint8_t padding_cmd) { - uint8_t padding_cmd = SSD1322_CMD_WRITE_RAM; - /* padding_cmd = SSDFB_NOP_CMD; */ - while (s->mask != 0x80) { ssdfb_bitstream_append_cmd(s, padding_cmd); } @@ -321,7 +321,8 @@ ssdfb_spi_cmd_4wire(void *cookie, uint8_t *cmd, size_t len, bool usepoll) if (error) return error; if (len > 1) { - ssdfb_spi_4wire_set_dc(sc, 1); + if (!sc->sc_late_dc_deassert) + ssdfb_spi_4wire_set_dc(sc, 1); len--; cmd++; error = spi_send(sc->sc_sh, len, cmd);