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