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