linux/drivers/staging/fbtft/fb_hx8357d.c
<<
>>
Prefs
   1/*
   2 * FB driver for the HX8357D LCD Controller
   3 * Copyright (C) 2015 Adafruit Industries
   4 *
   5 * Based on the HX8347D FB driver
   6 * Copyright (C) 2013 Christian Vogelgsang
   7 *
   8 * Based on driver code found here: https://github.com/watterott/r61505u-Adapter
   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/delay.h>
  25#include <video/mipi_display.h>
  26
  27#include "fbtft.h"
  28#include "fb_hx8357d.h"
  29
  30#define DRVNAME         "fb_hx8357d"
  31#define WIDTH           320
  32#define HEIGHT          480
  33
  34static int init_display(struct fbtft_par *par)
  35{
  36        par->fbtftops.reset(par);
  37
  38        /* Reset things like Gamma */
  39        write_reg(par, MIPI_DCS_SOFT_RESET);
  40        usleep_range(5000, 7000);
  41
  42        /* setextc */
  43        write_reg(par, HX8357D_SETC, 0xFF, 0x83, 0x57);
  44        msleep(150);
  45
  46        /* setRGB which also enables SDO */
  47        write_reg(par, HX8357_SETRGB, 0x00, 0x00, 0x06, 0x06);
  48
  49        /* -1.52V */
  50        write_reg(par, HX8357D_SETCOM, 0x25);
  51
  52        /* Normal mode 70Hz, Idle mode 55 Hz */
  53        write_reg(par, HX8357_SETOSC, 0x68);
  54
  55        /* Set Panel - BGR, Gate direction swapped */
  56        write_reg(par, HX8357_SETPANEL, 0x05);
  57
  58        write_reg(par, HX8357_SETPWR1,
  59                  0x00,  /* Not deep standby */
  60                  0x15,  /* BT */
  61                  0x1C,  /* VSPR */
  62                  0x1C,  /* VSNR */
  63                  0x83,  /* AP */
  64                  0xAA);  /* FS */
  65
  66        write_reg(par, HX8357D_SETSTBA,
  67                  0x50,  /* OPON normal */
  68                  0x50,  /* OPON idle */
  69                  0x01,  /* STBA */
  70                  0x3C,  /* STBA */
  71                  0x1E,  /* STBA */
  72                  0x08);  /* GEN */
  73
  74        write_reg(par, HX8357D_SETCYC,
  75                  0x02,  /* NW 0x02 */
  76                  0x40,  /* RTN */
  77                  0x00,  /* DIV */
  78                  0x2A,  /* DUM */
  79                  0x2A,  /* DUM */
  80                  0x0D,  /* GDON */
  81                  0x78);  /* GDOFF */
  82
  83        write_reg(par, HX8357D_SETGAMMA,
  84                  0x02,
  85                  0x0A,
  86                  0x11,
  87                  0x1d,
  88                  0x23,
  89                  0x35,
  90                  0x41,
  91                  0x4b,
  92                  0x4b,
  93                  0x42,
  94                  0x3A,
  95                  0x27,
  96                  0x1B,
  97                  0x08,
  98                  0x09,
  99                  0x03,
 100                  0x02,
 101                  0x0A,
 102                  0x11,
 103                  0x1d,
 104                  0x23,
 105                  0x35,
 106                  0x41,
 107                  0x4b,
 108                  0x4b,
 109                  0x42,
 110                  0x3A,
 111                  0x27,
 112                  0x1B,
 113                  0x08,
 114                  0x09,
 115                  0x03,
 116                  0x00,
 117                  0x01);
 118
 119        /* 16 bit */
 120        write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
 121
 122        write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0xC0);
 123
 124        /* TE off */
 125        write_reg(par, MIPI_DCS_SET_TEAR_ON, 0x00);
 126
 127        /* tear line */
 128        write_reg(par, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
 129
 130        /* Exit Sleep */
 131        write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
 132        msleep(150);
 133
 134        /* display on */
 135        write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
 136        usleep_range(5000, 7000);
 137
 138        return 0;
 139}
 140
 141static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 142{
 143        write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
 144                  xs >> 8, xs & 0xff,  /* XSTART */
 145                  xe >> 8, xe & 0xff); /* XEND */
 146
 147        write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
 148                  ys >> 8, ys & 0xff,  /* YSTART */
 149                  ye >> 8, ye & 0xff); /* YEND */
 150
 151        write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
 152}
 153
 154#define HX8357D_MADCTL_MY  0x80
 155#define HX8357D_MADCTL_MX  0x40
 156#define HX8357D_MADCTL_MV  0x20
 157#define HX8357D_MADCTL_ML  0x10
 158#define HX8357D_MADCTL_RGB 0x00
 159#define HX8357D_MADCTL_BGR 0x08
 160#define HX8357D_MADCTL_MH  0x04
 161static int set_var(struct fbtft_par *par)
 162{
 163        u8 val;
 164
 165        switch (par->info->var.rotate) {
 166        case 270:
 167                val = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX;
 168                break;
 169        case 180:
 170                val = 0;
 171                break;
 172        case 90:
 173                val = HX8357D_MADCTL_MV | HX8357D_MADCTL_MY;
 174                break;
 175        default:
 176                val = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY;
 177                break;
 178        }
 179
 180        val |= (par->bgr ? HX8357D_MADCTL_RGB : HX8357D_MADCTL_BGR);
 181
 182        /* Memory Access Control */
 183        write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, val);
 184
 185        return 0;
 186}
 187
 188static struct fbtft_display display = {
 189        .regwidth = 8,
 190        .width = WIDTH,
 191        .height = HEIGHT,
 192        .gamma_num = 2,
 193        .gamma_len = 14,
 194        .fbtftops = {
 195                .init_display = init_display,
 196                .set_addr_win = set_addr_win,
 197                .set_var = set_var,
 198        },
 199};
 200
 201FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8357d", &display);
 202
 203MODULE_ALIAS("spi:" DRVNAME);
 204MODULE_ALIAS("platform:" DRVNAME);
 205MODULE_ALIAS("spi:hx8357d");
 206MODULE_ALIAS("platform:hx8357d");
 207
 208MODULE_DESCRIPTION("FB driver for the HX8357D LCD Controller");
 209MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
 210MODULE_LICENSE("GPL");
 211