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: add support for SSD1322
details: https://anonhg.NetBSD.org/src/rev/741a8c553f9f
branches: trunk
changeset: 460745:741a8c553f9f
user: tnn <tnn%NetBSD.org@localhost>
date: Sat Nov 02 14:18:36 2019 +0000
description:
ssdfb: add support for SSD1322
diffstat:
sys/dev/ic/ssdfb.c | 362 ++++++++++++++++++++++++++++++++++++++++++-------
sys/dev/ic/ssdfbvar.h | 11 +-
2 files changed, 311 insertions(+), 62 deletions(-)
diffs (truncated from 649 to 300 lines):
diff -r ac53471c3fb2 -r 741a8c553f9f sys/dev/ic/ssdfb.c
--- a/sys/dev/ic/ssdfb.c Sat Nov 02 11:56:34 2019 +0000
+++ b/sys/dev/ic/ssdfb.c Sat Nov 02 14:18:36 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ssdfb.c,v 1.8 2019/10/22 22:03:27 tnn Exp $ */
+/* $NetBSD: ssdfb.c,v 1.9 2019/11/02 14:18:36 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.8 2019/10/22 22:03:27 tnn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ssdfb.c,v 1.9 2019/11/02 14:18:36 tnn Exp $");
#include "opt_ddb.h"
@@ -73,6 +73,7 @@
/* hardware interface */
static int ssdfb_init_ssd1306(struct ssdfb_softc *);
+static int ssdfb_init_ssd1322(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);
@@ -85,8 +86,9 @@
static void ssdfb_thread(void *);
static void ssdfb_set_usepoll(struct ssdfb_softc *, bool);
static int ssdfb_sync(struct ssdfb_softc *, bool);
-static uint64_t ssdfb_transpose_block_1bpp(uint8_t *, size_t);
-static uint64_t ssdfb_transpose_block_8bpp(uint8_t *, size_t);
+static int ssdfb_sync_ssd1306(struct ssdfb_softc *, bool);
+static int ssdfb_sync_ssd1322(struct ssdfb_softc *, bool);
+static uint64_t ssdfb_transpose_block(uint8_t *, size_t);
/* misc helpers */
static const struct ssdfb_product *
@@ -114,6 +116,7 @@
.p_name = "generic",
.p_width = 128,
.p_height = 64,
+ .p_bits_per_pixel = 1,
.p_panel_shift = 0,
.p_fosc = 0x8,
.p_fosc_div = 0,
@@ -124,9 +127,8 @@
.p_vcomh_deselect_level = SSD1306_VCOMH_DESELECT_LEVEL_0_77_VCC,
.p_default_contrast = 0x7f,
.p_multiplex_ratio = 0x3f,
- .p_chargepump_cmd = SSD1306_CMD_SET_CHARGE_PUMP,
- .p_chargepump_arg = SSD1306_CHARGE_PUMP_ENABLE,
- .p_init = ssdfb_init_ssd1306
+ .p_init = ssdfb_init_ssd1306,
+ .p_sync = ssdfb_sync_ssd1306
},
{
.p_product_id = SSDFB_PRODUCT_SH1106_GENERIC,
@@ -134,6 +136,7 @@
.p_name = "generic",
.p_width = 128,
.p_height = 64,
+ .p_bits_per_pixel = 1,
.p_panel_shift = 2,
.p_fosc = 0x5,
.p_fosc_div = 0,
@@ -144,9 +147,8 @@
.p_vcomh_deselect_level = SH1106_VCOMH_DESELECT_LEVEL_DEFAULT,
.p_default_contrast = 0x80,
.p_multiplex_ratio = 0x3f,
- .p_chargepump_cmd = SH1106_CMD_SET_CHARGE_PUMP_7V4,
- .p_chargepump_arg = SSDFB_CMD_NOP,
- .p_init = ssdfb_init_ssd1306
+ .p_init = ssdfb_init_ssd1306,
+ .p_sync = ssdfb_sync_ssd1306
},
{
.p_product_id = SSDFB_PRODUCT_ADAFRUIT_938,
@@ -154,6 +156,7 @@
.p_name = "Adafruit Industries, LLC product 938",
.p_width = 128,
.p_height = 64,
+ .p_bits_per_pixel = 1,
.p_panel_shift = 0,
.p_fosc = 0x8,
.p_fosc_div = 0,
@@ -163,9 +166,8 @@
.p_vcomh_deselect_level = 0x40,
.p_default_contrast = 0x8f,
.p_multiplex_ratio = 0x3f,
- .p_chargepump_cmd = SSD1306_CMD_SET_CHARGE_PUMP,
- .p_chargepump_arg = SSD1306_CHARGE_PUMP_ENABLE,
- .p_init = ssdfb_init_ssd1306
+ .p_init = ssdfb_init_ssd1306,
+ .p_sync = ssdfb_sync_ssd1306
},
{
.p_product_id = SSDFB_PRODUCT_ADAFRUIT_931,
@@ -173,6 +175,7 @@
.p_name = "Adafruit Industries, LLC product 931",
.p_width = 128,
.p_height = 32,
+ .p_bits_per_pixel = 1,
.p_panel_shift = 0,
.p_fosc = 0x8,
.p_fosc_div = 0,
@@ -182,9 +185,24 @@
.p_vcomh_deselect_level = 0x40,
.p_default_contrast = 0x8f,
.p_multiplex_ratio = 0x1f,
- .p_chargepump_cmd = SSD1306_CMD_SET_CHARGE_PUMP,
- .p_chargepump_arg = SSD1306_CHARGE_PUMP_ENABLE,
- .p_init = ssdfb_init_ssd1306
+ .p_init = ssdfb_init_ssd1306,
+ .p_sync = ssdfb_sync_ssd1306
+ },
+ {
+ .p_product_id = SSDFB_PRODUCT_SSD1322_GENERIC,
+ .p_controller_id = SSDFB_CONTROLLER_SSD1322,
+ .p_name = "generic",
+ .p_width = 256,
+ .p_height = 64,
+ .p_bits_per_pixel = 4,
+ .p_panel_shift = 28,
+ .p_vcomh_deselect_level = SSD1322_DEFAULT_VCOMH,
+ .p_fosc = SSD1322_DEFAULT_FREQUENCY,
+ .p_fosc_div = SSD1322_DEFAULT_DIVIDER,
+ .p_default_contrast = SSD1322_DEFAULT_CONTRAST_CURRENT,
+ .p_multiplex_ratio = 0x3f,
+ .p_init = ssdfb_init_ssd1322,
+ .p_sync = ssdfb_sync_ssd1322
}
};
@@ -198,6 +216,7 @@
#define SSDFB_CMD1(c) do { cmd[0] = (c); error = sc->sc_cmd(sc->sc_cookie, cmd, 1, usepoll); } while(0)
#define SSDFB_CMD2(c, a) do { cmd[0] = (c); cmd[1] = (a); error = sc->sc_cmd(sc->sc_cookie, cmd, 2, usepoll); } while(0)
+#define SSDFB_CMD3(c, a, b) do { cmd[0] = (c); cmd[1] = (a); cmd[2] = (b); error = sc->sc_cmd(sc->sc_cookie, cmd, 3, usepoll); } while(0)
void
ssdfb_attach(struct ssdfb_softc *sc, int flags)
@@ -207,6 +226,7 @@
int error = 0;
long defattr;
const struct ssdfb_product *p;
+ int kt_flags;
p = ssdfb_lookup_product(flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK);
if (p == NULL) {
@@ -226,7 +246,8 @@
sc->sc_upsidedown = flags & SSDFB_ATTACH_FLAG_UPSIDEDOWN ? true : false;
sc->sc_backoff = 1;
sc->sc_contrast = sc->sc_p->p_default_contrast;
- sc->sc_gddram_len = sc->sc_p->p_width * sc->sc_p->p_height / 8;
+ sc->sc_gddram_len = sc->sc_p->p_width * sc->sc_p->p_height
+ * sc->sc_p->p_bits_per_pixel / 8;
sc->sc_gddram = kmem_alloc(sc->sc_gddram_len, KM_SLEEP);
if (sc->sc_gddram == NULL)
goto out;
@@ -246,13 +267,17 @@
aprint_error_dev(sc->sc_dev, "no font\n");
goto out;
}
+#ifdef SSDFB_USE_NATIVE_DEPTH
+ ri->ri_depth = sc->sc_p->p_bits_per_pixel;
+#else
ri->ri_depth = 8;
+#endif
ri->ri_font = sc->sc_font;
ri->ri_width = sc->sc_p->p_width;
ri->ri_height = sc->sc_p->p_height;
ri->ri_stride = ri->ri_width * ri->ri_depth / 8;
ri->ri_hw = sc;
- ri->ri_flg = RI_FULLCLEAR;
+ ri->ri_flg = RI_FULLCLEAR | RI_FORCEMONO;
sc->sc_ri_bits_len = round_page(ri->ri_stride * ri->ri_height);
ri->ri_bits = (u_char *)uvm_km_alloc(kernel_map, sc->sc_ri_bits_len,
0, UVM_KMF_WIRED);
@@ -308,9 +333,12 @@
mutex_init(&sc->sc_cond_mtx, MUTEX_DEFAULT, IPL_SCHED);
cv_init(&sc->sc_cond, "ssdfb");
- error = kthread_create(PRI_SOFTCLOCK, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN,
- NULL, ssdfb_thread, sc, &sc->sc_thread, "%s",
- device_xname(sc->sc_dev));
+ kt_flags = KTHREAD_MUSTJOIN;
+ /* XXX spi(4) is not MPSAFE yet. */
+ if (ISSET(flags, SSDFB_ATTACH_FLAG_MPSAFE))
+ kt_flags |= KTHREAD_MPSAFE;
+ error = kthread_create(PRI_SOFTCLOCK, kt_flags, NULL, ssdfb_thread, sc,
+ &sc->sc_thread, "%s", device_xname(sc->sc_dev));
if (error) {
cv_destroy(&sc->sc_cond);
mutex_destroy(&sc->sc_cond_mtx);
@@ -379,7 +407,10 @@
struct ssdfb_softc *sc = v;
struct wsdisplay_param *wdp;
struct wsdisplay_cmap *wc;
- u_char cmap[] = {0, 0xff};
+ u_char cmap[16];
+ int cmaplen = 1 << sc->sc_p->p_bits_per_pixel;
+ int i;
+ struct wsdisplayio_fbinfo *fbi;
int error;
switch (cmd) {
@@ -391,12 +422,15 @@
.width = sc->sc_ri.ri_width,
.height = sc->sc_ri.ri_height,
.depth = sc->sc_ri.ri_depth,
- .cmsize = 2
+ .cmsize = cmaplen
};
return 0;
case WSDISPLAYIO_GET_FBINFO:
- return wsdisplayio_get_fbinfo(&sc->sc_ri,
- (struct wsdisplayio_fbinfo *)data);
+ fbi = (struct wsdisplayio_fbinfo *)data;
+ error = wsdisplayio_get_fbinfo(&sc->sc_ri, fbi);
+ fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = cmaplen;
+ /* fbi->fbi_pixeltype = WSFB_GREYSCALE */;
+ return error;
case WSDISPLAYIO_LINEBYTES:
*(u_int *)data = sc->sc_ri.ri_stride;
return 0;
@@ -453,9 +487,12 @@
#endif
case WSDISPLAYIO_GETCMAP:
wc = (struct wsdisplay_cmap *)data;
- if (wc->index >= __arraycount(cmap) ||
- wc->count > __arraycount(cmap) - wc->index)
+ if (wc->index >= cmaplen ||
+ wc->count > cmaplen - wc->index)
return EINVAL;
+ for(i = 0; i < cmaplen; i++) {
+ cmap[i] = 255 * i / (cmaplen - 1);
+ }
error = copyout(&cmap[wc->index], wc->red, wc->count);
if (error)
return error;
@@ -661,22 +698,152 @@
return error;
/*
- * Start charge pump.
+ * Start charge pumps.
*/
- SSDFB_CMD2(sc->sc_p->p_chargepump_cmd, sc->sc_p->p_chargepump_arg);
- if (error)
- return error;
-
if (sc->sc_p->p_controller_id == SSDFB_CONTROLLER_SH1106) {
+ SSDFB_CMD1(SH1106_CMD_SET_CHARGE_PUMP_7V4);
+ if (error)
+ return error;
SSDFB_CMD2(SH1106_CMD_SET_DC_DC, SH1106_DC_DC_ON);
if (error)
return error;
+ } else {
+ SSDFB_CMD2(SSD1306_CMD_SET_CHARGE_PUMP,
+ SSD1306_CHARGE_PUMP_ENABLE);
+ if (error)
+ return error;
}
ssdfb_clear_screen(sc);
+ error = sc->sc_p->p_sync(sc, usepoll);
+ if (error)
+ return error;
+ error = ssdfb_set_display_on(sc, true, usepoll);
+
+ return error;
+}
+
+static int
+ssdfb_init_ssd1322(struct ssdfb_softc *sc)
+{
+ int error;
+ uint8_t cmd[3];
+ bool usepoll = true;
+ uint8_t remap;
+ uint8_t dualcom;
+
+ /*
+ * Enter sleep.
+ */
+ SSDFB_CMD2(SSD1322_CMD_SET_COMMAND_LOCK, SSD1322_COMMAND_UNLOCK_MAGIC);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1322_CMD_SET_SLEEP_MODE_ON);
+ if (error)
+ return error;
+
+ /*
+ * Start charge pumps.
+ */
+ SSDFB_CMD2(SSD1322_CMD_FUNCTION_SELECTION,
+ SSD1322_FUNCTION_SELECTION_INTERNAL_VDD);
+ if (error)
Home |
Main Index |
Thread Index |
Old Index