Path: blob/master/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
15131 views
/*1* KFR2R09 LCD panel support2*3* Copyright (C) 2009 Magnus Damm4*5* Register settings based on the out-of-tree t33fb.c driver6* Copyright (C) 2008 Lineo Solutions, Inc.7*8* This file is subject to the terms and conditions of the GNU General Public9* License. See the file COPYING in the main directory of this archive for10* more details.11*/1213#include <linux/delay.h>14#include <linux/err.h>15#include <linux/fb.h>16#include <linux/init.h>17#include <linux/kernel.h>18#include <linux/module.h>19#include <linux/gpio.h>20#include <video/sh_mobile_lcdc.h>21#include <mach/kfr2r09.h>22#include <cpu/sh7724.h>2324/* The on-board LCD module is a Hitachi TX07D34VM0AAA. This module is made25* up of a 240x400 LCD hooked up to a R61517 driver IC. The driver IC is26* communicating with the main port of the LCDC using an 18-bit SYS interface.27*28* The device code for this LCD module is 0x01221517.29*/3031static const unsigned char data_frame_if[] = {320x02, /* WEMODE: 1=cont, 0=one-shot */330x00, 0x00,340x00, /* EPF, DFM */350x02, /* RIM[1] : 1 (18bpp) */36};3738static const unsigned char data_panel[] = {390x0b,400x63, /* 400 lines */410x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,42};4344static const unsigned char data_timing[] = {450x00, 0x00, 0x13, 0x08, 0x08,46};4748static const unsigned char data_timing_src[] = {490x11, 0x01, 0x00, 0x01,50};5152static const unsigned char data_gamma[] = {530x01, 0x02, 0x08, 0x23, 0x03, 0x0c, 0x00, 0x06, 0x00, 0x00,540x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,55};5657static const unsigned char data_power[] = {580x07, 0xc5, 0xdc, 0x02, 0x33, 0x0a,59};6061static unsigned long read_reg(void *sohandle,62struct sh_mobile_lcdc_sys_bus_ops *so)63{64return so->read_data(sohandle);65}6667static void write_reg(void *sohandle,68struct sh_mobile_lcdc_sys_bus_ops *so,69int i, unsigned long v)70{71if (i)72so->write_data(sohandle, v); /* PTH4/LCDRS High [param, 17:0] */73else74so->write_index(sohandle, v); /* PTH4/LCDRS Low [cmd, 7:0] */75}7677static void write_data(void *sohandle,78struct sh_mobile_lcdc_sys_bus_ops *so,79unsigned char const *data, int no_data)80{81int i;8283for (i = 0; i < no_data; i++)84write_reg(sohandle, so, 1, data[i]);85}8687static unsigned long read_device_code(void *sohandle,88struct sh_mobile_lcdc_sys_bus_ops *so)89{90unsigned long device_code;9192/* access protect OFF */93write_reg(sohandle, so, 0, 0xb0);94write_reg(sohandle, so, 1, 0x00);9596/* deep standby OFF */97write_reg(sohandle, so, 0, 0xb1);98write_reg(sohandle, so, 1, 0x00);99100/* device code command */101write_reg(sohandle, so, 0, 0xbf);102mdelay(50);103104/* dummy read */105read_reg(sohandle, so);106107/* read device code */108device_code = ((read_reg(sohandle, so) & 0xff) << 24);109device_code |= ((read_reg(sohandle, so) & 0xff) << 16);110device_code |= ((read_reg(sohandle, so) & 0xff) << 8);111device_code |= (read_reg(sohandle, so) & 0xff);112113return device_code;114}115116static void write_memory_start(void *sohandle,117struct sh_mobile_lcdc_sys_bus_ops *so)118{119write_reg(sohandle, so, 0, 0x2c);120}121122static void clear_memory(void *sohandle,123struct sh_mobile_lcdc_sys_bus_ops *so)124{125int i;126127/* write start */128write_memory_start(sohandle, so);129130/* paint it black */131for (i = 0; i < (240 * 400); i++)132write_reg(sohandle, so, 1, 0x00);133}134135static void display_on(void *sohandle,136struct sh_mobile_lcdc_sys_bus_ops *so)137{138/* access protect off */139write_reg(sohandle, so, 0, 0xb0);140write_reg(sohandle, so, 1, 0x00);141142/* exit deep standby mode */143write_reg(sohandle, so, 0, 0xb1);144write_reg(sohandle, so, 1, 0x00);145146/* frame memory I/F */147write_reg(sohandle, so, 0, 0xb3);148write_data(sohandle, so, data_frame_if, ARRAY_SIZE(data_frame_if));149150/* display mode and frame memory write mode */151write_reg(sohandle, so, 0, 0xb4);152write_reg(sohandle, so, 1, 0x00); /* DBI, internal clock */153154/* panel */155write_reg(sohandle, so, 0, 0xc0);156write_data(sohandle, so, data_panel, ARRAY_SIZE(data_panel));157158/* timing (normal) */159write_reg(sohandle, so, 0, 0xc1);160write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));161162/* timing (partial) */163write_reg(sohandle, so, 0, 0xc2);164write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));165166/* timing (idle) */167write_reg(sohandle, so, 0, 0xc3);168write_data(sohandle, so, data_timing, ARRAY_SIZE(data_timing));169170/* timing (source/VCOM/gate driving) */171write_reg(sohandle, so, 0, 0xc4);172write_data(sohandle, so, data_timing_src, ARRAY_SIZE(data_timing_src));173174/* gamma (red) */175write_reg(sohandle, so, 0, 0xc8);176write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));177178/* gamma (green) */179write_reg(sohandle, so, 0, 0xc9);180write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));181182/* gamma (blue) */183write_reg(sohandle, so, 0, 0xca);184write_data(sohandle, so, data_gamma, ARRAY_SIZE(data_gamma));185186/* power (common) */187write_reg(sohandle, so, 0, 0xd0);188write_data(sohandle, so, data_power, ARRAY_SIZE(data_power));189190/* VCOM */191write_reg(sohandle, so, 0, 0xd1);192write_reg(sohandle, so, 1, 0x00);193write_reg(sohandle, so, 1, 0x0f);194write_reg(sohandle, so, 1, 0x02);195196/* power (normal) */197write_reg(sohandle, so, 0, 0xd2);198write_reg(sohandle, so, 1, 0x63);199write_reg(sohandle, so, 1, 0x24);200201/* power (partial) */202write_reg(sohandle, so, 0, 0xd3);203write_reg(sohandle, so, 1, 0x63);204write_reg(sohandle, so, 1, 0x24);205206/* power (idle) */207write_reg(sohandle, so, 0, 0xd4);208write_reg(sohandle, so, 1, 0x63);209write_reg(sohandle, so, 1, 0x24);210211write_reg(sohandle, so, 0, 0xd8);212write_reg(sohandle, so, 1, 0x77);213write_reg(sohandle, so, 1, 0x77);214215/* TE signal */216write_reg(sohandle, so, 0, 0x35);217write_reg(sohandle, so, 1, 0x00);218219/* TE signal line */220write_reg(sohandle, so, 0, 0x44);221write_reg(sohandle, so, 1, 0x00);222write_reg(sohandle, so, 1, 0x00);223224/* column address */225write_reg(sohandle, so, 0, 0x2a);226write_reg(sohandle, so, 1, 0x00);227write_reg(sohandle, so, 1, 0x00);228write_reg(sohandle, so, 1, 0x00);229write_reg(sohandle, so, 1, 0xef);230231/* page address */232write_reg(sohandle, so, 0, 0x2b);233write_reg(sohandle, so, 1, 0x00);234write_reg(sohandle, so, 1, 0x00);235write_reg(sohandle, so, 1, 0x01);236write_reg(sohandle, so, 1, 0x8f);237238/* exit sleep mode */239write_reg(sohandle, so, 0, 0x11);240241mdelay(120);242243/* clear vram */244clear_memory(sohandle, so);245246/* display ON */247write_reg(sohandle, so, 0, 0x29);248mdelay(1);249250write_memory_start(sohandle, so);251}252253int kfr2r09_lcd_setup(void *board_data, void *sohandle,254struct sh_mobile_lcdc_sys_bus_ops *so)255{256/* power on */257gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */258gpio_set_value(GPIO_PTE4, 0); /* LCD_RST/ -> L */259gpio_set_value(GPIO_PTF4, 1); /* PROTECT/ -> H */260udelay(1100);261gpio_set_value(GPIO_PTE4, 1); /* LCD_RST/ -> H */262udelay(10);263gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */264mdelay(20);265266if (read_device_code(sohandle, so) != 0x01221517)267return -ENODEV;268269pr_info("KFR2R09 WQVGA LCD Module detected.\n");270271display_on(sohandle, so);272return 0;273}274275void kfr2r09_lcd_start(void *board_data, void *sohandle,276struct sh_mobile_lcdc_sys_bus_ops *so)277{278write_memory_start(sohandle, so);279}280281#define CTRL_CKSW 0x10282#define CTRL_C10 0x20283#define CTRL_CPSW 0x80284#define MAIN_MLED4 0x40285#define MAIN_MSW 0x80286287static int kfr2r09_lcd_backlight(int on)288{289struct i2c_adapter *a;290struct i2c_msg msg;291unsigned char buf[2];292int ret;293294a = i2c_get_adapter(0);295if (!a)296return -ENODEV;297298buf[0] = 0x00;299if (on)300buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;301else302buf[1] = 0;303304msg.addr = 0x75;305msg.buf = buf;306msg.len = 2;307msg.flags = 0;308ret = i2c_transfer(a, &msg, 1);309if (ret != 1)310return -ENODEV;311312buf[0] = 0x01;313if (on)314buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;315else316buf[1] = 0;317318msg.addr = 0x75;319msg.buf = buf;320msg.len = 2;321msg.flags = 0;322ret = i2c_transfer(a, &msg, 1);323if (ret != 1)324return -ENODEV;325326return 0;327}328329void kfr2r09_lcd_on(void *board_data, struct fb_info *info)330{331kfr2r09_lcd_backlight(1);332}333334void kfr2r09_lcd_off(void *board_data)335{336kfr2r09_lcd_backlight(0);337}338339340