Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic ssdfb: support the SSD1353 controller and the DEP...
details: https://anonhg.NetBSD.org/src/rev/17574e2f1317
branches: trunk
changeset: 1022759:17574e2f1317
user: tnn <tnn%NetBSD.org@localhost>
date: Thu Aug 05 19:07:09 2021 +0000
description:
ssdfb: support the SSD1353 controller and the DEP 160128A(1)-RGB display
DEP 160128A is a 160x128 18-bit RGB OLED display module advertised as
having an 8-bit parallel I/O interface. The controller can however attach
serially via spi(4) by moving jumper resistors J1 and J2 to GND position.
diffstat:
sys/dev/ic/ssdfb.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ic/ssdfbvar.h | 5 +-
2 files changed, 230 insertions(+), 5 deletions(-)
diffs (truncated from 323 to 300 lines):
diff -r 0e2e9d3cdf04 -r 17574e2f1317 sys/dev/ic/ssdfb.c
--- a/sys/dev/ic/ssdfb.c Thu Aug 05 12:52:47 2021 +0000
+++ b/sys/dev/ic/ssdfb.c Thu Aug 05 19:07:09 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ssdfb.c,v 1.17 2021/08/05 00:16:36 tnn Exp $ */
+/* $NetBSD: ssdfb.c,v 1.18 2021/08/05 19:07:09 tnn Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ssdfb.c,v 1.17 2021/08/05 00:16:36 tnn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ssdfb.c,v 1.18 2021/08/05 19:07:09 tnn Exp $");
#include "opt_ddb.h"
@@ -75,6 +75,7 @@
/* hardware interface */
static int ssdfb_init_ssd1306(struct ssdfb_softc *);
static int ssdfb_init_ssd1322(struct ssdfb_softc *);
+static int ssdfb_init_ssd1353(struct ssdfb_softc *);
static int ssdfb_set_contrast(struct ssdfb_softc *, uint8_t, bool);
static int ssdfb_set_display_on(struct ssdfb_softc *, bool, bool);
static int ssdfb_set_mode(struct ssdfb_softc *, u_int);
@@ -89,6 +90,7 @@
static int ssdfb_sync(struct ssdfb_softc *, bool);
static int ssdfb_sync_ssd1306(struct ssdfb_softc *, bool);
static int ssdfb_sync_ssd1322(struct ssdfb_softc *, bool);
+static int ssdfb_sync_ssd1353(struct ssdfb_softc *, bool);
static uint64_t ssdfb_transpose_block(uint8_t *, size_t);
/* misc helpers */
@@ -104,7 +106,8 @@
[SSDFB_CONTROLLER_UNKNOWN] = "unknown",
[SSDFB_CONTROLLER_SSD1306] = "Solomon Systech SSD1306",
[SSDFB_CONTROLLER_SH1106] = "Sino Wealth SH1106",
- [SSDFB_CONTROLLER_SSD1322] = "Solomon Systech SSD1322"
+ [SSDFB_CONTROLLER_SSD1322] = "Solomon Systech SSD1322",
+ [SSDFB_CONTROLLER_SSD1353] = "Solomon Systech SSD1353"
};
/*
@@ -204,6 +207,44 @@
.p_multiplex_ratio = 0x3f,
.p_init = ssdfb_init_ssd1322,
.p_sync = ssdfb_sync_ssd1322
+ },
+ {
+ .p_product_id = SSDFB_PRODUCT_SSD1353_GENERIC,
+ .p_controller_id = SSDFB_CONTROLLER_SSD1353,
+ .p_name = "generic",
+ .p_width = 160,
+ .p_height = 132,
+ .p_bits_per_pixel = 32,
+ .p_rgb = true,
+ .p_panel_shift = 0,
+ .p_compin_cfg = SSD1353_REMAP_RGB | SSD1353_REMAP_SPLIT_ODD_EVEN
+ | __SHIFTIN(2, SSD1353_REMAP_PIXEL_FORMAT_MASK),
+ .p_vcomh_deselect_level = SSD1353_DEFAULT_VCOMH,
+ .p_fosc = SSD1353_DEFAULT_FREQUENCY,
+ .p_fosc_div = SSD1353_DEFAULT_DIVIDER,
+ .p_default_contrast = SSD1353_DEFAULT_CONTRAST_CONTROL,
+ .p_multiplex_ratio = 0x83,
+ .p_init = ssdfb_init_ssd1353,
+ .p_sync = ssdfb_sync_ssd1353
+ },
+ {
+ .p_product_id = SSDFB_PRODUCT_DEP_160128A_RGB,
+ .p_controller_id = SSDFB_CONTROLLER_SSD1353,
+ .p_name = "Display Elektronik GmbH DEP 160128A(1)-RGB",
+ .p_width = 160,
+ .p_height = 128,
+ .p_bits_per_pixel = 32,
+ .p_rgb = true,
+ .p_panel_shift = 0,
+ .p_compin_cfg = SSD1353_REMAP_RGB | SSD1353_REMAP_SPLIT_ODD_EVEN
+ | __SHIFTIN(2, SSD1353_REMAP_PIXEL_FORMAT_MASK),
+ .p_vcomh_deselect_level = SSD1353_DEFAULT_VCOMH,
+ .p_fosc = SSD1353_DEFAULT_FREQUENCY,
+ .p_fosc_div = SSD1353_DEFAULT_DIVIDER,
+ .p_default_contrast = SSD1353_DEFAULT_CONTRAST_CONTROL,
+ .p_multiplex_ratio = 0x83,
+ .p_init = ssdfb_init_ssd1353,
+ .p_sync = ssdfb_sync_ssd1353
}
};
@@ -872,18 +913,148 @@
}
static int
+ssdfb_init_ssd1353(struct ssdfb_softc *sc)
+{
+ int error;
+ uint8_t cmd[3];
+ bool usepoll = true;
+ uint8_t remap;
+
+ /*
+ * Enter sleep.
+ */
+ SSDFB_CMD2(SSD1353_CMD_SET_COMMAND_LOCK, SSD1353_COMMAND_UNLOCK_MAGIC);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1353_CMD_RESET);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1353_CMD_DEACTIVATE_SCROLL);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1353_CMD_SET_DISPLAY_OFF);
+ if (error)
+ return error;
+
+ /*
+ * Start charge pumps.
+ */
+ SSDFB_CMD2(SSD1353_CMD_SET_VCOMH, sc->sc_p->p_vcomh_deselect_level);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_PRE_CHARGE_VOLTAGE_LEVEL,
+ SSD1353_DEFAULT_PRE_CHARGE_VOLTAGE_LEVEL);
+ if (error)
+ return error;
+
+ /*
+ * Configure timing characteristics.
+ */
+ SSDFB_CMD2(SSD1353_CMD_SET_FRONT_CLOCK_DIVIDER,
+ __SHIFTIN(sc->sc_p->p_fosc, SSD1322_FREQUENCY_MASK) |
+ __SHIFTIN(sc->sc_p->p_fosc_div, SSD1322_DIVIDER_MASK));
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_PHASE_LENGTH,
+ __SHIFTIN(SSD1353_DEFAULT_PHASE_2,
+ SSD1322_PHASE_LENGTH_PHASE_2_MASK) |
+ __SHIFTIN(SSD1353_DEFAULT_PHASE_1,
+ SSD1322_PHASE_LENGTH_PHASE_1_MASK));
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_SECOND_PRECHARGE_PERIOD,
+ SSD1353_DEFAULT_SECOND_PRECHARGE_PERIOD);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_SECOND_PRECHARGE_SPEED,
+ SSD1353_DEFAULT_SECOND_PRECHARGE_SPEED);
+ if (error)
+ return error;
+
+ /*
+ * Configure physical display panel layout.
+ */
+ SSDFB_CMD2(SSD1353_CMD_SET_MULTIPLEX_RATIO, sc->sc_p->p_multiplex_ratio);
+ if (error)
+ return error;
+ remap = sc->sc_p->p_compin_cfg;
+ if (sc->sc_upsidedown)
+ remap ^= SSD1353_REMAP_COM_DIRECTION;
+ else
+ remap ^= SSD1353_REMAP_SEG_DIRECTION;
+ SSDFB_CMD2(SSD1353_CMD_REMAP_COLOR_DEPTH, remap);
+ if (error)
+ return error;
+
+ /*
+ * Contrast settings.
+ */
+ SSDFB_CMD1(SSD1353_CMD_SET_DEFAULT_GRAY_SCALE_TABLE);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_CONTRAST_CONTROL_A, sc->sc_contrast);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_CONTRAST_CONTROL_B, sc->sc_contrast);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_CONTRAST_CONTROL_C, sc->sc_contrast);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_MASTER_CURRENT_CONTROL,
+ SSD1353_DEFAULT_MASTER_CURRENT_ATTENUATION);
+ if (error)
+ return error;
+
+ /*
+ * Reset display engine state.
+ */
+ SSDFB_CMD2(SSD1353_CMD_SET_DISPLAY_OFFSET, 0x00);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1353_CMD_SET_DISPLAY_START_LINE, 0x00);
+ if (error)
+ return error;
+ SSDFB_CMD1(sc->sc_inverse
+ ? SSD1353_CMD_INVERSE_DISPLAY
+ : SSD1353_CMD_NORMAL_DISPLAY);
+ if (error)
+ return error;
+
+ ssdfb_clear_screen(sc);
+ error = ssdfb_sync(sc, usepoll);
+ if (error)
+ return error;
+
+ error = ssdfb_set_display_on(sc, true, usepoll);
+
+ return error;
+}
+
+static int
ssdfb_set_contrast(struct ssdfb_softc *sc, uint8_t value, bool usepoll)
{
uint8_t cmd[2];
+ int error;
+ cmd[1] = sc->sc_contrast = value;
switch (sc->sc_p->p_controller_id) {
case SSDFB_CONTROLLER_SSD1322:
cmd[0] = SSD1322_CMD_SET_CONTRAST_CURRENT;
break;
+ case SSDFB_CONTROLLER_SSD1353:
+ cmd[0] = SSD1353_CMD_SET_CONTRAST_CONTROL_A;
+ error = sc->sc_cmd(sc->sc_cookie, cmd, sizeof(cmd), usepoll);
+ if (error)
+ return error;
+ cmd[0] = SSD1353_CMD_SET_CONTRAST_CONTROL_B;
+ error = sc->sc_cmd(sc->sc_cookie, cmd, sizeof(cmd), usepoll);
+ if (error)
+ return error;
+ cmd[0] = SSD1353_CMD_SET_CONTRAST_CONTROL_C;
default:
cmd[0] = SSDFB_CMD_SET_CONTRAST_CONTROL;
}
- cmd[1] = sc->sc_contrast = value;
return sc->sc_cmd(sc->sc_cookie, cmd, sizeof(cmd), usepoll);
}
@@ -1200,6 +1371,57 @@
return 0;
}
+static int
+ssdfb_sync_ssd1353(struct ssdfb_softc *sc, bool usepoll)
+{
+ int width = sc->sc_p->p_width;
+ int height = sc->sc_p->p_height;
+ struct rasops_info *ri = &sc->sc_ri;
+ int x, y;
+ uint32_t *src, *blockp;
+ int x1, x2, y1, y2;
+
+ /*
+ * Transfer rasops bitmap into gddram shadow buffer while keeping track
+ * of the bounding box of the dirty region we scribbled over.
+ */
+ x1 = width;
+ x2 = -1;
+ y1 = height;
+ y2 = -1;
+ blockp = (uint32_t*)sc->sc_gddram;
+ for (y = 0; y < height; y++) {
+ src = (uint32_t*)&ri->ri_bits[y * ri->ri_stride];
+ for (x = 0; x < width; x++) {
+ if (*blockp != *src) {
+ *blockp = *src;
+ if (x1 > x)
+ x1 = x;
+ if (x2 < x)
+ x2 = x;
+ if (y1 > y)
+ y1 = y;
+ if (y2 < y)
+ y2 = y;
+ }
+ blockp++;
+ src++;
+ }
+ }
+
+ blockp = (uint32_t*)sc->sc_gddram;
+ if (x2 != -1)
+ return sc->sc_transfer_rect(sc->sc_cookie,
+ x1 + sc->sc_p->p_panel_shift,
+ x2 + sc->sc_p->p_panel_shift,
+ y1,
+ y2,
+ (uint8_t*)&blockp[y1 * width + x1],
+ width * sc->sc_p->p_bits_per_pixel / 8,
+ usepoll);
+ return 0;
+}
+
static uint64_t
ssdfb_transpose_block(uint8_t *src, size_t src_stride)
{
diff -r 0e2e9d3cdf04 -r 17574e2f1317 sys/dev/ic/ssdfbvar.h
--- a/sys/dev/ic/ssdfbvar.h Thu Aug 05 12:52:47 2021 +0000
+++ b/sys/dev/ic/ssdfbvar.h Thu Aug 05 19:07:09 2021 +0000
Home |
Main Index |
Thread Index |
Old Index