0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/delay.h>
0016 #include <linux/device.h>
0017 #include <linux/kernel.h>
0018 #include <linux/lcd.h>
0019 #include <linux/module.h>
0020 #include <linux/spi/spi.h>
0021
0022 #define OTM3225A_INDEX_REG 0x70
0023 #define OTM3225A_DATA_REG 0x72
0024
0025
0026 #define DRIVER_OUTPUT_CTRL_1 0x01
0027 #define DRIVER_WAVEFORM_CTRL 0x02
0028 #define ENTRY_MODE 0x03
0029 #define SCALING_CTRL 0x04
0030 #define DISPLAY_CTRL_1 0x07
0031 #define DISPLAY_CTRL_2 0x08
0032 #define DISPLAY_CTRL_3 0x09
0033 #define FRAME_CYCLE_CTRL 0x0A
0034 #define EXT_DISP_IFACE_CTRL_1 0x0C
0035 #define FRAME_MAKER_POS 0x0D
0036 #define EXT_DISP_IFACE_CTRL_2 0x0F
0037 #define POWER_CTRL_1 0x10
0038 #define POWER_CTRL_2 0x11
0039 #define POWER_CTRL_3 0x12
0040 #define POWER_CTRL_4 0x13
0041 #define GRAM_ADDR_HORIZ_SET 0x20
0042 #define GRAM_ADDR_VERT_SET 0x21
0043 #define GRAM_READ_WRITE 0x22
0044 #define POWER_CTRL_7 0x29
0045 #define FRAME_RATE_CTRL 0x2B
0046 #define GAMMA_CTRL_1 0x30
0047 #define GAMMA_CTRL_2 0x31
0048 #define GAMMA_CTRL_3 0x32
0049 #define GAMMA_CTRL_4 0x35
0050 #define GAMMA_CTRL_5 0x36
0051 #define GAMMA_CTRL_6 0x37
0052 #define GAMMA_CTRL_7 0x38
0053 #define GAMMA_CTRL_8 0x39
0054 #define GAMMA_CTRL_9 0x3C
0055 #define GAMMA_CTRL_10 0x3D
0056 #define WINDOW_HORIZ_RAM_START 0x50
0057 #define WINDOW_HORIZ_RAM_END 0x51
0058 #define WINDOW_VERT_RAM_START 0x52
0059 #define WINDOW_VERT_RAM_END 0x53
0060 #define DRIVER_OUTPUT_CTRL_2 0x60
0061 #define BASE_IMG_DISPLAY_CTRL 0x61
0062 #define VERT_SCROLL_CTRL 0x6A
0063 #define PD1_DISPLAY_POS 0x80
0064 #define PD1_RAM_START 0x81
0065 #define PD1_RAM_END 0x82
0066 #define PD2_DISPLAY_POS 0x83
0067 #define PD2_RAM_START 0x84
0068 #define PD2_RAM_END 0x85
0069 #define PANEL_IFACE_CTRL_1 0x90
0070 #define PANEL_IFACE_CTRL_2 0x92
0071 #define PANEL_IFACE_CTRL_4 0x95
0072 #define PANEL_IFACE_CTRL_5 0x97
0073
0074 struct otm3225a_data {
0075 struct spi_device *spi;
0076 struct lcd_device *ld;
0077 int power;
0078 };
0079
0080 struct otm3225a_spi_instruction {
0081 unsigned char reg;
0082 unsigned short value;
0083 unsigned short delay;
0084 };
0085
0086 static struct otm3225a_spi_instruction display_init[] = {
0087 { DRIVER_OUTPUT_CTRL_1, 0x0000, 0 },
0088 { DRIVER_WAVEFORM_CTRL, 0x0700, 0 },
0089 { ENTRY_MODE, 0x50A0, 0 },
0090 { SCALING_CTRL, 0x0000, 0 },
0091 { DISPLAY_CTRL_2, 0x0606, 0 },
0092 { DISPLAY_CTRL_3, 0x0000, 0 },
0093 { FRAME_CYCLE_CTRL, 0x0000, 0 },
0094 { EXT_DISP_IFACE_CTRL_1, 0x0000, 0 },
0095 { FRAME_MAKER_POS, 0x0000, 0 },
0096 { EXT_DISP_IFACE_CTRL_2, 0x0002, 0 },
0097 { POWER_CTRL_2, 0x0007, 0 },
0098 { POWER_CTRL_3, 0x0000, 0 },
0099 { POWER_CTRL_4, 0x0000, 200 },
0100 { DISPLAY_CTRL_1, 0x0101, 0 },
0101 { POWER_CTRL_1, 0x12B0, 0 },
0102 { POWER_CTRL_2, 0x0007, 0 },
0103 { POWER_CTRL_3, 0x01BB, 50 },
0104 { POWER_CTRL_4, 0x0013, 0 },
0105 { POWER_CTRL_7, 0x0010, 50 },
0106 { GAMMA_CTRL_1, 0x000A, 0 },
0107 { GAMMA_CTRL_2, 0x1326, 0 },
0108 { GAMMA_CTRL_3, 0x0A29, 0 },
0109 { GAMMA_CTRL_4, 0x0A0A, 0 },
0110 { GAMMA_CTRL_5, 0x1E03, 0 },
0111 { GAMMA_CTRL_6, 0x031E, 0 },
0112 { GAMMA_CTRL_7, 0x0706, 0 },
0113 { GAMMA_CTRL_8, 0x0303, 0 },
0114 { GAMMA_CTRL_9, 0x010E, 0 },
0115 { GAMMA_CTRL_10, 0x040E, 0 },
0116 { WINDOW_HORIZ_RAM_START, 0x0000, 0 },
0117 { WINDOW_HORIZ_RAM_END, 0x00EF, 0 },
0118 { WINDOW_VERT_RAM_START, 0x0000, 0 },
0119 { WINDOW_VERT_RAM_END, 0x013F, 0 },
0120 { DRIVER_OUTPUT_CTRL_2, 0x2700, 0 },
0121 { BASE_IMG_DISPLAY_CTRL, 0x0001, 0 },
0122 { VERT_SCROLL_CTRL, 0x0000, 0 },
0123 { PD1_DISPLAY_POS, 0x0000, 0 },
0124 { PD1_RAM_START, 0x0000, 0 },
0125 { PD1_RAM_END, 0x0000, 0 },
0126 { PD2_DISPLAY_POS, 0x0000, 0 },
0127 { PD2_RAM_START, 0x0000, 0 },
0128 { PD2_RAM_END, 0x0000, 0 },
0129 { PANEL_IFACE_CTRL_1, 0x0010, 0 },
0130 { PANEL_IFACE_CTRL_2, 0x0000, 0 },
0131 { PANEL_IFACE_CTRL_4, 0x0210, 0 },
0132 { PANEL_IFACE_CTRL_5, 0x0000, 0 },
0133 { DISPLAY_CTRL_1, 0x0133, 0 },
0134 };
0135
0136 static struct otm3225a_spi_instruction display_enable_rgb_interface[] = {
0137 { ENTRY_MODE, 0x1080, 0 },
0138 { GRAM_ADDR_HORIZ_SET, 0x0000, 0 },
0139 { GRAM_ADDR_VERT_SET, 0x0000, 0 },
0140 { EXT_DISP_IFACE_CTRL_1, 0x0111, 500 },
0141 };
0142
0143 static struct otm3225a_spi_instruction display_off[] = {
0144 { DISPLAY_CTRL_1, 0x0131, 100 },
0145 { DISPLAY_CTRL_1, 0x0130, 100 },
0146 { DISPLAY_CTRL_1, 0x0100, 0 },
0147 { POWER_CTRL_1, 0x0280, 0 },
0148 { POWER_CTRL_3, 0x018B, 0 },
0149 };
0150
0151 static struct otm3225a_spi_instruction display_on[] = {
0152 { POWER_CTRL_1, 0x1280, 0 },
0153 { DISPLAY_CTRL_1, 0x0101, 100 },
0154 { DISPLAY_CTRL_1, 0x0121, 0 },
0155 { DISPLAY_CTRL_1, 0x0123, 100 },
0156 { DISPLAY_CTRL_1, 0x0133, 10 },
0157 };
0158
0159 static void otm3225a_write(struct spi_device *spi,
0160 struct otm3225a_spi_instruction *instruction,
0161 unsigned int count)
0162 {
0163 unsigned char buf[3];
0164
0165 while (count--) {
0166
0167 buf[0] = OTM3225A_INDEX_REG;
0168 buf[1] = 0x00;
0169 buf[2] = instruction->reg;
0170 spi_write(spi, buf, 3);
0171
0172
0173 buf[0] = OTM3225A_DATA_REG;
0174 buf[1] = (instruction->value >> 8) & 0xff;
0175 buf[2] = instruction->value & 0xff;
0176 spi_write(spi, buf, 3);
0177
0178
0179 if (instruction->delay)
0180 msleep(instruction->delay);
0181 instruction++;
0182 }
0183 }
0184
0185 static int otm3225a_set_power(struct lcd_device *ld, int power)
0186 {
0187 struct otm3225a_data *dd = lcd_get_data(ld);
0188
0189 if (power == dd->power)
0190 return 0;
0191
0192 if (power > FB_BLANK_UNBLANK)
0193 otm3225a_write(dd->spi, display_off, ARRAY_SIZE(display_off));
0194 else
0195 otm3225a_write(dd->spi, display_on, ARRAY_SIZE(display_on));
0196 dd->power = power;
0197
0198 return 0;
0199 }
0200
0201 static int otm3225a_get_power(struct lcd_device *ld)
0202 {
0203 struct otm3225a_data *dd = lcd_get_data(ld);
0204
0205 return dd->power;
0206 }
0207
0208 static struct lcd_ops otm3225a_ops = {
0209 .set_power = otm3225a_set_power,
0210 .get_power = otm3225a_get_power,
0211 };
0212
0213 static int otm3225a_probe(struct spi_device *spi)
0214 {
0215 struct otm3225a_data *dd;
0216 struct lcd_device *ld;
0217 struct device *dev = &spi->dev;
0218
0219 dd = devm_kzalloc(dev, sizeof(struct otm3225a_data), GFP_KERNEL);
0220 if (dd == NULL)
0221 return -ENOMEM;
0222
0223 ld = devm_lcd_device_register(dev, dev_name(dev), dev, dd,
0224 &otm3225a_ops);
0225 if (IS_ERR(ld))
0226 return PTR_ERR(ld);
0227
0228 dd->spi = spi;
0229 dd->ld = ld;
0230 dev_set_drvdata(dev, dd);
0231
0232 dev_info(dev, "Initializing and switching to RGB interface");
0233 otm3225a_write(spi, display_init, ARRAY_SIZE(display_init));
0234 otm3225a_write(spi, display_enable_rgb_interface,
0235 ARRAY_SIZE(display_enable_rgb_interface));
0236 return 0;
0237 }
0238
0239 static struct spi_driver otm3225a_driver = {
0240 .driver = {
0241 .name = "otm3225a",
0242 .owner = THIS_MODULE,
0243 },
0244 .probe = otm3225a_probe,
0245 };
0246
0247 module_spi_driver(otm3225a_driver);
0248
0249 MODULE_AUTHOR("Felix Brack <fb@ltec.ch>");
0250 MODULE_DESCRIPTION("OTM3225A TFT LCD driver");
0251 MODULE_VERSION("1.0.0");
0252 MODULE_LICENSE("GPL v2");