root/drivers/staging/fbtft/fb_ssd1325.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_display
  2. rgb565_to_g16
  3. set_addr_win
  4. blank
  5. set_gamma
  6. write_vmem

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * FB driver for the SSD1325 OLED Controller
   4  */
   5 
   6 #include <linux/module.h>
   7 #include <linux/kernel.h>
   8 #include <linux/init.h>
   9 #include <linux/gpio/consumer.h>
  10 #include <linux/delay.h>
  11 
  12 #include "fbtft.h"
  13 
  14 #define DRVNAME         "fb_ssd1325"
  15 
  16 #define WIDTH 128
  17 #define HEIGHT 64
  18 #define GAMMA_NUM   1
  19 #define GAMMA_LEN   15
  20 #define DEFAULT_GAMMA "7 1 1 1 1 2 2 3 3 4 4 5 5 6 6"
  21 
  22 /*
  23  * write_reg() caveat:
  24  *
  25  *    This doesn't work because D/C has to be LOW for both values:
  26  *      write_reg(par, val1, val2);
  27  *
  28  *    Do it like this:
  29  *      write_reg(par, val1);
  30  *      write_reg(par, val2);
  31  */
  32 
  33 /* Init sequence taken from the Adafruit SSD1306 Arduino library */
  34 static int init_display(struct fbtft_par *par)
  35 {
  36         par->fbtftops.reset(par);
  37 
  38         gpiod_set_value(par->gpio.cs, 0);
  39 
  40         write_reg(par, 0xb3);
  41         write_reg(par, 0xf0);
  42         write_reg(par, 0xae);
  43         write_reg(par, 0xa1);
  44         write_reg(par, 0x00);
  45         write_reg(par, 0xa8);
  46         write_reg(par, 0x3f);
  47         write_reg(par, 0xa0);
  48         write_reg(par, 0x45);
  49         write_reg(par, 0xa2);
  50         write_reg(par, 0x40);
  51         write_reg(par, 0x75);
  52         write_reg(par, 0x00);
  53         write_reg(par, 0x3f);
  54         write_reg(par, 0x15);
  55         write_reg(par, 0x00);
  56         write_reg(par, 0x7f);
  57         write_reg(par, 0xa4);
  58         write_reg(par, 0xaf);
  59 
  60         return 0;
  61 }
  62 
  63 static uint8_t rgb565_to_g16(u16 pixel)
  64 {
  65         u16 b = pixel & 0x1f;
  66         u16 g = (pixel & (0x3f << 5)) >> 5;
  67         u16 r = (pixel & (0x1f << (5 + 6))) >> (5 + 6);
  68 
  69         pixel = (299 * r + 587 * g + 114 * b) / 195;
  70         if (pixel > 255)
  71                 pixel = 255;
  72         return (uint8_t)pixel / 16;
  73 }
  74 
  75 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
  76 {
  77         fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
  78                       "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe,
  79                       ye);
  80 
  81         write_reg(par, 0x75);
  82         write_reg(par, 0x00);
  83         write_reg(par, 0x3f);
  84         write_reg(par, 0x15);
  85         write_reg(par, 0x00);
  86         write_reg(par, 0x7f);
  87 }
  88 
  89 static int blank(struct fbtft_par *par, bool on)
  90 {
  91         fbtft_par_dbg(DEBUG_BLANK, par, "(%s=%s)\n",
  92                       __func__, on ? "true" : "false");
  93 
  94         if (on)
  95                 write_reg(par, 0xAE);
  96         else
  97                 write_reg(par, 0xAF);
  98         return 0;
  99 }
 100 
 101 /*
 102  * Grayscale Lookup Table
 103  * GS1 - GS15
 104  * The "Gamma curve" contains the relative values between the entries
 105  * in the Lookup table.
 106  *
 107  * 0 = Setting of GS1 < Setting of GS2 < Setting of GS3.....<
 108  * Setting of GS14 < Setting of GS15
 109  */
 110 static int set_gamma(struct fbtft_par *par, u32 *curves)
 111 {
 112         int i;
 113 
 114         fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
 115 
 116         for (i = 0; i < GAMMA_LEN; i++) {
 117                 if (i > 0 && curves[i] < 1) {
 118                         dev_err(par->info->device,
 119                                 "Illegal value in Grayscale Lookup Table at index %d.\n"
 120                                 "Must be greater than 0\n", i);
 121                         return -EINVAL;
 122                 }
 123                 if (curves[i] > 7) {
 124                         dev_err(par->info->device,
 125                                 "Illegal value(s) in Grayscale Lookup Table.\n"
 126                                 "At index=%d, the accumulated value has exceeded 7\n",
 127                                 i);
 128                         return -EINVAL;
 129                 }
 130         }
 131         write_reg(par, 0xB8);
 132         for (i = 0; i < 8; i++)
 133                 write_reg(par, (curves[i] & 0xFF));
 134         return 0;
 135 }
 136 
 137 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
 138 {
 139         u16 *vmem16 = (u16 *)par->info->screen_buffer;
 140         u8 *buf = par->txbuf.buf;
 141         u8 n1;
 142         u8 n2;
 143         int y, x;
 144         int ret;
 145 
 146         for (x = 0; x < par->info->var.xres; x++) {
 147                 if (x % 2)
 148                         continue;
 149                 for (y = 0; y < par->info->var.yres; y++) {
 150                         n1 = rgb565_to_g16(vmem16[y * par->info->var.xres + x]);
 151                         n2 = rgb565_to_g16(vmem16
 152                                            [y * par->info->var.xres + x + 1]);
 153                         *buf = (n1 << 4) | n2;
 154                         buf++;
 155                 }
 156         }
 157 
 158         gpiod_set_value(par->gpio.dc, 1);
 159 
 160         /* Write data */
 161         ret = par->fbtftops.write(par, par->txbuf.buf,
 162                                 par->info->var.xres * par->info->var.yres / 2);
 163         if (ret < 0)
 164                 dev_err(par->info->device,
 165                         "%s: write failed and returned: %d\n", __func__, ret);
 166 
 167         return ret;
 168 }
 169 
 170 static struct fbtft_display display = {
 171         .regwidth = 8,
 172         .width = WIDTH,
 173         .height = HEIGHT,
 174         .txbuflen = WIDTH * HEIGHT / 2,
 175         .gamma_num = GAMMA_NUM,
 176         .gamma_len = GAMMA_LEN,
 177         .gamma = DEFAULT_GAMMA,
 178         .fbtftops = {
 179                 .write_vmem = write_vmem,
 180                 .init_display = init_display,
 181                 .set_addr_win = set_addr_win,
 182                 .blank = blank,
 183                 .set_gamma = set_gamma,
 184         },
 185 };
 186 
 187 FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1325", &display);
 188 
 189 MODULE_ALIAS("spi:" DRVNAME);
 190 MODULE_ALIAS("platform:" DRVNAME);
 191 MODULE_ALIAS("spi:ssd1325");
 192 MODULE_ALIAS("platform:ssd1325");
 193 
 194 MODULE_DESCRIPTION("SSD1325 OLED Driver");
 195 MODULE_AUTHOR("Alexey Mednyy");
 196 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */