1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * KFR2R09 LCD panel support 4 * 5 * Copyright (C) 2009 Magnus Damm 6 * 7 * Register settings based on the out-of-tree t33fb.c driver 8 * Copyright (C) 2008 Lineo Solutions, Inc. 9 */ 10 11 #include <linux/delay.h> 12 #include <linux/err.h> 13 #include <linux/fb.h> 14 #include <linux/init.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/gpio.h> 18 #include <video/sh_mobile_lcdc.h> 19 #include <mach/kfr2r09.h> 20 #include <cpu/sh7724.h> 21 22 /* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made 23 * up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is 24 * communicating with the main port of the LCDC using an 18-bit SYS interface. 25 * 26 * The device code for this LCD module is 0x01221517. 27 */ 28 29 static const unsigned char data_frame_if[] = { 30 0x02, /* WEMODE: 1=cont, 0=one-shot */ 31 0x00, 0x00, 32 0x00, /* EPF, DFM */ 33 0x02, /* RIM[1] : 1 (18bpp) */ 34 }; 35 36 static const unsigned char data_panel[] = { 37 0x0b, 38 0x63, /* 400 lines */ 39 0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 40 }; 41 42 static const unsigned char data_timing[] = { 43 0x00, 0x00, 0x13, 0x08, 0x08, 44 }; 45 46 static const unsigned char data_timing_src[] = { 47 0x11, 0x01, 0x00, 0x01, 48 }; 49 50 static const unsigned char data_gamma[] = { 51 0x01, 0x02, 0x08, 0x23, 0x03, 0x0c, 0x00, 0x06, 0x00, 0x00, 52 0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00, 53 }; 54 55 static const unsigned char data_power[] = { 56 0x07, 0xc5, 0xdc, 0x02, 0x33, 0x0a, 57 }; 58 59 static unsigned long read_reg(void *sohandle, 60 struct sh_mobile_lcdc_sys_bus_ops *so) 61 { 62 return so->read_data(sohandle); 63 } 64 65 static void write_reg(void *sohandle, 66 struct sh_mobile_lcdc_sys_bus_ops *so, 67 int i, unsigned long v) 68 { 69 if (i) 70 so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */ 71 else 72 so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */ 73 } 74 75 static void write_data(void *sohandle, 76 struct sh_mobile_lcdc_sys_bus_ops *so, 77 unsigned char const *data, int no_data) 78 { 79 int i; 80 81 for (i = 0; i < no_data; i++) 82 write_reg(sohandle, so, 1, data[i]); 83 } 84 85 static unsigned long read_device_code(void *sohandle, 86 struct sh_mobile_lcdc_sys_bus_ops *so) 87 { 88 unsigned long device_code; 89 90 /* access protect OFF */ 91 write_reg(sohandle, so, 0, 0xb0); 92 write_reg(sohandle, so, 1, 0x00); 93 94 /* deep standby OFF */ 95 write_reg(sohandle, so, 0, 0xb1); 96 write_reg(sohandle, so, 1, 0x00); 97 98 /* device code command */ 99 write_reg(sohandle, so, 0, 0xbf); 100 mdelay(50); 101 102 /* dummy read */ 103 read_reg(sohandle, so); 104 105 /* read device code */ 106 device_code = ((read_reg(sohandle, so) & 0xff) << 24); 107 device_code |= ((read_reg(sohandle, so) & 0xff) << 16); 108 device_code |= ((read_reg(sohandle, so) & 0xff) << 8); 109 device_code |= (read_reg(sohandle, so) & 0xff); 110 111 return device_code; 112 } 113 114 static void write_memory_start(void *sohandle, 115 struct sh_mobile_lcdc_sys_bus_ops *so) 116 { 117 write_reg(sohandle, so, 0, 0x2c); 118 } 119 120 static void clear_memory(void *sohandle, 121 struct sh_mobile_lcdc_sys_bus_ops *so) 122 { 123 int i; 124 125 /* write start */ 126 write_memory_start(sohandle, so); 127 128 /* paint it black */ 129 for (i = 0; i < (240 * 400); i++) 130 write_reg(sohandle, so, 1, 0x00); 131 } 132 133 static void display_on(void *sohandle, 134 struct sh_mobile_lcdc_sys_bus_ops *so) 135 { 136 /* access protect off */ 137 write_reg(sohandle, so, 0, 0xb0); 138 write_reg(sohandle, so, 1, 0x00); 139 140 /* exit deep standby mode */ 141 write_reg(sohandle, so, 0, 0xb1); 142 write_reg(sohandle, so, 1, 0x00); 143 144 /* frame memory I/F */ 145 write_reg(sohandle, so, 0, 0xb3); 146 write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if)); 147 148 /* display mode and frame memory write mode */ 149 write_reg(sohandle, so, 0, 0xb4); 150 write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */ 151 152 /* panel */ 153 write_reg(sohandle, so, 0, 0xc0); 154 write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel)); 155 156 /* timing (normal) */ 157 write_reg(sohandle, so, 0, 0xc1); 158 write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing)); 159 160 /* timing (partial) */ 161 write_reg(sohandle, so, 0, 0xc2); 162 write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing)); 163 164 /* timing (idle) */ 165 write_reg(sohandle, so, 0, 0xc3); 166 write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing)); 167 168 /* timing (source/VCOM/gate driving) */ 169 write_reg(sohandle, so, 0, 0xc4); 170 write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src)); 171 172 /* gamma (red) */ 173 write_reg(sohandle, so, 0, 0xc8); 174 write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma)); 175 176 /* gamma (green) */ 177 write_reg(sohandle, so, 0, 0xc9); 178 write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma)); 179 180 /* gamma (blue) */ 181 write_reg(sohandle, so, 0, 0xca); 182 write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma)); 183 184 /* power (common) */ 185 write_reg(sohandle, so, 0, 0xd0); 186 write_data(sohandle, so, data_power, ARRAY_SIZE(data_power)); 187 188 /* VCOM */ 189 write_reg(sohandle, so, 0, 0xd1); 190 write_reg(sohandle, so, 1, 0x00); 191 write_reg(sohandle, so, 1, 0x0f); 192 write_reg(sohandle, so, 1, 0x02); 193 194 /* power (normal) */ 195 write_reg(sohandle, so, 0, 0xd2); 196 write_reg(sohandle, so, 1, 0x63); 197 write_reg(sohandle, so, 1, 0x24); 198 199 /* power (partial) */ 200 write_reg(sohandle, so, 0, 0xd3); 201 write_reg(sohandle, so, 1, 0x63); 202 write_reg(sohandle, so, 1, 0x24); 203 204 /* power (idle) */ 205 write_reg(sohandle, so, 0, 0xd4); 206 write_reg(sohandle, so, 1, 0x63); 207 write_reg(sohandle, so, 1, 0x24); 208 209 write_reg(sohandle, so, 0, 0xd8); 210 write_reg(sohandle, so, 1, 0x77); 211 write_reg(sohandle, so, 1, 0x77); 212 213 /* TE signal */ 214 write_reg(sohandle, so, 0, 0x35); 215 write_reg(sohandle, so, 1, 0x00); 216 217 /* TE signal line */ 218 write_reg(sohandle, so, 0, 0x44); 219 write_reg(sohandle, so, 1, 0x00); 220 write_reg(sohandle, so, 1, 0x00); 221 222 /* column address */ 223 write_reg(sohandle, so, 0, 0x2a); 224 write_reg(sohandle, so, 1, 0x00); 225 write_reg(sohandle, so, 1, 0x00); 226 write_reg(sohandle, so, 1, 0x00); 227 write_reg(sohandle, so, 1, 0xef); 228 229 /* page address */ 230 write_reg(sohandle, so, 0, 0x2b); 231 write_reg(sohandle, so, 1, 0x00); 232 write_reg(sohandle, so, 1, 0x00); 233 write_reg(sohandle, so, 1, 0x01); 234 write_reg(sohandle, so, 1, 0x8f); 235 236 /* exit sleep mode */ 237 write_reg(sohandle, so, 0, 0x11); 238 239 mdelay(120); 240 241 /* clear vram */ 242 clear_memory(sohandle, so); 243 244 /* display ON */ 245 write_reg(sohandle, so, 0, 0x29); 246 mdelay(1); 247 248 write_memory_start(sohandle, so); 249 } 250 251 int kfr2r09_lcd_setup(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so) 252 { 253 /* power on */ 254 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */ 255 gpio_set_value(GPIO_PTE4, 0); /* LCD_RST/ -> L */ 256 gpio_set_value(GPIO_PTF4, 1); /* PROTECT/ -> H */ 257 udelay(1100); 258 gpio_set_value(GPIO_PTE4, 1); /* LCD_RST/ -> H */ 259 udelay(10); 260 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */ 261 mdelay(20); 262 263 if (read_device_code(sohandle, so) != 0x01221517) 264 return -ENODEV; 265 266 pr_info("KFR2R09 WQVGA LCD Module detected.\n"); 267 268 display_on(sohandle, so); 269 return 0; 270 } 271 272 void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so) 273 { 274 write_memory_start(sohandle, so); 275 } 276
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.