aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-graphics/mesa/mesa-dri_7.7.bb
blob: a5899f38924ed2406866d06c9365a1a81f40ce45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
include mesa-common.inc

SRC_URI = "ftp://ftp.freedesktop.org/pub/mesa/7.7/MesaLib-${PV}.tar.bz2 \
           ftp://ftp.freedesktop.org/pub/mesa/7.7/MesaDemos-${PV}.tar.bz2  \
           file://crossfix.patch;patch=1"

PROTO_DEPS = "xf86driproto glproto dri2proto"
LIB_DEPS = "libdrm virtual/libx11 libxext libxxf86vm libxdamage libxfixes expat"

DEPENDS = "${PROTO_DEPS}  ${LIB_DEPS}"

PR = "r11"

# most of our targets do not have DRI so will use mesa-xlib
DEFAULT_PREFERENCE = "-1"

# Netbooks have DRI support so use mesa-dri by default
DEFAULT_PREFERENCE_netbook = "1"

PACKAGES =+ "${PN}-xprogs"
PACKAGES_DYNAMIC = "mesa-dri-driver-*"

FILES_${PN}-dbg += "${libdir}/dri/.debug/*"
FILES_${PN}-xprogs = "${bindir}/glxdemo ${bindir}/glxgears ${bindir}/glxheads ${bindir}/glxinfo"

LEAD_SONAME = "libGL.so.1"

EXTRA_OECONF += "--with-driver=dri --disable-egl --disable-gallium"

do_install_append () {
    install -d ${D}/usr/bin
    install -m 0755 ${S}/progs/xdemos/{glxdemo,glxgears,glxheads,glxinfo} ${D}/usr/bin/
}

python populate_packages_prepend() {
	import os.path

	dri_drivers_root = os.path.join(bb.data.getVar('libdir', d, 1), "dri")

	do_split_packages(d, dri_drivers_root, '^(.*)_dri\.so$', 'mesa-dri-driver-%s', 'Mesa %s DRI driver', extra_depends='')
}

COMPATIBLE_HOST = '(i.86.*-linux|x86_64.*-linux)'


#
# Header generated by i586-poky-linux-gcc gen_matypes.c -o gen_matypes -I ../../../include/GL -I ../../../include -I .. -I ../main/ -I ../math -I ../glapi/ -I ../tnl
# then run gen_matypes > matypes.h on device
#
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
From 18a25382e81c03230e022ca2eb7e0fce24479d6a Mon Sep 17 00:00:00 2001
From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Date: Thu, 2 Apr 2009 10:31:57 +0300
Subject: [PATCH] DSS2: HACK: Add DSS2 support for N800

Works, but it an ugly quick hack.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
---
 arch/arm/mach-omap2/board-n800.c             |  216 +++++++++++---
 drivers/video/omap2/displays/Kconfig         |   10 +
 drivers/video/omap2/displays/Makefile        |    3 +
 drivers/video/omap2/displays/ctrl-blizzard.c |  279 +++++++++++++++++
 drivers/video/omap2/displays/panel-n800.c    |  435 ++++++++++++++++++++++++++
 5 files changed, 905 insertions(+), 38 deletions(-)
 create mode 100644 drivers/video/omap2/displays/ctrl-blizzard.c
 create mode 100644 drivers/video/omap2/displays/panel-n800.c

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index f6f6571..6de60ae 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -41,6 +41,8 @@
 #include <mach/clock.h>
 #include <mach/gpio-switch.h>
 #include <mach/blizzard.h>
+#include <mach/display.h>
+#include <mach/vram.h>
 
 #include <../drivers/cbus/tahvo.h>
 #include <../drivers/media/video/tcm825x.h>
@@ -161,23 +163,176 @@ static struct omap_uart_config n800_uart_config __initdata = {
 
 #include "../../../drivers/cbus/retu.h"
 
-static struct omap_fbmem_config n800_fbmem0_config __initdata = {
-	.size = 752 * 1024,
+static struct omap_tmp105_config n800_tmp105_config __initdata = {
+	.tmp105_irq_pin = 125,
+	.set_power = n800_tmp105_set_power,
 };
 
-static struct omap_fbmem_config n800_fbmem1_config __initdata = {
-	.size = 752 * 1024,
-};
 
-static struct omap_fbmem_config n800_fbmem2_config __initdata = {
-	.size = 752 * 1024,
+
+
+/* DISPLAY */
+static struct {
+	struct clk *sys_ck;
+} blizzard;
+
+static int blizzard_get_clocks(void)
+{
+	blizzard.sys_ck = clk_get(0, "osc_ck");
+	if (IS_ERR(blizzard.sys_ck)) {
+		printk(KERN_ERR "can't get Blizzard clock\n");
+		return PTR_ERR(blizzard.sys_ck);
+	}
+	return 0;
+}
+
+static unsigned long blizzard_get_clock_rate(void)
+{
+	return clk_get_rate(blizzard.sys_ck);
+}
+
+static int n800_pn800_enable(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1) {
+		printk("enabling panel gpio\n");
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
+	}
+
+	return 0;
+}
+
+static void n800_pn800_disable(struct omap_display *display)
+{
+	if (display->hw_config.panel_reset_gpio != -1) {
+		printk("disabling panel gpio\n");
+		gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
+		msleep(120);
+	}
+}
+
+static int n800_blizzard_enable(struct omap_display *display)
+{
+	printk("enabling bliz powers\n");
+
+	/* Vcore to 1.475V */
+	tahvo_set_clear_reg_bits(0x07, 0, 0xf);
+	msleep(10);
+
+	clk_enable(blizzard.sys_ck);
+
+	if (display->hw_config.ctrl_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.ctrl_reset_gpio, 1);
+
+	printk("osc_ck %lu\n", blizzard_get_clock_rate());
+
+	return 0;
+}
+
+static void n800_blizzard_disable(struct omap_display *display)
+{
+	printk("disabling bliz powers\n");
+
+	if (display->hw_config.ctrl_reset_gpio != -1)
+		gpio_direction_output(display->hw_config.ctrl_reset_gpio, 0);
+
+	clk_disable(blizzard.sys_ck);
+
+	/* Vcore to 1.005V */
+	tahvo_set_clear_reg_bits(0x07, 0xf, 0);
+}
+
+static int n800_set_backlight_level(struct omap_display *display, int level)
+{
+	return 0;
+}
+
+static struct omap_dss_display_config n800_dsi_display_data = {
+	.type = OMAP_DISPLAY_TYPE_DBI,
+	.name = "lcd",
+	.ctrl_name = "ctrl-blizzard",
+	.panel_name = "panel-pn800",
+	.panel_reset_gpio = -1,
+	.ctrl_reset_gpio = N800_BLIZZARD_POWERDOWN_GPIO,
+	.panel_enable = n800_pn800_enable,
+	.panel_disable = n800_pn800_disable,
+	.ctrl_enable = n800_blizzard_enable,
+	.ctrl_disable = n800_blizzard_disable,
+	.set_backlight = n800_set_backlight_level,
+	.u.rfbi = {
+		.channel = 0,
+		/* 8 for cmd mode, 16 for pixel data. ctrl-blizzard handles switching */
+		.data_lines = 8,
+	},
+	.panel_data = 0, // XXX used for panel datalines
+};
+static struct omap_dss_board_info n800_dss_data = {
+	.num_displays = 1,
+	.displays = {
+		&n800_dsi_display_data,
+	},
 };
 
-static struct omap_tmp105_config n800_tmp105_config __initdata = {
-	.tmp105_irq_pin = 125,
-	.set_power = n800_tmp105_set_power,
+static struct platform_device n800_dss_device = {
+	.name          = "omapdss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &n800_dss_data,
+	},
 };
 
+static void __init n800_display_init(void)
+{
+	int r;
+	const struct omap_lcd_config *conf;
+
+	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+	if (conf != NULL) {
+		n800_dsi_display_data.panel_reset_gpio = conf->nreset_gpio;
+		n800_dsi_display_data.panel_data =
+			(void*)(u32)conf->data_lines; // XXX
+		//printk("\n\nTULI %d\n\n", conf->data_lines);
+	} else {
+		printk("\n\nEI TULLU MIOTÄÄÄ\n\n");
+	}
+
+	blizzard_get_clocks();
+	clk_enable(blizzard.sys_ck); // XXX always enable
+
+	//omapfb_set_ctrl_platform_data(&n800_blizzard_data);
+	//
+	if (n800_dsi_display_data.ctrl_reset_gpio != -1) {
+		r = gpio_request(n800_dsi_display_data.ctrl_reset_gpio,
+				"Blizzard pd");
+		if (r < 0) {
+			n800_dsi_display_data.ctrl_reset_gpio = -1;
+			printk(KERN_ERR "Unable to get Blizzard GPIO\n");
+		} else {
+			gpio_direction_output(n800_dsi_display_data.ctrl_reset_gpio,
+					1);
+			// XXX always enable
+		}
+	}
+
+	if (n800_dsi_display_data.panel_reset_gpio != -1) {
+		r = gpio_request(n800_dsi_display_data.panel_reset_gpio,
+				"panel reset");
+		if (r < 0) {
+			n800_dsi_display_data.panel_reset_gpio = -1;
+			printk(KERN_ERR "Unable to get pn800 GPIO\n");
+		} else {
+			gpio_direction_output(n800_dsi_display_data.panel_reset_gpio,
+					1);
+			// XXX always enable
+		}
+	}
+}
+
+/* DISPLAY END */
+
+
+
+
+
 static void mipid_shutdown(struct mipid_platform_data *pdata)
 {
 	if (pdata->nreset_gpio != -1) {
@@ -191,6 +346,7 @@ static struct mipid_platform_data n800_mipid_platform_data = {
 	.shutdown = mipid_shutdown,
 };
 
+#if 0
 static void __init mipid_dev_init(void)
 {
 	const struct omap_lcd_config *conf;
@@ -201,26 +357,9 @@ static void __init mipid_dev_init(void)
 		n800_mipid_platform_data.data_lines = conf->data_lines;
 	}
 }
+#endif
 
-static struct {
-	struct clk *sys_ck;
-} blizzard;
-
-static int blizzard_get_clocks(void)
-{
-	blizzard.sys_ck = clk_get(0, "osc_ck");
-	if (IS_ERR(blizzard.sys_ck)) {
-		printk(KERN_ERR "can't get Blizzard clock\n");
-		return PTR_ERR(blizzard.sys_ck);
-	}
-	return 0;
-}
-
-static unsigned long blizzard_get_clock_rate(struct device *dev)
-{
-	return clk_get_rate(blizzard.sys_ck);
-}
-
+#if 0
 static void blizzard_enable_clocks(int enable)
 {
 	if (enable)
@@ -265,14 +404,12 @@ static void __init blizzard_dev_init(void)
 	gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1);
 
 	blizzard_get_clocks();
-	omapfb_set_ctrl_platform_data(&n800_blizzard_data);
+	//omapfb_set_ctrl_platform_data(&n800_blizzard_data);
 }
+#endif
 
 static struct omap_board_config_kernel n800_config[] __initdata = {
 	{ OMAP_TAG_UART,	                &n800_uart_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem0_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem1_config },
-	{ OMAP_TAG_FBMEM,			&n800_fbmem2_config },
 	{ OMAP_TAG_TMP105,			&n800_tmp105_config },
 };
 
@@ -379,7 +516,7 @@ static struct omap2_mcspi_device_config tsc2005_mcspi_config = {
 
 static struct spi_board_info n800_spi_board_info[] __initdata = {
 	{
-		.modalias	= "lcd_mipid",
+		.modalias	= "panel-n800",
 		.bus_num	= 1,
 		.chip_select	= 1,
 		.max_speed_hz	= 4000000,
@@ -404,7 +541,7 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
 
 static struct spi_board_info n810_spi_board_info[] __initdata = {
 	{
-		.modalias	 = "lcd_mipid",
+		.modalias	 = "panel-n800",
 		.bus_num	 = 1,
 		.chip_select	 = 1,
 		.max_speed_hz	 = 4000000,
@@ -582,6 +719,7 @@ static struct platform_device *n800_devices[] __initdata = {
 #if defined(CONFIG_CBUS_RETU_HEADSET)
 	&retu_headset_device,
 #endif
+	&n800_dss_device,
 };
 
 #ifdef CONFIG_MENELAUS
@@ -713,9 +851,10 @@ void __init nokia_n800_common_init(void)
 	if (machine_is_nokia_n810())
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 			ARRAY_SIZE(n810_i2c_board_info_2));
-		
-	mipid_dev_init();
-	blizzard_dev_init();
+
+	//mipid_dev_init();
+	//blizzard_dev_init();
+	n800_display_init();
 }
 
 static void __init nokia_n800_init(void)
@@ -735,6 +874,7 @@ void __init nokia_n800_map_io(void)
 	omap_board_config_size = ARRAY_SIZE(n800_config);
 
 	omap2_set_globals_242x();
+	omap2_set_sdram_vram(800 * 480 * 2 * 3, 0);
 	omap2_map_common_io();
 }
 
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 0419ec8..356ceb1 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -18,4 +18,14 @@ config PANEL_SHARP_LS037V7DW01
         depends on OMAP2_DSS
         help
           LCD Panel used in TI's SDP3430 and EVM boards
+
+config PANEL_N800
+        tristate "Panel N8x0"
+        help
+          N8x0 LCD (hack)
+
+config CTRL_BLIZZARD
+        tristate "Blizzard Controller"
+        help
+          Blizzard Controller (hack)
 endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index a26bbd2..1b74b7e 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,3 +1,6 @@
 obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
 obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+
+obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
+obj-$(CONFIG_PANEL_N800) += panel-n800.o
diff --git a/drivers/video/omap2/displays/ctrl-blizzard.c b/drivers/video/omap2/displays/ctrl-blizzard.c
new file mode 100644
index 0000000..6698e4d
--- /dev/null
+++ b/drivers/video/omap2/displays/ctrl-blizzard.c
@@ -0,0 +1,279 @@
+
+//#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#define BLIZZARD_REV_CODE			0x00
+#define BLIZZARD_CONFIG				0x02
+#define BLIZZARD_PLL_DIV			0x04
+#define BLIZZARD_PLL_LOCK_RANGE			0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0		0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1		0x0a
+#define BLIZZARD_PLL_MODE			0x0c
+#define BLIZZARD_CLK_SRC			0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE		0x10
+#define BLIZZARD_MEM_BANK0_STATUS		0x14
+#define BLIZZARD_PANEL_CONFIGURATION		0x28
+#define BLIZZARD_HDISP				0x2a
+#define BLIZZARD_HNDP				0x2c
+#define BLIZZARD_VDISP0				0x2e
+#define BLIZZARD_VDISP1				0x30
+#define BLIZZARD_VNDP				0x32
+#define BLIZZARD_HSW				0x34
+#define BLIZZARD_VSW				0x38
+#define BLIZZARD_DISPLAY_MODE			0x68
+#define BLIZZARD_INPUT_WIN_X_START_0		0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT		0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT		0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0		0x92
+#define BLIZZARD_POWER_SAVE			0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS		0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD			0x00
+#define BLIZZARD_SRC_BLT_LCD			0x06
+
+#define BLIZZARD_COLOR_RGB565			0x01
+#define BLIZZARD_COLOR_YUV420			0x09
+
+#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */
+
+#define BLIZZARD_AUTO_UPDATE_TIME		(HZ / 20)
+
+
+
+static struct {
+	int			version;
+} blizzard;
+
+
+static inline void blizzard_cmd(u8 cmd)
+{
+        omap_rfbi_write_command(&cmd, 1);
+}
+
+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
+{
+        omap_rfbi_write_command(&cmd, 1);
+        omap_rfbi_write_data(buf, len);
+}
+
+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
+{
+        omap_rfbi_write_command(&cmd, 1);
+        omap_rfbi_read_data(buf, len);
+}
+
+static u8 blizzard_read_reg(u8 cmd)
+{
+	u8 data;
+	blizzard_read(cmd, &data, 1);
+	return data;
+}
+
+static int blizzard_ctrl_init(struct omap_display *display)
+{
+	DBG("blizzard_ctrl_init\n");
+
+	return 0;
+}
+
+
+static int blizzard_ctrl_enable(struct omap_display *display)
+{
+	int r = 0;
+	u8 rev, conf;
+
+	DBG("blizzard_ctrl_enable\n");
+
+	if (display->hw_config.ctrl_enable) {
+		r = display->hw_config.ctrl_enable(display);
+		if (r)
+			return r;
+	}
+
+	msleep(100);
+
+	rev = blizzard_read_reg(BLIZZARD_CLK_SRC);
+	printk("CLK_SRC %x\n", rev);
+
+	rev = blizzard_read_reg(BLIZZARD_PLL_DIV);
+	printk("PLLDIV %x\n", rev);
+
+	rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+	conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+	printk("rev %x, conf %x\n", rev, conf);
+
+	switch (rev & 0xfc) {
+	case 0x9c:
+		blizzard.version = BLIZZARD_VERSION_S1D13744;
+		pr_info("omapfb: s1d13744 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	case 0xa4:
+		blizzard.version = BLIZZARD_VERSION_S1D13745;
+		pr_info("omapfb: s1d13745 LCD controller rev %d "
+			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+		break;
+	default:
+		printk("invalid s1d1374x revision %02x\n",
+			rev);
+		r = -ENODEV;
+	}
+
+	return r;
+}
+
+static void blizzard_ctrl_disable(struct omap_display *display)
+{
+	DBG("blizzard_ctrl_disable\n");
+
+	if (display->hw_config.ctrl_disable)
+		display->hw_config.ctrl_disable(display);
+}
+
+int rfbi_configure(int rfbi_module, int bpp, int lines);
+
+static void blizzard_ctrl_setup_update(struct omap_display *display,
+				    u16 x, u16 y, u16 w, u16 h)
+{
+	u8 tmp[18];
+	int x_end, y_end;
+
+	DBG("blizzard_ctrl_setup_update\n");
+
+	x_end = x + w - 1;
+	y_end = y + h - 1;
+
+	tmp[0] = x;
+	tmp[1] = x >> 8;
+	tmp[2] = y;
+	tmp[3] = y >> 8;
+	tmp[4] = x_end;
+	tmp[5] = x_end >> 8;
+	tmp[6] = y_end;
+	tmp[7] = y_end >> 8;
+
+	/* scaling? */
+	tmp[8] = x;
+	tmp[9] = x >> 8;
+	tmp[10] = y;
+	tmp[11] = y >> 8;
+	tmp[12] = x_end;
+	tmp[13] = x_end >> 8;
+	tmp[14] = y_end;
+	tmp[15] = y_end >> 8;
+
+	tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode;
+
+	if (blizzard.version == BLIZZARD_VERSION_S1D13745)
+		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+	else
+		tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
+				BLIZZARD_SRC_WRITE_LCD :
+				BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+	rfbi_configure(display->hw_config.u.rfbi.channel,
+		       16,
+		       8);
+
+	blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
+
+	rfbi_configure(display->hw_config.u.rfbi.channel,
+		       16,
+		       16);
+}
+
+static int blizzard_ctrl_enable_te(struct omap_display *display, bool enable)
+{
+	return 0;
+}
+
+static int blizzard_ctrl_rotate(struct omap_display *display, u8 rotate)
+{
+	return 0;
+}
+
+static int blizzard_ctrl_mirror(struct omap_display *display, bool enable)
+{
+	return 0;
+}
+
+static int blizzard_run_test(struct omap_display *display, int test_num)
+{
+	return 0;
+}
+
+static struct omap_ctrl blizzard_ctrl = {
+	.owner = THIS_MODULE,
+	.name = "ctrl-blizzard",
+	.init = blizzard_ctrl_init,
+	.enable = blizzard_ctrl_enable,
+	.disable = blizzard_ctrl_disable,
+	.setup_update = blizzard_ctrl_setup_update,
+	.enable_te = blizzard_ctrl_enable_te,
+	.set_rotate = blizzard_ctrl_rotate,
+	.set_mirror = blizzard_ctrl_mirror,
+	.run_test = blizzard_run_test,
+	.pixel_size = 16,
+
+	.timings = {
+                .cs_on_time     = 0,
+
+                .we_on_time     = 9000,
+                .we_off_time    = 18000,
+                .we_cycle_time  = 36000,
+
+                .re_on_time     = 9000,
+                .re_off_time    = 27000,
+                .re_cycle_time  = 36000,
+
+                .access_time    = 27000,
+                .cs_off_time    = 36000,
+
+                .cs_pulse_width = 0,
+        },
+};
+
+
+static int __init blizzard_init(void)
+{
+	DBG("blizzard_init\n");
+	omap_dss_register_ctrl(&blizzard_ctrl);
+	return 0;
+}
+
+static void __exit blizzard_exit(void)
+{
+	DBG("blizzard_exit\n");
+
+	omap_dss_unregister_ctrl(&blizzard_ctrl);
+}
+
+module_init(blizzard_init);
+module_exit(blizzard_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("Blizzard Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-n800.c b/drivers/video/omap2/displays/panel-n800.c
new file mode 100644
index 0000000..91d3e37
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n800.c
@@ -0,0 +1,435 @@
+
+/*#define DEBUG*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <mach/display.h>
+#include <mach/dma.h>
+
+#define MIPID_CMD_READ_DISP_ID		0x04
+#define MIPID_CMD_READ_RED		0x06
+#define MIPID_CMD_READ_GREEN		0x07
+#define MIPID_CMD_READ_BLUE		0x08
+#define MIPID_CMD_READ_DISP_STATUS	0x09
+#define MIPID_CMD_RDDSDR		0x0F
+#define MIPID_CMD_SLEEP_IN		0x10
+#define MIPID_CMD_SLEEP_OUT		0x11
+#define MIPID_CMD_DISP_OFF		0x28
+#define MIPID_CMD_DISP_ON		0x29
+
+#define MIPID_VER_LPH8923		3
+#define MIPID_VER_LS041Y3		4
+
+#define MIPID_ESD_CHECK_PERIOD		msecs_to_jiffies(5000)
+
+#ifdef DEBUG
+#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+struct pn800_device {
+	struct backlight_device *bl_dev;
+	int		enabled;
+	int		model;
+	int		revision;
+	u8		display_id[3];
+	unsigned int	saved_bklight_level;
+	unsigned long	hw_guard_end;		/* next value of jiffies
+						   when we can issue the
+						   next sleep in/out command */
+	unsigned long	hw_guard_wait;		/* max guard time in jiffies */
+
+	struct spi_device	*spi;
+	struct mutex		mutex;
+	struct omap_panel	panel;
+	struct omap_display	*display;
+};
+
+
+static void pn800_transfer(struct pn800_device *md, int cmd,
+			      const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	struct spi_message	m;
+	struct spi_transfer	*x, xfer[4];
+	u16			w;
+	int			r;
+
+	BUG_ON(md->spi == NULL);
+
+	spi_message_init(&m);
+
+	memset(xfer, 0, sizeof(xfer));
+	x = &xfer[0];
+
+	cmd &=  0xff;
+	x->tx_buf = &cmd;
+	x->bits_per_word = 9;
+	x->len = 2;
+	spi_message_add_tail(x, &m);
+
+	if (wlen) {
+		x++;
+		x->tx_buf = wbuf;
+		x->len = wlen;
+		x->bits_per_word = 9;
+		spi_message_add_tail(x, &m);
+	}
+
+	if (rlen) {
+		x++;
+		x->rx_buf = &w;
+		x->len = 1;
+		spi_message_add_tail(x, &m);
+
+		if (rlen > 1) {
+			/* Arrange for the extra clock before the first
+			 * data bit.
+			 */
+			x->bits_per_word = 9;
+			x->len		 = 2;
+
+			x++;
+			x->rx_buf	 = &rbuf[1];
+			x->len		 = rlen - 1;
+			spi_message_add_tail(x, &m);
+		}
+	}
+
+	r = spi_sync(md->spi, &m);
+	if (r < 0)
+		dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
+
+	if (rlen)
+		rbuf[0] = w & 0xff;
+}
+
+static inline void pn800_cmd(struct pn800_device *md, int cmd)
+{
+	pn800_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void pn800_write(struct pn800_device *md,
+			       int reg, const u8 *buf, int len)
+{
+	pn800_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void pn800_read(struct pn800_device *md,
+			      int reg, u8 *buf, int len)
+{
+	pn800_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct pn800_device *md, int data_lines)
+{
+	u16 par;
+
+	switch (data_lines) {
+	case 16:
+		par = 0x150;
+		break;
+	case 18:
+		par = 0x160;
+		break;
+	case 24:
+		par = 0x170;
+		break;
+	}
+	pn800_write(md, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct pn800_device *md)
+{
+	u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+	int data_lines;
+
+	pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
+
+	data_lines = (int)md->display->hw_config.panel_data; // XXX
+
+	set_data_lines(md, data_lines);
+}
+
+static void hw_guard_start(struct pn800_device *md, int guard_msec)
+{
+	md->hw_guard_wait = msecs_to_jiffies(guard_msec);
+	md->hw_guard_end = jiffies + md->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct pn800_device *md)
+{
+	unsigned long wait = md->hw_guard_end - jiffies;
+
+	if ((long)wait > 0 && wait <= md->hw_guard_wait) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(wait);
+	}
+}
+
+static void set_sleep_mode(struct pn800_device *md, int on)
+{
+	int cmd, sleep_time = 50;
+
+	if (on)
+		cmd = MIPID_CMD_SLEEP_IN;
+	else
+		cmd = MIPID_CMD_SLEEP_OUT;
+	hw_guard_wait(md);
+	pn800_cmd(md, cmd);
+	hw_guard_start(md, 120);
+	/*
+	 * When we enable the panel, it seems we _have_ to sleep
+	 * 120 ms before sending the init string. When disabling the
+	 * panel we'll sleep for the duration of 2 frames, so that the
+	 * controller can still provide the PCLK,HS,VS signals. */
+	if (!on)
+		sleep_time = 120;
+	msleep(sleep_time);
+}
+
+static void set_display_state(struct pn800_device *md, int enabled)
+{
+	int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+	pn800_cmd(md, cmd);
+}
+
+static int panel_enabled(struct pn800_device *md)
+{
+	u32 disp_status;
+	int enabled;
+
+	pn800_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
+	disp_status = __be32_to_cpu(disp_status);
+	enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
+	dev_dbg(&md->spi->dev,
+		"LCD panel %s enabled by bootloader (status 0x%04x)\n",
+		enabled ? "" : "not ", disp_status);
+	DBG("status %#08x\n", disp_status);
+	return enabled;
+}
+
+static int panel_detect(struct pn800_device *md)
+{
+	pn800_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
+	dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
+		md->display_id[0], md->display_id[1], md->display_id[2]);
+
+	switch (md->display_id[0]) {
+	case 0x45:
+		md->model = MIPID_VER_LPH8923;
+		md->panel.name = "lph8923";
+		break;
+	case 0x83:
+		md->model = MIPID_VER_LS041Y3;
+		md->panel.name = "ls041y3";
+		//md->esd_check = ls041y3_esd_check;
+		break;
+	default:
+		md->panel.name = "unknown";
+		dev_err(&md->spi->dev, "invalid display ID\n");
+		return -ENODEV;
+	}
+
+	md->revision = md->display_id[1];
+	pr_info("omapfb: %s rev %02x LCD detected\n",
+			md->panel.name, md->revision);
+
+	return 0;
+}
+
+
+
+static int pn800_panel_enable(struct omap_display *display)
+{
+	int r;
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_enable\n");
+
+	mutex_lock(&md->mutex);
+
+	if (display->hw_config.panel_enable)
+		display->hw_config.panel_enable(display);
+
+	msleep(50); // wait for power up
+
+	r = panel_detect(md);
+	if (r) {
+		mutex_unlock(&md->mutex);
+		return r;
+	}
+
+	md->enabled = panel_enabled(md);
+
+	if (md->enabled) {
+		DBG("panel already enabled\n");
+		; /*pn800_esd_start_check(md);*/
+	} else {
+		; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+	}
+
+
+	if (md->enabled) {
+		mutex_unlock(&md->mutex);
+		return 0;
+	}
+
+	set_sleep_mode(md, 0);
+	md->enabled = 1;
+	send_init_string(md);
+	set_display_state(md, 1);
+	//mipid_set_bklight_level(panel, md->saved_bklight_level);
+	//mipid_esd_start_check(md);
+
+	mutex_unlock(&md->mutex);
+	return 0;
+}
+
+static void pn800_panel_disable(struct omap_display *display)
+{
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_disable\n");
+
+	mutex_lock(&md->mutex);
+
+	if (!md->enabled) {
+		mutex_unlock(&md->mutex);
+		return;
+	}
+	/*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
+	/*pn800_set_bklight_level(panel, 0);*/
+
+	set_display_state(md, 0);
+	set_sleep_mode(md, 1);
+	md->enabled = 0;
+
+
+	if (display->hw_config.panel_disable)
+		display->hw_config.panel_disable(display);
+
+	mutex_unlock(&md->mutex);
+}
+
+static int pn800_panel_init(struct omap_display *display)
+{
+	struct pn800_device *md =
+		(struct pn800_device *)display->panel->priv;
+
+	DBG("pn800_panel_init\n");
+
+	mutex_init(&md->mutex);
+	md->display = display;
+
+	return 0;
+}
+
+static int pn800_run_test(struct omap_display *display, int test_num)
+{
+	return 0;
+}
+
+static struct omap_panel pn800_panel = {
+	.owner		= THIS_MODULE,
+	.name		= "panel-pn800",
+	.init		= pn800_panel_init,
+	/*.remove	= pn800_cleanup,*/
+	.enable		= pn800_panel_enable,
+	.disable	= pn800_panel_disable,
+	//.set_mode	= pn800_set_mode,
+	.run_test	= pn800_run_test,
+
+	.timings = {
+		.x_res = 800,
+		.y_res = 480,
+
+		.pixel_clock	= 21940,
+		.hsw		= 50,
+		.hfp		= 20,
+		.hbp		= 15,
+
+		.vsw		= 2,
+		.vfp		= 1,
+		.vbp		= 3,
+	},
+	.config		= OMAP_DSS_LCD_TFT,
+};
+
+static int pn800_spi_probe(struct spi_device *spi)
+{
+	struct pn800_device *md;
+
+	DBG("pn800_spi_probe\n");
+
+	md = kzalloc(sizeof(*md), GFP_KERNEL);
+	if (md == NULL) {
+		dev_err(&spi->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	spi->mode = SPI_MODE_0;
+	md->spi = spi;
+	dev_set_drvdata(&spi->dev, md);
+	md->panel = pn800_panel;
+	pn800_panel.priv = md;
+
+	omap_dss_register_panel(&pn800_panel);
+
+	return 0;
+}
+
+static int pn800_spi_remove(struct spi_device *spi)
+{
+	struct pn800_device *md = dev_get_drvdata(&spi->dev);
+
+	DBG("pn800_spi_remove\n");
+
+	omap_dss_unregister_panel(&pn800_panel);
+
+	/*pn800_disable(&md->panel);*/
+	kfree(md);
+
+	return 0;
+}
+
+static struct spi_driver pn800_spi_driver = {
+	.driver = {
+		.name	= "panel-n800",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= pn800_spi_probe,
+	.remove	= __devexit_p(pn800_spi_remove),
+};
+
+static int __init pn800_init(void)
+{
+	DBG("pn800_init\n");
+	return spi_register_driver(&pn800_spi_driver);
+}
+
+static void __exit pn800_exit(void)
+{
+	DBG("pn800_exit\n");
+	spi_unregister_driver(&pn800_spi_driver);
+}
+
+module_init(pn800_init);
+module_exit(pn800_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
+MODULE_DESCRIPTION("N800 LCD Driver");
+MODULE_LICENSE("GPL");
-- 
1.5.6.5