linux/drivers/staging/fbtft/fb_hx8340bn.c
<<
>>
Prefs
   1/*
   2 * FB driver for the HX8340BN LCD Controller
   3 *
   4 * This display uses 9-bit SPI: Data/Command bit + 8 data bits
   5 * For platforms that doesn't support 9-bit, the driver is capable
   6 * of emulating this using 8-bit transfer.
   7 * This is done by transferring eight 9-bit words in 9 bytes.
   8 *
   9 * Copyright (C) 2013 Noralf Tronnes
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/kernel.h>
  24#include <linux/init.h>
  25#include <linux/vmalloc.h>
  26#include <linux/spi/spi.h>
  27#include <linux/delay.h>
  28#include <video/mipi_display.h>
  29
  30#include "fbtft.h"
  31
  32#define DRVNAME         "fb_hx8340bn"
  33#define WIDTH           176
  34#define HEIGHT          220
  35#define TXBUFLEN        (4 * PAGE_SIZE)
  36#define DEFAULT_GAMMA   "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \
  37                        "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 "
  38
  39static bool emulate;
  40module_param(emulate, bool, 0000);
  41MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
  42
  43static int init_display(struct fbtft_par *par)
  44{
  45        par->fbtftops.reset(par);
  46
  47        /* BTL221722-276L startup sequence, from datasheet */
  48
  49        /*
  50         * SETEXTCOM: Set extended command set (C1h)
  51         * This command is used to set extended command set access enable.
  52         * Enable: After command (C1h), must write: ffh,83h,40h
  53         */
  54        write_reg(par, 0xC1, 0xFF, 0x83, 0x40);
  55
  56        /*
  57         * Sleep out
  58         * This command turns off sleep mode.
  59         * In this mode the DC/DC converter is enabled, Internal oscillator
  60         * is started, and panel scanning is started.
  61         */
  62        write_reg(par, 0x11);
  63        mdelay(150);
  64
  65        /* Undoc'd register? */
  66        write_reg(par, 0xCA, 0x70, 0x00, 0xD9);
  67
  68        /*
  69         * SETOSC: Set Internal Oscillator (B0h)
  70         * This command is used to set internal oscillator related settings
  71         *      OSC_EN: Enable internal oscillator
  72         *      Internal oscillator frequency: 125% x 2.52MHz
  73         */
  74        write_reg(par, 0xB0, 0x01, 0x11);
  75
  76        /* Drive ability setting */
  77        write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06);
  78        mdelay(20);
  79
  80        /*
  81         * SETPWCTR5: Set Power Control 5(B5h)
  82         * This command is used to set VCOM Low and VCOM High Voltage
  83         * VCOMH 0110101 :  3.925
  84         * VCOML 0100000 : -1.700
  85         * 45h=69  VCOMH: "VMH" + 5d   VCOML: "VMH" + 5d
  86         */
  87        write_reg(par, 0xB5, 0x35, 0x20, 0x45);
  88
  89        /*
  90         * SETPWCTR4: Set Power Control 4(B4h)
  91         *      VRH[4:0]:       Specify the VREG1 voltage adjusting.
  92         *                      VREG1 voltage is for gamma voltage setting.
  93         *      BT[2:0]:        Switch the output factor of step-up circuit 2
  94         *                      for VGH and VGL voltage generation.
  95         */
  96        write_reg(par, 0xB4, 0x33, 0x25, 0x4C);
  97        mdelay(10);
  98
  99        /*
 100         * Interface Pixel Format (3Ah)
 101         * This command is used to define the format of RGB picture data,
 102         * which is to be transfer via the system and RGB interface.
 103         * RGB interface: 16 Bit/Pixel
 104         */
 105        write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
 106
 107        /*
 108         * Display on (29h)
 109         * This command is used to recover from DISPLAY OFF mode.
 110         * Output from the Frame Memory is enabled.
 111         */
 112        write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
 113        mdelay(10);
 114
 115        return 0;
 116}
 117
 118static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 119{
 120        write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0x00, xs, 0x00, xe);
 121        write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0x00, ys, 0x00, ye);
 122        write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
 123}
 124
 125static int set_var(struct fbtft_par *par)
 126{
 127        /* MADCTL - Memory data access control */
 128        /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */
 129#define MY BIT(7)
 130#define MX BIT(6)
 131#define MV BIT(5)
 132        switch (par->info->var.rotate) {
 133        case 0:
 134                write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, par->bgr << 3);
 135                break;
 136        case 270:
 137                write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
 138                          MX | MV | (par->bgr << 3));
 139                break;
 140        case 180:
 141                write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
 142                          MX | MY | (par->bgr << 3));
 143                break;
 144        case 90:
 145                write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
 146                          MY | MV | (par->bgr << 3));
 147                break;
 148        }
 149
 150        return 0;
 151}
 152
 153/*
 154 * Gamma Curve selection, GC (only GC0 can be customized):
 155 *   0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0
 156 * Gamma string format:
 157 *   OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1
 158 *   ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX  GC
 159 */
 160#define CURVE(num, idx)  curves[(num) * par->gamma.num_values + (idx)]
 161static int set_gamma(struct fbtft_par *par, u32 *curves)
 162{
 163        unsigned long mask[] = {
 164                0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07,
 165                0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f,
 166                0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
 167        };
 168        int i, j;
 169
 170        /* apply mask */
 171        for (i = 0; i < par->gamma.num_curves; i++)
 172                for (j = 0; j < par->gamma.num_values; j++)
 173                        CURVE(i, j) &= mask[i * par->gamma.num_values + j];
 174
 175        /* Gamma Set (26h) */
 176        write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 1 << CURVE(1, 14));
 177
 178        if (CURVE(1, 14))
 179                return 0; /* only GC0 can be customized */
 180
 181        write_reg(par, 0xC2,
 182                  (CURVE(0, 8) << 4) | CURVE(0, 7),
 183                  (CURVE(0, 10) << 4) | CURVE(0, 9),
 184                  (CURVE(0, 12) << 4) | CURVE(0, 11),
 185                  CURVE(0, 2),
 186                  (CURVE(0, 4) << 4) | CURVE(0, 3),
 187                  CURVE(0, 5),
 188                  CURVE(0, 6),
 189                  (CURVE(0, 1) << 4) | CURVE(0, 0),
 190                  (CURVE(0, 14) << 2) | CURVE(0, 13));
 191
 192        write_reg(par, 0xC3,
 193                  (CURVE(1, 8) << 4) | CURVE(1, 7),
 194                  (CURVE(1, 10) << 4) | CURVE(1, 9),
 195                  (CURVE(1, 12) << 4) | CURVE(1, 11),
 196                  CURVE(1, 2),
 197                  (CURVE(1, 4) << 4) | CURVE(1, 3),
 198                  CURVE(1, 5),
 199                  CURVE(1, 6),
 200                  (CURVE(1, 1) << 4) | CURVE(1, 0));
 201
 202        mdelay(10);
 203
 204        return 0;
 205}
 206
 207#undef CURVE
 208
 209static struct fbtft_display display = {
 210        .regwidth = 8,
 211        .width = WIDTH,
 212        .height = HEIGHT,
 213        .txbuflen = TXBUFLEN,
 214        .gamma_num = 2,
 215        .gamma_len = 15,
 216        .gamma = DEFAULT_GAMMA,
 217        .fbtftops = {
 218                .init_display = init_display,
 219                .set_addr_win = set_addr_win,
 220                .set_var = set_var,
 221                .set_gamma = set_gamma,
 222        },
 223};
 224
 225FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display);
 226
 227MODULE_ALIAS("spi:" DRVNAME);
 228MODULE_ALIAS("platform:" DRVNAME);
 229MODULE_ALIAS("spi:hx8340bn");
 230MODULE_ALIAS("platform:hx8340bn");
 231
 232MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller");
 233MODULE_AUTHOR("Noralf Tronnes");
 234MODULE_LICENSE("GPL");
 235