diff options
Diffstat (limited to 'drivers/video/wmt/devices/lcd-b079xan01.c')
-rw-r--r--[-rwxr-xr-x] | drivers/video/wmt/devices/lcd-b079xan01.c | 378 |
1 files changed, 240 insertions, 138 deletions
diff --git a/drivers/video/wmt/devices/lcd-b079xan01.c b/drivers/video/wmt/devices/lcd-b079xan01.c index 05a6e957..54e5921e 100755..100644 --- a/drivers/video/wmt/devices/lcd-b079xan01.c +++ b/drivers/video/wmt/devices/lcd-b079xan01.c @@ -1,82 +1,209 @@ -/*++
- * linux/drivers/video/wmt/lcd-b079xan01.c
- * WonderMedia video post processor (VPP) driver
- *
- * Copyright c 2014 WonderMedia Technologies, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * WonderMedia Technologies, Inc.
- * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
---*/
-
-#include <linux/delay.h> +/*++ + linux/drivers/video/wmt/devices/lcd-b079xan01.c -#include <mach/hardware.h> + Copyright (c) 2013 WonderMedia Technologies, Inc. + + This program is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software Foundation, + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with + this program. If not, see <http://www.gnu.org/licenses/>. + + WonderMedia Technologies, Inc. + 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <linux/delay.h> #include <linux/spi/spi.h> +#include <mach/hardware.h> #include <mach/wmt-spi.h> - #include <linux/gpio.h> #include <mach/wmt_iomux.h> - #include "../lcd.h" #define DRIVERNAME "ssd2828" +#define DELAY_MASK 0xff000000 + +#undef pr_err +#undef pr_info +#undef pr_warning +#define pr_err(fmt, args...) printk("[" DRIVERNAME "] " fmt, ##args) +#define pr_info(fmt, args...) printk("[" DRIVERNAME "] " fmt, ##args) +#define pr_warning(fmt, args...) printk("[" DRIVERNAME "] " fmt, ##args) + +extern void lcd_power_on(bool on); + +struct ssd2828_chip { + struct spi_device *spi; + int id; + int gpio_reset; +}; + +static int wmt_lcd_panel_id(void) +{ + char buf[96]; + int len = sizeof(buf); + int type, id = 0; + + if (wmt_getsyspara("wmt.display.param", buf, &len)) { + return -ENODEV; + } -static struct lcd_parm_t lcd_b079xan01_parm = { - .bits_per_pixel = 24, - .capability = 0, + sscanf(buf, "%d:%d", &type, &id); + return id; +} + +// B079XAN01 + +static const uint32_t b079xan01_init_sequence[] = { + 0x7000B1, 0x723240, //VSA=50, HAS=64 + 0x7000B2, 0x725078, //VBP=30+50, HBP=56+64 + 0x7000B3, 0x72243C, //VFP=36, HFP=60 + 0x7000B4, 0x720300, //HACT=768 + 0x7000B5, 0x720400, //VACT=1024 + 0x7000B6, 0x72000b, //burst mode, 24bpp loosely packed + 0x7000DE, 0x720003, //no of lane=4 + 0x7000D6, 0x720005, //RGB order and packet number in blanking period + 0x7000B9, 0x720000, //disable PLL + + //lane speed=576 (24MHz * 24 = 576) + //may modify according to requirement, 500Mbps to 560Mbps + //LP clock : 576 / 9 / 8 = 8 MHz + 0x7000BA, 0x728018, + 0x7000BB, 0x720008, + + 0x7000B9, 0x720001, //enable PPL + 0x7000C4, 0x720001, //enable BTA + 0x7000B7, 0x720342, //enter LP mode + 0x7000B8, 0x720000, //VC + 0x7000BC, 0x720000, //set packet size + + 0x700011, //sleep out cmd + + DELAY_MASK + 200, + + 0x700029, //display on + + DELAY_MASK + 200, + + 0x7000B7, 0x72030b, //video mode on +}; + +static lcd_parm_t lcd_b079xan01_parm = { + .bits_per_pixel = 24, + .capability = 0, .vmode = { - .name = "B079XAN01", - .refresh = 60, - .xres = 768, - .yres = 1024, - .pixclock = KHZ2PICOS(64800), - .left_margin = 56, - .right_margin = 60, - .upper_margin = 30, - .lower_margin = 36, - .hsync_len = 64, - .vsync_len = 50, - .sync = 0, /* FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, */ - .vmode = 0, - .flag = 0, + .name = "B079XAN01", + .refresh = 60, + .xres = 768, + .yres = 1024, + .pixclock = KHZ2PICOS(64800), + .left_margin = 56, + .right_margin = 60, + .upper_margin = 30, + .lower_margin = 36, + .hsync_len = 64, + .vsync_len = 50, + .sync = 0, + .vmode = 0, + .flag = 0, }, - .width = 120, - .height = 160, -#if 0 - .initial = lcd_power_on, - .uninitial = lcd_power_off, -#endif }; -static struct lcd_parm_t *lcd_b079xan01_get_parm(int arg) +static lcd_parm_t *lcd_b079xan01_get_parm(int arg) { return &lcd_b079xan01_parm; } -static int lcd_b079xan01_init(void) -{ - return lcd_panel_register(LCD_B079XAN01, - (void *) lcd_b079xan01_get_parm); -} +// BP080WX7 -struct ssd2828_chip { - struct spi_device *spi; - int gpio_reset; +static const uint32_t bp080wx7_init_sequence[] = { + 0x7000B1, 0x720202, // VSA=02 , HSA=02 + 0x7000B2, 0x720828, // VBP+VSA=8, HBP+HSA=40 + 0x7000B3, 0x72040A, // VFP=04 , HFP=10 + 0x7000B4, 0x720500, // HACT=1280 + 0x7000B5, 0x720320, // vACT=800 + 0x7000B6, 0x720007, // Non burst mode with sync event 24bpp + + //DELAY_MASK + 10, + + 0x7000DE, 0x720003, // 4lanes + 0x7000D6, 0x720005, // BGR + 0x7000B9, 0x720000, + + //DELAY_MASK + 10, + + 0x7000BA, 0x72C012, // PLL=24*16 = 384MHz + 0x7000BB, 0x720008, // LP CLK=8.3MHz + 0x7000B9, 0x720001, + + //DELAY_MASK + 200, + + 0x7000B8, 0x720000, // Virtual Channel 0 + 0x7000B7, 0x720342, // LP Mode + + //DELAY_MASK + 10, + + 0x7000BC, 0x720000, + 0x700011, //sleep out + + DELAY_MASK + 200, + + 0x7000BC, 0x720000, + 0x700029, //display on + + //DELAY_MASK + 50, + + 0x7000B7, 0x72034B, //Video Mode + + DELAY_MASK + 200, + + 0x7000BC, 0x720000, + 0x700029, //display on }; +//Timing parameter for 3.0" QVGA LCD +#define VBPD (6) +#define VFPD (4) +#define VSPW (2) + +#define HBPD (38) +#define HFPD (10) +#define HSPW (2) + +// setenv wmt.display.tmr 64800:0:8:47:1280:45:4:16:800:16 + +static lcd_parm_t lcd_bp080wx7_parm = { + .bits_per_pixel = 24, + .capability = 0, + .vmode = { + .name = "BP080WX7", + .refresh = 60, + .xres = 1280, + .yres = 800, + .pixclock = KHZ2PICOS(64800), + .left_margin = HBPD, + .right_margin = HFPD, + .upper_margin = VBPD, + .lower_margin = VFPD, + .hsync_len = HSPW, + .vsync_len = VSPW, + .sync = 0, + .vmode = 0, + .flag = 0, + }, +}; + +static lcd_parm_t *lcd_bp080wx7_get_parm(int arg) +{ + return &lcd_bp080wx7_parm; +} + +// SSD2828 api static int ssd2828_read(struct spi_device *spi, uint8_t reg) { int ret; @@ -88,13 +215,12 @@ static int ssd2828_read(struct spi_device *spi, uint8_t reg) ret = spi_write(spi, buf1, 3); if (ret) { pr_err("spi_write ret=%d\n", ret); - return -EIO; + return ret; } ret = spi_w8r16(spi, buf2[0]); if (ret < 0) { pr_err("spi_write ret=%d\n", ret); - return ret; } return ret; @@ -142,35 +268,7 @@ static inline int spi_write_24bit(struct spi_device *spi, uint32_t data) return ret; } -static const uint32_t ssd2828_init_sequence[] = { - 0x7000B1, 0x723240, /* VSA=50, HAS=64 */ - 0x7000B2, 0x725078, /* VBP=30+50, HBP=56+64 */ - 0x7000B3, 0x72243C, /* VFP=36, HFP=60 */ - 0x7000B4, 0x720300, /* HACT=768 */ - 0x7000B5, 0x720400, /* VACT=1024 */ - 0x7000B6, 0x72000b, /* burst mode, 24bpp loosely packed */ - 0x7000DE, 0x720003, /* no of lane=4 */ - 0x7000D6, 0x720005, /* RGB order and packet number in blanking period */ - 0x7000B9, 0x720000, /* disable PLL */ - - /* lane speed=576 (24MHz * 24 = 576) */ - /* may modify according to requirement, 500Mbps to 560Mbps */ - /* LP clock : 576 / 9 / 8 = 8 MHz */ - 0x7000BA, 0x728018, - 0x7000BB, 0x720008, - - 0x7000B9, 0x720001, /* enable PPL */ - 0x7000C4, 0x720001, /* enable BTA */ - 0x7000B7, 0x720342, /* enter LP mode */ - 0x7000B8, 0x720000, /* VC */ - 0x7000BC, 0x720000, /* set packet size */ - - 0x700011, 0xff0000 + 200, /* sleep out cmd */ - 0x700029, 0xff0000 + 200, /* display on */ - 0x7000B7, 0x72030b, /* video mode on */ -}; - -static int ssd2828_hw_reset(struct ssd2828_chip *chip) +static inline void ssd2828_hw_reset(struct ssd2828_chip *chip) { lcd_power_on(1); msleep(10); @@ -178,16 +276,16 @@ static int ssd2828_hw_reset(struct ssd2828_chip *chip) gpio_direction_output(chip->gpio_reset, 1); msleep(10); gpio_direction_output(chip->gpio_reset, 0); - msleep(20); + msleep(200); gpio_direction_output(chip->gpio_reset, 1); - msleep(20); - return 0; + msleep(200); } static int ssd2828_hw_init(struct ssd2828_chip *chip) { - int ret = 0; - int i; + const uint32_t *init_sequence; + size_t n; + int i, ret = 0; ssd2828_hw_reset(chip); @@ -197,14 +295,27 @@ static int ssd2828_hw_init(struct ssd2828_chip *chip) return -ENODEV; } - for (i = 0; i < ARRAY_SIZE(ssd2828_init_sequence); i++) { - if (ssd2828_init_sequence[i] & 0xff000000) { - msleep(ssd2828_init_sequence[i] & 0xff); - continue; + switch (chip->id) { + case LCD_B079XAN01: + init_sequence = b079xan01_init_sequence; + n = ARRAY_SIZE(b079xan01_init_sequence); + break; + case LCD_BP080WX7: + init_sequence = bp080wx7_init_sequence; + n = ARRAY_SIZE(bp080wx7_init_sequence); + break; + default: + return -EINVAL; + } + + for (i = 0; i < n; i++) { + if ((init_sequence[i] & DELAY_MASK) == DELAY_MASK) { + msleep(init_sequence[i] & 0xff); + } else { + ret = spi_write_24bit(chip->spi, init_sequence[i]); + if (ret) + break; } - ret = spi_write_24bit(chip->spi, ssd2828_init_sequence[i]); - if (ret) - break; } return ret; @@ -232,7 +343,7 @@ static ssize_t option_port_testmode_show(struct device *dev, s += sprintf(s, "=========\n"); out: - return s - buf; + return (s - buf); } static ssize_t option_port_testmode_store(struct device *dev, @@ -246,7 +357,7 @@ static DEVICE_ATTR(testmode, S_IRUGO, option_port_testmode_show, option_port_testmode_store); -static int __devinit ssd2828_probe(struct spi_device *spi) +static int __devinit ssd2828_spi_probe(struct spi_device *spi) { struct ssd2828_chip *chip; int gpio = WMT_PIN_GP0_GPIO0; @@ -269,12 +380,14 @@ static int __devinit ssd2828_probe(struct spi_device *spi) return -ENOMEM; chip->spi = spi; + chip->id = wmt_lcd_panel_id(); chip->gpio_reset = gpio; spi_set_drvdata(spi, chip); ret = sysfs_create_file(&spi->dev.kobj, &dev_attr_testmode.attr); - if (unlikely(ret)) + if (unlikely(ret)) { pr_err("ssd2828 sysfs_create_file failed\n"); + } return ret; } @@ -287,15 +400,11 @@ static int ssd2828_spi_resume(struct spi_device *spi) static struct spi_driver ssd2828_driver = { .driver = { - .name = DRIVERNAME, - .owner = THIS_MODULE, + .name = DRIVERNAME, + .owner = THIS_MODULE, }, - .probe = ssd2828_probe, - .resume = ssd2828_spi_resume, -#if 0 - .remove = __devexit_p(ssd2828_remove), - .shutdown = ssd2828_shutdown, -#endif + .probe = ssd2828_spi_probe, + .resume = ssd2828_spi_resume, }; static struct spi_board_info ssd2828_spi_info[] __initdata = { @@ -309,25 +418,16 @@ static struct spi_board_info ssd2828_spi_info[] __initdata = { }, }; -static int wmt_lcd_panel(void) -{ - char buf[96]; - int len = sizeof(buf); - int type, id = 0; - - if (wmt_getsyspara("wmt.display.param", buf, &len)) - return -ENODEV; - - sscanf(buf, "%d:%d", &type, &id); - return id; -} - -static int __init b079xan01_init(void) +static int __init ssd2828_init(void) { int ret; - if (wmt_lcd_panel() != LCD_B079XAN01) { - pr_err("LCD B079XAN01 not found\n"); + switch (wmt_lcd_panel_id()) { + case LCD_B079XAN01: + case LCD_BP080WX7: + break; + default: + pr_warning("lcd for ssd2828 not found\n"); return -EINVAL; } @@ -341,23 +441,25 @@ static int __init b079xan01_init(void) ret = spi_register_driver(&ssd2828_driver); if (ret) { pr_err("spi_register_driver failed\n"); - return -EIO; + return ret; } - if (lcd_b079xan01_init()) { - spi_unregister_driver(&ssd2828_driver); - return -ENODEV; - } + lcd_panel_register(LCD_B079XAN01, (void *)lcd_b079xan01_get_parm); + lcd_panel_register(LCD_BP080WX7, (void *)lcd_bp080wx7_get_parm); pr_info("spi %s register success\n", DRIVERNAME); - return 0; } -static void b079xan01_exit(void) +static void ssd2828_exit(void) { spi_unregister_driver(&ssd2828_driver); } -module_init(b079xan01_init); -module_exit(b079xan01_exit); +module_init(ssd2828_init); +module_exit(ssd2828_exit); + +MODULE_AUTHOR("Sam Mei"); +MODULE_DESCRIPTION("WonderMedia Mipi LCD Driver"); +MODULE_LICENSE("GPL"); + |