linux/drivers/staging/fbtft/fb_ssd1289.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * FB driver for the SSD1289 LCD Controller
   4 *
   5 * Copyright (C) 2013 Noralf Tronnes
   6 *
   7 * Init sequence taken from ITDB02_Graph16.cpp - (C)2010-2011 Henning Karlsen
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/gpio/consumer.h>
  14
  15#include "fbtft.h"
  16
  17#define DRVNAME         "fb_ssd1289"
  18#define WIDTH           240
  19#define HEIGHT          320
  20#define DEFAULT_GAMMA   "02 03 2 5 7 7 4 2 4 2\n" \
  21                        "02 03 2 5 7 5 4 2 4 2"
  22
  23static unsigned int reg11 = 0x6040;
  24module_param(reg11, uint, 0000);
  25MODULE_PARM_DESC(reg11, "Register 11h value");
  26
  27static int init_display(struct fbtft_par *par)
  28{
  29        par->fbtftops.reset(par);
  30
  31        if (par->gpio.cs)
  32                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
  33
  34        write_reg(par, 0x00, 0x0001);
  35        write_reg(par, 0x03, 0xA8A4);
  36        write_reg(par, 0x0C, 0x0000);
  37        write_reg(par, 0x0D, 0x080C);
  38        write_reg(par, 0x0E, 0x2B00);
  39        write_reg(par, 0x1E, 0x00B7);
  40        write_reg(par, 0x01,
  41                  BIT(13) | (par->bgr << 11) | BIT(9) | (HEIGHT - 1));
  42        write_reg(par, 0x02, 0x0600);
  43        write_reg(par, 0x10, 0x0000);
  44        write_reg(par, 0x05, 0x0000);
  45        write_reg(par, 0x06, 0x0000);
  46        write_reg(par, 0x16, 0xEF1C);
  47        write_reg(par, 0x17, 0x0003);
  48        write_reg(par, 0x07, 0x0233);
  49        write_reg(par, 0x0B, 0x0000);
  50        write_reg(par, 0x0F, 0x0000);
  51        write_reg(par, 0x41, 0x0000);
  52        write_reg(par, 0x42, 0x0000);
  53        write_reg(par, 0x48, 0x0000);
  54        write_reg(par, 0x49, 0x013F);
  55        write_reg(par, 0x4A, 0x0000);
  56        write_reg(par, 0x4B, 0x0000);
  57        write_reg(par, 0x44, 0xEF00);
  58        write_reg(par, 0x45, 0x0000);
  59        write_reg(par, 0x46, 0x013F);
  60        write_reg(par, 0x23, 0x0000);
  61        write_reg(par, 0x24, 0x0000);
  62        write_reg(par, 0x25, 0x8000);
  63        write_reg(par, 0x4f, 0x0000);
  64        write_reg(par, 0x4e, 0x0000);
  65        write_reg(par, 0x22);
  66        return 0;
  67}
  68
  69static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
  70{
  71        switch (par->info->var.rotate) {
  72        /* R4Eh - Set GDDRAM X address counter */
  73        /* R4Fh - Set GDDRAM Y address counter */
  74        case 0:
  75                write_reg(par, 0x4e, xs);
  76                write_reg(par, 0x4f, ys);
  77                break;
  78        case 180:
  79                write_reg(par, 0x4e, par->info->var.xres - 1 - xs);
  80                write_reg(par, 0x4f, par->info->var.yres - 1 - ys);
  81                break;
  82        case 270:
  83                write_reg(par, 0x4e, par->info->var.yres - 1 - ys);
  84                write_reg(par, 0x4f, xs);
  85                break;
  86        case 90:
  87                write_reg(par, 0x4e, ys);
  88                write_reg(par, 0x4f, par->info->var.xres - 1 - xs);
  89                break;
  90        }
  91
  92        /* R22h - RAM data write */
  93        write_reg(par, 0x22);
  94}
  95
  96static int set_var(struct fbtft_par *par)
  97{
  98        if (par->fbtftops.init_display != init_display) {
  99                /* don't risk messing up register 11h */
 100                fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
 101                              "%s: skipping since custom init_display() is used\n",
 102                              __func__);
 103                return 0;
 104        }
 105
 106        switch (par->info->var.rotate) {
 107        case 0:
 108                write_reg(par, 0x11, reg11 | 0x30);
 109                break;
 110        case 270:
 111                write_reg(par, 0x11, reg11 | 0x28);
 112                break;
 113        case 180:
 114                write_reg(par, 0x11, reg11 | 0x00);
 115                break;
 116        case 90:
 117                write_reg(par, 0x11, reg11 | 0x18);
 118                break;
 119        }
 120
 121        return 0;
 122}
 123
 124/*
 125 * Gamma string format:
 126 * VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5
 127 * VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5
 128 */
 129#define CURVE(num, idx)  curves[(num) * par->gamma.num_values + (idx)]
 130static int set_gamma(struct fbtft_par *par, u32 *curves)
 131{
 132        static const unsigned long mask[] = {
 133                0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
 134                0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
 135        };
 136        int i, j;
 137
 138        /* apply mask */
 139        for (i = 0; i < 2; i++)
 140                for (j = 0; j < 10; j++)
 141                        CURVE(i, j) &= mask[i * par->gamma.num_values + j];
 142
 143        write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4));
 144        write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6));
 145        write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8));
 146        write_reg(par, 0x0033, CURVE(0, 3) << 8 | CURVE(0, 2));
 147        write_reg(par, 0x0034, CURVE(1, 5) << 8 | CURVE(1, 4));
 148        write_reg(par, 0x0035, CURVE(1, 7) << 8 | CURVE(1, 6));
 149        write_reg(par, 0x0036, CURVE(1, 9) << 8 | CURVE(1, 8));
 150        write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2));
 151        write_reg(par, 0x003A, CURVE(0, 1) << 8 | CURVE(0, 0));
 152        write_reg(par, 0x003B, CURVE(1, 1) << 8 | CURVE(1, 0));
 153
 154        return 0;
 155}
 156
 157#undef CURVE
 158
 159static struct fbtft_display display = {
 160        .regwidth = 16,
 161        .width = WIDTH,
 162        .height = HEIGHT,
 163        .gamma_num = 2,
 164        .gamma_len = 10,
 165        .gamma = DEFAULT_GAMMA,
 166        .fbtftops = {
 167                .init_display = init_display,
 168                .set_addr_win = set_addr_win,
 169                .set_var = set_var,
 170                .set_gamma = set_gamma,
 171        },
 172};
 173
 174FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1289", &display);
 175
 176MODULE_ALIAS("spi:" DRVNAME);
 177MODULE_ALIAS("platform:" DRVNAME);
 178MODULE_ALIAS("spi:ssd1289");
 179MODULE_ALIAS("platform:ssd1289");
 180
 181MODULE_DESCRIPTION("FB driver for the SSD1289 LCD Controller");
 182MODULE_AUTHOR("Noralf Tronnes");
 183MODULE_LICENSE("GPL");
 184