summaryrefslogtreecommitdiff
path: root/drivers/video/wmt/devices/lcd.c
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-13 15:08:24 +0530
committerSrikant Patnaik2015-01-13 15:08:24 +0530
commit97327692361306d1e6259021bc425e32832fdb50 (patch)
treefe9088f3248ec61e24f404f21b9793cb644b7f01 /drivers/video/wmt/devices/lcd.c
parent2d05a8f663478a44e088d122e0d62109bbc801d0 (diff)
parenta3a8b90b61e21be3dde9101c4e86c881e0f06210 (diff)
downloadFOSSEE-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.c422
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