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