0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/module.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/vmalloc.h>
0017 #include <linux/spi/spi.h>
0018 #include <linux/delay.h>
0019 #include <video/mipi_display.h>
0020
0021 #include "fbtft.h"
0022
0023 #define DRVNAME "fb_hx8340bn"
0024 #define WIDTH 176
0025 #define HEIGHT 220
0026 #define TXBUFLEN (4 * PAGE_SIZE)
0027 #define DEFAULT_GAMMA "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \
0028 "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 "
0029
0030 static bool emulate;
0031 module_param(emulate, bool, 0000);
0032 MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
0033
0034 static int init_display(struct fbtft_par *par)
0035 {
0036 par->fbtftops.reset(par);
0037
0038
0039
0040
0041
0042
0043
0044
0045 write_reg(par, 0xC1, 0xFF, 0x83, 0x40);
0046
0047
0048
0049
0050
0051
0052
0053 write_reg(par, 0x11);
0054 mdelay(150);
0055
0056
0057 write_reg(par, 0xCA, 0x70, 0x00, 0xD9);
0058
0059
0060
0061
0062
0063
0064
0065 write_reg(par, 0xB0, 0x01, 0x11);
0066
0067
0068 write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06);
0069 mdelay(20);
0070
0071
0072
0073
0074
0075
0076
0077
0078 write_reg(par, 0xB5, 0x35, 0x20, 0x45);
0079
0080
0081
0082
0083
0084
0085
0086
0087 write_reg(par, 0xB4, 0x33, 0x25, 0x4C);
0088 mdelay(10);
0089
0090
0091
0092
0093
0094
0095
0096 write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
0097
0098
0099
0100
0101
0102
0103 write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
0104 mdelay(10);
0105
0106 return 0;
0107 }
0108
0109 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
0110 {
0111 write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0x00, xs, 0x00, xe);
0112 write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0x00, ys, 0x00, ye);
0113 write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
0114 }
0115
0116 static int set_var(struct fbtft_par *par)
0117 {
0118
0119
0120 #define MY BIT(7)
0121 #define MX BIT(6)
0122 #define MV BIT(5)
0123 switch (par->info->var.rotate) {
0124 case 0:
0125 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, par->bgr << 3);
0126 break;
0127 case 270:
0128 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
0129 MX | MV | (par->bgr << 3));
0130 break;
0131 case 180:
0132 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
0133 MX | MY | (par->bgr << 3));
0134 break;
0135 case 90:
0136 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
0137 MY | MV | (par->bgr << 3));
0138 break;
0139 }
0140
0141 return 0;
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151 #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)]
0152 static int set_gamma(struct fbtft_par *par, u32 *curves)
0153 {
0154 static const unsigned long mask[] = {
0155 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07,
0156 0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f,
0157 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
0158 };
0159 int i, j;
0160
0161
0162 for (i = 0; i < par->gamma.num_curves; i++)
0163 for (j = 0; j < par->gamma.num_values; j++)
0164 CURVE(i, j) &= mask[i * par->gamma.num_values + j];
0165
0166
0167 write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 1 << CURVE(1, 14));
0168
0169 if (CURVE(1, 14))
0170 return 0;
0171
0172 write_reg(par, 0xC2,
0173 (CURVE(0, 8) << 4) | CURVE(0, 7),
0174 (CURVE(0, 10) << 4) | CURVE(0, 9),
0175 (CURVE(0, 12) << 4) | CURVE(0, 11),
0176 CURVE(0, 2),
0177 (CURVE(0, 4) << 4) | CURVE(0, 3),
0178 CURVE(0, 5),
0179 CURVE(0, 6),
0180 (CURVE(0, 1) << 4) | CURVE(0, 0),
0181 (CURVE(0, 14) << 2) | CURVE(0, 13));
0182
0183 write_reg(par, 0xC3,
0184 (CURVE(1, 8) << 4) | CURVE(1, 7),
0185 (CURVE(1, 10) << 4) | CURVE(1, 9),
0186 (CURVE(1, 12) << 4) | CURVE(1, 11),
0187 CURVE(1, 2),
0188 (CURVE(1, 4) << 4) | CURVE(1, 3),
0189 CURVE(1, 5),
0190 CURVE(1, 6),
0191 (CURVE(1, 1) << 4) | CURVE(1, 0));
0192
0193 mdelay(10);
0194
0195 return 0;
0196 }
0197
0198 #undef CURVE
0199
0200 static struct fbtft_display display = {
0201 .regwidth = 8,
0202 .width = WIDTH,
0203 .height = HEIGHT,
0204 .txbuflen = TXBUFLEN,
0205 .gamma_num = 2,
0206 .gamma_len = 15,
0207 .gamma = DEFAULT_GAMMA,
0208 .fbtftops = {
0209 .init_display = init_display,
0210 .set_addr_win = set_addr_win,
0211 .set_var = set_var,
0212 .set_gamma = set_gamma,
0213 },
0214 };
0215
0216 FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display);
0217
0218 MODULE_ALIAS("spi:" DRVNAME);
0219 MODULE_ALIAS("platform:" DRVNAME);
0220 MODULE_ALIAS("spi:hx8340bn");
0221 MODULE_ALIAS("platform:hx8340bn");
0222
0223 MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller");
0224 MODULE_AUTHOR("Noralf Tronnes");
0225 MODULE_LICENSE("GPL");