linux/drivers/staging/fbtft/fb_s6d1121.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * FB driver for the S6D1121 LCD Controller
   4 *
   5 * Copyright (C) 2013 Roman Rolinsky
   6 *
   7 * Based on fb_ili9325.c by Noralf Tronnes
   8 * Based on ili9325.c by Jeroen Domburg
   9 * Init code from UTFT library by Henning Karlsen
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/kernel.h>
  14#include <linux/init.h>
  15#include <linux/delay.h>
  16
  17#include "fbtft.h"
  18
  19#define DRVNAME         "fb_s6d1121"
  20#define WIDTH           240
  21#define HEIGHT          320
  22#define BPP             16
  23#define FPS             20
  24#define DEFAULT_GAMMA   "26 09 24 2C 1F 23 24 25 22 26 25 23 0D 00\n" \
  25                        "1C 1A 13 1D 0B 11 12 10 13 15 36 19 00 0D"
  26
  27static int init_display(struct fbtft_par *par)
  28{
  29        par->fbtftops.reset(par);
  30
  31        /* Initialization sequence from Lib_UTFT */
  32
  33        write_reg(par, 0x0011, 0x2004);
  34        write_reg(par, 0x0013, 0xCC00);
  35        write_reg(par, 0x0015, 0x2600);
  36        write_reg(par, 0x0014, 0x252A);
  37        write_reg(par, 0x0012, 0x0033);
  38        write_reg(par, 0x0013, 0xCC04);
  39        write_reg(par, 0x0013, 0xCC06);
  40        write_reg(par, 0x0013, 0xCC4F);
  41        write_reg(par, 0x0013, 0x674F);
  42        write_reg(par, 0x0011, 0x2003);
  43        write_reg(par, 0x0016, 0x0007);
  44        write_reg(par, 0x0002, 0x0013);
  45        write_reg(par, 0x0003, 0x0003);
  46        write_reg(par, 0x0001, 0x0127);
  47        write_reg(par, 0x0008, 0x0303);
  48        write_reg(par, 0x000A, 0x000B);
  49        write_reg(par, 0x000B, 0x0003);
  50        write_reg(par, 0x000C, 0x0000);
  51        write_reg(par, 0x0041, 0x0000);
  52        write_reg(par, 0x0050, 0x0000);
  53        write_reg(par, 0x0060, 0x0005);
  54        write_reg(par, 0x0070, 0x000B);
  55        write_reg(par, 0x0071, 0x0000);
  56        write_reg(par, 0x0078, 0x0000);
  57        write_reg(par, 0x007A, 0x0000);
  58        write_reg(par, 0x0079, 0x0007);
  59        write_reg(par, 0x0007, 0x0051);
  60        write_reg(par, 0x0007, 0x0053);
  61        write_reg(par, 0x0079, 0x0000);
  62
  63        write_reg(par, 0x0022); /* Write Data to GRAM */
  64
  65        return 0;
  66}
  67
  68static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
  69{
  70        switch (par->info->var.rotate) {
  71        /* R20h = Horizontal GRAM Start Address */
  72        /* R21h = Vertical GRAM Start Address */
  73        case 0:
  74                write_reg(par, 0x0020, xs);
  75                write_reg(par, 0x0021, ys);
  76                break;
  77        case 180:
  78                write_reg(par, 0x0020, WIDTH - 1 - xs);
  79                write_reg(par, 0x0021, HEIGHT - 1 - ys);
  80                break;
  81        case 270:
  82                write_reg(par, 0x0020, WIDTH - 1 - ys);
  83                write_reg(par, 0x0021, xs);
  84                break;
  85        case 90:
  86                write_reg(par, 0x0020, ys);
  87                write_reg(par, 0x0021, HEIGHT - 1 - xs);
  88                break;
  89        }
  90        write_reg(par, 0x0022); /* Write Data to GRAM */
  91}
  92
  93static int set_var(struct fbtft_par *par)
  94{
  95        switch (par->info->var.rotate) {
  96        /* AM: GRAM update direction */
  97        case 0:
  98                write_reg(par, 0x03, 0x0003 | (par->bgr << 12));
  99                break;
 100        case 180:
 101                write_reg(par, 0x03, 0x0000 | (par->bgr << 12));
 102                break;
 103        case 270:
 104                write_reg(par, 0x03, 0x000A | (par->bgr << 12));
 105                break;
 106        case 90:
 107                write_reg(par, 0x03, 0x0009 | (par->bgr << 12));
 108                break;
 109        }
 110
 111        return 0;
 112}
 113
 114/*
 115 * Gamma string format:
 116 * PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1
 117 * PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1
 118 */
 119#define CURVE(num, idx)  curves[(num) * par->gamma.num_values + (idx)]
 120static int set_gamma(struct fbtft_par *par, u32 *curves)
 121{
 122        static const unsigned long mask[] = {
 123                0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 124                0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 125                0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f,
 126        };
 127        int i, j;
 128
 129        /* apply mask */
 130        for (i = 0; i < 2; i++)
 131                for (j = 0; j < 14; j++)
 132                        CURVE(i, j) &= mask[i * par->gamma.num_values + j];
 133
 134        write_reg(par, 0x0030, CURVE(0, 1) << 8 | CURVE(0, 0));
 135        write_reg(par, 0x0031, CURVE(0, 3) << 8 | CURVE(0, 2));
 136        write_reg(par, 0x0032, CURVE(0, 5) << 8 | CURVE(0, 3));
 137        write_reg(par, 0x0033, CURVE(0, 7) << 8 | CURVE(0, 6));
 138        write_reg(par, 0x0034, CURVE(0, 9) << 8 | CURVE(0, 8));
 139        write_reg(par, 0x0035, CURVE(0, 11) << 8 | CURVE(0, 10));
 140
 141        write_reg(par, 0x0036, CURVE(1, 1) << 8 | CURVE(1, 0));
 142        write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2));
 143        write_reg(par, 0x0038, CURVE(1, 5) << 8 | CURVE(1, 4));
 144        write_reg(par, 0x0039, CURVE(1, 7) << 8 | CURVE(1, 6));
 145        write_reg(par, 0x003A, CURVE(1, 9) << 8 | CURVE(1, 8));
 146        write_reg(par, 0x003B, CURVE(1, 11) << 8 | CURVE(1, 10));
 147
 148        write_reg(par, 0x003C, CURVE(0, 13) << 8 | CURVE(0, 12));
 149        write_reg(par, 0x003D, CURVE(1, 13) << 8 | CURVE(1, 12));
 150
 151        return 0;
 152}
 153
 154#undef CURVE
 155
 156static struct fbtft_display display = {
 157        .regwidth = 16,
 158        .width = WIDTH,
 159        .height = HEIGHT,
 160        .bpp = BPP,
 161        .fps = FPS,
 162        .gamma_num = 2,
 163        .gamma_len = 14,
 164        .gamma = DEFAULT_GAMMA,
 165        .fbtftops = {
 166                .init_display = init_display,
 167                .set_addr_win = set_addr_win,
 168                .set_var = set_var,
 169                .set_gamma = set_gamma,
 170        },
 171};
 172
 173FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display);
 174
 175MODULE_ALIAS("spi:" DRVNAME);
 176MODULE_ALIAS("platform:" DRVNAME);
 177MODULE_ALIAS("spi:s6d1121");
 178MODULE_ALIAS("platform:s6d1121");
 179
 180MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller");
 181MODULE_AUTHOR("Roman Rolinsky");
 182MODULE_LICENSE("GPL");
 183