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