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