mtk android lcm除錯
參考MTK 文件LCM_Customer_document_MT6575.pdf
The following shows the steps to add a new LCM driver:
(1) Create LCM driver folder $LCM in alps/mediatek/custom/common/kernel/lcm/
(2) Create LCM driver source file $LCM.c in alps/mediatek/custom/common/kernel/lcm/$LCM
(3) Implement LCM driver and export lcm_driver_list/lcm_count variables.
Adaptive LCM Support
At first you should add you new lcm driver as listed in the previous section, and then add the
adaptive support:
1. Modify the adaptive lcm driver common file:
alps/mediatek/custom/common/kernel/lcm/mt65xx_lcm_list.c
2. Add the new LCM driver global variables as shown in the figure below:
3. [VERY IMPORTANT] Please delete the unused LCM driver folder in the customization folder,
such as shown in the figure below:
other LCM drivers will be compiled into codebase too; And if your project doesn’t define
GPIO usage for serial interface, there will be build error.
5. Modify the project makefile alps/mediate/config/(project)/ProjetConfig.mk
Modify CUSTOM_KERNEL_LCM=mt65xx
Modify CUSTOM_UBOOT_LCM=mt65xx
Case Study – DBI Interface LCM Driver Porting
In this chapter, we’ll go through a real case study of DBI LCM driver porting.
LCM specifications:
LCM Drive IC: hx8369
Interface: 24-bit 80 system bus interface
LCD size: 480*800
1. Create LCM driver folder and LCM driver source file
alps/mediatek/custom/common/kernel/lcm/hx8369/lcm_dr.c
2. Modify the project makefile alps/mtk/make/$(project).mak
Add CUSTOM_KERNEL_LCM= hx8369
Add CUSTOM_UBOOT_LCM= hx8369
3. Fill the LCM parameters
A. Configure the basic information according to the HW connection, LCM type and LCM size:
MT6575 LCD IO selection is as shown in following table. LCD data pin can share between DPI and NAND data pin
Pin DPIR[7:0], DPIG[7:0], DPIB[7:0]. So we must set io_select_mode to be 1; if connect LCM data
pin to Nand IF, we must set io_select_mode to be 0
B. Configure data format according to the RGB data pin assignment of the LCM datasheet
C. Configure LCM waveform timing according to the requirement specified in the LCM datasheet
Note: MT6575 LCD controller clock frequency is 130MHz, so clock cycle time is 1/130MHz = 7.69ns
4. Implement LCM init function
According the init process specified in LCM datasheet, pull down/up the reset pin, delay and set
LCM init register settings.
5. Implement LCM update function
Send the block update commands to LCM
6. Implement LCM suspend/resume functions
Send suspend/resume commands to LCM
7. Rebuild uboot and kernel
In the root directory:
./mk $(project) gen_cust
./mk $(project) remake uboot/kernel
./mk $(project) bootimage
參考程式碼:
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2008
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
#include <linux/string.h>
#include "lcm_drv.h"
//#include <linux/kernel.h> //for printk()
//extern void printf(const char* fmt, ...);
#ifdef BUILD_UBOOT
#include <asm/arch/mt6575_gpio.h>
#define print(x...) printf(x)
#else
#include <mach/mt6575_gpio.h>
#define print(x...) printk(x)
#endif
//libin modify for M1-4 on 20120726
#define GPIO_LCD_RST 18 //GPIO18
#define GPIO_MODE_00 0
#define GPIO_DIR_OUT 1
#define GPIO_OUT_ONE 1
#define GPIO_OUT_ZERO 0
extern s32 mt_set_gpio_mode(u32 u4Pin, u32 u4Mode);
extern s32 mt_set_gpio_out(u32 u4Pin, u32 u4PinOut);
extern s32 mt_set_gpio_dir(u32 u4Pin, u32 u4Dir);
// ---------------------------------------------------------------------------
// Local Constants
// ---------------------------------------------------------------------------
#define FRAME_WIDTH (320)
#define FRAME_HEIGHT (480)
// ---------------------------------------------------------------------------
// Local Variables
// ---------------------------------------------------------------------------
static LCM_UTIL_FUNCS lcm_util = {0};
#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
#define UDELAY(n) (lcm_util.udelay(n))
#define MDELAY(n) (lcm_util.mdelay(n))
// ---------------------------------------------------------------------------
// Local Functions
// ---------------------------------------------------------------------------
static __inline unsigned int HIGH_BYTE(unsigned int val)
{
return (val >> 8) & 0xFF;
}
static __inline unsigned int LOW_BYTE(unsigned int val)
{
return (val & 0xFF);
}
static __inline void send_ctrl_cmd(unsigned int cmd)
{
//MDELAY(5);
//mt_set_gpio_out(16, GPIO_OUT_ZERO);
lcm_util.send_cmd(cmd);
// mt_set_gpio_out(16, GPIO_OUT_ONE);
}
static __inline void send_data_cmd(unsigned int data)
{
//MDELAY(5);
//mt_set_gpio_out(16, GPIO_OUT_ZERO);
lcm_util.send_data(data);
// mt_set_gpio_out(16, GPIO_OUT_ONE);
}
static __inline unsigned int read_data_cmd()
{
return lcm_util.read_data();
}
static __inline void set_lcm_register(unsigned int regIndex,
unsigned int regData)
{
send_ctrl_cmd(regIndex);
send_data_cmd(regData);
}
static void init_lcm_registers(void)
{
send_ctrl_cmd(0xF1);
send_data_cmd(0x36);
send_data_cmd(0x04);
send_data_cmd(0x00);
send_data_cmd(0x3C);
send_data_cmd(0x0F);
send_data_cmd(0x8F);
send_ctrl_cmd(0xf2);
send_data_cmd(0x18);
send_data_cmd(0xa3);
send_data_cmd(0x12);
send_data_cmd(0x02);
send_data_cmd(0xb2);
send_data_cmd(0x12);
send_data_cmd(0xff);
send_data_cmd(0x10);
send_data_cmd(0x00);
send_ctrl_cmd(0xf8);
send_data_cmd(0x21);
send_data_cmd(0x04);
send_ctrl_cmd(0xf9);
send_data_cmd(0x00);
send_data_cmd(0x08);
send_ctrl_cmd(0xC0);
send_data_cmd(0x0F);
send_data_cmd(0x0F);
send_ctrl_cmd(0xc1);
send_data_cmd(0x42);
send_ctrl_cmd(0xC2);
send_data_cmd(0x22);
send_ctrl_cmd(0xc5);
send_data_cmd(0x00);
send_data_cmd(0x08);
send_data_cmd(0x80);
send_ctrl_cmd(0xb1);
send_data_cmd(0xB0);
send_data_cmd(0x11);
send_ctrl_cmd(0xb4);
send_data_cmd(0x02);
send_ctrl_cmd(0xb6);
send_data_cmd(0x02);
send_data_cmd(0x02); //cpu?02
send_ctrl_cmd(0xb7);
send_data_cmd(0xC6);
send_ctrl_cmd(0x3a);
send_data_cmd(0x66/*0x55*/);//16bit ?55 18bit ?66
send_ctrl_cmd(0x35);
send_data_cmd(0x00);
send_ctrl_cmd(0x44);
send_data_cmd(0x00);
send_data_cmd(0x5f);
send_ctrl_cmd(0x36);
send_data_cmd(0x08); // 0xc8
send_ctrl_cmd(0x2a);
send_data_cmd(0x00);
send_data_cmd(0x00);
send_data_cmd(0x01);
send_data_cmd(0x3f);
send_ctrl_cmd(0x2b);
send_data_cmd(0x00);
send_data_cmd(0x00);
send_data_cmd(0x01);
send_data_cmd(0xdf);
send_ctrl_cmd(0xe0);
send_data_cmd(0x00);
send_data_cmd(0x1D);
send_data_cmd(0x19);
send_data_cmd(0x0c);
send_data_cmd(0x0f);
send_data_cmd(0x0A);
send_data_cmd(0x45);
send_data_cmd(0x95);
send_data_cmd(0x38);
send_data_cmd(0x0a);
send_data_cmd(0x12);
send_data_cmd(0x03);
send_data_cmd(0x09);
send_data_cmd(0x06);
send_data_cmd(0x00);
send_ctrl_cmd(0xe1);
send_data_cmd(0x0f);
send_data_cmd(0x37);
send_data_cmd(0x35);
send_data_cmd(0x0C);
send_data_cmd(0x0d);
send_data_cmd(0x04);
send_data_cmd(0x48);
send_data_cmd(0x43);
send_data_cmd(0x35);
send_data_cmd(0x04);
send_data_cmd(0x0D);
send_data_cmd(0x02);
send_data_cmd(0x1C);
send_data_cmd(0x18);
send_data_cmd(0x0F);
send_ctrl_cmd(0x11);
MDELAY(120);
send_ctrl_cmd(0x29);
send_ctrl_cmd(0x2c);
MDELAY(10);
}
// ---------------------------------------------------------------------------
// LCM Driver Implementations
// ---------------------------------------------------------------------------
static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
{
memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
}
static void lcm_get_params(LCM_PARAMS *params)
{
memset(params, 0, sizeof(LCM_PARAMS));
params->type = LCM_TYPE_DBI;
params->ctrl = LCM_CTRL_PARALLEL_DBI;
params->width = FRAME_WIDTH;
params->height = FRAME_HEIGHT;
params->io_select_mode = 1;
params->dbi.port = 0; // 1;
//params->dbi.clock_freq = LCM_DBI_CLOCK_FREQ_104M; //aa
params->dbi.data_width = LCM_DBI_DATA_WIDTH_18BITS; //LCM_DBI_DATA_WIDTH_16BITS;
params->dbi.data_format.color_order = LCM_COLOR_ORDER_RGB;
params->dbi.data_format.trans_seq = LCM_DBI_TRANS_SEQ_MSB_FIRST;
params->dbi.data_format.padding = LCM_DBI_PADDING_ON_LSB; //LCM_DBI_PADDING_ON_LSB; //bb
params->dbi.data_format.format = LCM_DBI_FORMAT_RGB666; //LCM_DBI_FORMAT_RGB565;
params->dbi.data_format.width = LCM_DBI_DATA_WIDTH_18BITS; //LCM_DBI_DATA_WIDTH_16BITS;
params->dbi.cpu_write_bits = LCM_DBI_CPU_WRITE_32_BITS; //LCM_DBI_CPU_WRITE_16_BITS;
params->dbi.io_driving_current = LCM_DRIVING_CURRENT_6575_8MA ; // 0;
/* params->dbi.parallel.write_setup = 1;
params->dbi.parallel.write_hold = 1;
params->dbi.parallel.write_wait = 9; // 3;
params->dbi.parallel.read_setup = 1;
params->dbi.parallel.read_latency = 31;
params->dbi.parallel.wait_period = 2;*/
params->dbi.parallel.write_setup = 2;
params->dbi.parallel.write_hold = 2;
params->dbi.parallel.write_wait = 15;
params->dbi.parallel.read_setup = 1;
params->dbi.parallel.read_latency = 31;
params->dbi.parallel.wait_period = 2;
params->dbi.parallel.cs_high_width = 0;
// enable tearing-free
// params->dbi.te_mode = LCM_DBI_TE_MODE_VSYNC_ONLY;
// params->dbi.te_edge_polarity = LCM_POLARITY_FALLING;
/* params->dbi.te_mode = LCM_DBI_TE_MODE_VSYNC_OR_HSYNC;
params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
params->dbi.te_hs_delay_cnt = 50;
params->dbi.te_vs_width_cnt = 277;
params->dbi.te_vs_width_cnt_div = LCM_DBI_TE_VS_WIDTH_CNT_DIV_16;*/
}
#define GPIO_LCD_RST 18 //GPIO18
#define GPIO_MODE_00 0
#define GPIO_DIR_OUT 1
#define GPIO_OUT_ONE 1
#define GPIO_OUT_ZERO 0
extern s32 mt_set_gpio_mode(u32 u4Pin, u32 u4Mode);
extern s32 mt_set_gpio_out(u32 u4Pin, u32 u4PinOut);
extern s32 mt_set_gpio_dir(u32 u4Pin, u32 u4Dir);
static void lcm_init(void)
{
/* SET_RESET_PIN(0);
MDELAY(200);
SET_RESET_PIN(1);
MDELAY(400);*/
// SET_RESET_PIN(1);
mt_set_gpio_mode(GPIO_LCD_RST,GPIO_MODE_00);
mt_set_gpio_dir(GPIO_LCD_RST,GPIO_DIR_OUT);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ONE);
MDELAY(1);
//SET_RESET_PIN(0);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ZERO);
MDELAY(10);
//SET_RESET_PIN(1);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ONE);
MDELAY(100);
init_lcm_registers();
}
static void lcm_suspend(void)
{
send_ctrl_cmd(0x28);
MDELAY(20);
send_ctrl_cmd(0x10);
MDELAY(100);
}
static void lcm_resume(void)
{
send_ctrl_cmd(0x11);
MDELAY(100);
send_ctrl_cmd(0x29);
//MDELAY(100);
/*
send_ctrl_cmd(0x29);
MDELAY(120);
send_ctrl_cmd(0x11);
MDELAY(120); */
}
static void lcm_update(unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{
unsigned int x0 = x;
unsigned int y0 = y;
unsigned int x1 = x0 + width - 1;
unsigned int y1 = y0 + height - 1;
print( "[LCM] *********************ili9486 lcm_update*******************\n\r");
send_ctrl_cmd(0x2A);
send_data_cmd(HIGH_BYTE(x0));
send_data_cmd(LOW_BYTE(x0));
send_data_cmd(HIGH_BYTE(x1));
send_data_cmd(LOW_BYTE(x1));
send_ctrl_cmd(0x2B);
send_data_cmd(HIGH_BYTE(y0));
send_data_cmd(LOW_BYTE(y0));
send_data_cmd(HIGH_BYTE(y1));
send_data_cmd(LOW_BYTE(y1));
// Write To GRAM
send_ctrl_cmd(0x2C);
}
static unsigned int lcm_compare_id(void)
{
return 1;
}
// ---------------------------------------------------------------------------
// Get LCM Driver Hooks
// ---------------------------------------------------------------------------
LCM_DRIVER ili9486_lcm_drv =
{
.name = "ili9486",
.set_util_funcs = lcm_set_util_funcs,
.get_params = lcm_get_params,
.init = lcm_init,
.suspend = lcm_suspend,
.resume = lcm_resume,
.update = lcm_update,
.compare_id = lcm_compare_id
};
注意事項:
1.除錯螢幕主要的工作是初始化和時序設定
2.編譯的時候,僅僅使用./mk r ub k 是不夠的,還需要執行./mk bootimage命令
3.可能是更改了gpio口中LRSTB的原因導致reset失敗,程式碼中通過以下程式碼手動設定reset訊號
static void lcm_init(void)
{
// SET_RESET_PIN(1);
mt_set_gpio_mode(GPIO_LCD_RST,GPIO_MODE_00);
mt_set_gpio_dir(GPIO_LCD_RST,GPIO_DIR_OUT);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ONE);
MDELAY(1);
//SET_RESET_PIN(0);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ZERO);
MDELAY(10);
//SET_RESET_PIN(1);
mt_set_gpio_out(GPIO_LCD_RST,GPIO_OUT_ONE);
MDELAY(100);
...
}