Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * FB driver for the S6D1121 LCD Controller
0004  *
0005  * Copyright (C) 2013 Roman Rolinsky
0006  *
0007  * Based on fb_ili9325.c by Noralf Tronnes
0008  * Based on ili9325.c by Jeroen Domburg
0009  * Init code from UTFT library by Henning Karlsen
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/delay.h>
0016 
0017 #include "fbtft.h"
0018 
0019 #define DRVNAME     "fb_s6d1121"
0020 #define WIDTH       240
0021 #define HEIGHT      320
0022 #define BPP     16
0023 #define FPS     20
0024 #define DEFAULT_GAMMA   "26 09 24 2C 1F 23 24 25 22 26 25 23 0D 00\n" \
0025             "1C 1A 13 1D 0B 11 12 10 13 15 36 19 00 0D"
0026 
0027 static int init_display(struct fbtft_par *par)
0028 {
0029     par->fbtftops.reset(par);
0030 
0031     /* Initialization sequence from Lib_UTFT */
0032 
0033     write_reg(par, 0x0011, 0x2004);
0034     write_reg(par, 0x0013, 0xCC00);
0035     write_reg(par, 0x0015, 0x2600);
0036     write_reg(par, 0x0014, 0x252A);
0037     write_reg(par, 0x0012, 0x0033);
0038     write_reg(par, 0x0013, 0xCC04);
0039     write_reg(par, 0x0013, 0xCC06);
0040     write_reg(par, 0x0013, 0xCC4F);
0041     write_reg(par, 0x0013, 0x674F);
0042     write_reg(par, 0x0011, 0x2003);
0043     write_reg(par, 0x0016, 0x0007);
0044     write_reg(par, 0x0002, 0x0013);
0045     write_reg(par, 0x0003, 0x0003);
0046     write_reg(par, 0x0001, 0x0127);
0047     write_reg(par, 0x0008, 0x0303);
0048     write_reg(par, 0x000A, 0x000B);
0049     write_reg(par, 0x000B, 0x0003);
0050     write_reg(par, 0x000C, 0x0000);
0051     write_reg(par, 0x0041, 0x0000);
0052     write_reg(par, 0x0050, 0x0000);
0053     write_reg(par, 0x0060, 0x0005);
0054     write_reg(par, 0x0070, 0x000B);
0055     write_reg(par, 0x0071, 0x0000);
0056     write_reg(par, 0x0078, 0x0000);
0057     write_reg(par, 0x007A, 0x0000);
0058     write_reg(par, 0x0079, 0x0007);
0059     write_reg(par, 0x0007, 0x0051);
0060     write_reg(par, 0x0007, 0x0053);
0061     write_reg(par, 0x0079, 0x0000);
0062 
0063     write_reg(par, 0x0022); /* Write Data to GRAM */
0064 
0065     return 0;
0066 }
0067 
0068 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
0069 {
0070     switch (par->info->var.rotate) {
0071     /* R20h = Horizontal GRAM Start Address */
0072     /* R21h = Vertical GRAM Start Address */
0073     case 0:
0074         write_reg(par, 0x0020, xs);
0075         write_reg(par, 0x0021, ys);
0076         break;
0077     case 180:
0078         write_reg(par, 0x0020, WIDTH - 1 - xs);
0079         write_reg(par, 0x0021, HEIGHT - 1 - ys);
0080         break;
0081     case 270:
0082         write_reg(par, 0x0020, WIDTH - 1 - ys);
0083         write_reg(par, 0x0021, xs);
0084         break;
0085     case 90:
0086         write_reg(par, 0x0020, ys);
0087         write_reg(par, 0x0021, HEIGHT - 1 - xs);
0088         break;
0089     }
0090     write_reg(par, 0x0022); /* Write Data to GRAM */
0091 }
0092 
0093 static int set_var(struct fbtft_par *par)
0094 {
0095     switch (par->info->var.rotate) {
0096     /* AM: GRAM update direction */
0097     case 0:
0098         write_reg(par, 0x03, 0x0003 | (par->bgr << 12));
0099         break;
0100     case 180:
0101         write_reg(par, 0x03, 0x0000 | (par->bgr << 12));
0102         break;
0103     case 270:
0104         write_reg(par, 0x03, 0x000A | (par->bgr << 12));
0105         break;
0106     case 90:
0107         write_reg(par, 0x03, 0x0009 | (par->bgr << 12));
0108         break;
0109     }
0110 
0111     return 0;
0112 }
0113 
0114 /*
0115  * Gamma string format:
0116  * PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1
0117  * PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1
0118  */
0119 #define CURVE(num, idx)  curves[(num) * par->gamma.num_values + (idx)]
0120 static int set_gamma(struct fbtft_par *par, u32 *curves)
0121 {
0122     static const unsigned long mask[] = {
0123         0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0124         0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0125         0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f,
0126     };
0127     int i, j;
0128 
0129     /* apply mask */
0130     for (i = 0; i < 2; i++)
0131         for (j = 0; j < 14; j++)
0132             CURVE(i, j) &= mask[i * par->gamma.num_values + j];
0133 
0134     write_reg(par, 0x0030, CURVE(0, 1) << 8 | CURVE(0, 0));
0135     write_reg(par, 0x0031, CURVE(0, 3) << 8 | CURVE(0, 2));
0136     write_reg(par, 0x0032, CURVE(0, 5) << 8 | CURVE(0, 3));
0137     write_reg(par, 0x0033, CURVE(0, 7) << 8 | CURVE(0, 6));
0138     write_reg(par, 0x0034, CURVE(0, 9) << 8 | CURVE(0, 8));
0139     write_reg(par, 0x0035, CURVE(0, 11) << 8 | CURVE(0, 10));
0140 
0141     write_reg(par, 0x0036, CURVE(1, 1) << 8 | CURVE(1, 0));
0142     write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2));
0143     write_reg(par, 0x0038, CURVE(1, 5) << 8 | CURVE(1, 4));
0144     write_reg(par, 0x0039, CURVE(1, 7) << 8 | CURVE(1, 6));
0145     write_reg(par, 0x003A, CURVE(1, 9) << 8 | CURVE(1, 8));
0146     write_reg(par, 0x003B, CURVE(1, 11) << 8 | CURVE(1, 10));
0147 
0148     write_reg(par, 0x003C, CURVE(0, 13) << 8 | CURVE(0, 12));
0149     write_reg(par, 0x003D, CURVE(1, 13) << 8 | CURVE(1, 12));
0150 
0151     return 0;
0152 }
0153 
0154 #undef CURVE
0155 
0156 static struct fbtft_display display = {
0157     .regwidth = 16,
0158     .width = WIDTH,
0159     .height = HEIGHT,
0160     .bpp = BPP,
0161     .fps = FPS,
0162     .gamma_num = 2,
0163     .gamma_len = 14,
0164     .gamma = DEFAULT_GAMMA,
0165     .fbtftops = {
0166         .init_display = init_display,
0167         .set_addr_win = set_addr_win,
0168         .set_var = set_var,
0169         .set_gamma = set_gamma,
0170     },
0171 };
0172 
0173 FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display);
0174 
0175 MODULE_ALIAS("spi:" DRVNAME);
0176 MODULE_ALIAS("platform:" DRVNAME);
0177 MODULE_ALIAS("spi:s6d1121");
0178 MODULE_ALIAS("platform:s6d1121");
0179 
0180 MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller");
0181 MODULE_AUTHOR("Roman Rolinsky");
0182 MODULE_LICENSE("GPL");