Public feed #891969

Miscellany

public text v1 · immutable
Raw Edit
·published 2008-02-05 01:17 UTC
rendered paste body
/*
 * File: drivers/video/omap_new/lcd-htcartemis.c
 *
 * LCD panel support for the HTC htcartemis phone
 *
 * Authors:
 *   Thomas Cougnard <tgnard@free.fr>
 *   Vivien Chappelier <vivien.chappelier@free.fr>
 *
 *   Based on the lcd_p2.c file
 * 
 * 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, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/platform_device.h>

#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
#include <asm/arch/omapfb.h>
#include <asm/arch/htcartemis-gpio.h>

/* htcartemis panels */
#define LCD_ID_SONY    1
#define LCD_ID_TOPPOLY 3

/* Backlight */
#define BKLIGHT_OFF  0
#define BKLIGHT_DIM  1
#define BKLIGHT_FULL 2

static int bklight_level = BKLIGHT_FULL;

static int htcartemis_panel_init(struct lcd_panel *panel,
				struct omapfb_device *fbdev)
{
	return 0;
}

static void htcartemis_panel_cleanup(struct lcd_panel *panel)
{
}

static int htcartemis_panel_enable(struct lcd_panel *panel)
{
	return 0;
}

static void htcartemis_panel_disable(struct lcd_panel *panel)
{
}

static unsigned long htcartemis_panel_get_caps(struct lcd_panel *panel)
{
	return 0;
}

static int htcartemis_set_bklight_level(struct lcd_panel *panel,
					unsigned int level)
{
	if(level > 2)
		return(-EINVAL);

	bklight_level = level;

	omap_set_gpio_direction(HTCARTEMIS_GPIO_LCD_BACKLIGHT_ON, 0);
	omap_set_gpio_direction(HTCARTEMIS_GPIO_LCD_BACKLIGHT_INTENSITY, 0);

	if(level > 0)
		omap_set_gpio_dataout(HTCARTEMIS_GPIO_LCD_BACKLIGHT_ON, 1);
	else
		omap_set_gpio_dataout(HTCARTEMIS_GPIO_LCD_BACKLIGHT_ON, 0);
	if(level > 1)
		omap_set_gpio_dataout(HTCARTEMIS_GPIO_LCD_BACKLIGHT_INTENSITY, 1);
	else
		omap_set_gpio_dataout(HTCARTEMIS_GPIO_LCD_BACKLIGHT_INTENSITY, 0);
	return(0);
}

static unsigned int htcartemis_get_bklight_level(struct lcd_panel *panel)
{
	return(bklight_level);
}

static unsigned int htcartemis_get_bklight_max(struct lcd_panel *panel)
{
	return(BKLIGHT_FULL);
}

/* htcartemis panels */
static struct lcd_panel htcartemis_toppoly_panel = {
	.name		= "htcartemis-toppoly",
	.x_res		= 240,
	.y_res		= 320,
	.config		= OMAP_LCDC_PANEL_TFT |
				OMAP_LCDC_INV_VSYNC |
				OMAP_LCDC_INV_HSYNC |
				OMAP_LCDC_HSVS_OPPOSITE,
	.pixel_clock	= 5500,
	.hsw		= 10,
	.hfp		= 10,
	.hbp		= 20,
	.vsw		= 2,
	.vfp		= 2,
	.vbp		= 3,
};

static struct lcd_panel htcartemis_sony_panel = {
	.name		= "htcartemis-sony",
	.x_res		= 240,
	.y_res		= 320,
	.config		= OMAP_LCDC_PANEL_TFT |
				OMAP_LCDC_INV_VSYNC |
				OMAP_LCDC_INV_HSYNC |
				OMAP_LCDC_HSVS_RISING_EDGE |
				OMAP_LCDC_HSVS_OPPOSITE,
	.pixel_clock	= 5000,
	.hsw		= 2,
	.hfp		= 8,
	.hbp		= 14,
	.vsw		= 2,
	.vfp		= 4,
	.vbp		= 2,
};

/* get the panel identifier */
static unsigned int htcartemis_lcd_identify(void)
{
	omap_set_gpio_direction(HTCARTEMIS_GPIO_PANEL_ID0, 1);
	omap_set_gpio_direction(HTCARTEMIS_GPIO_PANEL_ID1, 1);

	return (omap_get_gpio_datain(HTCARTEMIS_GPIO_PANEL_ID1) << 1) |
		omap_get_gpio_datain(HTCARTEMIS_GPIO_PANEL_ID0);
}

struct panel_id {
	unsigned int lcd_id;
	struct lcd_panel *panel;
};

struct panel_id htcartemis_lcd_panel[] = {
	{ LCD_ID_TOPPOLY,
	  &htcartemis_toppoly_panel },
	{ LCD_ID_SONY,
	  &htcartemis_sony_panel },
};

static struct lcd_panel *htcartemis_lcd_find_panel(struct platform_device *pdev)
{
	struct lcd_panel *panel;
	unsigned int lcd_id;
	int i;

	lcd_id = htcartemis_lcd_identify();

	panel = NULL;
	for (i = 0; i < ARRAY_SIZE(htcartemis_lcd_panel); i++) {
		if ( htcartemis_lcd_panel[i].lcd_id == lcd_id)
			return htcartemis_lcd_panel[i].panel;
	}

	printk(KERN_ERR "lcd-htcartemis: unknown panel (%d)\n",
	       lcd_id);

	return NULL;
}

static int htcartemis_panel_probe(struct platform_device *pdev)
{
	struct lcd_panel *panel;

	/* set the timings according to the panel type */
	if ((panel = htcartemis_lcd_find_panel(pdev)) == NULL) {
		return -ENODEV;
	}

	panel->bpp = 16;
	panel->data_lines = 16;

	/* common callbacks */
	panel->init = htcartemis_panel_init;
	panel->cleanup = htcartemis_panel_cleanup;
	panel->enable  = htcartemis_panel_enable;
	panel->disable = htcartemis_panel_disable;
	panel->get_caps= htcartemis_panel_get_caps;
	panel->set_bklight_level = htcartemis_set_bklight_level;
	panel->get_bklight_level = htcartemis_get_bklight_level;
	panel->get_bklight_max   = htcartemis_get_bklight_max;

	omapfb_register_panel(panel);
	return 0;
}

static int htcartemis_panel_remove(struct platform_device *pdev)
{
	return 0;
}

static int htcartemis_panel_suspend(struct platform_device *pdev,
				 pm_message_t mesg)
{
	return 0;
}

static int htcartemis_panel_resume(struct platform_device *pdev)
{
	return 0;
}

struct platform_driver htcartemis_panel_driver = {
	.probe		= htcartemis_panel_probe,
	.remove		= htcartemis_panel_remove,
	.suspend	= htcartemis_panel_suspend,
	.resume		= htcartemis_panel_resume,
	.driver		= {
		.name	= "lcd_htcartemis",
		.owner	= THIS_MODULE,
	},
};

static int htcartemis_panel_drv_init(void)
{
	return platform_driver_register(&htcartemis_panel_driver);
}

static void htcartemis_panel_drv_cleanup(void)
{
	platform_driver_unregister(&htcartemis_panel_driver);
}

module_init(htcartemis_panel_drv_init);
module_exit(htcartemis_panel_drv_cleanup);