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/068e2bc1938a
branches:  trunk
changeset: 846154:068e2bc1938a
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 4bc7f000f65d -r 068e2bc1938a 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