Module Name: src
Committed By: tnn
Date: Sat Nov 2 14:18:36 UTC 2019
Modified Files:
src/sys/dev/ic: ssdfb.c ssdfbvar.h
Log Message:
ssdfb: add support for SSD1322
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/ic/ssdfb.c
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/ic/ssdfbvar.h
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/ic/ssdfb.c
diff -u src/sys/dev/ic/ssdfb.c:1.8 src/sys/dev/ic/ssdfb.c:1.9
--- src/sys/dev/ic/ssdfb.c:1.8 Tue Oct 22 22:03:27 2019
+++ src/sys/dev/ic/ssdfb.c Sat Nov 2 14:18:36 2019
@@ -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 @@ static void ssdfb_cursor(void *, int, in
/* 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_damage(struct ssdfb_so
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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct ssdfb_product ssdfb_
.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 @@ static const struct wsdisplay_accessops
#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 @@ ssdfb_attach(struct ssdfb_softc *sc, int
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 @@ ssdfb_attach(struct ssdfb_softc *sc, int
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 @@ ssdfb_attach(struct ssdfb_softc *sc, int
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 @@ ssdfb_attach(struct ssdfb_softc *sc, int
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 @@ ssdfb_ioctl(void *v, void *vs, u_long cm
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 @@ ssdfb_ioctl(void *v, void *vs, u_long cm
.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 @@ ssdfb_ioctl(void *v, void *vs, u_long cm
#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 @@ ssdfb_init_ssd1306(struct ssdfb_softc *s
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)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_VCOMH, sc->sc_p->p_vcomh_deselect_level);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_PRE_CHARGE_VOLTAGE_LEVEL,
+ SSD1322_DEFAULT_PRE_CHARGE_VOLTAGE_LEVEL);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_GPIO,
+ SSD1322_GPIO0_DISABLED | SSD1322_GPIO1_DISABLED);
+ if (error)
+ return error;
+
+ /*
+ * Configure timing characteristics.
+ */
+ SSDFB_CMD2(SSD1322_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(SSD1322_CMD_SET_PHASE_LENGTH,
+ __SHIFTIN(SSD1322_DEFAULT_PHASE_2,
+ SSD1322_PHASE_LENGTH_PHASE_2_MASK) |
+ __SHIFTIN(SSD1322_DEFAULT_PHASE_1,
+ SSD1322_PHASE_LENGTH_PHASE_1_MASK));
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_SECOND_PRECHARGE_PERIOD,
+ SSD1322_DEFAULT_SECOND_PRECHARGE);
+ if (error)
+ return error;
+
+ /*
+ * Configure physical display panel layout.
+ */
+ SSDFB_CMD2(SSD1322_CMD_SET_MUX_RATIO, sc->sc_p->p_multiplex_ratio);
+ if (error)
+ return error;
+ if (sc->sc_upsidedown)
+ remap = 0x10;
+ else
+ remap = 0x2;
+ dualcom = 0x1;
+ if (sc->sc_p->p_multiplex_ratio <= 63)
+ dualcom |= 0x10;
+ SSDFB_CMD3(SSD1322_CMD_SET_REMAP_AND_DUAL_COM_LINE_MODE, remap, dualcom);
+ if (error)
+ return error;
+
+ /*
+ * Contrast settings.
+ */
+ SSDFB_CMD1(SSD1322_CMD_SET_DEFAULT_GRAY_SCALE_TABLE);
+ if (error)
+ return error;
+ SSDFB_CMD3(SSD1322_CMD_DISPLAY_ENHANCEMENT_A,
+ SSD1322_DISPLAY_ENHANCEMENT_A_MAGIC1,
+ SSD1322_DISPLAY_ENHANCEMENT_A_MAGIC2);
+ if (error)
+ return error;
+ SSDFB_CMD3(SSD1322_CMD_DISPLAY_ENHANCEMENT_B,
+ SSD1322_DISPLAY_ENHANCEMENT_B_MAGIC1,
+ SSD1322_DISPLAY_ENHANCEMENT_B_MAGIC2);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_CONTRAST_CURRENT,
+ sc->sc_contrast);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_MASTER_CONTRAST_CURRENT_CONTROL,
+ SSD1322_DEFAULT_MASTER_CONTRAST_CURRENT_CONTROL);
+ if (error)
+ return error;
+
+ /*
+ * Reset display engine state.
+ */
+ SSDFB_CMD2(SSD1322_CMD_SET_DISPLAY_OFFSET, 0x00);
+ if (error)
+ return error;
+ SSDFB_CMD2(SSD1322_CMD_SET_DISPLAY_START_LINE, 0x00);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1322_CMD_NORMAL_DISPLAY + (uint8_t)sc->sc_inverse);
+ if (error)
+ return error;
+ SSDFB_CMD1(SSD1322_CMD_EXIT_PARTIAL_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;
@@ -686,12 +853,17 @@ static int
ssdfb_set_contrast(struct ssdfb_softc *sc, uint8_t value, bool usepoll)
{
uint8_t cmd[2];
- int error;
- sc->sc_contrast = value;
- SSDFB_CMD2(SSDFB_CMD_SET_CONTRAST_CONTROL, value);
+ switch (sc->sc_p->p_controller_id) {
+ case SSDFB_CONTROLLER_SSD1322:
+ cmd[0] = SSD1322_CMD_SET_CONTRAST_CURRENT;
+ break;
+ default:
+ cmd[0] = SSDFB_CMD_SET_CONTRAST_CONTROL;
+ }
+ cmd[1] = sc->sc_contrast = value;
- return error;
+ return sc->sc_cmd(sc->sc_cookie, cmd, sizeof(cmd), usepoll);
}
static int
@@ -795,8 +967,10 @@ ssdfb_clear_modify(struct ssdfb_softc *s
bool ret;
if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
+ mutex_enter(&sc->sc_cond_mtx);
ret = sc->sc_modified;
sc->sc_modified = false;
+ mutex_exit(&sc->sc_cond_mtx);
return ret;
}
@@ -843,14 +1017,15 @@ ssdfb_thread(void *arg)
continue;
}
sc->sc_backoff = 1;
- (void) ssdfb_clear_modify(sc);
- if (sc->sc_usepoll)
- continue;
mutex_exit(&sc->sc_cond_mtx);
- error = ssdfb_sync(sc, false);
- if (error)
- device_printf(sc->sc_dev, "ssdfb_sync: error %d\n",
- error);
+ (void) ssdfb_clear_modify(sc);
+ if (!sc->sc_usepoll) {
+ error = ssdfb_sync(sc, false);
+ if (error)
+ device_printf(sc->sc_dev,
+ "ssdfb_sync: error %d\n",
+ error);
+ }
mutex_enter(&sc->sc_cond_mtx);
}
@@ -867,6 +1042,12 @@ ssdfb_set_usepoll(struct ssdfb_softc *sc
static int
ssdfb_sync(struct ssdfb_softc *sc, bool usepoll)
{
+ return sc->sc_p->p_sync(sc, usepoll);
+}
+
+static int
+ssdfb_sync_ssd1306(struct ssdfb_softc *sc, bool usepoll)
+{
struct rasops_info *ri = &sc->sc_ri;
int block_size = 8;
int ri_block_stride = ri->ri_stride * block_size;
@@ -888,12 +1069,10 @@ ssdfb_sync(struct ssdfb_softc *sc, bool
y1 = height_in_blocks;
y2 = -1;
for (y = 0; y < height_in_blocks; y++) {
- src = &ri->ri_bits[y*ri_block_stride];
+ src = &ri->ri_bits[y * ri_block_stride];
blockp = &sc->sc_gddram[y * width_in_blocks];
for (x = 0; x < width_in_blocks; x++) {
- raw_block = (ri->ri_depth == 1)
- ? ssdfb_transpose_block_1bpp(src, ri->ri_stride)
- : ssdfb_transpose_block_8bpp(src, ri->ri_stride);
+ raw_block = ssdfb_transpose_block(src, ri->ri_stride);
if (raw_block != blockp->raw) {
blockp->raw = raw_block;
if (x1 > x)
@@ -922,10 +1101,86 @@ ssdfb_sync(struct ssdfb_softc *sc, bool
return 0;
}
+static int
+ssdfb_sync_ssd1322(struct ssdfb_softc *sc, bool usepoll)
+{
+ struct rasops_info *ri = &sc->sc_ri;
+ int block_size_w = 4;
+ int width = sc->sc_p->p_width;
+ int height = sc->sc_p->p_height;
+ int width_in_blocks = width / block_size_w;
+ int x, y;
+ uint16_t *blockp;
+ uint16_t raw_block;
+ uint16_t *src;
+ uint32_t *src32;
+ 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 = sc->sc_p->p_width;
+ x2 = -1;
+ y1 = sc->sc_p->p_height;
+ y2 = -1;
+ blockp = (uint16_t*)sc->sc_gddram;
+ for (y = 0; y < height; y++) {
+ src = (uint16_t*)&ri->ri_bits[y * ri->ri_stride];
+ src32 = (uint32_t*)src;
+ for (x = 0; x < width_in_blocks; x++) {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+# ifdef SSDFB_USE_NATIVE_DEPTH
+ raw_block =
+ ((*src << 12) & 0xf000) |
+ ((*src << 4) & 0x0f00) |
+ ((*src >> 4) & 0x00f0) |
+ ((*src >> 12) & 0x000f);
+ src++;
+# else
+ raw_block =
+ ((*src32 << 8) & 0x0f00) |
+ ((*src32 << 4) & 0xf000) |
+ ((*src32 >> 16) & 0x000f) |
+ ((*src32 >> 20) & 0x00f0);
+# endif
+ src32++;
+#else
+# error please add big endian host support here
+#endif
+ if (raw_block != *blockp) {
+ *blockp = raw_block;
+ if (x1 > x)
+ x1 = x;
+ if (x2 < x)
+ x2 = x;
+ if (y1 > y)
+ y1 = y;
+ if (y2 < y)
+ y2 = y;
+ }
+ blockp++;
+ }
+ }
+
+ blockp = (uint16_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_in_blocks + x1],
+ width * sc->sc_p->p_bits_per_pixel / 8,
+ usepoll);
+ return 0;
+}
+
static uint64_t
-ssdfb_transpose_block_1bpp(uint8_t *src, size_t src_stride)
+ssdfb_transpose_block(uint8_t *src, size_t src_stride)
{
uint64_t x = 0;
+#ifdef SSDFB_USE_NATIVE_DEPTH
uint64_t t;
int i;
@@ -949,14 +1204,7 @@ ssdfb_transpose_block_1bpp(uint8_t *src,
t = (x ^ (x >> 7)) & 0x00AA00AA00AA00AAULL;
x = x ^ t ^ (t << 7);
x = bswap64(x);
-
- return htole64(x);
-}
-
-static uint64_t
-ssdfb_transpose_block_8bpp(uint8_t *src, size_t src_stride)
-{
- uint64_t x = 0;
+#else
int m, n;
for (m = 0; m < 8; m++) {
@@ -965,7 +1213,7 @@ ssdfb_transpose_block_8bpp(uint8_t *src,
x |= src[n * src_stride + m] ? (1ULL << 63) : 0;
}
}
-
+#endif
return htole64(x);
}
Index: src/sys/dev/ic/ssdfbvar.h
diff -u src/sys/dev/ic/ssdfbvar.h:1.4 src/sys/dev/ic/ssdfbvar.h:1.5
--- src/sys/dev/ic/ssdfbvar.h:1.4 Tue Oct 22 22:03:27 2019
+++ src/sys/dev/ic/ssdfbvar.h Sat Nov 2 14:18:36 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ssdfbvar.h,v 1.4 2019/10/22 22:03:27 tnn Exp $ */
+/* $NetBSD: ssdfbvar.h,v 1.5 2019/11/02 14:18:36 tnn Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -36,6 +36,7 @@
#define SSDFB_ATTACH_FLAG_UPSIDEDOWN 0x00000100
#define SSDFB_ATTACH_FLAG_INVERSE 0x00000200
#define SSDFB_ATTACH_FLAG_CONSOLE 0x00000400
+#define SSDFB_ATTACH_FLAG_MPSAFE 0x00000800
/*
* Fundamental commands
@@ -159,14 +160,14 @@
#define SSD1322_CMD_ENTIRE_DISPLAY_ON 0xa5
#define SSD1322_CMD_NORMAL_DISPLAY 0xa6
#define SSD1322_CMD_INVERSE_DISPLAY 0xa7
+#define SSD1322_CMD_SET_SLEEP_MODE_ON 0xae
+#define SSD1322_CMD_SET_SLEEP_MODE_OFF 0xaf
#define SSD1322_CMD_ENABLE_PARTIAL_DISPLAY 0xa8
#define SSD1322_CMD_EXIT_PARTIAL_DISPLAY 0xa9
#define SSD1322_CMD_FUNCTION_SELECTION 0xab
#define SSD1322_FUNCTION_SELECTION_EXTERNAL_VDD 0
#define SSD1322_FUNCTION_SELECTION_INTERNAL_VDD __BIT(0)
-#define SSD1322_CMD_SET_SLEEP_MODE_ON 0xae
-#define SSD1322_CMD_SET_SLEEP_MODE_OFF 0xaf
#define SSD1322_CMD_SET_PHASE_LENGTH 0xb1
#define SSD1322_PHASE_LENGTH_PHASE_2_MASK __BITS(7, 4)
#define SSD1322_DEFAULT_PHASE_2 7
@@ -245,6 +246,7 @@ struct ssdfb_product {
const char *p_name;
int p_width;
int p_height;
+ int p_bits_per_pixel;
int p_panel_shift;
uint8_t p_fosc;
uint8_t p_fosc_div;
@@ -254,9 +256,8 @@ struct ssdfb_product {
uint8_t p_vcomh_deselect_level;
uint8_t p_default_contrast;
uint8_t p_multiplex_ratio;
- uint8_t p_chargepump_cmd;
- uint8_t p_chargepump_arg;
int (*p_init)(struct ssdfb_softc *);
+ int (*p_sync)(struct ssdfb_softc *, bool);
};
struct ssdfb_softc {