diff options
author | Srikant Patnaik | 2015-01-13 15:08:24 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-13 15:08:24 +0530 |
commit | 97327692361306d1e6259021bc425e32832fdb50 (patch) | |
tree | fe9088f3248ec61e24f404f21b9793cb644b7f01 /drivers/video/wmt/devices/lcd.c | |
parent | 2d05a8f663478a44e088d122e0d62109bbc801d0 (diff) | |
parent | a3a8b90b61e21be3dde9101c4e86c881e0f06210 (diff) | |
download | FOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.tar.gz FOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.tar.bz2 FOSSEE-netbook-kernel-source-97327692361306d1e6259021bc425e32832fdb50.zip |
dirty fix to merging
Diffstat (limited to 'drivers/video/wmt/devices/lcd.c')
-rw-r--r-- | drivers/video/wmt/devices/lcd.c | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/drivers/video/wmt/devices/lcd.c b/drivers/video/wmt/devices/lcd.c new file mode 100644 index 00000000..195d3483 --- /dev/null +++ b/drivers/video/wmt/devices/lcd.c @@ -0,0 +1,422 @@ +/*++ + * linux/drivers/video/wmt/lcd.c + * WonderMedia video post processor (VPP) driver + * + * 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. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include <linux/gpio.h> +#include "../lcd.h" +#include "../vout.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ +struct lcd_device_t { + lcd_parm_t* (*get_parm)(int arg); +}; + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_device_t lcd_device_array[LCD_PANEL_MAX]; +int lcd_panel_on = 1; +int lcd_pwm_enable; +lcd_panel_t lcd_panel_id = LCD_PANEL_MAX; +int lcd_panel_bpp = 24; + +vout_dev_t lcd_vout_dev_ops; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ +lcd_panel_t lcd_lvds_id = LCD_PANEL_MAX; +int lcd_type; + +/*----------------------- Function Body --------------------------------------*/ +/*----------------------- Backlight --------------------------------------*/ +void lcd_set_type(int type) +{ + lcd_type = type; /* 0-LCD, 1-LVDS */ +} + +int lcd_get_type(void) +{ + return lcd_type; +} + +static struct { + int gpio; + int active; +} lcd_power; + +/*----------------------- Function Body --------------------------------------*/ +static int parse_uboot_param(void) +{ + char buf[64]; + size_t l = sizeof(buf); + int ret; + + if (wmt_getsyspara("wmt.lcd.power", buf, &l)) { + pr_err("please set wmt.lcd.power\n"); + return -EINVAL; + } + + ret = sscanf(buf, "%d:%d", &lcd_power.gpio, &lcd_power.active); + if (ret < 2) { + pr_err("Batt: bat env param: %s\n", buf); + return -EINVAL; + } + + printk("lcd power: gpio-%d, active %d\n", lcd_power.gpio, lcd_power.active); + + ret = gpio_request(lcd_power.gpio, "lcd power"); + if (ret) { + pr_err("request gpio %d failed\n", lcd_power.gpio); + return ret; + } + + return 0; +} + +void lcd_power_on(bool on) +{ + if (lcd_power.gpio < 0) + return; + + gpio_direction_output(lcd_power.gpio, on ? lcd_power.active : !lcd_power.active); +} + +/*----------------------- Backlight --------------------------------------*/ +void lcd_set_lvds_id(int id) +{ + lcd_lvds_id = id; +} + +int lcd_get_lvds_id(void) +{ + return lcd_lvds_id; +} + +void lcd_set_parm(int id, int bpp) +{ + lcd_panel_id = id; + lcd_panel_bpp = bpp; +} + +lcd_parm_t *lcd_get_parm(lcd_panel_t id, unsigned int arg) +{ + struct lcd_device_t *p; + + p = &lcd_device_array[id]; + if (p && p->get_parm) + return p->get_parm(arg); + return 0; +} + +vout_dev_t *lcd_get_dev(void) +{ + if (lcd_panel_id >= LCD_PANEL_MAX) + return 0; + return &lcd_vout_dev_ops; +} + +#ifdef CONFIG_KERNEL +static DEFINE_SEMAPHORE(lcd_sem); +#endif +void lcd_set_mutex(int lock) +{ +#ifdef CONFIG_KERNEL + if (lock) + down(&lcd_sem); + else + up(&lcd_sem); +#endif +} + + +/* #define CONFIG_PANEL_SET_CLOCK */ +void lcd_set_enable(int enable) +{ +#ifdef CONFIG_PANEL_SET_CLOCK + int hdmi_off; +#endif + + DBG_MSG("%d\n", enable); + if (!p_lcd) + return; + + lcd_set_mutex(1); +#ifdef CONFIG_PANEL_SET_CLOCK + /* enable NA12 in Panel on */ + hdmi_off = (govrh_get_MIF_enable(p_govrh)) ? 0 : 1; + if (hdmi_off && enable) + vpp_set_clock_enable(DEV_NA12, enable, 1); +#endif + + if (enable) { + if (p_lcd->initial) + p_lcd->initial(); + else { + lcd_enable_signal(1); /* singal enable */ + //REG32_VAL(GPIO_BASE_ADDR + 0x80) |= 0x801; + //REG32_VAL(GPIO_BASE_ADDR + 0xC0) |= 0x801; + } + } else { + if (p_lcd->uninitial) + p_lcd->uninitial(); + else { + lcd_enable_signal(0); /* singal disable */ + //REG32_VAL(GPIO_BASE_ADDR + 0xC0) &= ~0x801; + } + } + +#ifdef CONFIG_PANEL_SET_CLOCK + /* disable VPP & NA12 clock in Panel off */ + if (hdmi_off) { + vpp_set_clock_enable(DEV_VPP, enable, 1); + vpp_set_clock_enable(DEV_GOVRHD, enable, 1); + vpp_set_clock_enable(DEV_HDMILVDS, enable, 1); + if (enable == 0) + vpp_set_clock_enable(DEV_NA12, enable, 1); + } +#endif + lcd_set_mutex(0); +} + +void lcd_enable_signal(int enable) +{ + int hdmi_off; + + DBG_MSG("%d\n", enable); + if (lcd_get_type()) { /* LVDS */ + /* TODO */ + } else { /* LCD */ + govrh_set_dvo_enable(p_govrh2, enable); + } + + hdmi_off = (govrh_get_MIF_enable(p_govrh)) ? 0 : 1; + vpp_set_clock_enable(DEV_DVO, (hdmi_off && !enable) ? 0 : 1, 1); +} + +#ifdef __KERNEL__ +/*----------------------- LCD --------------------------------------*/ +static int __init lcd_arg_panel_id +( + char *str /*!<; // argument string */ +) +{ + sscanf(str, "%d", (int *) &lcd_panel_id); + if (lcd_panel_id >= LCD_PANEL_MAX) + lcd_panel_id = LCD_PANEL_MAX; + DBGMSG(KERN_INFO "set lcd panel id = %d\n", lcd_panel_id); + return 1; +} /* End of lcd_arg_panel_id */ + +__setup("lcdid=", lcd_arg_panel_id); +#endif +int lcd_panel_register(int no, void (*get_parm)(int mode)) +{ + struct lcd_device_t *p; + + if (no >= LCD_PANEL_MAX) { + DBGMSG(KERN_ERR "*E* lcd device no max is %d !\n", + LCD_PANEL_MAX); + return -1; + } + + p = &lcd_device_array[no]; + if (p->get_parm) { + DBGMSG(KERN_ERR "*E* lcd device %d exist !\n", no); + return -1; + } + p->get_parm = (void *) get_parm; + return 0; +} /* End of lcd_device_register */ + +/*----------------------- vout device plugin --------------------------------------*/ +void lcd_set_power_down(int enable) +{ + static int save_state = -1; + + if (save_state != enable) { + /* lcd enable control by user */ + lcd_power_on(enable ? false : true); + lcd_set_enable(enable ? false : true); + save_state = enable; + } +} + +static void wmt_config_govrh_polar(vout_t *vo) +{ + /* wmt.display.polar [clock polar]:[hsync polart]:[vsync polar]*/ + char buf[64]; + size_t l = sizeof(buf); + int clk_pol, hsync_pol, vsync_pol; + + if (wmt_getsyspara("wmt.display.polar", buf, &l)) { + return; + } + + sscanf(buf, "%d:%d:%d", &clk_pol, &hsync_pol, &vsync_pol); + + printk("govrh polar: clk-pol %d, hsync %d, vsync %d\n", clk_pol, hsync_pol, vsync_pol); + govrh_set_dvo_clock_delay(vo->govr, clk_pol ? 0 : 1, 0); + govrh_set_dvo_sync_polar(vo->govr, hsync_pol ? 0 : 1, vsync_pol ? 0 : 1); +} + +int lcd_set_mode(unsigned int *option) +{ + vout_t *vo; + vout_inf_mode_t inf_mode; + + DBG_MSG("option %d,%d\n", option[0], option[1]); + + vo = lcd_vout_dev_ops.vout; + inf_mode = vo->inf->mode; + if (option) { + unsigned int capability; + + if (lcd_panel_id == 0) + p_lcd = lcd_get_oem_parm(vo->resx, vo->resy); + else + p_lcd = lcd_get_parm(lcd_panel_id, lcd_panel_bpp); + + if (!p_lcd) { + DBG_ERR("lcd %d not support\n", lcd_panel_id); + return -1; + } + DBG_MSG("[%s] %s (id %d,bpp %d)\n", vout_inf_str[inf_mode], + p_lcd->vmode.name, lcd_panel_id, lcd_panel_bpp); + capability = p_lcd->capability; + switch (inf_mode) { + case VOUT_INF_LVDS: + lvds_set_sync_polar( + (capability & LCD_CAP_HSYNC_HI) ? 0 : 1, + (capability & LCD_CAP_VSYNC_HI) ? 0 : 1); + lvds_set_rgb_type(lcd_panel_bpp); + break; + case VOUT_INF_DVI: + govrh_set_dvo_clock_delay(vo->govr, + (capability & LCD_CAP_CLK_HI) ? 0 : 1, 0); + govrh_set_dvo_sync_polar(vo->govr, + (capability & LCD_CAP_HSYNC_HI) ? 0 : 1, + (capability & LCD_CAP_VSYNC_HI) ? 0 : 1); + switch (lcd_panel_bpp) { + case 15: + govrh_IGS_set_mode(vo->govr, 0, 1, 1); + break; + case 16: + govrh_IGS_set_mode(vo->govr, 0, 3, 1); + break; + case 18: + govrh_IGS_set_mode(vo->govr, 0, 2, 1); + break; + case 24: + govrh_IGS_set_mode(vo->govr, 0, 0, 0); + break; + default: + break; + } + break; + default: + break; + } + } else + p_lcd = 0; + + wmt_config_govrh_polar(vo); + return 0; +} + +int lcd_check_plugin(int hotplug) +{ + return (p_lcd) ? 1 : 0; +} + +int lcd_get_edid(char *buf) +{ + return 1; +} + +int lcd_config(vout_info_t *info) +{ + info->resx = p_lcd->vmode.xres; + info->resy = p_lcd->vmode.yres; + info->fps = p_lcd->vmode.refresh; + return 0; +} + +int lcd_init(vout_t *vo) +{ + DBG_MSG("%d\n", lcd_panel_id); + + /* vo_set_lcd_id(LCD_CHILIN_LW0700AT9003); */ + if (lcd_panel_id >= LCD_PANEL_MAX) + return -1; + + if (lcd_panel_id == 0) + p_lcd = lcd_get_oem_parm(vo->resx, vo->resy); + else + p_lcd = lcd_get_parm(lcd_panel_id, 24); + + if (p_lcd == 0) + return -1; + + /* set default parameters */ + vo->resx = p_lcd->vmode.xres; + vo->resy = p_lcd->vmode.yres; + vo->pixclk = PICOS2KHZ(p_lcd->vmode.pixclock) * 1000; + return 0; +} + +vout_dev_t lcd_vout_dev_ops = { + .name = "LCD", + .mode = VOUT_INF_DVI, + .capability = VOUT_DEV_CAP_FIX_RES + VOUT_DEV_CAP_FIX_PLUG, + + .init = lcd_init, + .set_power_down = lcd_set_power_down, + .set_mode = lcd_set_mode, + .config = lcd_config, + .check_plugin = lcd_check_plugin, + .get_edid = lcd_get_edid, +}; + +int lcd_module_init(void) +{ + if (parse_uboot_param()) { + lcd_power.gpio = -1; + } + + vout_device_register(&lcd_vout_dev_ops); + return 0; +} /* End of lcd_module_init */ +module_init(lcd_module_init); +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_C |