root/drivers/staging/fbtft/fb_ssd1305.c

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

DEFINITIONS

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

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * FB driver for the SSD1305 OLED Controller
   4  *
   5  * based on SSD1306 driver by Noralf Tronnes
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/kernel.h>
  10 #include <linux/init.h>
  11 #include <linux/gpio/consumer.h>
  12 #include <linux/delay.h>
  13 
  14 #include "fbtft.h"
  15 
  16 #define DRVNAME         "fb_ssd1305"
  17 
  18 #define WIDTH 128
  19 #define HEIGHT 64
  20 
  21 /*
  22  * write_reg() caveat:
  23  *
  24  *    This doesn't work because D/C has to be LOW for both values:
  25  *      write_reg(par, val1, val2);
  26  *
  27  *    Do it like this:
  28  *      write_reg(par, val1);
  29  *      write_reg(par, val2);
  30  */
  31 
  32 /* Init sequence taken from the Adafruit SSD1306 Arduino library */
  33 static int init_display(struct fbtft_par *par)
  34 {
  35         par->fbtftops.reset(par);
  36 
  37         if (par->gamma.curves[0] == 0) {
  38                 mutex_lock(&par->gamma.lock);
  39                 if (par->info->var.yres == 64)
  40                         par->gamma.curves[0] = 0xCF;
  41                 else
  42                         par->gamma.curves[0] = 0x8F;
  43                 mutex_unlock(&par->gamma.lock);
  44         }
  45 
  46         /* Set Display OFF */
  47         write_reg(par, 0xAE);
  48 
  49         /* Set Display Clock Divide Ratio/ Oscillator Frequency */
  50         write_reg(par, 0xD5);
  51         write_reg(par, 0x80);
  52 
  53         /* Set Multiplex Ratio */
  54         write_reg(par, 0xA8);
  55         if (par->info->var.yres == 64)
  56                 write_reg(par, 0x3F);
  57         else
  58                 write_reg(par, 0x1F);
  59 
  60         /* Set Display Offset */
  61         write_reg(par, 0xD3);
  62         write_reg(par, 0x0);
  63 
  64         /* Set Display Start Line */
  65         write_reg(par, 0x40 | 0x0);
  66 
  67         /* Charge Pump Setting */
  68         write_reg(par, 0x8D);
  69         /* A[2] = 1b, Enable charge pump during display on */
  70         write_reg(par, 0x14);
  71 
  72         /* Set Memory Addressing Mode */
  73         write_reg(par, 0x20);
  74         /* Vertical addressing mode  */
  75         write_reg(par, 0x01);
  76 
  77         /*
  78          * Set Segment Re-map
  79          * column address 127 is mapped to SEG0
  80          */
  81         write_reg(par, 0xA0 | ((par->info->var.rotate == 180) ? 0x0 : 0x1));
  82 
  83         /*
  84          * Set COM Output Scan Direction
  85          * remapped mode. Scan from COM[N-1] to COM0
  86          */
  87         write_reg(par, ((par->info->var.rotate == 180) ? 0xC8 : 0xC0));
  88 
  89         /* Set COM Pins Hardware Configuration */
  90         write_reg(par, 0xDA);
  91         if (par->info->var.yres == 64) {
  92                 /* A[4]=1b, Alternative COM pin configuration */
  93                 write_reg(par, 0x12);
  94         } else {
  95                 /* A[4]=0b, Sequential COM pin configuration */
  96                 write_reg(par, 0x02);
  97         }
  98 
  99         /* Set Pre-charge Period */
 100         write_reg(par, 0xD9);
 101         write_reg(par, 0xF1);
 102 
 103         /*
 104          * Entire Display ON
 105          * Resume to RAM content display. Output follows RAM content
 106          */
 107         write_reg(par, 0xA4);
 108 
 109         /*
 110          * Set Normal Display
 111          *  0 in RAM: OFF in display panel
 112          *  1 in RAM: ON in display panel
 113          */
 114         write_reg(par, 0xA6);
 115 
 116         /* Set Display ON */
 117         write_reg(par, 0xAF);
 118 
 119         return 0;
 120 }
 121 
 122 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 123 {
 124         /* Set Lower Column Start Address for Page Addressing Mode */
 125         write_reg(par, 0x00 | ((par->info->var.rotate == 180) ? 0x0 : 0x4));
 126         /* Set Higher Column Start Address for Page Addressing Mode */
 127         write_reg(par, 0x10 | 0x0);
 128         /* Set Display Start Line */
 129         write_reg(par, 0x40 | 0x0);
 130 }
 131 
 132 static int blank(struct fbtft_par *par, bool on)
 133 {
 134         if (on)
 135                 write_reg(par, 0xAE);
 136         else
 137                 write_reg(par, 0xAF);
 138         return 0;
 139 }
 140 
 141 /* Gamma is used to control Contrast */
 142 static int set_gamma(struct fbtft_par *par, u32 *curves)
 143 {
 144         curves[0] &= 0xFF;
 145         /* Set Contrast Control for BANK0 */
 146         write_reg(par, 0x81);
 147         write_reg(par, curves[0]);
 148 
 149         return 0;
 150 }
 151 
 152 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
 153 {
 154         u16 *vmem16 = (u16 *)par->info->screen_buffer;
 155         u8 *buf = par->txbuf.buf;
 156         int x, y, i;
 157         int ret;
 158 
 159         for (x = 0; x < par->info->var.xres; x++) {
 160                 for (y = 0; y < par->info->var.yres / 8; y++) {
 161                         *buf = 0x00;
 162                         for (i = 0; i < 8; i++)
 163                                 *buf |= (vmem16[(y * 8 + i) *
 164                                                 par->info->var.xres + x] ?
 165                                          1 : 0) << i;
 166                         buf++;
 167                 }
 168         }
 169 
 170         /* Write data */
 171         gpiod_set_value(par->gpio.dc, 1);
 172         ret = par->fbtftops.write(par, par->txbuf.buf,
 173                                   par->info->var.xres * par->info->var.yres /
 174                                   8);
 175         if (ret < 0)
 176                 dev_err(par->info->device, "write failed and returned: %d\n",
 177                         ret);
 178         return ret;
 179 }
 180 
 181 static struct fbtft_display display = {
 182         .regwidth = 8,
 183         .width = WIDTH,
 184         .height = HEIGHT,
 185         .txbuflen = WIDTH * HEIGHT / 8,
 186         .gamma_num = 1,
 187         .gamma_len = 1,
 188         .gamma = "00",
 189         .fbtftops = {
 190                 .write_vmem = write_vmem,
 191                 .init_display = init_display,
 192                 .set_addr_win = set_addr_win,
 193                 .blank = blank,
 194                 .set_gamma = set_gamma,
 195         },
 196 };
 197 
 198 FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1305", &display);
 199 
 200 MODULE_ALIAS("spi:" DRVNAME);
 201 MODULE_ALIAS("platform:" DRVNAME);
 202 MODULE_ALIAS("spi:ssd1305");
 203 MODULE_ALIAS("platform:ssd1305");
 204 
 205 MODULE_DESCRIPTION("SSD1305 OLED Driver");
 206 MODULE_AUTHOR("Alexey Mednyy");
 207 MODULE_LICENSE("GPL");

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