Files
linux-legacy/drivers/video/mxc/mxcfb_mtl017.c
2011-02-17 17:06:01 -06:00

862 lines
24 KiB
C

/*
* Copyright 2009 Pegatron, Inc. All Rights Reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @defgroup Framebuffer Framebuffer Driver for Efikasb Platform.
*/
/*!
* @file mxcfb_mtl017.c
*
* @brief MXC Frame buffer driver for Efikasb Platform
*
* @ingroup Framebuffer
*/
/*!
* Include files
*/
#define DEBUG
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/i2c.h>
#include <linux/mxcfb.h>
#include <linux/ipu.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
#define EDID_LENGTH 128
#define DEBUG_MTL017 1
typedef struct mtl017_dev_data_tag {
struct i2c_client *client;
u8 edid[EDID_LENGTH];
struct fb_videomode *mode;
u8 *regs;
int suspending;
int disp_on;
struct semaphore sem;
void (*reset)(void);
void (*lcd_power) (int);
void (*lvds_power) (int);
void (*lvds_enable) (int);
} mtl017_dev_data;
//vv static struct mtl017_dev_data *mtl017 = NULL;
static mtl017_dev_data * mtl017 = NULL; //vv
static void mtl017_conf(u8 *reg_tbl);
static void disp_power_on(void);
static void disp_power_off(void);
static void disp_on_work_handler(struct work_struct *work);
static void disp_off_work_handler(struct work_struct *work);
static void disp_on_work_handler(struct work_struct *work)
{
disp_power_on();
}
static void disp_off_work_handler(struct work_struct *work)
{
disp_power_off();
}
static DECLARE_WORK(disp_off_work, disp_off_work_handler);
static DECLARE_WORK(disp_on_work, disp_on_work_handler);
#ifdef DEBUG_MTL017
static void dump_edid(unsigned char *id)
{
int i;
printk("EDID Dump:\n");
for (i = 0; i < EDID_LENGTH; i+=32) {
int j;
for ( j = 0; j < 32; j++) {
printk("%02x", id[i+j]);
}
printk("\n");
}
}
static void dump_screeninfo(struct fb_var_screeninfo *einfo)
{
printk("resolution: r(%d, %d), v(%d, %d) o(%d, %d)\n",
einfo->xres,
einfo->yres,
einfo->xres_virtual,
einfo->yres_virtual,
einfo->xoffset,
einfo->yoffset);
printk("bpp=%d, hw(%d, %d), pclk=%d\n",
einfo->bits_per_pixel,
einfo->height,
einfo->width,
einfo->pixclock);
printk("margin(%d, %d, %d, %d)\n",
einfo->left_margin,
einfo->right_margin,
einfo->upper_margin,
einfo->lower_margin);
printk("hv(%d, %d), sync=%x, vmode=%x\n",
einfo->hsync_len,
einfo->vsync_len,
einfo->sync,
einfo->vmode);
}
#else
static void dump_edid(unsigned char *edid) {}
static void dump_screeninfo(struct fb_var_screeninfo *einfo) {}
#endif
static u8 mtl017_auo_tbl[] = {
/* ron: 66M to 66M */
/* 0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00, */
/* 0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00, */
/* 0x00,0x21,0x01,0x08,0x00,0x1E,0x01,0x05, */
/* 0x00,0x01,0x7C,0x04,0x32,0x00,0x00,0x04, */
/* 0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58, */
/* 0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00, */
/* 0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01, */
/* 0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04, */
/* 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A, */
/* 0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C, */
/* 0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45, */
/* 0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48, */
/* 0x00,0x00,0x06,0x01,0x02,0x00,0x10,0x04, */
/* 0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00, */
/* 0x32,0x00,0x00,0x04,0x12,0x00,0x00,0x03, */
/* 0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18, */
/* 0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* ron: 44MHz to 54MHz */
/* 0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00, */
/* 0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00, */
/* 0x00,0x3B,0x01,0x08,0x00,0x1E,0x01,0x05, */
/* 0x00,0x01,0x82,0x05,0x32,0x00,0x00,0x04, */
/* 0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58, */
/* 0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00, */
/* 0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01, */
/* 0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04, */
/* 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A, */
/* 0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C, */
/* 0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45, */
/* 0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48, */
/* 0x00,0x04,0x2A,0x01,0x02,0x00,0x10,0x04, */
/* 0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00, */
/* 0x32,0x00,0x00,0x04,0x12,0x00,0x58,0x02, */
/* 0x02,0x7C,0x04,0x7E,0x02,0x11,0x78,0x18, */
/* 0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* ron: 44MHz to 48MHz */
/* 0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00, */
/* 0x00,0x04,0x16,0x00,0x59,0x02,0x00,0x00, */
/* 0x00,0x21,0x00,0x09,0x00,0x1E,0x01,0x05, */
/* 0x00,0x01,0xEA,0x04,0x32,0x00,0x00,0x04, */
/* 0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58, */
/* 0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00, */
/* 0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01, */
/* 0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04, */
/* 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A, */
/* 0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C, */
/* 0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45, */
/* 0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48, */
/* 0x00,0x02,0x16,0x01,0x02,0x00,0x10,0x04, */
/* 0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00, */
/* 0x32,0x00,0x00,0x04,0x12,0x00,0x00,0x03, */
/* 0x02,0x7C,0x04,0x7E,0x02,0x11,0x78,0x18, */
/* 0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* ron: 44M to 53.8M */
/* 0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00, */
/* 0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00, */
/* 0x00,0x3B,0x01,0x08,0x00,0x1E,0x01,0x05, */
/* 0x00,0x01,0x7E,0x05,0x32,0x00,0x00,0x04, */
/* 0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58, */
/* 0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00, */
/* 0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01, */
/* 0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04, */
/* 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A, */
/* 0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C, */
/* 0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45, */
/* 0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48, */
/* 0x00,0x06,0x3B,0x01,0x02,0x00,0x10,0x04, */
/* 0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00, */
/* 0x32,0x00,0x00,0x04,0x12,0x00,0x58,0x02, */
/* 0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18, */
/* 0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* ron: 44M to 53.9M */
0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00,
0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00,
0x00,0x3B,0x01,0x08,0x00,0x1E,0x01,0x05,
0x00,0x01,0x72,0x05,0x32,0x00,0x00,0x04,
0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58,
0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01,
0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04,
0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A,
0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C,
0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45,
0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48,
0x00,0x01,0x10,0x01,0x00,0x00,0x10,0x04,
0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00,
0x32,0x00,0x00,0x04,0x12,0x00,0x58,0x02,
0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18,
0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
static u8 mtl017_cpt_tbl[] = {
/* 0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00, */
/* 0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00, */
/* 0x00,0x21,0x01,0x08,0x00,0x1E,0x01,0x05, */
/* 0x00,0x01,0x7C,0x04,0x32,0x00,0x00,0x04, */
/* 0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58, */
/* 0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00, */
/* 0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01, */
/* 0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04, */
/* 0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A, */
/* 0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C, */
/* 0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45, */
/* 0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00, */
/* 0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48, */
/* 0x00,0x00,0x06,0x01,0x02,0x00,0x10,0x04, */
/* 0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00, */
/* 0x32,0x00,0x00,0x04,0x12,0x00,0x00,0x03, */
/* 0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18, */
/* 0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, */
/* ron: 44M to 53.9M */
0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00,
0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00,
0x00,0x3B,0x01,0x08,0x00,0x1E,0x01,0x05,
0x00,0x01,0x72,0x05,0x32,0x00,0x00,0x04,
0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58,
0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01,
0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04,
0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A,
0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C,
0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45,
0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48,
0x00,0x01,0x10,0x01,0x00,0x00,0x10,0x04,
0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00,
0x32,0x00,0x00,0x04,0x12,0x00,0x58,0x02,
0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18,
0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
static u8 mtl017_auo_hires_tbl[] = {
0x00,0x20,0xAF,0x59,0x2B,0xDE,0x3D,0x00,
0x00,0x05,0x0C,0x00,0xD0,0x02,0x00,0x00,
0x00,0x05,0x00,0x02,0x00,0x02,0x00,0x0A,
0x00,0x01,0x70,0x05,0x3D,0x00,0x00,0x05,
0x00,0x00,0x20,0xF0,0x02,0x0C,0x00,0xD0,
0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01,
0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04,
0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A,
0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C,
0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45,
0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48,
0x00,0x00,0x06,0x01,0x02,0x00,0x12,0x04,
0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00,
0x3D,0x00,0x00,0x05,0x0C,0x00,0xD0,0x02,
0x02,0x70,0x05,0xE0,0x02,0x11,0x78,0x18,
0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
static u8 mtl017_cmo_tbl[] = {
/* ron: 44M to 53.9M */
0x00,0x20,0xAF,0x59,0x2B,0xDE,0x51,0x00,
0x00,0x04,0x17,0x00,0x58,0x02,0x00,0x00,
0x00,0x3B,0x01,0x08,0x00,0x1E,0x01,0x05,
0x00,0x01,0x72,0x05,0x32,0x00,0x00,0x04,
0x00,0x00,0x20,0xA8,0x02,0x12,0x00,0x58,
0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
0x00,0x02,0x10,0x01,0x68,0x03,0xC2,0x01,
0x4A,0x03,0x46,0x00,0xF1,0x01,0x5C,0x04,
0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3A,
0x18,0x4B,0x29,0x5C,0xDE,0xF6,0xE0,0x1C,
0x03,0xFC,0xE3,0x1F,0xF3,0x75,0x26,0x45,
0x4A,0x91,0x8A,0xFF,0x3F,0x83,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x20,0x4E,0x48,
0x00,0x01,0x10,0x01,0x00,0x00,0x10,0x04,
0x02,0x1F,0x00,0x00,0x00,0x0A,0x00,0x00,
0x32,0x00,0x00,0x04,0x12,0x00,0x58,0x02,
0x02,0x7C,0x04,0x98,0x02,0x11,0x78,0x18,
0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
#define REGMAP_LENGTH ( sizeof(mtl017_auo_tbl) / sizeof(u8) )
#define BLOCK_TX_SIZE 32
static int mtl017_read_edid(struct i2c_adapter *adp, unsigned char *edid)
{
u8 buf0[2] = {0, 0};
int dat = 0;
u16 addr = 0x50;
struct i2c_msg msg[2] = {
{
.addr = addr,
.flags = 0,
.len = 1,
.buf = buf0,
}, {
.addr = addr,
.flags = I2C_M_RD,
.len = EDID_LENGTH,
.buf = edid,
},
};
if (adp == NULL)
return -EINVAL;
buf0[0] = 0x00;
memset(edid, 0, EDID_LENGTH);
dat = i2c_transfer(adp, msg, 2);
if (dat <= 0)
return -ENODEV;
if (edid[1] == 0x00)
return -ENOENT;
return 0;
}
/* ron: for AUO B101AW02 1024x600 LCD Panel */
static struct fb_videomode auo_mode = {
.name = "AUO B101AW02 1024x600",
.refresh = 60,
.xres = 1024,
.yres = 600,
/* .pixclock = 16666, */ /* ron: 66MHz display clock*/
.pixclock = 22800, /* ron: 44MHz display clock*/
.left_margin = 80,
.right_margin = 40,
.upper_margin = 21,
.lower_margin = 21,
.hsync_len = 4,
.vsync_len = 4,
.sync = FB_SYNC_OE_LOW_ACT,
.vmode = FB_VMODE_NONINTERLACED,
};
/* ron: for AUO B101EW01 1280x720 LCD Panel */
static struct fb_videomode auo_hires_mode = {
.name = "AUO B101EW01 1280x720",
.refresh = 60,
.xres = 1280,
.yres = 720,
.pixclock = 16260,
.left_margin = 32,
.right_margin = 48,
.upper_margin = 7,
.lower_margin = 3,
.hsync_len = 32,
.vsync_len = 6,
.sync = FB_SYNC_OE_LOW_ACT,
.vmode = FB_VMODE_NONINTERLACED,
};
/* ron: for CPT CLAA101NB03A 1024x600 LCD Panel */
static struct fb_videomode cpt_mode = {
.name = "CPT CLAA101 1024x600",
.refresh = 60,
.xres = 1024,
.yres = 600,
.pixclock = 22800, /* ron: 44M display clock */
.left_margin = 80,
.right_margin = 40,
.upper_margin = 20,
.lower_margin = 21,
.hsync_len = 4,
.vsync_len = 4,
.sync = FB_SYNC_OE_LOW_ACT,
.vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_videomode cmo_mode = {
.name = "CMO N101L6-L0D 1024x600",
.refresh = 60,
.xres = 1024,
.yres = 600,
.pixclock = 22800, /* ron: 44MHz display clock*/
.left_margin = 80,
.right_margin = 40,
.upper_margin = 20,
.lower_margin = 21,
.hsync_len = 4,
.vsync_len = 4,
.sync = FB_SYNC_OE_LOW_ACT,
.vmode = FB_VMODE_NONINTERLACED,
};
struct lcd_panel_info {
char manufacture[16];
char product_name[16];
struct fb_videomode *mode;
u8 *regs;
};
static struct lcd_panel_info pinfo[] = {
{
.manufacture = "AUO",
.product_name = "B101AW02 V0",
.mode = &auo_mode,
.regs = mtl017_auo_tbl,
},
{
.manufacture = "CPT",
.product_name = "CLAA101NB03A",
.mode = &cpt_mode,
.regs = mtl017_cpt_tbl,
},
{
.manufacture = "AUO",
.product_name = "B101EW01",
.mode = &auo_hires_mode,
.regs = mtl017_auo_hires_tbl,
},
{
.manufacture = "CMO",
.product_name = "N101L6-L0D",
.mode = &cmo_mode,
.regs = mtl017_cmo_tbl,
}
};
//vv static void mtl017_find_videomode(struct mtl017_dev_data *mtl017)
static void mtl017_find_videomode(mtl017_dev_data *mtl017)
{
int i;
struct i2c_adapter *adp;
struct fb_var_screeninfo var;
int err;
adp = i2c_get_adapter(1);
err = mtl017_read_edid(adp, mtl017->edid);
dump_edid(mtl017->edid);
/* ron: use edid to parse screeninfo,
but these parameters have some problem */
memset(&var, 0, sizeof(var));
fb_parse_edid(mtl017->edid, &var);
dump_screeninfo(&var);
for (i = 0; i < ARRAY_SIZE(pinfo); i ++) {
if(/* (memcmp(mtl017->edid + 0x5f, pinfo[i].manufacture, strlen(pinfo[i].manufacture)) == 0) && */
(memcmp(mtl017->edid + 0x71, pinfo[i].product_name, strlen(pinfo[i].product_name)) == 0)) {
printk("mtl017: Probe LCD Panel: %s %s\n",
pinfo[i].manufacture,
pinfo[i].product_name);
mtl017->mode = pinfo[i].mode;
mtl017->regs = pinfo[i].regs;
return;
}
}
mtl017->regs = NULL;
mtl017->mode = NULL;
}
static void lcd_init_fb(struct fb_info *info)
{
struct fb_var_screeninfo var;
memset(&var, 0, sizeof(var));
fb_videomode_to_var(&var, mtl017->mode);
var.activate = FB_ACTIVATE_ALL;
acquire_console_sem();
info->flags |= FBINFO_MISC_USEREVENT;
fb_set_var(info, &var);
fb_blank(info, FB_BLANK_UNBLANK);
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
}
static int lcd_fb_event(struct notifier_block *nb, unsigned long val, void *v)
{
struct fb_event *event = v;
if (strcmp(event->info->fix.id, "DISP3 BG - DI1")) {
return 0;
}
switch (val) {
case FB_EVENT_FB_REGISTERED:
lcd_init_fb(event->info);
break;
}
return 0;
}
static struct notifier_block fb_nb = {
.notifier_call = lcd_fb_event,
};
/*!
* This function is called whenever the SPI slave device is detected.
*
* @param spi the SPI slave device
*
* @return Returns 0 on SUCCESS and error on FAILURE.
*/
static int __devinit mtl017_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct mxc_lcd_platform_data *plat = client->dev.platform_data;
int retval;
int i;
//vv mtl017 = kzalloc(sizeof(*mtl017), GFP_KERNEL);
mtl017 = (mtl017_dev_data*)kzalloc(sizeof(*mtl017), GFP_KERNEL);
if(!mtl017) {
dev_err(&client->dev, "failed to allocate mtl017 device\n");
retval = -ENOMEM;
return retval;
}
mtl017->suspending = 0;
mtl017->client = client;
if(plat) {
mtl017->reset = plat->reset;
mtl017->lcd_power = plat->lcd_power;
mtl017->lvds_power = plat->lvds_power;
mtl017->lvds_enable = plat->lvds_enable;
}
/* mtl017->lock = SPIN_LOCK_UNLOCKED; */
sema_init(&mtl017->sem, 1);
mtl017_find_videomode(mtl017);
if(mtl017->mode == NULL)
mtl017->mode = &auo_mode;
if(mtl017->regs == NULL)
mtl017->regs = mtl017_auo_tbl;
for (i = 0; i < num_registered_fb; i++) {
if (strcmp(registered_fb[i]->fix.id, "DISP3 BG - DI1") == 0) {
lcd_init_fb(registered_fb[i]);
fb_show_logo(registered_fb[i], 0);
}
}
fb_register_client(&fb_nb);
/* disp_power_on(); */
schedule_work(&disp_on_work);
return 0;
}
static int __devexit mtl017_remove(struct i2c_client *client)
{
fb_unregister_client(&fb_nb);
disp_power_off();
kfree(mtl017);
return 0;
}
static int mtl017_suspend(struct i2c_client *client, pm_message_t message)
{
mtl017->suspending = 1;
disp_power_off();
return 0;
}
static int mtl017_resume(struct i2c_client *client)
{
/* ron: because we turn off regulator, */
/* so re-initialize MTL017 controller after suspending */
mtl017->suspending = 0;
disp_power_on();
return 0;
}
static void mtl017_conf(u8 *reg_tbl)
{
int i;
int ret;
int retry = 5;
dev_dbg(&mtl017->client->dev, "Initializing MTL017 LVDS Controller\n");
// Writing configuration table.
for (i = 0; i < REGMAP_LENGTH; i+=BLOCK_TX_SIZE) {
retry:
msleep(1);
ret = i2c_smbus_write_i2c_block_data(mtl017->client, i, BLOCK_TX_SIZE, &(reg_tbl[i]));
if (ret < 0) {
printk(KERN_WARNING "MTL017 LVDS Controller Initialize Fail!\n");
if(retry -- > 0)
goto retry;
return;
}
}
}
static void disp_power_on(void)
{
if(mtl017->disp_on || mtl017->suspending)
return;
if (down_interruptible(&mtl017->sem))
return;
if(mtl017->lcd_power) {
mtl017->lcd_power(1);
msleep(10);
}
if(mtl017->lvds_enable) {
mtl017->lvds_enable(1);
msleep(5);
}
if(mtl017->lvds_power) {
mtl017->lvds_power(1);
msleep(5);
}
mtl017_conf(mtl017->regs);
msleep(200);
mtl017->disp_on = 1;
up(&mtl017->sem);
}
static void disp_power_off(void)
{
if(mtl017->disp_on == 0)
return;
if (down_interruptible(&mtl017->sem))
return;
msleep(200);
if(mtl017->lvds_enable) {
mtl017->lvds_enable(0);
}
if(mtl017->lvds_power) {
mtl017->lvds_power(0);
msleep(5);
}
if(mtl017->lcd_power) {
mtl017->lcd_power(0);
}
mtl017->disp_on = 0;
up(&mtl017->sem);
}
static const struct i2c_device_id mtl017_id[] = {
{ "mtl017", 0 },
{},
};
MODULE_DEVICE_TABLE(i2c, mtl017_id);
static struct i2c_driver mtl017_driver = {
.driver = {
.name = "mtl017",
},
.probe = mtl017_probe,
.remove = mtl017_remove,
.suspend = mtl017_suspend,
.resume = mtl017_resume,
.id_table = mtl017_id,
};
static int __init mtl017_init(void)
{
return i2c_add_driver(&mtl017_driver);
}
static void __exit mtl017_exit(void)
{
i2c_del_driver(&mtl017_driver);
}
module_init(mtl017_init);
module_exit(mtl017_exit);
MODULE_AUTHOR("Ron Lee <ron1_lee@pegatroncorp.com> Pegatron Corp.");
MODULE_DESCRIPTION("MTL017 LVDS Controller driver");
MODULE_LICENSE("GPL");