Merge branch 'for-paul' of git://gitorious.org/linux-omap-dss2/linux
authorPaul Mundt <lethal@linux-sh.org>
Tue, 22 Mar 2011 05:27:36 +0000 (14:27 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 22 Mar 2011 05:27:36 +0000 (14:27 +0900)
Conflicts:
arch/arm/mach-omap2/board-overo.c

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
51 files changed:
MAINTAINERS
arch/arm/configs/omap2plus_defconfig
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/plat-omap/include/plat/display.h
drivers/video/omap/Kconfig
drivers/video/omap2/displays/Kconfig
drivers/video/omap2/displays/Makefile
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-lgphilips-lb035q02.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/display.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c [new file with mode: 0644]
drivers/video/omap2/dss/hdmi.h [new file with mode: 0644]
drivers/video/omap2/dss/hdmi_omap4_panel.c [new file with mode: 0644]
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/omapfb/Kconfig
drivers/video/omap2/omapfb/omapfb-main.c

index 38077a6..5b28ed0 100644 (file)
@@ -4542,14 +4542,14 @@ S:      Maintained
 F:     sound/soc/omap/
 
 OMAP FRAMEBUFFER SUPPORT
-M:     Tomi Valkeinen <tomi.valkeinen@nokia.com>
+M:     Tomi Valkeinen <tomi.valkeinen@ti.com>
 L:     linux-fbdev@vger.kernel.org
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     drivers/video/omap/
 
 OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
-M:     Tomi Valkeinen <tomi.valkeinen@nokia.com>
+M:     Tomi Valkeinen <tomi.valkeinen@ti.com>
 L:     linux-omap@vger.kernel.org
 L:     linux-fbdev@vger.kernel.org
 S:     Maintained
index 019fb7c..076db52 100644 (file)
@@ -193,6 +193,17 @@ CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_OMAP_LCD_VGA=y
+CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_SDI=y
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_FB_OMAP2=m
+CONFIG_PANEL_GENERIC_DPI=m
+CONFIG_PANEL_SHARP_LS037V7DW01=m
+CONFIG_PANEL_NEC_NL8048HL11_01B=m
+CONFIG_PANEL_TAAL=m
+CONFIG_PANEL_TPO_TD043MTEA1=m
+CONFIG_PANEL_ACX565AKM=m
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=y
index c06eb42..9afd087 100644 (file)
@@ -307,9 +307,6 @@ static struct omap_dss_board_info sdp3430_dss_data = {
        .default_device = &sdp3430_lcd_device,
 };
 
-static struct regulator_consumer_supply sdp3430_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
-
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
@@ -398,12 +395,13 @@ static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
 };
 
 static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = {
-       REGULATOR_SUPPLY("vdda_dac", "omapdss"),
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
 };
 
 /* VPLL2 for digital video outputs */
 static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
        REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
 static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
index 333ceb2..62c78de 100644 (file)
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
+#include <plat/display.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -47,6 +48,8 @@
 #define ETH_KS8851_QUART               138
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO       184
 #define OMAP4_SFH7741_ENABLE_GPIO              188
+#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
 
 static const int sdp4430_keymap[] = {
        KEY(0, 0, KEY_E),
@@ -621,6 +624,76 @@ static void __init omap_sfh7741prox_init(void)
        }
 }
 
+static void sdp4430_hdmi_mux_init(void)
+{
+       /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+       omap_mux_init_signal("hdmi_hpd",
+                       OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("hdmi_cec",
+                       OMAP_PIN_INPUT_PULLUP);
+       /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+       omap_mux_init_signal("hdmi_ddc_scl",
+                       OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("hdmi_ddc_sda",
+                       OMAP_PIN_INPUT_PULLUP);
+}
+
+static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
+{
+       int status;
+
+       status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH,
+                                                       "hdmi_gpio_hpd");
+       if (status) {
+               pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD);
+               return status;
+       }
+       status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH,
+                                                       "hdmi_gpio_ls_oe");
+       if (status) {
+               pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE);
+               goto error1;
+       }
+
+       return 0;
+
+error1:
+       gpio_free(HDMI_GPIO_HPD);
+
+       return status;
+}
+
+static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
+{
+       gpio_free(HDMI_GPIO_LS_OE);
+       gpio_free(HDMI_GPIO_HPD);
+}
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+       .name = "hdmi",
+       .driver_name = "hdmi_panel",
+       .type = OMAP_DISPLAY_TYPE_HDMI,
+       .platform_enable = sdp4430_panel_enable_hdmi,
+       .platform_disable = sdp4430_panel_disable_hdmi,
+       .channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *sdp4430_dss_devices[] = {
+       &sdp4430_hdmi_device,
+};
+
+static struct omap_dss_board_info sdp4430_dss_data = {
+       .num_devices    = ARRAY_SIZE(sdp4430_dss_devices),
+       .devices        = sdp4430_dss_devices,
+       .default_device = &sdp4430_hdmi_device,
+};
+
+void omap_4430sdp_display_init(void)
+{
+       sdp4430_hdmi_mux_init();
+       omap_display_init(&sdp4430_dss_data);
+}
+
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -729,6 +802,8 @@ static void __init omap_4430sdp_init(void)
        status = omap4_keyboard_init(&sdp4430_keypad_data);
        if (status)
                pr_err("Keypad initialization failed: %d\n", status);
+
+       omap_4430sdp_display_init();
 }
 
 static void __init omap_4430sdp_map_io(void)
index 7b56479..02a12b4 100644 (file)
@@ -488,7 +488,7 @@ static struct regulator_consumer_supply cm_t35_vsim_supply = {
 };
 
 static struct regulator_consumer_supply cm_t35_vdac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static struct regulator_consumer_supply cm_t35_vdvi_supply =
        REGULATOR_SUPPLY("vdvi", "omapdss");
index aa27483..65f9fde 100644 (file)
@@ -196,7 +196,7 @@ static struct omap_dss_board_info devkit8000_dss_data = {
 };
 
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_1),
@@ -277,8 +277,10 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
        .setup          = devkit8000_twl_gpio_setup,
 };
 
-static struct regulator_consumer_supply devkit8000_vpll1_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data devkit8000_vmmc1 = {
@@ -319,8 +321,8 @@ static struct regulator_init_data devkit8000_vpll1 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &devkit8000_vpll1_supply,
+       .num_consumer_supplies  = ARRAY_SIZE(devkit8000_vpll1_supplies),
+       .consumer_supplies      = devkit8000_vpll1_supplies,
 };
 
 /* VAUX4 for ads7846 and nubs */
index d3199b4..5f8a2fd 100644 (file)
@@ -485,8 +485,10 @@ static struct omap_dss_board_info igep2_dss_data = {
        .default_device = &igep2_dvi_device,
 };
 
-static struct regulator_consumer_supply igep2_vpll2_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply igep2_vpll2_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_init_data igep2_vpll2 = {
        .constraints = {
@@ -499,8 +501,8 @@ static struct regulator_init_data igep2_vpll2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &igep2_vpll2_supply,
+       .num_consumer_supplies  = ARRAY_SIZE(igep2_vpll2_supplies),
+       .consumer_supplies      = igep2_vpll2_supplies,
 };
 
 static void __init igep2_display_init(void)
index 7640c05..33007fd 100644 (file)
@@ -232,10 +232,12 @@ static struct omap_dss_board_info beagle_dss_data = {
 };
 
 static struct regulator_consumer_supply beagle_vdac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
-static struct regulator_consumer_supply beagle_vdvi_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply beagle_vdvi_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static void __init beagle_display_init(void)
 {
@@ -422,8 +424,8 @@ static struct regulator_init_data beagle_vpll2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &beagle_vdvi_supply,
+       .num_consumer_supplies  = ARRAY_SIZE(beagle_vdvi_supplies),
+       .consumer_supplies      = beagle_vdvi_supplies,
 };
 
 static struct twl4030_usb_data beagle_usb_data = {
index 0fa2c7b..5a1a916 100644 (file)
@@ -542,7 +542,7 @@ static struct twl4030_codec_data omap3evm_codec_data = {
 };
 
 static struct regulator_consumer_supply omap3_evm_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_evm_vdac = {
@@ -560,8 +560,10 @@ static struct regulator_init_data omap3_evm_vdac = {
 };
 
 /* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_evm_vpll2_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_init_data omap3_evm_vpll2 = {
        .constraints = {
@@ -573,8 +575,8 @@ static struct regulator_init_data omap3_evm_vpll2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &omap3_evm_vpll2_supply,
+       .num_consumer_supplies  = ARRAY_SIZE(omap3_evm_vpll2_supplies),
+       .consumer_supplies      = omap3_evm_vpll2_supplies,
 };
 
 /* ads7846 on SPI */
index 2e5dc21..07dba88 100644 (file)
@@ -342,11 +342,12 @@ static struct regulator_consumer_supply pandora_vmmc3_supply =
        REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2");
 
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
        REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
        REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
 static struct regulator_consumer_supply pandora_vcc_lcd_supply =
index 8ebdbc3..a6e0b91 100644 (file)
@@ -439,7 +439,7 @@ static struct twl4030_codec_data omap3stalker_codec_data = {
 };
 
 static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_stalker_vdac = {
@@ -457,8 +457,10 @@ static struct regulator_init_data omap3_stalker_vdac = {
 };
 
 /* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_stalker_vpll2_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_init_data omap3_stalker_vpll2 = {
        .constraints            = {
@@ -471,8 +473,8 @@ static struct regulator_init_data omap3_stalker_vpll2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &omap3_stalker_vpll2_supply,
+       .num_consumer_supplies  = ARRAY_SIZE(omap3_stalker_vpll2_supplies),
+       .consumer_supplies      = omap3_stalker_vpll2_supplies,
 };
 
 static struct twl4030_platform_data omap3stalker_twldata = {
index 0f4d8a7..209cffb 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <plat/display.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include <plat/panel-generic-dpi.h>
 #include "timer-gp.h"
 
 #include "hsmmc.h"
@@ -49,6 +51,8 @@
 #define GPIO_HUB_NRESET                62
 #define GPIO_WIFI_PMENA                43
 #define GPIO_WIFI_IRQ          53
+#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
 
 /* wl127x BT, FM, GPS connectivity chip */
 static int wl1271_gpios[] = {46, -1, -1};
@@ -433,6 +437,17 @@ static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = {
                .platform_data = &omap4_panda_twldata,
        },
 };
+
+/*
+ * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
+ * is connected as I2C slave device, and can be accessed at address 0x50
+ */
+static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
 static int __init omap4_panda_i2c_init(void)
 {
        /*
@@ -442,7 +457,12 @@ static int __init omap4_panda_i2c_init(void)
        omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo,
                        ARRAY_SIZE(omap4_panda_i2c_boardinfo));
        omap_register_i2c_bus(2, 400, NULL, 0);
-       omap_register_i2c_bus(3, 400, NULL, 0);
+       /*
+        * Bus 3 is attached to the DVI port where devices like the pico DLP
+        * projector don't work reliably with 400kHz
+        */
+       omap_register_i2c_bus(3, 100, panda_i2c_eeprom,
+                                       ARRAY_SIZE(panda_i2c_eeprom));
        omap_register_i2c_bus(4, 400, NULL, 0);
        return 0;
 }
@@ -462,6 +482,64 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
        OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
        OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+       /* gpio 0 - TFP410 PD */
+       OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3),
+       /* dispc2_data23 */
+       OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data22 */
+       OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data21 */
+       OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data20 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data19 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data18 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data15 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data14 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data13 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data12 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data11 */
+       OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data10 */
+       OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data9 */
+       OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data16 */
+       OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data17 */
+       OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_hsync */
+       OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_pclk */
+       OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_vsync */
+       OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_de */
+       OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data8 */
+       OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data7 */
+       OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data6 */
+       OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data5 */
+       OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data4 */
+       OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data3 */
+       OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data2 */
+       OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data1 */
+       OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* dispc2_data0 */
+       OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
@@ -535,6 +613,128 @@ static inline void board_serial_init(void)
 }
 #endif
 
+/* Display DVI */
+#define PANDA_DVI_TFP410_POWER_DOWN_GPIO       0
+
+static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev)
+{
+       gpio_set_value(dssdev->reset_gpio, 1);
+       return 0;
+}
+
+static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
+{
+       gpio_set_value(dssdev->reset_gpio, 0);
+}
+
+/* Using generic display panel */
+static struct panel_generic_dpi_data omap4_dvi_panel = {
+       .name                   = "generic",
+       .platform_enable        = omap4_panda_enable_dvi,
+       .platform_disable       = omap4_panda_disable_dvi,
+};
+
+struct omap_dss_device omap4_panda_dvi_device = {
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .name                   = "dvi",
+       .driver_name            = "generic_dpi_panel",
+       .data                   = &omap4_dvi_panel,
+       .phy.dpi.data_lines     = 24,
+       .reset_gpio             = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+       .channel                = OMAP_DSS_CHANNEL_LCD2,
+};
+
+int __init omap4_panda_dvi_init(void)
+{
+       int r;
+
+       /* Requesting TFP410 DVI GPIO and disabling it, at bootup */
+       r = gpio_request_one(omap4_panda_dvi_device.reset_gpio,
+                               GPIOF_OUT_INIT_LOW, "DVI PD");
+       if (r)
+               pr_err("Failed to get DVI powerdown GPIO\n");
+
+       return r;
+}
+
+
+static void omap4_panda_hdmi_mux_init(void)
+{
+       /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+       omap_mux_init_signal("hdmi_hpd",
+                       OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("hdmi_cec",
+                       OMAP_PIN_INPUT_PULLUP);
+       /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+       omap_mux_init_signal("hdmi_ddc_scl",
+                       OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_signal("hdmi_ddc_sda",
+                       OMAP_PIN_INPUT_PULLUP);
+}
+
+static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
+{
+       int status;
+
+       status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH,
+                                                       "hdmi_gpio_hpd");
+       if (status) {
+               pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD);
+               return status;
+       }
+       status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH,
+                                                       "hdmi_gpio_ls_oe");
+       if (status) {
+               pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE);
+               goto error1;
+       }
+
+       return 0;
+
+error1:
+       gpio_free(HDMI_GPIO_HPD);
+
+       return status;
+}
+
+static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
+{
+       gpio_free(HDMI_GPIO_LS_OE);
+       gpio_free(HDMI_GPIO_HPD);
+}
+
+static struct omap_dss_device  omap4_panda_hdmi_device = {
+       .name = "hdmi",
+       .driver_name = "hdmi_panel",
+       .type = OMAP_DISPLAY_TYPE_HDMI,
+       .platform_enable = omap4_panda_panel_enable_hdmi,
+       .platform_disable = omap4_panda_panel_disable_hdmi,
+       .channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *omap4_panda_dss_devices[] = {
+       &omap4_panda_dvi_device,
+       &omap4_panda_hdmi_device,
+};
+
+static struct omap_dss_board_info omap4_panda_dss_data = {
+       .num_devices    = ARRAY_SIZE(omap4_panda_dss_devices),
+       .devices        = omap4_panda_dss_devices,
+       .default_device = &omap4_panda_dvi_device,
+};
+
+void omap4_panda_display_init(void)
+{
+       int r;
+
+       r = omap4_panda_dvi_init();
+       if (r)
+               pr_err("error initializing panda DVI\n");
+
+       omap4_panda_hdmi_mux_init();
+       omap_display_init(&omap4_panda_dss_data);
+}
+
 static void __init omap4_panda_init(void)
 {
        int package = OMAP_PACKAGE_CBS;
@@ -553,6 +753,7 @@ static void __init omap4_panda_init(void)
        omap4_twl6030_hsmmc_init(mmc);
        omap4_ehci_init();
        usb_musb_init(&musb_board_data);
+       omap4_panda_display_init();
 }
 
 static void __init omap4_panda_map_io(void)
index d096194..59ca333 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/spi/spi.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
+#include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 #include <mach/gpio.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
+#include <plat/mcspi.h>
+#include <plat/mux.h>
 #include <plat/usb.h>
 
 #include "mux.h"
@@ -68,8 +74,6 @@
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
        defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
-#include <plat/mcspi.h>
-#include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
@@ -94,16 +98,32 @@ static struct ads7846_platform_data ads7846_config = {
        .keep_vref_on           = 1,
 };
 
-static struct spi_board_info overo_spi_board_info[] __initdata = {
-       {
-               .modalias               = "ads7846",
-               .bus_num                = 1,
-               .chip_select            = 0,
-               .max_speed_hz           = 1500000,
-               .controller_data        = &ads7846_mcspi_config,
-               .irq                    = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
-               .platform_data          = &ads7846_config,
-       }
+/* fixed regulator for ads7846 */
+static struct regulator_consumer_supply ads7846_supply =
+       REGULATOR_SUPPLY("vcc", "spi1.0");
+
+static struct regulator_init_data vads7846_regulator = {
+       .constraints = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &ads7846_supply,
+};
+
+static struct fixed_voltage_config vads7846 = {
+       .supply_name            = "vads7846",
+       .microvolts             = 3300000, /* 3.3V */
+       .gpio                   = -EINVAL,
+       .startup_delay          = 0,
+       .init_data              = &vads7846_regulator,
+};
+
+static struct platform_device vads7846_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 1,
+       .dev = {
+               .platform_data = &vads7846,
+       },
 };
 
 static void __init overo_ads7846_init(void)
@@ -116,8 +136,7 @@ static void __init overo_ads7846_init(void)
                return;
        }
 
-       spi_register_board_info(overo_spi_board_info,
-                       ARRAY_SIZE(overo_spi_board_info));
+       platform_device_register(&vads7846_device);
 }
 
 #else
@@ -233,6 +252,137 @@ static inline void __init overo_init_smsc911x(void)
 static inline void __init overo_init_smsc911x(void) { return; }
 #endif
 
+/* DSS */
+static int lcd_enabled;
+static int dvi_enabled;
+
+#define OVERO_GPIO_LCD_EN 144
+#define OVERO_GPIO_LCD_BL 145
+
+static void __init overo_display_init(void)
+{
+       if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0))
+               gpio_export(OVERO_GPIO_LCD_EN, 0);
+       else
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_LCD_EN\n");
+
+       if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0))
+               gpio_export(OVERO_GPIO_LCD_BL, 0);
+       else
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_LCD_BL\n");
+}
+
+static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
+{
+       if (lcd_enabled) {
+               printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+               return -EINVAL;
+       }
+       dvi_enabled = 1;
+
+       return 0;
+}
+
+static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
+{
+       dvi_enabled = 0;
+}
+
+static struct panel_generic_dpi_data dvi_panel = {
+       .name                   = "generic",
+       .platform_enable        = overo_panel_enable_dvi,
+       .platform_disable       = overo_panel_disable_dvi,
+};
+
+static struct omap_dss_device overo_dvi_device = {
+       .name                   = "dvi",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .driver_name            = "generic_dpi_panel",
+       .data                   = &dvi_panel,
+       .phy.dpi.data_lines     = 24,
+};
+
+static struct omap_dss_device overo_tv_device = {
+       .name = "tv",
+       .driver_name = "venc",
+       .type = OMAP_DISPLAY_TYPE_VENC,
+       .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+       if (dvi_enabled) {
+               printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+               return -EINVAL;
+       }
+
+       gpio_set_value(OVERO_GPIO_LCD_EN, 1);
+       gpio_set_value(OVERO_GPIO_LCD_BL, 1);
+       lcd_enabled = 1;
+       return 0;
+}
+
+static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+       gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+       gpio_set_value(OVERO_GPIO_LCD_BL, 0);
+       lcd_enabled = 0;
+}
+
+static struct panel_generic_dpi_data lcd43_panel = {
+       .name                   = "samsung_lte430wq_f0c",
+       .platform_enable        = overo_panel_enable_lcd,
+       .platform_disable       = overo_panel_disable_lcd,
+};
+
+static struct omap_dss_device overo_lcd43_device = {
+       .name                   = "lcd43",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .driver_name            = "generic_dpi_panel",
+       .data                   = &lcd43_panel,
+       .phy.dpi.data_lines     = 24,
+};
+
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+       defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+static struct omap_dss_device overo_lcd35_device = {
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .name                   = "lcd35",
+       .driver_name            = "lgphilips_lb035q02_panel",
+       .phy.dpi.data_lines     = 24,
+       .platform_enable        = overo_panel_enable_lcd,
+       .platform_disable       = overo_panel_disable_lcd,
+};
+#endif
+
+static struct omap_dss_device *overo_dss_devices[] = {
+       &overo_dvi_device,
+       &overo_tv_device,
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+       defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+       &overo_lcd35_device,
+#endif
+       &overo_lcd43_device,
+};
+
+static struct omap_dss_board_info overo_dss_data = {
+       .num_devices    = ARRAY_SIZE(overo_dss_devices),
+       .devices        = overo_dss_devices,
+       .default_device = &overo_dvi_device,
+};
+
+static struct regulator_consumer_supply overo_vdda_dac_supply =
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
+
+static struct regulator_consumer_supply overo_vdds_dsi_supply[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
 static struct mtd_partition overo_nand_partitions[] = {
        {
                .name           = "xloader",
@@ -323,6 +473,93 @@ static struct regulator_consumer_supply overo_vmmc1_supply = {
        .supply                 = "vmmc",
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led gpio_leds[] = {
+       {
+               .name                   = "overo:red:gpio21",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 21,
+               .active_low             = true,
+       },
+       {
+               .name                   = "overo:blue:gpio22",
+               .default_trigger        = "none",
+               .gpio                   = 22,
+               .active_low             = true,
+       },
+       {
+               .name                   = "overo:blue:COM",
+               .default_trigger        = "mmc0",
+               .gpio                   = -EINVAL,      /* gets replaced */
+               .active_low             = true,
+       },
+};
+
+static struct gpio_led_platform_data gpio_leds_pdata = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_leds_pdata,
+       },
+};
+
+static void __init overo_init_led(void)
+{
+       platform_device_register(&gpio_leds_device);
+}
+
+#else
+static inline void __init overo_init_led(void) { return; }
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button gpio_buttons[] = {
+       {
+               .code                   = BTN_0,
+               .gpio                   = 23,
+               .desc                   = "button0",
+               .wakeup                 = 1,
+       },
+       {
+               .code                   = BTN_1,
+               .gpio                   = 14,
+               .desc                   = "button1",
+               .wakeup                 = 1,
+       },
+};
+
+static struct gpio_keys_platform_data gpio_keys_pdata = {
+       .buttons        = gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_keys_pdata,
+       },
+};
+
+static void __init overo_init_keys(void)
+{
+       platform_device_register(&gpio_keys_device);
+}
+
+#else
+static inline void __init overo_init_keys(void) { return; }
+#endif
+
 static int overo_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
@@ -330,6 +567,11 @@ static int overo_twl_gpio_setup(struct device *dev,
 
        overo_vmmc1_supply.dev = mmc[0].dev;
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+       /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
        return 0;
 }
 
@@ -337,6 +579,7 @@ static struct twl4030_gpio_platform_data overo_gpio_data = {
        .gpio_base      = OMAP_MAX_GPIO_LINES,
        .irq_base       = TWL4030_GPIO_IRQ_BASE,
        .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
        .setup          = overo_twl_gpio_setup,
 };
 
@@ -358,6 +601,35 @@ static struct regulator_init_data overo_vmmc1 = {
        .consumer_supplies      = &overo_vmmc1_supply,
 };
 
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data overo_vdac = {
+       .constraints = {
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &overo_vdda_dac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data overo_vpll2 = {
+       .constraints = {
+               .name                   = "VDVI",
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(overo_vdds_dsi_supply),
+       .consumer_supplies      = overo_vdds_dsi_supply,
+};
+
 static struct twl4030_codec_audio_data overo_audio_data;
 
 static struct twl4030_codec_data overo_codec_data = {
@@ -365,8 +637,6 @@ static struct twl4030_codec_data overo_codec_data = {
        .audio = &overo_audio_data,
 };
 
-/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
-
 static struct twl4030_platform_data overo_twldata = {
        .irq_base       = TWL4030_IRQ_BASE,
        .irq_end        = TWL4030_IRQ_END,
@@ -374,6 +644,8 @@ static struct twl4030_platform_data overo_twldata = {
        .usb            = &overo_usb_data,
        .codec          = &overo_codec_data,
        .vmmc1          = &overo_vmmc1,
+       .vdac           = &overo_vdac,
+       .vpll2          = &overo_vpll2,
 };
 
 static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
@@ -394,18 +666,38 @@ static int __init overo_i2c_init(void)
        return 0;
 }
 
-static struct platform_device overo_lcd_device = {
-       .name           = "overo_lcd",
-       .id             = -1,
-};
-
-static struct omap_lcd_config overo_lcd_config __initdata = {
-       .ctrl_name      = "internal",
+static struct spi_board_info overo_spi_board_info[] __initdata = {
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
+       defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+       {
+               .modalias               = "ads7846",
+               .bus_num                = 1,
+               .chip_select            = 0,
+               .max_speed_hz           = 1500000,
+               .controller_data        = &ads7846_mcspi_config,
+               .irq                    = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
+               .platform_data          = &ads7846_config,
+       },
+#endif
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+       defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+       {
+               .modalias               = "lgphilips_lb035q02_panel-spi",
+               .bus_num                = 1,
+               .chip_select            = 1,
+               .max_speed_hz           = 500000,
+               .mode                   = SPI_MODE_3,
+       },
+#endif
 };
 
-static struct omap_board_config_kernel overo_config[] __initdata = {
-       { OMAP_TAG_LCD,         &overo_lcd_config },
-};
+static int __init overo_spi_init(void)
+{
+       overo_ads7846_init();
+       spi_register_board_info(overo_spi_board_info,
+                       ARRAY_SIZE(overo_spi_board_info));
+       return 0;
+}
 
 static void __init overo_init_early(void)
 {
@@ -414,15 +706,10 @@ static void __init overo_init_early(void)
                                  mt46h32m32lf6_sdrc_params);
 }
 
-static struct platform_device *overo_devices[] __initdata = {
-       &overo_lcd_device,
-};
-
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
        .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
        .phy_reset  = true,
        .reset_gpio_port[0]  = -EINVAL,
        .reset_gpio_port[1]  = OVERO_GPIO_USBH_NRESET,
@@ -444,16 +731,18 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init overo_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-       omap_board_config = overo_config;
-       omap_board_config_size = ARRAY_SIZE(overo_config);
        overo_i2c_init();
-       platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
+       omap_display_init(&overo_dss_data);
        omap_serial_init();
        overo_flash_init();
        usb_musb_init(&musb_board_data);
        usbhs_init(&usbhs_bdata);
+       overo_spi_init();
        overo_ads7846_init();
        overo_init_smsc911x();
+       overo_display_init();
+       overo_init_led();
+       overo_init_keys();
 
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
index 5f1900c..bbcb677 100644 (file)
@@ -372,7 +372,7 @@ static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
 };
 
 static struct regulator_consumer_supply rx51_vdac_supply[] = {
-       REGULATOR_SUPPLY("vdda_dac", "omapdss"),
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
 };
 
 static struct regulator_init_data rx51_vaux1 = {
index 448ab60..8dee754 100644 (file)
@@ -226,11 +226,13 @@ static struct omap2_hsmmc_info mmc[] = {
        {}      /* Terminator */
 };
 
-static struct regulator_consumer_supply zoom_vpll2_supply =
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply zoom_vpll2_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_consumer_supply zoom_vdda_dac_supply =
-       REGULATOR_SUPPLY("vdda_dac", "omapdss");
+       REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static struct regulator_init_data zoom_vpll2 = {
        .constraints = {
@@ -241,8 +243,8 @@ static struct regulator_init_data zoom_vpll2 = {
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies          = 1,
-       .consumer_supplies              = &zoom_vpll2_supply,
+       .num_consumer_supplies          = ARRAY_SIZE(zoom_vpll2_supplies),
+       .consumer_supplies              = zoom_vpll2_supplies,
 };
 
 static struct regulator_init_data zoom_vdac = {
index b6f65d4..2926d02 100644 (file)
@@ -1804,10 +1804,10 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gfx_2d_fck",   &gfx_2d_fck,    CK_242X),
        CLK(NULL,       "gfx_ick",      &gfx_ick,       CK_242X),
        /* DSS domain clocks */
-       CLK("omapdss",  "ick",          &dss_ick,       CK_242X),
-       CLK("omapdss",  "dss1_fck",     &dss1_fck,      CK_242X),
-       CLK("omapdss",  "dss2_fck",     &dss2_fck,      CK_242X),
-       CLK("omapdss",  "tv_fck",       &dss_54m_fck,   CK_242X),
+       CLK("omapdss_dss",      "ick",          &dss_ick,       CK_242X),
+       CLK("omapdss_dss",      "fck",          &dss1_fck,      CK_242X),
+       CLK("omapdss_dss",      "sys_clk",      &dss2_fck,      CK_242X),
+       CLK("omapdss_dss",      "tv_clk",       &dss_54m_fck,   CK_242X),
        /* L3 domain clocks */
        CLK(NULL,       "core_l3_ck",   &core_l3_ck,    CK_242X),
        CLK(NULL,       "ssi_fck",      &ssi_ssr_sst_fck, CK_242X),
index bba0183..0c79d39 100644 (file)
@@ -1894,10 +1894,10 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "mdm_ick",      &mdm_ick,       CK_243X),
        CLK(NULL,       "mdm_osc_ck",   &mdm_osc_ck,    CK_243X),
        /* DSS domain clocks */
-       CLK("omapdss",  "ick",          &dss_ick,       CK_243X),
-       CLK("omapdss",  "dss1_fck",     &dss1_fck,      CK_243X),
-       CLK("omapdss",  "dss2_fck",     &dss2_fck,      CK_243X),
-       CLK("omapdss",  "tv_fck",       &dss_54m_fck,   CK_243X),
+       CLK("omapdss_dss",      "ick",          &dss_ick,       CK_243X),
+       CLK("omapdss_dss",      "fck",          &dss1_fck,      CK_243X),
+       CLK("omapdss_dss",      "sys_clk",      &dss2_fck,      CK_243X),
+       CLK("omapdss_dss",      "tv_clk",       &dss_54m_fck,   CK_243X),
        /* L3 domain clocks */
        CLK(NULL,       "core_l3_ck",   &core_l3_ck,    CK_243X),
        CLK(NULL,       "ssi_fck",      &ssi_ssr_sst_fck, CK_243X),
index fcb321a..75b119b 100644 (file)
@@ -3356,13 +3356,13 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("omap_rng", "ick",          &rng_ick,       CK_34XX | CK_36XX),
        CLK(NULL,       "sha11_ick",    &sha11_ick,     CK_34XX | CK_36XX),
        CLK(NULL,       "des1_ick",     &des1_ick,      CK_34XX | CK_36XX),
-       CLK("omapdss",  "dss1_fck",     &dss1_alwon_fck_3430es1, CK_3430ES1),
-       CLK("omapdss",  "dss1_fck",     &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-       CLK("omapdss",  "tv_fck",       &dss_tv_fck,    CK_3XXX),
-       CLK("omapdss",  "video_fck",    &dss_96m_fck,   CK_3XXX),
-       CLK("omapdss",  "dss2_fck",     &dss2_alwon_fck, CK_3XXX),
-       CLK("omapdss",  "ick",          &dss_ick_3430es1,       CK_3430ES1),
-       CLK("omapdss",  "ick",          &dss_ick_3430es2,       CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK("omapdss_dss",      "fck",          &dss1_alwon_fck_3430es1, CK_3430ES1),
+       CLK("omapdss_dss",      "fck",          &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK("omapdss_dss",      "tv_clk",       &dss_tv_fck,    CK_3XXX),
+       CLK("omapdss_dss",      "video_clk",    &dss_96m_fck,   CK_3XXX),
+       CLK("omapdss_dss",      "sys_clk",      &dss2_alwon_fck, CK_3XXX),
+       CLK("omapdss_dss",      "ick",          &dss_ick_3430es1,       CK_3430ES1),
+       CLK("omapdss_dss",      "ick",          &dss_ick_3430es2,       CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "cam_mclk",     &cam_mclk,      CK_34XX | CK_36XX),
        CLK(NULL,       "cam_ick",      &cam_ick,       CK_34XX | CK_36XX),
        CLK(NULL,       "csi2_96m_fck", &csi2_96m_fck,  CK_34XX | CK_36XX),
index d32ed97..276992d 100644 (file)
@@ -3114,11 +3114,16 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "dmic_sync_mux_ck",             &dmic_sync_mux_ck,      CK_443X),
        CLK(NULL,       "dmic_fck",                     &dmic_fck,      CK_443X),
        CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
-       CLK(NULL,       "dss_sys_clk",                  &dss_sys_clk,   CK_443X),
-       CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk,    CK_443X),
-       CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk,   CK_443X),
-       CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk, CK_443X),
-       CLK(NULL,       "dss_fck",                      &dss_fck,       CK_443X),
+       CLK("omapdss_dss",      "sys_clk",                      &dss_sys_clk,   CK_443X),
+       CLK("omapdss_dss",      "tv_clk",                       &dss_tv_clk,    CK_443X),
+       CLK("omapdss_dss",      "dss_clk",                      &dss_dss_clk,   CK_443X),
+       CLK("omapdss_dss",      "video_clk",                    &dss_48mhz_clk, CK_443X),
+       CLK("omapdss_dss",      "fck",                          &dss_fck,       CK_443X),
+       /*
+        * On OMAP4, DSS ick is a dummy clock; this is needed for compatibility
+        * with OMAP2/3.
+        */
+       CLK("omapdss_dss",      "ick",                          &dummy_ck,      CK_443X),
        CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
        CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
        CLK(NULL,       "emif2_fck",                    &emif2_fck,     CK_443X),
index b18db84..256d23f 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/err.h>
 
 #include <plat/display.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
@@ -32,9 +34,87 @@ static struct platform_device omap_display_device = {
        },
 };
 
+static struct omap_device_pm_latency omap_dss_latency[] = {
+       [0] = {
+               .deactivate_func        = omap_device_idle_hwmods,
+               .activate_func          = omap_device_enable_hwmods,
+               .flags                  = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+/* oh_core is used for getting opt-clocks */
+static struct omap_hwmod       *oh_core;
+
+static bool opt_clock_available(const char *clk_role)
+{
+       int i;
+
+       for (i = 0; i < oh_core->opt_clks_cnt; i++) {
+               if (!strcmp(oh_core->opt_clks[i].role, clk_role))
+                       return true;
+       }
+       return false;
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
        int r = 0;
+       struct omap_hwmod *oh;
+       struct omap_device *od;
+       int i;
+       struct omap_display_platform_data pdata;
+
+       /*
+        * omap: valid DSS hwmod names
+        * omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc
+        * omap3,4: dss_dsi1
+        * omap4: dss_dsi2, dss_hdmi
+        */
+       char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc",
+               "dss_dsi1", "dss_dsi2", "dss_hdmi" };
+       char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi",
+               "omapdss_venc", "omapdss_dsi1", "omapdss_dsi2",
+               "omapdss_hdmi" };
+       int oh_count;
+
+       memset(&pdata, 0, sizeof(pdata));
+
+       if (cpu_is_omap24xx())
+               oh_count = ARRAY_SIZE(oh_name) - 3;
+               /* last 3 hwmod dev in oh_name are not available for omap2 */
+       else if (cpu_is_omap44xx())
+               oh_count = ARRAY_SIZE(oh_name);
+       else
+               oh_count = ARRAY_SIZE(oh_name) - 2;
+               /* last 2 hwmod dev in oh_name are not available for omap3 */
+
+       /* opt_clks are always associated with dss hwmod */
+       oh_core = omap_hwmod_lookup("dss_core");
+       if (!oh_core) {
+               pr_err("Could not look up dss_core.\n");
+               return -ENODEV;
+       }
+
+       pdata.board_data = board_data;
+       pdata.board_data->get_last_off_on_transaction_id = NULL;
+       pdata.opt_clock_available = opt_clock_available;
+
+       for (i = 0; i < oh_count; i++) {
+               oh = omap_hwmod_lookup(oh_name[i]);
+               if (!oh) {
+                       pr_err("Could not look up %s\n", oh_name[i]);
+                       return -ENODEV;
+               }
+
+               od = omap_device_build(dev_name[i], -1, oh, &pdata,
+                               sizeof(struct omap_display_platform_data),
+                               omap_dss_latency,
+                               ARRAY_SIZE(omap_dss_latency), 0);
+
+               if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+                               oh_name[i]))
+                       return -ENODEV;
+       }
        omap_display_device.dev.platform_data = board_data;
 
        r = platform_device_register(&omap_display_device);
index 6282346..8eb3ce1 100644 (file)
@@ -1168,11 +1168,6 @@ static struct omap_hwmod_class omap2420_dss_hwmod_class = {
        .sysc = &omap2420_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap2420_dss_irqs[] = {
-       { .irq = 25 },
-};
-
 static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
        { .name = "dispc", .dma_req = 5 },
 };
@@ -1221,8 +1216,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
        .name           = "dss_core",
        .class          = &omap2420_dss_hwmod_class,
        .main_clk       = "dss1_fck", /* instead of dss_fck */
-       .mpu_irqs       = omap2420_dss_irqs,
-       .mpu_irqs_cnt   = ARRAY_SIZE(omap2420_dss_irqs),
        .sdma_reqs      = omap2420_dss_sdma_chs,
        .sdma_reqs_cnt  = ARRAY_SIZE(omap2420_dss_sdma_chs),
        .prcm           = {
@@ -1265,6 +1258,10 @@ static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
        .sysc = &omap2420_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = {
+       { .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
        {
                .pa_start       = 0x48050400,
@@ -1297,6 +1294,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
 static struct omap_hwmod omap2420_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap2420_dispc_hwmod_class,
+       .mpu_irqs       = omap2420_dispc_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap2420_dispc_irqs),
        .main_clk       = "dss1_fck",
        .prcm           = {
                .omap2 = {
index 0fdf2ca..a860fb5 100644 (file)
@@ -1268,10 +1268,6 @@ static struct omap_hwmod_class omap2430_dss_hwmod_class = {
        .sysc = &omap2430_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap2430_dss_irqs[] = {
-       { .irq = 25 },
-};
 static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
        { .name = "dispc", .dma_req = 5 },
 };
@@ -1314,8 +1310,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
        .name           = "dss_core",
        .class          = &omap2430_dss_hwmod_class,
        .main_clk       = "dss1_fck", /* instead of dss_fck */
-       .mpu_irqs       = omap2430_dss_irqs,
-       .mpu_irqs_cnt   = ARRAY_SIZE(omap2430_dss_irqs),
        .sdma_reqs      = omap2430_dss_sdma_chs,
        .sdma_reqs_cnt  = ARRAY_SIZE(omap2430_dss_sdma_chs),
        .prcm           = {
@@ -1358,6 +1352,10 @@ static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
        .sysc = &omap2430_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = {
+       { .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
        {
                .pa_start       = 0x48050400,
@@ -1384,6 +1382,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
 static struct omap_hwmod omap2430_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap2430_dispc_hwmod_class,
+       .mpu_irqs       = omap2430_dispc_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap2430_dispc_irqs),
        .main_clk       = "dss1_fck",
        .prcm           = {
                .omap2 = {
index c819c30..b98e2df 100644 (file)
@@ -1480,11 +1480,6 @@ static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
        .sysc = &omap3xxx_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = {
-       { .irq = 25 },
-};
-
 static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
        { .name = "dispc", .dma_req = 5 },
        { .name = "dsi1", .dma_req = 74 },
@@ -1548,7 +1543,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
        { .role = "tv_clk", .clk = "dss_tv_fck" },
-       { .role = "dssclk", .clk = "dss_96m_fck" },
+       { .role = "video_clk", .clk = "dss_96m_fck" },
        { .role = "sys_clk", .clk = "dss2_alwon_fck" },
 };
 
@@ -1556,8 +1551,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
        .name           = "dss_core",
        .class          = &omap3xxx_dss_hwmod_class,
        .main_clk       = "dss1_alwon_fck", /* instead of dss_fck */
-       .mpu_irqs       = omap3xxx_dss_irqs,
-       .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_dss_irqs),
        .sdma_reqs      = omap3xxx_dss_sdma_chs,
        .sdma_reqs_cnt  = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
 
@@ -1584,8 +1577,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
        .name           = "dss_core",
        .class          = &omap3xxx_dss_hwmod_class,
        .main_clk       = "dss1_alwon_fck", /* instead of dss_fck */
-       .mpu_irqs       = omap3xxx_dss_irqs,
-       .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_dss_irqs),
        .sdma_reqs      = omap3xxx_dss_sdma_chs,
        .sdma_reqs_cnt  = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
 
@@ -1631,6 +1622,10 @@ static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
        .sysc = &omap3xxx_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = {
+       { .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
        {
                .pa_start       = 0x48050400,
@@ -1664,6 +1659,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap3xxx_dispc_hwmod_class,
+       .mpu_irqs       = omap3xxx_dispc_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_dispc_irqs),
        .main_clk       = "dss1_alwon_fck",
        .prcm           = {
                .omap2 = {
@@ -1689,6 +1686,10 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
        .name = "dsi",
 };
 
+static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
+       { .irq = 25 },
+};
+
 /* dss_dsi1 */
 static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
        {
@@ -1722,6 +1723,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
        .name           = "dss_dsi1",
        .class          = &omap3xxx_dsi_hwmod_class,
+       .mpu_irqs       = omap3xxx_dsi1_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_dsi1_irqs),
        .main_clk       = "dss1_alwon_fck",
        .prcm           = {
                .omap2 = {
index 0f140ec..5e04ddc 100644 (file)
@@ -58,6 +58,7 @@ enum omap_display_type {
        OMAP_DISPLAY_TYPE_SDI           = 1 << 2,
        OMAP_DISPLAY_TYPE_DSI           = 1 << 3,
        OMAP_DISPLAY_TYPE_VENC          = 1 << 4,
+       OMAP_DISPLAY_TYPE_HDMI          = 1 << 5,
 };
 
 enum omap_plane {
@@ -237,6 +238,13 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data)
 }
 #endif
 
+struct omap_display_platform_data {
+       struct omap_dss_board_info *board_data;
+       /* TODO: Additional members to be added when PM is considered */
+
+       bool (*opt_clock_available)(const char *clk_role);
+};
+
 struct omap_video_timings {
        /* Unit: pixels */
        u16 x_res;
@@ -396,8 +404,8 @@ struct omap_dss_device {
                        struct {
                                u16 regn;
                                u16 regm;
-                               u16 regm3;
-                               u16 regm4;
+                               u16 regm_dispc;
+                               u16 regm_dsi;
 
                                u16 lp_clk_div;
 
@@ -555,6 +563,9 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
                int channel,
                u16 x, u16 y, u16 w, u16 h,
                void (*callback)(int, void *), void *data);
+int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
+int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
+void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
index 083c8fe..15e7f19 100644 (file)
@@ -5,13 +5,18 @@ config FB_OMAP
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select TWL4030_CORE if MACH_OMAP_2430SDP
        help
           Frame buffer driver for OMAP based boards.
 
 config FB_OMAP_LCD_VGA
         bool "Use LCD in VGA mode"
                depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
-
+               help
+                 Set LCD resolution as VGA (640 X 480).
+                 Default resolution without this option is QVGA(320 X 240).
+                 Please take a look at drivers/video/omap/lcd_ldp.c file
+                 for lcd driver code.
 choice
        depends on FB_OMAP && MACH_OVERO
        prompt "Screen resolution"
index 940cab3..d18ad6b 100644 (file)
@@ -9,6 +9,12 @@ config PANEL_GENERIC_DPI
          Supports LCD Panel used in TI SDP3430 and EVM boards,
          OMAP3517 EVM boards and CM-T35.
 
+config PANEL_LGPHILIPS_LB035Q02
+       tristate "LG.Philips LB035Q02 LCD Panel"
+       depends on OMAP2_DSS && SPI
+       help
+         LCD Panel used on the Gumstix Overo Palo35
+
 config PANEL_SHARP_LS037V7DW01
         tristate "Sharp LS037V7DW01 LCD Panel"
         depends on OMAP2_DSS
index 861f025..0f601ab 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
+obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
 obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
 
index 07eb30e..4a9b9ff 100644 (file)
@@ -156,6 +156,31 @@ static struct panel_config generic_dpi_panels[] = {
                .power_off_delay        = 0,
                .name                   = "toppoly_tdo35s",
        },
+
+       /* Samsung LTE430WQ-F0C */
+       {
+               {
+                       .x_res          = 480,
+                       .y_res          = 272,
+
+                       .pixel_clock    = 9200,
+
+                       .hfp            = 8,
+                       .hsw            = 41,
+                       .hbp            = 45 - 41,
+
+                       .vfp            = 4,
+                       .vsw            = 10,
+                       .vbp            = 12 - 10,
+               },
+               .acbi                   = 0x0,
+               .acb                    = 0x0,
+               .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+                                               OMAP_DSS_LCD_IHS,
+               .power_on_delay         = 0,
+               .power_off_delay        = 0,
+               .name                   = "samsung_lte430wq_f0c",
+       },
 };
 
 struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
new file mode 100644 (file)
index 0000000..271324d
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * LCD panel driver for LG.Philips LB035Q02
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/mutex.h>
+
+#include <plat/display.h>
+
+struct lb035q02_data {
+       struct mutex lock;
+};
+
+static struct omap_video_timings lb035q02_timings = {
+       .x_res = 320,
+       .y_res = 240,
+
+       .pixel_clock    = 6500,
+
+       .hsw            = 2,
+       .hfp            = 20,
+       .hbp            = 68,
+
+       .vsw            = 2,
+       .vfp            = 4,
+       .vbp            = 18,
+};
+
+static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
+{
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld;
+       int r;
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+               OMAP_DSS_LCD_IHS;
+       dssdev->panel.timings = lb035q02_timings;
+
+       ld = kzalloc(sizeof(*ld), GFP_KERNEL);
+       if (!ld) {
+               r = -ENOMEM;
+               goto err;
+       }
+       mutex_init(&ld->lock);
+       dev_set_drvdata(&dssdev->dev, ld);
+       return 0;
+err:
+       return r;
+}
+
+static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
+
+       kfree(ld);
+}
+
+static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&ld->lock);
+
+       r = lb035q02_panel_power_on(dssdev);
+       if (r)
+               goto err;
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ld->lock);
+       return 0;
+err:
+       mutex_unlock(&ld->lock);
+       return r;
+}
+
+static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ld->lock);
+
+       lb035q02_panel_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&ld->lock);
+}
+
+static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ld->lock);
+
+       lb035q02_panel_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+       mutex_unlock(&ld->lock);
+       return 0;
+}
+
+static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
+{
+       struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&ld->lock);
+
+       r = lb035q02_panel_power_on(dssdev);
+       if (r)
+               goto err;
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ld->lock);
+       return 0;
+err:
+       mutex_unlock(&ld->lock);
+       return r;
+}
+
+static struct omap_dss_driver lb035q02_driver = {
+       .probe          = lb035q02_panel_probe,
+       .remove         = lb035q02_panel_remove,
+
+       .enable         = lb035q02_panel_enable,
+       .disable        = lb035q02_panel_disable,
+       .suspend        = lb035q02_panel_suspend,
+       .resume         = lb035q02_panel_resume,
+
+       .driver         = {
+               .name   = "lgphilips_lb035q02_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
+{
+       struct spi_message msg;
+       struct spi_transfer index_xfer = {
+               .len            = 3,
+               .cs_change      = 1,
+       };
+       struct spi_transfer value_xfer = {
+               .len            = 3,
+       };
+       u8      buffer[16];
+
+       spi_message_init(&msg);
+
+       /* register index */
+       buffer[0] = 0x70;
+       buffer[1] = 0x00;
+       buffer[2] = reg & 0x7f;
+       index_xfer.tx_buf = buffer;
+       spi_message_add_tail(&index_xfer, &msg);
+
+       /* register value */
+       buffer[4] = 0x72;
+       buffer[5] = val >> 8;
+       buffer[6] = val;
+       value_xfer.tx_buf = buffer + 4;
+       spi_message_add_tail(&value_xfer, &msg);
+
+       return spi_sync(spi, &msg);
+}
+
+static void init_lb035q02_panel(struct spi_device *spi)
+{
+       /* Init sequence from page 28 of the lb035q02 spec */
+       lb035q02_write_reg(spi, 0x01, 0x6300);
+       lb035q02_write_reg(spi, 0x02, 0x0200);
+       lb035q02_write_reg(spi, 0x03, 0x0177);
+       lb035q02_write_reg(spi, 0x04, 0x04c7);
+       lb035q02_write_reg(spi, 0x05, 0xffc0);
+       lb035q02_write_reg(spi, 0x06, 0xe806);
+       lb035q02_write_reg(spi, 0x0a, 0x4008);
+       lb035q02_write_reg(spi, 0x0b, 0x0000);
+       lb035q02_write_reg(spi, 0x0d, 0x0030);
+       lb035q02_write_reg(spi, 0x0e, 0x2800);
+       lb035q02_write_reg(spi, 0x0f, 0x0000);
+       lb035q02_write_reg(spi, 0x16, 0x9f80);
+       lb035q02_write_reg(spi, 0x17, 0x0a0f);
+       lb035q02_write_reg(spi, 0x1e, 0x00c1);
+       lb035q02_write_reg(spi, 0x30, 0x0300);
+       lb035q02_write_reg(spi, 0x31, 0x0007);
+       lb035q02_write_reg(spi, 0x32, 0x0000);
+       lb035q02_write_reg(spi, 0x33, 0x0000);
+       lb035q02_write_reg(spi, 0x34, 0x0707);
+       lb035q02_write_reg(spi, 0x35, 0x0004);
+       lb035q02_write_reg(spi, 0x36, 0x0302);
+       lb035q02_write_reg(spi, 0x37, 0x0202);
+       lb035q02_write_reg(spi, 0x3a, 0x0a0d);
+       lb035q02_write_reg(spi, 0x3b, 0x0806);
+}
+
+static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi)
+{
+       init_lb035q02_panel(spi);
+       return omap_dss_register_driver(&lb035q02_driver);
+}
+
+static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi)
+{
+       omap_dss_unregister_driver(&lb035q02_driver);
+       return 0;
+}
+
+static struct spi_driver lb035q02_spi_driver = {
+       .driver         = {
+               .name   = "lgphilips_lb035q02_panel-spi",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = lb035q02_panel_spi_probe,
+       .remove         = __devexit_p(lb035q02_panel_spi_remove),
+};
+
+static int __init lb035q02_panel_drv_init(void)
+{
+       return spi_register_driver(&lb035q02_spi_driver);
+}
+
+static void __exit lb035q02_panel_drv_exit(void)
+{
+       spi_unregister_driver(&lb035q02_spi_driver);
+}
+
+module_init(lb035q02_panel_drv_init);
+module_exit(lb035q02_panel_drv_exit);
+MODULE_LICENSE("GPL");
index 61026f9..abdfdd8 100644 (file)
@@ -218,6 +218,8 @@ struct taal_data {
                u16 w;
                u16 h;
        } update_region;
+       int channel;
+
        struct delayed_work te_timeout_work;
 
        bool use_dsi_bl;
@@ -257,12 +259,12 @@ static void hw_guard_wait(struct taal_data *td)
        }
 }
 
-static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
+static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data)
 {
        int r;
        u8 buf[1];
 
-       r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
+       r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1);
 
        if (r < 0)
                return r;
@@ -272,17 +274,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
        return 0;
 }
 
-static int taal_dcs_write_0(u8 dcs_cmd)
+static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd)
 {
-       return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
+       return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1);
 }
 
-static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
+static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param)
 {
        u8 buf[2];
        buf[0] = dcs_cmd;
        buf[1] = param;
-       return dsi_vc_dcs_write(TCH, buf, 2);
+       return dsi_vc_dcs_write(td->channel, buf, 2);
 }
 
 static int taal_sleep_in(struct taal_data *td)
@@ -294,7 +296,7 @@ static int taal_sleep_in(struct taal_data *td)
        hw_guard_wait(td);
 
        cmd = DCS_SLEEP_IN;
-       r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
+       r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1);
        if (r)
                return r;
 
@@ -312,7 +314,7 @@ static int taal_sleep_out(struct taal_data *td)
 
        hw_guard_wait(td);
 
-       r = taal_dcs_write_0(DCS_SLEEP_OUT);
+       r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
        if (r)
                return r;
 
@@ -324,30 +326,30 @@ static int taal_sleep_out(struct taal_data *td)
        return 0;
 }
 
-static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
+static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
 {
        int r;
 
-       r = taal_dcs_read_1(DCS_GET_ID1, id1);
+       r = taal_dcs_read_1(td, DCS_GET_ID1, id1);
        if (r)
                return r;
-       r = taal_dcs_read_1(DCS_GET_ID2, id2);
+       r = taal_dcs_read_1(td, DCS_GET_ID2, id2);
        if (r)
                return r;
-       r = taal_dcs_read_1(DCS_GET_ID3, id3);
+       r = taal_dcs_read_1(td, DCS_GET_ID3, id3);
        if (r)
                return r;
 
        return 0;
 }
 
-static int taal_set_addr_mode(u8 rotate, bool mirror)
+static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
 {
        int r;
        u8 mode;
        int b5, b6, b7;
 
-       r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
+       r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
        if (r)
                return r;
 
@@ -381,10 +383,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror)
        mode &= ~((1<<7) | (1<<6) | (1<<5));
        mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
 
-       return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
+       return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
 }
 
-static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
+static int taal_set_update_window(struct taal_data *td,
+               u16 x, u16 y, u16 w, u16 h)
 {
        int r;
        u16 x1 = x;
@@ -399,7 +402,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
        buf[3] = (x2 >> 8) & 0xff;
        buf[4] = (x2 >> 0) & 0xff;
 
-       r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+       r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf));
        if (r)
                return r;
 
@@ -409,11 +412,11 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
        buf[3] = (y2 >> 8) & 0xff;
        buf[4] = (y2 >> 0) & 0xff;
 
-       r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+       r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf));
        if (r)
                return r;
 
-       dsi_vc_send_bta_sync(TCH);
+       dsi_vc_send_bta_sync(td->channel);
 
        return r;
 }
@@ -439,7 +442,7 @@ static int taal_bl_update_status(struct backlight_device *dev)
        if (td->use_dsi_bl) {
                if (td->enabled) {
                        dsi_bus_lock();
-                       r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
+                       r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
                        dsi_bus_unlock();
                } else {
                        r = 0;
@@ -502,7 +505,7 @@ static ssize_t taal_num_errors_show(struct device *dev,
 
        if (td->enabled) {
                dsi_bus_lock();
-               r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
+               r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
                dsi_bus_unlock();
        } else {
                r = -ENODEV;
@@ -528,7 +531,7 @@ static ssize_t taal_hw_revision_show(struct device *dev,
 
        if (td->enabled) {
                dsi_bus_lock();
-               r = taal_get_id(&id1, &id2, &id3);
+               r = taal_get_id(td, &id1, &id2, &id3);
                dsi_bus_unlock();
        } else {
                r = -ENODEV;
@@ -590,7 +593,7 @@ static ssize_t store_cabc_mode(struct device *dev,
        if (td->enabled) {
                dsi_bus_lock();
                if (!td->cabc_broken)
-                       taal_dcs_write_1(DCS_WRITE_CABC, i);
+                       taal_dcs_write_1(td, DCS_WRITE_CABC, i);
                dsi_bus_unlock();
        }
 
@@ -774,14 +777,29 @@ static int taal_probe(struct omap_dss_device *dssdev)
                dev_dbg(&dssdev->dev, "Using GPIO TE\n");
        }
 
+       r = omap_dsi_request_vc(dssdev, &td->channel);
+       if (r) {
+               dev_err(&dssdev->dev, "failed to get virtual channel\n");
+               goto err_req_vc;
+       }
+
+       r = omap_dsi_set_vc_id(dssdev, td->channel, TCH);
+       if (r) {
+               dev_err(&dssdev->dev, "failed to set VC_ID\n");
+               goto err_vc_id;
+       }
+
        r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
        if (r) {
                dev_err(&dssdev->dev, "failed to create sysfs files\n");
-               goto err_sysfs;
+               goto err_vc_id;
        }
 
        return 0;
-err_sysfs:
+
+err_vc_id:
+       omap_dsi_release_vc(dssdev, td->channel);
+err_req_vc:
        if (panel_data->use_ext_te)
                free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
 err_irq:
@@ -808,6 +826,7 @@ static void taal_remove(struct omap_dss_device *dssdev)
        dev_dbg(&dssdev->dev, "remove\n");
 
        sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
+       omap_dsi_release_vc(dssdev, td->channel);
 
        if (panel_data->use_ext_te) {
                int gpio = panel_data->ext_te_gpio;
@@ -846,13 +865,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 
        taal_hw_reset(dssdev);
 
-       omapdss_dsi_vc_enable_hs(TCH, false);
+       omapdss_dsi_vc_enable_hs(td->channel, false);
 
        r = taal_sleep_out(td);
        if (r)
                goto err;
 
-       r = taal_get_id(&id1, &id2, &id3);
+       r = taal_get_id(td, &id1, &id2, &id3);
        if (r)
                goto err;
 
@@ -861,30 +880,30 @@ static int taal_power_on(struct omap_dss_device *dssdev)
                (id2 == 0x00 || id2 == 0xff || id2 == 0x81))
                td->cabc_broken = true;
 
-       r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
+       r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
        if (r)
                goto err;
 
-       r = taal_dcs_write_1(DCS_CTRL_DISPLAY,
+       r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY,
                        (1<<2) | (1<<5));       /* BL | BCTRL */
        if (r)
                goto err;
 
-       r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+       r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
        if (r)
                goto err;
 
-       r = taal_set_addr_mode(td->rotate, td->mirror);
+       r = taal_set_addr_mode(td, td->rotate, td->mirror);
        if (r)
                goto err;
 
        if (!td->cabc_broken) {
-               r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
+               r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
                if (r)
                        goto err;
        }
 
-       r = taal_dcs_write_0(DCS_DISPLAY_ON);
+       r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
        if (r)
                goto err;
 
@@ -903,7 +922,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
                td->intro_printed = true;
        }
 
-       omapdss_dsi_vc_enable_hs(TCH, true);
+       omapdss_dsi_vc_enable_hs(td->channel, true);
 
        return 0;
 err:
@@ -921,7 +940,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
        int r;
 
-       r = taal_dcs_write_0(DCS_DISPLAY_OFF);
+       r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
        if (!r) {
                r = taal_sleep_in(td);
                /* HACK: wait a bit so that the message goes through */
@@ -1089,7 +1108,7 @@ static irqreturn_t taal_te_isr(int irq, void *data)
        if (old) {
                cancel_delayed_work(&td->te_timeout_work);
 
-               r = omap_dsi_update(dssdev, TCH,
+               r = omap_dsi_update(dssdev, td->channel,
                                td->update_region.x,
                                td->update_region.y,
                                td->update_region.w,
@@ -1139,7 +1158,7 @@ static int taal_update(struct omap_dss_device *dssdev,
        if (r)
                goto err;
 
-       r = taal_set_update_window(x, y, w, h);
+       r = taal_set_update_window(td, x, y, w, h);
        if (r)
                goto err;
 
@@ -1153,7 +1172,7 @@ static int taal_update(struct omap_dss_device *dssdev,
                                msecs_to_jiffies(250));
                atomic_set(&td->do_update, 1);
        } else {
-               r = omap_dsi_update(dssdev, TCH, x, y, w, h,
+               r = omap_dsi_update(dssdev, td->channel, x, y, w, h,
                                taal_framedone_cb, dssdev);
                if (r)
                        goto err;
@@ -1191,9 +1210,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
        int r;
 
        if (enable)
-               r = taal_dcs_write_1(DCS_TEAR_ON, 0);
+               r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
        else
-               r = taal_dcs_write_0(DCS_TEAR_OFF);
+               r = taal_dcs_write_0(td, DCS_TEAR_OFF);
 
        if (!panel_data->use_ext_te)
                omapdss_dsi_enable_te(dssdev, enable);
@@ -1263,7 +1282,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
        dsi_bus_lock();
 
        if (td->enabled) {
-               r = taal_set_addr_mode(rotate, td->mirror);
+               r = taal_set_addr_mode(td, rotate, td->mirror);
                if (r)
                        goto err;
        }
@@ -1306,7 +1325,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
 
        dsi_bus_lock();
        if (td->enabled) {
-               r = taal_set_addr_mode(td->rotate, enable);
+               r = taal_set_addr_mode(td, td->rotate, enable);
                if (r)
                        goto err;
        }
@@ -1350,13 +1369,13 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
 
        dsi_bus_lock();
 
-       r = taal_dcs_read_1(DCS_GET_ID1, &id1);
+       r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
        if (r)
                goto err2;
-       r = taal_dcs_read_1(DCS_GET_ID2, &id2);
+       r = taal_dcs_read_1(td, DCS_GET_ID2, &id2);
        if (r)
                goto err2;
-       r = taal_dcs_read_1(DCS_GET_ID3, &id3);
+       r = taal_dcs_read_1(td, DCS_GET_ID3, &id3);
        if (r)
                goto err2;
 
@@ -1404,9 +1423,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
        else
                plen = 2;
 
-       taal_set_update_window(x, y, w, h);
+       taal_set_update_window(td, x, y, w, h);
 
-       r = dsi_vc_set_max_rx_packet_size(TCH, plen);
+       r = dsi_vc_set_max_rx_packet_size(td->channel, plen);
        if (r)
                goto err2;
 
@@ -1414,7 +1433,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
                u8 dcs_cmd = first ? 0x2e : 0x3e;
                first = 0;
 
-               r = dsi_vc_dcs_read(TCH, dcs_cmd,
+               r = dsi_vc_dcs_read(td->channel, dcs_cmd,
                                buf + buf_used, size - buf_used);
 
                if (r < 0) {
@@ -1440,7 +1459,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
        r = buf_used;
 
 err3:
-       dsi_vc_set_max_rx_packet_size(TCH, 1);
+       dsi_vc_set_max_rx_packet_size(td->channel, 1);
 err2:
        dsi_bus_unlock();
 err1:
@@ -1466,7 +1485,7 @@ static void taal_esd_work(struct work_struct *work)
 
        dsi_bus_lock();
 
-       r = taal_dcs_read_1(DCS_RDDSDR, &state1);
+       r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
        if (r) {
                dev_err(&dssdev->dev, "failed to read Taal status\n");
                goto err;
@@ -1479,7 +1498,7 @@ static void taal_esd_work(struct work_struct *work)
                goto err;
        }
 
-       r = taal_dcs_read_1(DCS_RDDSDR, &state2);
+       r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
        if (r) {
                dev_err(&dssdev->dev, "failed to read Taal status\n");
                goto err;
@@ -1495,7 +1514,7 @@ static void taal_esd_work(struct work_struct *work)
        /* Self-diagnostics result is also shown on TE GPIO line. We need
         * to re-enable TE after self diagnostics */
        if (td->te_enabled && panel_data->use_ext_te) {
-               r = taal_dcs_write_1(DCS_TEAR_ON, 0);
+               r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
                if (r)
                        goto err;
        }
index 43b6440..bfc5da0 100644 (file)
@@ -1,8 +1,8 @@
 menuconfig OMAP2_DSS
-        tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
-        depends on ARCH_OMAP2 || ARCH_OMAP3
+        tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
+        depends on ARCH_OMAP2PLUS
         help
-          OMAP2/3 Display Subsystem support.
+         OMAP2+ Display Subsystem support.
 
 if OMAP2_DSS
 
@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC
        help
          OMAP Video Encoder support for S-Video and composite TV-out.
 
+config OMAP4_DSS_HDMI
+       bool "HDMI support"
+       depends on ARCH_OMAP4
+        default y
+       help
+         HDMI Interface. This adds the High Definition Multimedia Interface.
+         See http://www.hdmi.org/ for HDMI specification.
+
 config OMAP2_DSS_SDI
        bool "SDI support"
        depends on ARCH_OMAP3
index 7db17b5..10d9d3b 100644 (file)
@@ -5,3 +5,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
 omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
+omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
+                                   hdmi_omap4_panel.o
index 8e89f60..1aa2ed1 100644 (file)
 #include <linux/regulator/consumer.h>
 
 #include <plat/display.h>
-#include <plat/clock.h>
 
 #include "dss.h"
 #include "dss_features.h"
 
 static struct {
        struct platform_device *pdev;
-       int             ctx_id;
-
-       struct clk      *dss_ick;
-       struct clk      *dss1_fck;
-       struct clk      *dss2_fck;
-       struct clk      *dss_54m_fck;
-       struct clk      *dss_96m_fck;
-       unsigned        num_clks_enabled;
 
        struct regulator *vdds_dsi_reg;
        struct regulator *vdds_sdi_reg;
-       struct regulator *vdda_dac_reg;
 } core;
 
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
 static char *def_disp_name;
 module_param_named(def_disp, def_disp_name, charp, 0);
-MODULE_PARM_DESC(def_disp_name, "default display name");
+MODULE_PARM_DESC(def_disp, "default display name");
 
 #ifdef DEBUG
 unsigned int dss_debug;
 module_param_named(debug, dss_debug, bool, 0644);
 #endif
 
-/* CONTEXT */
-static int dss_get_ctx_id(void)
-{
-       struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
-       int r;
-
-       if (!pdata->get_last_off_on_transaction_id)
-               return 0;
-       r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
-       if (r < 0) {
-               dev_err(&core.pdev->dev, "getting transaction ID failed, "
-                               "will force context restore\n");
-               r = -1;
-       }
-       return r;
-}
-
-int dss_need_ctx_restore(void)
-{
-       int id = dss_get_ctx_id();
-
-       if (id < 0 || id != core.ctx_id) {
-               DSSDBG("ctx id %d -> id %d\n",
-                               core.ctx_id, id);
-               core.ctx_id = id;
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
-static void save_all_ctx(void)
-{
-       DSSDBG("save context\n");
-
-       dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       dss_save_context();
-       dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_save_context();
-#endif
-
-       dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
-}
-
-static void restore_all_ctx(void)
-{
-       DSSDBG("restore context\n");
-
-       dss_clk_enable_all_no_ctx();
-
-       dss_restore_context();
-       dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_restore_context();
-#endif
-
-       dss_clk_disable_all_no_ctx();
-}
-
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
-       int i;
-       struct clk *clocks[5] = {
-               core.dss_ick,
-               core.dss1_fck,
-               core.dss2_fck,
-               core.dss_54m_fck,
-               core.dss_96m_fck
-       };
-
-       seq_printf(s, "- CORE -\n");
-
-       seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
-
-       for (i = 0; i < 5; i++) {
-               if (!clocks[i])
-                       continue;
-               seq_printf(s, "%-15s\t%lu\t%d\n",
-                               clocks[i]->name,
-                               clk_get_rate(clocks[i]),
-                               clocks[i]->usecount);
-       }
-}
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
-       struct clk *clk;
-
-       clk = clk_get(&core.pdev->dev, clk_name);
-
-       if (IS_ERR(clk)) {
-               DSSERR("can't get clock %s", clk_name);
-               return PTR_ERR(clk);
-       }
-
-       *clock = clk;
-
-       DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
-       return 0;
-}
-
-static int dss_get_clocks(void)
-{
-       int r;
-
-       core.dss_ick = NULL;
-       core.dss1_fck = NULL;
-       core.dss2_fck = NULL;
-       core.dss_54m_fck = NULL;
-       core.dss_96m_fck = NULL;
-
-       r = dss_get_clock(&core.dss_ick, "ick");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&core.dss1_fck, "dss1_fck");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&core.dss2_fck, "dss2_fck");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&core.dss_96m_fck, "video_fck");
-       if (r)
-               goto err;
-
-       return 0;
-
-err:
-       if (core.dss_ick)
-               clk_put(core.dss_ick);
-       if (core.dss1_fck)
-               clk_put(core.dss1_fck);
-       if (core.dss2_fck)
-               clk_put(core.dss2_fck);
-       if (core.dss_54m_fck)
-               clk_put(core.dss_54m_fck);
-       if (core.dss_96m_fck)
-               clk_put(core.dss_96m_fck);
-
-       return r;
-}
-
-static void dss_put_clocks(void)
-{
-       if (core.dss_96m_fck)
-               clk_put(core.dss_96m_fck);
-       clk_put(core.dss_54m_fck);
-       clk_put(core.dss1_fck);
-       clk_put(core.dss2_fck);
-       clk_put(core.dss_ick);
-}
-
-unsigned long dss_clk_get_rate(enum dss_clock clk)
-{
-       switch (clk) {
-       case DSS_CLK_ICK:
-               return clk_get_rate(core.dss_ick);
-       case DSS_CLK_FCK1:
-               return clk_get_rate(core.dss1_fck);
-       case DSS_CLK_FCK2:
-               return clk_get_rate(core.dss2_fck);
-       case DSS_CLK_54M:
-               return clk_get_rate(core.dss_54m_fck);
-       case DSS_CLK_96M:
-               return clk_get_rate(core.dss_96m_fck);
-       }
-
-       BUG();
-       return 0;
-}
-
-static unsigned count_clk_bits(enum dss_clock clks)
-{
-       unsigned num_clks = 0;
-
-       if (clks & DSS_CLK_ICK)
-               ++num_clks;
-       if (clks & DSS_CLK_FCK1)
-               ++num_clks;
-       if (clks & DSS_CLK_FCK2)
-               ++num_clks;
-       if (clks & DSS_CLK_54M)
-               ++num_clks;
-       if (clks & DSS_CLK_96M)
-               ++num_clks;
-
-       return num_clks;
-}
-
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_enable(core.dss_ick);
-       if (clks & DSS_CLK_FCK1)
-               clk_enable(core.dss1_fck);
-       if (clks & DSS_CLK_FCK2)
-               clk_enable(core.dss2_fck);
-       if (clks & DSS_CLK_54M)
-               clk_enable(core.dss_54m_fck);
-       if (clks & DSS_CLK_96M)
-               clk_enable(core.dss_96m_fck);
-
-       core.num_clks_enabled += num_clks;
-}
-
-void dss_clk_enable(enum dss_clock clks)
-{
-       bool check_ctx = core.num_clks_enabled == 0;
-
-       dss_clk_enable_no_ctx(clks);
-
-       if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
-               restore_all_ctx();
-}
-
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
-{
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_disable(core.dss_ick);
-       if (clks & DSS_CLK_FCK1)
-               clk_disable(core.dss1_fck);
-       if (clks & DSS_CLK_FCK2)
-               clk_disable(core.dss2_fck);
-       if (clks & DSS_CLK_54M)
-               clk_disable(core.dss_54m_fck);
-       if (clks & DSS_CLK_96M)
-               clk_disable(core.dss_96m_fck);
-
-       core.num_clks_enabled -= num_clks;
-}
-
-void dss_clk_disable(enum dss_clock clks)
-{
-       if (cpu_is_omap34xx()) {
-               unsigned num_clks = count_clk_bits(clks);
-
-               BUG_ON(core.num_clks_enabled < num_clks);
-
-               if (core.num_clks_enabled == num_clks)
-                       save_all_ctx();
-       }
-
-       dss_clk_disable_no_ctx(clks);
-}
-
-static void dss_clk_enable_all_no_ctx(void)
-{
-       enum dss_clock clks;
-
-       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_96M;
-       dss_clk_enable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all_no_ctx(void)
-{
-       enum dss_clock clks;
-
-       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_96M;
-       dss_clk_disable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all(void)
-{
-       enum dss_clock clks;
-
-       clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_96M;
-       dss_clk_disable(clks);
-}
-
 /* REGULATORS */
 
 struct regulator *dss_get_vdds_dsi(void)
@@ -390,32 +84,7 @@ struct regulator *dss_get_vdds_sdi(void)
        return reg;
 }
 
-struct regulator *dss_get_vdda_dac(void)
-{
-       struct regulator *reg;
-
-       if (core.vdda_dac_reg != NULL)
-               return core.vdda_dac_reg;
-
-       reg = regulator_get(&core.pdev->dev, "vdda_dac");
-       if (!IS_ERR(reg))
-               core.vdda_dac_reg = reg;
-
-       return reg;
-}
-
-/* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-static void dss_debug_dump_clocks(struct seq_file *s)
-{
-       core_dump_clocks(s);
-       dss_dump_clocks(s);
-       dispc_dump_clocks(s);
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_dump_clocks(s);
-#endif
-}
-
 static int dss_debug_show(struct seq_file *s, void *unused)
 {
        void (*func)(struct seq_file *) = s->private;
@@ -497,7 +166,6 @@ static inline void dss_uninitialize_debugfs(void)
 static int omap_dss_probe(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-       int skip_init = 0;
        int r;
        int i;
 
@@ -508,63 +176,43 @@ static int omap_dss_probe(struct platform_device *pdev)
        dss_init_overlay_managers(pdev);
        dss_init_overlays(pdev);
 
-       r = dss_get_clocks();
-       if (r)
-               goto err_clocks;
-
-       dss_clk_enable_all_no_ctx();
-
-       core.ctx_id = dss_get_ctx_id();
-       DSSDBG("initial ctx id %u\n", core.ctx_id);
-
-#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
-       /* DISPC_CONTROL */
-       if (omap_readl(0x48050440) & 1) /* LCD enabled? */
-               skip_init = 1;
-#endif
-
-       r = dss_init(skip_init);
+       r = dss_init_platform_driver();
        if (r) {
-               DSSERR("Failed to initialize DSS\n");
+               DSSERR("Failed to initialize DSS platform driver\n");
                goto err_dss;
        }
 
-       r = rfbi_init();
-       if (r) {
-               DSSERR("Failed to initialize rfbi\n");
-               goto err_rfbi;
-       }
+       /* keep clocks enabled to prevent context saves/restores during init */
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
-       r = dpi_init(pdev);
+       r = rfbi_init_platform_driver();
        if (r) {
-               DSSERR("Failed to initialize dpi\n");
-               goto err_dpi;
+               DSSERR("Failed to initialize rfbi platform driver\n");
+               goto err_rfbi;
        }
 
-       r = dispc_init();
+       r = dispc_init_platform_driver();
        if (r) {
-               DSSERR("Failed to initialize dispc\n");
+               DSSERR("Failed to initialize dispc platform driver\n");
                goto err_dispc;
        }
 
-       r = venc_init(pdev);
+       r = venc_init_platform_driver();
        if (r) {
-               DSSERR("Failed to initialize venc\n");
+               DSSERR("Failed to initialize venc platform driver\n");
                goto err_venc;
        }
 
-       if (cpu_is_omap34xx()) {
-               r = sdi_init(skip_init);
-               if (r) {
-                       DSSERR("Failed to initialize SDI\n");
-                       goto err_sdi;
-               }
+       r = dsi_init_platform_driver();
+       if (r) {
+               DSSERR("Failed to initialize DSI platform driver\n");
+               goto err_dsi;
+       }
 
-               r = dsi_init(pdev);
-               if (r) {
-                       DSSERR("Failed to initialize DSI\n");
-                       goto err_dsi;
-               }
+       r = hdmi_init_platform_driver();
+       if (r) {
+               DSSERR("Failed to initialize hdmi\n");
+               goto err_hdmi;
        }
 
        r = dss_initialize_debugfs();
@@ -589,32 +237,25 @@ static int omap_dss_probe(struct platform_device *pdev)
                        pdata->default_device = dssdev;
        }
 
-       dss_clk_disable_all();
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        return 0;
 
 err_register:
        dss_uninitialize_debugfs();
 err_debugfs:
-       if (cpu_is_omap34xx())
-               dsi_exit();
+       hdmi_uninit_platform_driver();
+err_hdmi:
+       dsi_uninit_platform_driver();
 err_dsi:
-       if (cpu_is_omap34xx())
-               sdi_exit();
-err_sdi:
-       venc_exit();
+       venc_uninit_platform_driver();
 err_venc:
-       dispc_exit();
+       dispc_uninit_platform_driver();
 err_dispc:
-       dpi_exit();
-err_dpi:
-       rfbi_exit();
+       rfbi_uninit_platform_driver();
 err_rfbi:
-       dss_exit();
+       dss_uninit_platform_driver();
 err_dss:
-       dss_clk_disable_all_no_ctx();
-       dss_put_clocks();
-err_clocks:
 
        return r;
 }
@@ -623,61 +264,15 @@ static int omap_dss_remove(struct platform_device *pdev)
 {
        struct omap_dss_board_info *pdata = pdev->dev.platform_data;
        int i;
-       int c;
 
        dss_uninitialize_debugfs();
 
-       venc_exit();
-       dispc_exit();
-       dpi_exit();
-       rfbi_exit();
-       if (cpu_is_omap34xx()) {
-               dsi_exit();
-               sdi_exit();
-       }
-
-       dss_exit();
-
-       /* these should be removed at some point */
-       c = core.dss_ick->usecount;
-       if (c > 0) {
-               DSSERR("warning: dss_ick usecount %d, disabling\n", c);
-               while (c-- > 0)
-                       clk_disable(core.dss_ick);
-       }
-
-       c = core.dss1_fck->usecount;
-       if (c > 0) {
-               DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
-               while (c-- > 0)
-                       clk_disable(core.dss1_fck);
-       }
-
-       c = core.dss2_fck->usecount;
-       if (c > 0) {
-               DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
-               while (c-- > 0)
-                       clk_disable(core.dss2_fck);
-       }
-
-       c = core.dss_54m_fck->usecount;
-       if (c > 0) {
-               DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
-               while (c-- > 0)
-                       clk_disable(core.dss_54m_fck);
-       }
-
-       if (core.dss_96m_fck) {
-               c = core.dss_96m_fck->usecount;
-               if (c > 0) {
-                       DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
-                                       c);
-                       while (c-- > 0)
-                               clk_disable(core.dss_96m_fck);
-               }
-       }
-
-       dss_put_clocks();
+       venc_uninit_platform_driver();
+       dispc_uninit_platform_driver();
+       rfbi_uninit_platform_driver();
+       dsi_uninit_platform_driver();
+       hdmi_uninit_platform_driver();
+       dss_uninit_platform_driver();
 
        dss_uninit_overlays(pdev);
        dss_uninit_overlay_managers(pdev);
@@ -965,11 +560,6 @@ static void __exit omap_dss_exit(void)
                core.vdds_sdi_reg = NULL;
        }
 
-       if (core.vdda_dac_reg != NULL) {
-               regulator_put(core.vdda_dac_reg);
-               core.vdda_dac_reg = NULL;
-       }
-
        platform_driver_unregister(&omap_dss_driver);
 
        omap_dss_bus_unregister();
index 9f8c69f..7804779 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
+#include <linux/interrupt.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -42,8 +43,6 @@
 #include "dss_features.h"
 
 /* DISPC */
-#define DISPC_BASE                     0x48050400
-
 #define DISPC_SZ_REGS                  SZ_4K
 
 struct dispc_reg { u16 idx; };
@@ -74,7 +73,7 @@ struct dispc_reg { u16 idx; };
 #define DISPC_TIMING_H(ch)             DISPC_REG(ch != 2 ? 0x0064 : 0x0400)
 #define DISPC_TIMING_V(ch)             DISPC_REG(ch != 2 ? 0x0068 : 0x0404)
 #define DISPC_POL_FREQ(ch)             DISPC_REG(ch != 2 ? 0x006C : 0x0408)
-#define DISPC_DIVISOR(ch)              DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
+#define DISPC_DIVISORo(ch)             DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
 #define DISPC_GLOBAL_ALPHA             DISPC_REG(0x0074)
 #define DISPC_SIZE_DIG                 DISPC_REG(0x0078)
 #define DISPC_SIZE_LCD(ch)             DISPC_REG(ch != 2 ? 0x007C : 0x03CC)
@@ -129,6 +128,7 @@ struct dispc_reg { u16 idx; };
 
 #define DISPC_VID_PRELOAD(n)           DISPC_REG(0x230 + (n)*0x04)
 
+#define DISPC_DIVISOR                  DISPC_REG(0x0804)
 
 #define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
                                         DISPC_IRQ_OCP_ERR | \
@@ -178,7 +178,9 @@ struct dispc_irq_stats {
 };
 
 static struct {
+       struct platform_device *pdev;
        void __iomem    *base;
+       int irq;
 
        u32     fifo_size[3];
 
@@ -230,7 +232,7 @@ void dispc_save_context(void)
        SR(TIMING_H(0));
        SR(TIMING_V(0));
        SR(POL_FREQ(0));
-       SR(DIVISOR(0));
+       SR(DIVISORo(0));
        SR(GLOBAL_ALPHA);
        SR(SIZE_DIG);
        SR(SIZE_LCD(0));
@@ -242,7 +244,7 @@ void dispc_save_context(void)
                SR(TIMING_H(2));
                SR(TIMING_V(2));
                SR(POL_FREQ(2));
-               SR(DIVISOR(2));
+               SR(DIVISORo(2));
                SR(CONFIG2);
        }
 
@@ -373,6 +375,9 @@ void dispc_save_context(void)
        SR(VID_FIR_COEF_V(1, 7));
 
        SR(VID_PRELOAD(1));
+
+       if (dss_has_feature(FEAT_CORE_CLK_DIV))
+               SR(DIVISOR);
 }
 
 void dispc_restore_context(void)
@@ -389,7 +394,7 @@ void dispc_restore_context(void)
        RR(TIMING_H(0));
        RR(TIMING_V(0));
        RR(POL_FREQ(0));
-       RR(DIVISOR(0));
+       RR(DIVISORo(0));
        RR(GLOBAL_ALPHA);
        RR(SIZE_DIG);
        RR(SIZE_LCD(0));
@@ -400,7 +405,7 @@ void dispc_restore_context(void)
                RR(TIMING_H(2));
                RR(TIMING_V(2));
                RR(POL_FREQ(2));
-               RR(DIVISOR(2));
+               RR(DIVISORo(2));
                RR(CONFIG2);
        }
 
@@ -532,6 +537,9 @@ void dispc_restore_context(void)
 
        RR(VID_PRELOAD(1));
 
+       if (dss_has_feature(FEAT_CORE_CLK_DIV))
+               RR(DIVISOR);
+
        /* enable last, because LCD & DIGIT enable are here */
        RR(CONTROL);
        if (dss_has_feature(FEAT_MGR_LCD2))
@@ -552,9 +560,9 @@ void dispc_restore_context(void)
 static inline void enable_clocks(bool enable)
 {
        if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 }
 
 bool dispc_go_busy(enum omap_channel channel)
@@ -1000,6 +1008,20 @@ void dispc_set_burst_size(enum omap_plane plane,
        enable_clocks(0);
 }
 
+void dispc_enable_gamma_table(bool enable)
+{
+       /*
+        * This is partially implemented to support only disabling of
+        * the gamma table.
+        */
+       if (enable) {
+               DSSWARN("Gamma table enabling for TV not yet supported");
+               return;
+       }
+
+       REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
+}
+
 static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
 {
        u32 val;
@@ -1129,10 +1151,16 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
        u32 val;
        const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
                                      DISPC_VID_ACCU0(1) };
+       u8 hor_start, hor_end, vert_start, vert_end;
 
        BUG_ON(plane == OMAP_DSS_GFX);
 
-       val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+       dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
+       dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
+
+       val = FLD_VAL(vaccu, vert_start, vert_end) |
+                       FLD_VAL(haccu, hor_start, hor_end);
+
        dispc_write_reg(ac0_reg[plane-1], val);
 }
 
@@ -1141,10 +1169,16 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
        u32 val;
        const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
                                      DISPC_VID_ACCU1(1) };
+       u8 hor_start, hor_end, vert_start, vert_end;
 
        BUG_ON(plane == OMAP_DSS_GFX);
 
-       val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+       dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
+       dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
+
+       val = FLD_VAL(vaccu, vert_start, vert_end) |
+                       FLD_VAL(haccu, hor_start, hor_end);
+
        dispc_write_reg(ac1_reg[plane-1], val);
 }
 
@@ -1182,16 +1216,25 @@ static void _dispc_set_scaling(enum omap_plane plane,
        _dispc_set_fir(plane, fir_hinc, fir_vinc);
 
        l = dispc_read_reg(dispc_reg_att[plane]);
-       l &= ~((0x0f << 5) | (0x3 << 21));
 
+       /* RESIZEENABLE and VERTICALTAPS */
+       l &= ~((0x3 << 5) | (0x1 << 21));
        l |= fir_hinc ? (1 << 5) : 0;
        l |= fir_vinc ? (1 << 6) : 0;
+       l |= five_taps ? (1 << 21) : 0;
 
-       l |= hscaleup ? 0 : (1 << 7);
-       l |= vscaleup ? 0 : (1 << 8);
+       /* VRESIZECONF and HRESIZECONF */
+       if (dss_has_feature(FEAT_RESIZECONF)) {
+               l &= ~(0x3 << 7);
+               l |= hscaleup ? 0 : (1 << 7);
+               l |= vscaleup ? 0 : (1 << 8);
+       }
 
-       l |= five_taps ? (1 << 21) : 0;
-       l |= five_taps ? (1 << 22) : 0;
+       /* LINEBUFFERSPLIT */
+       if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
+               l &= ~(0x1 << 22);
+               l |= five_taps ? (1 << 22) : 0;
+       }
 
        dispc_write_reg(dispc_reg_att[plane], l);
 
@@ -1215,9 +1258,11 @@ static void _dispc_set_scaling(enum omap_plane plane,
 static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
                bool mirroring, enum omap_color_mode color_mode)
 {
+       bool row_repeat = false;
+       int vidrot = 0;
+
        if (color_mode == OMAP_DSS_COLOR_YUV2 ||
                        color_mode == OMAP_DSS_COLOR_UYVY) {
-               int vidrot = 0;
 
                if (mirroring) {
                        switch (rotation) {
@@ -1251,16 +1296,15 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
                        }
                }
 
-               REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
-
                if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
-                       REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
+                       row_repeat = true;
                else
-                       REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
-       } else {
-               REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
-               REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
+                       row_repeat = false;
        }
+
+       REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
+       if (dss_has_feature(FEAT_ROWREPEATENABLE))
+               REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18);
 }
 
 static int color_mode_to_bpp(enum omap_color_mode color_mode)
@@ -2293,7 +2337,7 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
        BUG_ON(pck_div < 2);
 
        enable_clocks(1);
-       dispc_write_reg(DISPC_DIVISOR(channel),
+       dispc_write_reg(DISPC_DIVISORo(channel),
                        FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
        enable_clocks(0);
 }
@@ -2302,7 +2346,7 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
                int *pck_div)
 {
        u32 l;
-       l = dispc_read_reg(DISPC_DIVISOR(channel));
+       l = dispc_read_reg(DISPC_DIVISORo(channel));
        *lck_div = FLD_GET(l, 23, 16);
        *pck_div = FLD_GET(l, 7, 0);
 }
@@ -2311,14 +2355,17 @@ unsigned long dispc_fclk_rate(void)
 {
        unsigned long r = 0;
 
-       if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
-               r = dss_clk_get_rate(DSS_CLK_FCK1);
-       else
-#ifdef CONFIG_OMAP2_DSS_DSI
-               r = dsi_get_dsi1_pll_rate();
-#else
-       BUG();
-#endif
+       switch (dss_get_dispc_clk_source()) {
+       case DSS_CLK_SRC_FCK:
+               r = dss_clk_get_rate(DSS_CLK_FCK);
+               break;
+       case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+               r = dsi_get_pll_hsdiv_dispc_rate();
+               break;
+       default:
+               BUG();
+       }
+
        return r;
 }
 
@@ -2328,47 +2375,72 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
        unsigned long r;
        u32 l;
 
-       l = dispc_read_reg(DISPC_DIVISOR(channel));
+       l = dispc_read_reg(DISPC_DIVISORo(channel));
 
        lcd = FLD_GET(l, 23, 16);
 
-       r = dispc_fclk_rate();
+       switch (dss_get_lcd_clk_source(channel)) {
+       case DSS_CLK_SRC_FCK:
+               r = dss_clk_get_rate(DSS_CLK_FCK);
+               break;
+       case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+               r = dsi_get_pll_hsdiv_dispc_rate();
+               break;
+       default:
+               BUG();
+       }
 
        return r / lcd;
 }
 
 unsigned long dispc_pclk_rate(enum omap_channel channel)
 {
-       int lcd, pcd;
+       int pcd;
        unsigned long r;
        u32 l;
 
-       l = dispc_read_reg(DISPC_DIVISOR(channel));
+       l = dispc_read_reg(DISPC_DIVISORo(channel));
 
-       lcd = FLD_GET(l, 23, 16);
        pcd = FLD_GET(l, 7, 0);
 
-       r = dispc_fclk_rate();
+       r = dispc_lclk_rate(channel);
 
-       return r / lcd / pcd;
+       return r / pcd;
 }
 
 void dispc_dump_clocks(struct seq_file *s)
 {
        int lcd, pcd;
+       u32 l;
+       enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
+       enum dss_clk_source lcd_clk_src;
 
        enable_clocks(1);
 
        seq_printf(s, "- DISPC -\n");
 
-       seq_printf(s, "dispc fclk source = %s\n",
-                       dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
-                       "dss1_alwon_fclk" : "dsi1_pll_fclk");
+       seq_printf(s, "dispc fclk source = %s (%s)\n",
+                       dss_get_generic_clk_source_name(dispc_clk_src),
+                       dss_feat_get_clk_source_name(dispc_clk_src));
 
        seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
 
+       if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
+               seq_printf(s, "- DISPC-CORE-CLK -\n");
+               l = dispc_read_reg(DISPC_DIVISOR);
+               lcd = FLD_GET(l, 23, 16);
+
+               seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
+                               (dispc_fclk_rate()/lcd), lcd);
+       }
        seq_printf(s, "- LCD1 -\n");
 
+       lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
+
+       seq_printf(s, "lcd1_clk source = %s (%s)\n",
+               dss_get_generic_clk_source_name(lcd_clk_src),
+               dss_feat_get_clk_source_name(lcd_clk_src));
+
        dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
 
        seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
@@ -2378,6 +2450,12 @@ void dispc_dump_clocks(struct seq_file *s)
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                seq_printf(s, "- LCD2 -\n");
 
+               lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
+
+               seq_printf(s, "lcd2_clk source = %s (%s)\n",
+                       dss_get_generic_clk_source_name(lcd_clk_src),
+                       dss_feat_get_clk_source_name(lcd_clk_src));
+
                dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
 
                seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
@@ -2440,7 +2518,7 @@ void dispc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        DUMPREG(DISPC_REVISION);
        DUMPREG(DISPC_SYSCONFIG);
@@ -2459,7 +2537,7 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_TIMING_H(0));
        DUMPREG(DISPC_TIMING_V(0));
        DUMPREG(DISPC_POL_FREQ(0));
-       DUMPREG(DISPC_DIVISOR(0));
+       DUMPREG(DISPC_DIVISORo(0));
        DUMPREG(DISPC_GLOBAL_ALPHA);
        DUMPREG(DISPC_SIZE_DIG);
        DUMPREG(DISPC_SIZE_LCD(0));
@@ -2471,7 +2549,7 @@ void dispc_dump_regs(struct seq_file *s)
                DUMPREG(DISPC_TIMING_H(2));
                DUMPREG(DISPC_TIMING_V(2));
                DUMPREG(DISPC_POL_FREQ(2));
-               DUMPREG(DISPC_DIVISOR(2));
+               DUMPREG(DISPC_DIVISORo(2));
                DUMPREG(DISPC_SIZE_LCD(2));
        }
 
@@ -2597,7 +2675,7 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_VID_PRELOAD(0));
        DUMPREG(DISPC_VID_PRELOAD(1));
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
 }
 
@@ -2713,8 +2791,8 @@ int dispc_get_clock_div(enum omap_channel channel,
 
        fck = dispc_fclk_rate();
 
-       cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16);
-       cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0);
+       cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
+       cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
 
        cinfo->lck = fck / cinfo->lck_div;
        cinfo->pck = cinfo->lck / cinfo->pck_div;
@@ -2791,6 +2869,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
                break;
        }
 
+       if (ret)
+               goto err;
+
        _omap_dispc_set_irqs();
 
        spin_unlock_irqrestore(&dispc.irq_lock, flags);
@@ -2866,10 +2947,10 @@ static void print_irq_status(u32 status)
  * but we presume they are on because we got an IRQ. However,
  * an irq handler may turn the clocks off, so we may not have
  * clock later in the function. */
-void dispc_irq_handler(void)
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
 {
        int i;
-       u32 irqstatus;
+       u32 irqstatus, irqenable;
        u32 handledirqs = 0;
        u32 unhandled_errors;
        struct omap_dispc_isr_data *isr_data;
@@ -2878,6 +2959,13 @@ void dispc_irq_handler(void)
        spin_lock(&dispc.irq_lock);
 
        irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
+       irqenable = dispc_read_reg(DISPC_IRQENABLE);
+
+       /* IRQ is not for us */
+       if (!(irqstatus & irqenable)) {
+               spin_unlock(&dispc.irq_lock);
+               return IRQ_NONE;
+       }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        spin_lock(&dispc.irq_stats_lock);
@@ -2929,6 +3017,8 @@ void dispc_irq_handler(void)
        }
 
        spin_unlock(&dispc.irq_lock);
+
+       return IRQ_HANDLED;
 }
 
 static void dispc_error_worker(struct work_struct *work)
@@ -3253,6 +3343,15 @@ static void _omap_dispc_initial_config(void)
        l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
        dispc_write_reg(DISPC_SYSCONFIG, l);
 
+       /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
+       if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
+               l = dispc_read_reg(DISPC_DIVISOR);
+               /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
+               l = FLD_MOD(l, 1, 0, 0);
+               l = FLD_MOD(l, 1, 23, 16);
+               dispc_write_reg(DISPC_DIVISOR, l);
+       }
+
        /* FUNCGATED */
        if (dss_has_feature(FEAT_FUNCGATED))
                REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
@@ -3269,47 +3368,6 @@ static void _omap_dispc_initial_config(void)
        dispc_read_plane_fifo_sizes();
 }
 
-int dispc_init(void)
-{
-       u32 rev;
-
-       spin_lock_init(&dispc.irq_lock);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-       spin_lock_init(&dispc.irq_stats_lock);
-       dispc.irq_stats.last_reset = jiffies;
-#endif
-
-       INIT_WORK(&dispc.error_work, dispc_error_worker);
-
-       dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
-       if (!dispc.base) {
-               DSSERR("can't ioremap DISPC\n");
-               return -ENOMEM;
-       }
-
-       enable_clocks(1);
-
-       _omap_dispc_initial_config();
-
-       _omap_dispc_initialize_irq();
-
-       dispc_save_context();
-
-       rev = dispc_read_reg(DISPC_REVISION);
-       printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
-              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-       enable_clocks(0);
-
-       return 0;
-}
-
-void dispc_exit(void)
-{
-       iounmap(dispc.base);
-}
-
 int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
        DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -3359,3 +3417,94 @@ int dispc_setup_plane(enum omap_plane plane,
 
        return r;
 }
+
+/* DISPC HW IP initialisation */
+static int omap_dispchw_probe(struct platform_device *pdev)
+{
+       u32 rev;
+       int r = 0;
+       struct resource *dispc_mem;
+
+       dispc.pdev = pdev;
+
+       spin_lock_init(&dispc.irq_lock);
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+       spin_lock_init(&dispc.irq_stats_lock);
+       dispc.irq_stats.last_reset = jiffies;
+#endif
+
+       INIT_WORK(&dispc.error_work, dispc_error_worker);
+
+       dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
+       if (!dispc_mem) {
+               DSSERR("can't get IORESOURCE_MEM DISPC\n");
+               r = -EINVAL;
+               goto fail0;
+       }
+       dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
+       if (!dispc.base) {
+               DSSERR("can't ioremap DISPC\n");
+               r = -ENOMEM;
+               goto fail0;
+       }
+       dispc.irq = platform_get_irq(dispc.pdev, 0);
+       if (dispc.irq < 0) {
+               DSSERR("platform_get_irq failed\n");
+               r = -ENODEV;
+               goto fail1;
+       }
+
+       r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
+               "OMAP DISPC", dispc.pdev);
+       if (r < 0) {
+               DSSERR("request_irq failed\n");
+               goto fail1;
+       }
+
+       enable_clocks(1);
+
+       _omap_dispc_initial_config();
+
+       _omap_dispc_initialize_irq();
+
+       dispc_save_context();
+
+       rev = dispc_read_reg(DISPC_REVISION);
+       dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
+              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+       enable_clocks(0);
+
+       return 0;
+fail1:
+       iounmap(dispc.base);
+fail0:
+       return r;
+}
+
+static int omap_dispchw_remove(struct platform_device *pdev)
+{
+       free_irq(dispc.irq, dispc.pdev);
+       iounmap(dispc.base);
+       return 0;
+}
+
+static struct platform_driver omap_dispchw_driver = {
+       .probe          = omap_dispchw_probe,
+       .remove         = omap_dispchw_remove,
+       .driver         = {
+               .name   = "omapdss_dispc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int dispc_init_platform_driver(void)
+{
+       return platform_driver_register(&omap_dispchw_driver);
+}
+
+void dispc_uninit_platform_driver(void)
+{
+       return platform_driver_unregister(&omap_dispchw_driver);
+}
index 22dd7a4..a85a6f3 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/jiffies.h>
-#include <linux/list.h>
 #include <linux/platform_device.h>
 
 #include <plat/display.h>
 #include "dss.h"
 
-static LIST_HEAD(display_list);
-
 static ssize_t display_enabled_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -345,6 +342,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
                        return 16;
        case OMAP_DISPLAY_TYPE_VENC:
        case OMAP_DISPLAY_TYPE_SDI:
+       case OMAP_DISPLAY_TYPE_HDMI:
                return 24;
        default:
                BUG();
@@ -371,6 +369,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
        case OMAP_DISPLAY_TYPE_DPI:
                bpp = dssdev->phy.dpi.data_lines;
                break;
+       case OMAP_DISPLAY_TYPE_HDMI:
        case OMAP_DISPLAY_TYPE_VENC:
        case OMAP_DISPLAY_TYPE_SDI:
                bpp = 24;
@@ -393,29 +392,6 @@ void dss_init_device(struct platform_device *pdev,
        int i;
        int r;
 
-       switch (dssdev->type) {
-#ifdef CONFIG_OMAP2_DSS_DPI
-       case OMAP_DISPLAY_TYPE_DPI:
-#endif
-#ifdef CONFIG_OMAP2_DSS_RFBI
-       case OMAP_DISPLAY_TYPE_DBI:
-#endif
-#ifdef CONFIG_OMAP2_DSS_SDI
-       case OMAP_DISPLAY_TYPE_SDI:
-#endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-       case OMAP_DISPLAY_TYPE_DSI:
-#endif
-#ifdef CONFIG_OMAP2_DSS_VENC
-       case OMAP_DISPLAY_TYPE_VENC:
-#endif
-               break;
-       default:
-               DSSERR("Support for display '%s' not compiled in.\n",
-                               dssdev->name);
-               return;
-       }
-
        switch (dssdev->type) {
 #ifdef CONFIG_OMAP2_DSS_DPI
        case OMAP_DISPLAY_TYPE_DPI:
@@ -442,8 +418,13 @@ void dss_init_device(struct platform_device *pdev,
                r = dsi_init_display(dssdev);
                break;
 #endif
+       case OMAP_DISPLAY_TYPE_HDMI:
+               r = hdmi_init_display(dssdev);
+               break;
        default:
-               BUG();
+               DSSERR("Support for display '%s' not compiled in.\n",
+                               dssdev->name);
+               return;
        }
 
        if (r) {
index 75fb0a5..2d3ca4c 100644 (file)
@@ -57,13 +57,13 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
        if (r)
                return r;
 
-       dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
+       dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
 
        r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r)
                return r;
 
-       *fck = dsi_cinfo.dsi1_pll_fclk;
+       *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
        *lck_div = dispc_cinfo.lck_div;
        *pck_div = dispc_cinfo.pck_div;
 
@@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        bool is_tft;
        int r = 0;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
@@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        dispc_set_lcd_timings(dssdev->manager->id, t);
 
 err0:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
        return r;
 }
 
@@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
                        goto err1;
        }
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        r = dpi_basic_init(dssdev);
        if (r)
                goto err2;
 
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
-       dss_clk_enable(DSS_CLK_FCK2);
+       dss_clk_enable(DSS_CLK_SYSCK);
        r = dsi_pll_init(dssdev, 0, 1);
        if (r)
                goto err3;
@@ -199,10 +199,10 @@ err4:
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
        dsi_pll_uninit();
 err3:
-       dss_clk_disable(DSS_CLK_FCK2);
+       dss_clk_disable(DSS_CLK_SYSCK);
 #endif
 err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
 err1:
@@ -217,12 +217,12 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
        dssdev->manager->disable(dssdev->manager);
 
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
-       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
+       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
        dsi_pll_uninit();
-       dss_clk_disable(DSS_CLK_FCK2);
+       dss_clk_disable(DSS_CLK_SYSCK);
 #endif
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
@@ -271,7 +271,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
                if (r)
                        return r;
 
-               fck = dsi_cinfo.dsi1_pll_fclk;
+               fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
                lck_div = dispc_cinfo.lck_div;
                pck_div = dispc_cinfo.pck_div;
        }
@@ -303,22 +303,27 @@ int dpi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       return 0;
-}
+       if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
+               struct regulator *vdds_dsi;
 
-int dpi_init(struct platform_device *pdev)
-{
-       if (cpu_is_omap34xx()) {
-               dpi.vdds_dsi_reg = dss_get_vdds_dsi();
-               if (IS_ERR(dpi.vdds_dsi_reg)) {
+               vdds_dsi = dss_get_vdds_dsi();
+
+               if (IS_ERR(vdds_dsi)) {
                        DSSERR("can't get VDDS_DSI regulator\n");
-                       return PTR_ERR(dpi.vdds_dsi_reg);
+                       return PTR_ERR(vdds_dsi);
                }
+
+               dpi.vdds_dsi_reg = vdds_dsi;
        }
 
        return 0;
 }
 
+int dpi_init(void)
+{
+       return 0;
+}
+
 void dpi_exit(void)
 {
 }
index ddf3a05..0a7f1a4 100644 (file)
 #include <plat/clock.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /*#define VERBOSE_IRQ*/
 #define DSI_CATCH_MISSING_TE
 
-#define DSI_BASE               0x4804FC00
-
 struct dsi_reg { u16 idx; };
 
 #define DSI_REG(idx)           ((const struct dsi_reg) { idx })
@@ -186,13 +185,15 @@ struct dsi_reg { u16 idx; };
 #define DSI_DT_RX_SHORT_READ_1         0x21
 #define DSI_DT_RX_SHORT_READ_2         0x22
 
-#define FINT_MAX 2100000
-#define FINT_MIN 750000
-#define REGN_MAX (1 << 7)
-#define REGM_MAX ((1 << 11) - 1)
-#define REGM3_MAX (1 << 4)
-#define REGM4_MAX (1 << 4)
-#define LP_DIV_MAX ((1 << 13) - 1)
+typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
+
+#define DSI_MAX_NR_ISRS                2
+
+struct dsi_isr_data {
+       omap_dsi_isr_t  isr;
+       void            *arg;
+       u32             mask;
+};
 
 enum fifo_size {
        DSI_FIFO_SIZE_0         = 0,
@@ -220,9 +221,17 @@ struct dsi_irq_stats {
        unsigned cio_irqs[32];
 };
 
+struct dsi_isr_tables {
+       struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
+       struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
+       struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
+};
+
 static struct
 {
+       struct platform_device *pdev;
        void __iomem    *base;
+       int irq;
 
        struct dsi_clock_info current_cinfo;
 
@@ -232,6 +241,7 @@ static struct
                enum dsi_vc_mode mode;
                struct omap_dss_device *dssdev;
                enum fifo_size fifo_size;
+               int vc_id;
        } vc[4];
 
        struct mutex lock;
@@ -239,8 +249,10 @@ static struct
 
        unsigned pll_locked;
 
-       struct completion bta_completion;
-       void (*bta_callback)(void);
+       spinlock_t irq_lock;
+       struct dsi_isr_tables isr_tables;
+       /* space for a copy used by the interrupt handler */
+       struct dsi_isr_tables isr_tables_copy;
 
        int update_channel;
        struct dsi_update_region update_region;
@@ -275,6 +287,11 @@ static struct
        spinlock_t irq_stats_lock;
        struct dsi_irq_stats irq_stats;
 #endif
+       /* DSI PLL Parameter Ranges */
+       unsigned long regm_max, regn_max;
+       unsigned long  regm_dispc_max, regm_dsi_max;
+       unsigned long  fint_min, fint_max;
+       unsigned long lpdiv_max;
 } dsi;
 
 #ifdef DEBUG
@@ -318,6 +335,11 @@ static bool dsi_bus_is_locked(void)
        return dsi.bus_lock.count == 0;
 }
 
+static void dsi_completion_handler(void *data, u32 mask)
+{
+       complete((struct completion *)data);
+}
+
 static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
                int value)
 {
@@ -387,6 +409,9 @@ static void dsi_perf_show(const char *name)
 
 static void print_irq_status(u32 status)
 {
+       if (status == 0)
+               return;
+
 #ifndef VERBOSE_IRQ
        if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
                return;
@@ -422,6 +447,9 @@ static void print_irq_status(u32 status)
 
 static void print_irq_status_vc(int channel, u32 status)
 {
+       if (status == 0)
+               return;
+
 #ifndef VERBOSE_IRQ
        if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
                return;
@@ -448,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status)
 
 static void print_irq_status_cio(u32 status)
 {
+       if (status == 0)
+               return;
+
        printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
 
 #define PIS(x) \
@@ -478,22 +509,33 @@ static void print_irq_status_cio(u32 status)
        printk("\n");
 }
 
-static int debug_irq;
-
-/* called from dss */
-void dsi_irq_handler(void)
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
 {
-       u32 irqstatus, vcstatus, ciostatus;
        int i;
 
-       irqstatus = dsi_read_reg(DSI_IRQSTATUS);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        spin_lock(&dsi.irq_stats_lock);
+
        dsi.irq_stats.irq_count++;
        dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
+
+       for (i = 0; i < 4; ++i)
+               dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]);
+
+       dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
+
+       spin_unlock(&dsi.irq_stats_lock);
+}
+#else
+#define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus)
 #endif
 
+static int debug_irq;
+
+static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+{
+       int i;
+
        if (irqstatus & DSI_IRQ_ERROR_MASK) {
                DSSERR("DSI error, irqstatus %x\n", irqstatus);
                print_irq_status(irqstatus);
@@ -504,37 +546,88 @@ void dsi_irq_handler(void)
                print_irq_status(irqstatus);
        }
 
-#ifdef DSI_CATCH_MISSING_TE
-       if (irqstatus & DSI_IRQ_TE_TRIGGER)
-               del_timer(&dsi.te_timer);
-#endif
+       for (i = 0; i < 4; ++i) {
+               if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
+                       DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
+                                      i, vcstatus[i]);
+                       print_irq_status_vc(i, vcstatus[i]);
+               } else if (debug_irq) {
+                       print_irq_status_vc(i, vcstatus[i]);
+               }
+       }
+
+       if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
+               DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+               print_irq_status_cio(ciostatus);
+       } else if (debug_irq) {
+               print_irq_status_cio(ciostatus);
+       }
+}
+
+static void dsi_call_isrs(struct dsi_isr_data *isr_array,
+               unsigned isr_array_size, u32 irqstatus)
+{
+       struct dsi_isr_data *isr_data;
+       int i;
+
+       for (i = 0; i < isr_array_size; i++) {
+               isr_data = &isr_array[i];
+               if (isr_data->isr && isr_data->mask & irqstatus)
+                       isr_data->isr(isr_data->arg, irqstatus);
+       }
+}
+
+static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
+               u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+{
+       int i;
+
+       dsi_call_isrs(isr_tables->isr_table,
+                       ARRAY_SIZE(isr_tables->isr_table),
+                       irqstatus);
 
        for (i = 0; i < 4; ++i) {
-               if ((irqstatus & (1<<i)) == 0)
+               if (vcstatus[i] == 0)
                        continue;
+               dsi_call_isrs(isr_tables->isr_table_vc[i],
+                               ARRAY_SIZE(isr_tables->isr_table_vc[i]),
+                               vcstatus[i]);
+       }
 
-               vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+       if (ciostatus != 0)
+               dsi_call_isrs(isr_tables->isr_table_cio,
+                               ARRAY_SIZE(isr_tables->isr_table_cio),
+                               ciostatus);
+}
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-               dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
-#endif
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
+{
+       u32 irqstatus, vcstatus[4], ciostatus;
+       int i;
 
-               if (vcstatus & DSI_VC_IRQ_BTA) {
-                       complete(&dsi.bta_completion);
+       spin_lock(&dsi.irq_lock);
 
-                       if (dsi.bta_callback)
-                               dsi.bta_callback();
-               }
+       irqstatus = dsi_read_reg(DSI_IRQSTATUS);
 
-               if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
-                       DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
-                                      i, vcstatus);
-                       print_irq_status_vc(i, vcstatus);
-               } else if (debug_irq) {
-                       print_irq_status_vc(i, vcstatus);
+       /* IRQ is not for us */
+       if (!irqstatus) {
+               spin_unlock(&dsi.irq_lock);
+               return IRQ_NONE;
+       }
+
+       dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+       /* flush posted write */
+       dsi_read_reg(DSI_IRQSTATUS);
+
+       for (i = 0; i < 4; ++i) {
+               if ((irqstatus & (1 << i)) == 0) {
+                       vcstatus[i] = 0;
+                       continue;
                }
 
-               dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
+               vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+               dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]);
                /* flush posted write */
                dsi_read_reg(DSI_VC_IRQSTATUS(i));
        }
@@ -542,117 +635,307 @@ void dsi_irq_handler(void)
        if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
                ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-               dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
-#endif
-
                dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
                /* flush posted write */
                dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+       } else {
+               ciostatus = 0;
+       }
 
-               if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
-                       DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
-                       print_irq_status_cio(ciostatus);
-               } else if (debug_irq) {
-                       print_irq_status_cio(ciostatus);
-               }
+#ifdef DSI_CATCH_MISSING_TE
+       if (irqstatus & DSI_IRQ_TE_TRIGGER)
+               del_timer(&dsi.te_timer);
+#endif
+
+       /* make a copy and unlock, so that isrs can unregister
+        * themselves */
+       memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
+
+       spin_unlock(&dsi.irq_lock);
+
+       dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus);
+
+       dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
+
+       dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
+
+       return IRQ_HANDLED;
+}
+
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array,
+               unsigned isr_array_size, u32 default_mask,
+               const struct dsi_reg enable_reg,
+               const struct dsi_reg status_reg)
+{
+       struct dsi_isr_data *isr_data;
+       u32 mask;
+       u32 old_mask;
+       int i;
+
+       mask = default_mask;
+
+       for (i = 0; i < isr_array_size; i++) {
+               isr_data = &isr_array[i];
+
+               if (isr_data->isr == NULL)
+                       continue;
+
+               mask |= isr_data->mask;
        }
 
-       dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
-       /* flush posted write */
-       dsi_read_reg(DSI_IRQSTATUS);
+       old_mask = dsi_read_reg(enable_reg);
+       /* clear the irqstatus for newly enabled irqs */
+       dsi_write_reg(status_reg, (mask ^ old_mask) & mask);
+       dsi_write_reg(enable_reg, mask);
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-       spin_unlock(&dsi.irq_stats_lock);
+       /* flush posted writes */
+       dsi_read_reg(enable_reg);
+       dsi_read_reg(status_reg);
+}
+
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs(void)
+{
+       u32 mask = DSI_IRQ_ERROR_MASK;
+#ifdef DSI_CATCH_MISSING_TE
+       mask |= DSI_IRQ_TE_TRIGGER;
 #endif
+       _omap_dsi_configure_irqs(dsi.isr_tables.isr_table,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table), mask,
+                       DSI_IRQENABLE, DSI_IRQSTATUS);
+}
+
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_vc(int vc)
+{
+       _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc],
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]),
+                       DSI_VC_IRQ_ERROR_MASK,
+                       DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
 }
 
+/* dsi.irq_lock has to be locked by the caller */
+static void _omap_dsi_set_irqs_cio(void)
+{
+       _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_cio),
+                       DSI_CIO_IRQ_ERROR_MASK,
+                       DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
+}
 
 static void _dsi_initialize_irq(void)
 {
-       u32 l;
+       unsigned long flags;
+       int vc;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables));
+
+       _omap_dsi_set_irqs();
+       for (vc = 0; vc < 4; ++vc)
+               _omap_dsi_set_irqs_vc(vc);
+       _omap_dsi_set_irqs_cio();
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
+}
+
+static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+               struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+       struct dsi_isr_data *isr_data;
+       int free_idx;
        int i;
 
-       /* disable all interrupts */
-       dsi_write_reg(DSI_IRQENABLE, 0);
-       for (i = 0; i < 4; ++i)
-               dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
-       dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
+       BUG_ON(isr == NULL);
 
-       /* clear interrupt status */
-       l = dsi_read_reg(DSI_IRQSTATUS);
-       dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
+       /* check for duplicate entry and find a free slot */
+       free_idx = -1;
+       for (i = 0; i < isr_array_size; i++) {
+               isr_data = &isr_array[i];
 
-       for (i = 0; i < 4; ++i) {
-               l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
-               dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
+               if (isr_data->isr == isr && isr_data->arg == arg &&
+                               isr_data->mask == mask) {
+                       return -EINVAL;
+               }
+
+               if (isr_data->isr == NULL && free_idx == -1)
+                       free_idx = i;
        }
 
-       l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
-       dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
+       if (free_idx == -1)
+               return -EBUSY;
 
-       /* enable error irqs */
-       l = DSI_IRQ_ERROR_MASK;
-#ifdef DSI_CATCH_MISSING_TE
-       l |= DSI_IRQ_TE_TRIGGER;
-#endif
-       dsi_write_reg(DSI_IRQENABLE, l);
+       isr_data = &isr_array[free_idx];
+       isr_data->isr = isr;
+       isr_data->arg = arg;
+       isr_data->mask = mask;
 
-       l = DSI_VC_IRQ_ERROR_MASK;
-       for (i = 0; i < 4; ++i)
-               dsi_write_reg(DSI_VC_IRQENABLE(i), l);
+       return 0;
+}
+
+static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
+               struct dsi_isr_data *isr_array, unsigned isr_array_size)
+{
+       struct dsi_isr_data *isr_data;
+       int i;
+
+       for (i = 0; i < isr_array_size; i++) {
+               isr_data = &isr_array[i];
+               if (isr_data->isr != isr || isr_data->arg != arg ||
+                               isr_data->mask != mask)
+                       continue;
+
+               isr_data->isr = NULL;
+               isr_data->arg = NULL;
+               isr_data->mask = 0;
+
+               return 0;
+       }
 
-       l = DSI_CIO_IRQ_ERROR_MASK;
-       dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
+       return -EINVAL;
 }
 
-static u32 dsi_get_errors(void)
+static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
 {
        unsigned long flags;
-       u32 e;
-       spin_lock_irqsave(&dsi.errors_lock, flags);
-       e = dsi.errors;
-       dsi.errors = 0;
-       spin_unlock_irqrestore(&dsi.errors_lock, flags);
-       return e;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table));
+
+       if (r == 0)
+               _omap_dsi_set_irqs();
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+       return r;
 }
 
-static void dsi_vc_enable_bta_irq(int channel)
+static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
 {
-       u32 l;
+       unsigned long flags;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table));
+
+       if (r == 0)
+               _omap_dsi_set_irqs();
 
-       dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
 
-       l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
-       l |= DSI_VC_IRQ_BTA;
-       dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+       return r;
 }
 
-static void dsi_vc_disable_bta_irq(int channel)
+static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
+               u32 mask)
 {
-       u32 l;
+       unsigned long flags;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_register_isr(isr, arg, mask,
+                       dsi.isr_tables.isr_table_vc[channel],
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
+
+       if (r == 0)
+               _omap_dsi_set_irqs_vc(channel);
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+       return r;
+}
+
+static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
+               u32 mask)
+{
+       unsigned long flags;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_unregister_isr(isr, arg, mask,
+                       dsi.isr_tables.isr_table_vc[channel],
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
+
+       if (r == 0)
+               _omap_dsi_set_irqs_vc(channel);
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+       return r;
+}
+
+static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+       unsigned long flags;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
+
+       if (r == 0)
+               _omap_dsi_set_irqs_cio();
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
+
+       return r;
+}
+
+static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
+{
+       unsigned long flags;
+       int r;
+
+       spin_lock_irqsave(&dsi.irq_lock, flags);
+
+       r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
+                       ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
+
+       if (r == 0)
+               _omap_dsi_set_irqs_cio();
+
+       spin_unlock_irqrestore(&dsi.irq_lock, flags);
 
-       l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
-       l &= ~DSI_VC_IRQ_BTA;
-       dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+       return r;
 }
 
-/* DSI func clock. this could also be DSI2_PLL_FCLK */
+static u32 dsi_get_errors(void)
+{
+       unsigned long flags;
+       u32 e;
+       spin_lock_irqsave(&dsi.errors_lock, flags);
+       e = dsi.errors;
+       dsi.errors = 0;
+       spin_unlock_irqrestore(&dsi.errors_lock, flags);
+       return e;
+}
+
+/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
 static inline void enable_clocks(bool enable)
 {
        if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
 static inline void dsi_enable_pll_clock(bool enable)
 {
        if (enable)
-               dss_clk_enable(DSS_CLK_FCK2);
+               dss_clk_enable(DSS_CLK_SYSCK);
        else
-               dss_clk_disable(DSS_CLK_FCK2);
+               dss_clk_disable(DSS_CLK_SYSCK);
 
        if (enable && dsi.pll_locked) {
                if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
@@ -707,14 +990,14 @@ static inline int dsi_if_enable(bool enable)
        return 0;
 }
 
-unsigned long dsi_get_dsi1_pll_rate(void)
+unsigned long dsi_get_pll_hsdiv_dispc_rate(void)
 {
-       return dsi.current_cinfo.dsi1_pll_fclk;
+       return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk;
 }
 
-static unsigned long dsi_get_dsi2_pll_rate(void)
+static unsigned long dsi_get_pll_hsdiv_dsi_rate(void)
 {
-       return dsi.current_cinfo.dsi2_pll_fclk;
+       return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk;
 }
 
 static unsigned long dsi_get_txbyteclkhs(void)
@@ -726,12 +1009,12 @@ static unsigned long dsi_fclk_rate(void)
 {
        unsigned long r;
 
-       if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) {
-               /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
-               r = dss_clk_get_rate(DSS_CLK_FCK1);
+       if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) {
+               /* DSI FCLK source is DSS_CLK_FCK */
+               r = dss_clk_get_rate(DSS_CLK_FCK);
        } else {
-               /* DSI FCLK source is DSI2_PLL_FCLK */
-               r = dsi_get_dsi2_pll_rate();
+               /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
+               r = dsi_get_pll_hsdiv_dsi_rate();
        }
 
        return r;
@@ -745,7 +1028,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
 
        lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
 
-       if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX)
+       if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max)
                return -EINVAL;
 
        dsi_fclk = dsi_fclk_rate();
@@ -795,22 +1078,22 @@ static int dsi_pll_power(enum dsi_pll_power_state state)
 static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
                struct dsi_clock_info *cinfo)
 {
-       if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
+       if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max)
                return -EINVAL;
 
-       if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
+       if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max)
                return -EINVAL;
 
-       if (cinfo->regm3 > REGM3_MAX)
+       if (cinfo->regm_dispc > dsi.regm_dispc_max)
                return -EINVAL;
 
-       if (cinfo->regm4 > REGM4_MAX)
+       if (cinfo->regm_dsi > dsi.regm_dsi_max)
                return -EINVAL;
 
-       if (cinfo->use_dss2_fck) {
-               cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
+       if (cinfo->use_sys_clk) {
+               cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
                /* XXX it is unclear if highfreq should be used
-                * with DSS2_FCK source also */
+                * with DSS_SYS_CLK source also */
                cinfo->highfreq = 0;
        } else {
                cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
@@ -823,7 +1106,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
 
        cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
 
-       if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
+       if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min)
                return -EINVAL;
 
        cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
@@ -831,15 +1114,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
        if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
                return -EINVAL;
 
-       if (cinfo->regm3 > 0)
-               cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3;
+       if (cinfo->regm_dispc > 0)
+               cinfo->dsi_pll_hsdiv_dispc_clk =
+                       cinfo->clkin4ddr / cinfo->regm_dispc;
        else
-               cinfo->dsi1_pll_fclk = 0;
+               cinfo->dsi_pll_hsdiv_dispc_clk = 0;
 
-       if (cinfo->regm4 > 0)
-               cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4;
+       if (cinfo->regm_dsi > 0)
+               cinfo->dsi_pll_hsdiv_dsi_clk =
+                       cinfo->clkin4ddr / cinfo->regm_dsi;
        else
-               cinfo->dsi2_pll_fclk = 0;
+               cinfo->dsi_pll_hsdiv_dsi_clk = 0;
 
        return 0;
 }
@@ -852,23 +1137,25 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
        struct dispc_clock_info best_dispc;
        int min_fck_per_pck;
        int match = 0;
-       unsigned long dss_clk_fck2;
+       unsigned long dss_sys_clk, max_dss_fck;
+
+       dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
 
-       dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
+       max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
        if (req_pck == dsi.cache_req_pck &&
-                       dsi.cache_cinfo.clkin == dss_clk_fck2) {
+                       dsi.cache_cinfo.clkin == dss_sys_clk) {
                DSSDBG("DSI clock info found from cache\n");
                *dsi_cinfo = dsi.cache_cinfo;
-               dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk,
-                               dispc_cinfo);
+               dispc_find_clk_divs(is_tft, req_pck,
+                       dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo);
                return 0;
        }
 
        min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
 
        if (min_fck_per_pck &&
-               req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+               req_pck * min_fck_per_pck > max_dss_fck) {
                DSSERR("Requested pixel clock not possible with the current "
                                "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
                                "the constraint off.\n");
@@ -882,24 +1169,24 @@ retry:
        memset(&best_dispc, 0, sizeof(best_dispc));
 
        memset(&cur, 0, sizeof(cur));
-       cur.clkin = dss_clk_fck2;
-       cur.use_dss2_fck = 1;
+       cur.clkin = dss_sys_clk;
+       cur.use_sys_clk = 1;
        cur.highfreq = 0;
 
        /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
        /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
        /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
-       for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+       for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) {
                if (cur.highfreq == 0)
                        cur.fint = cur.clkin / cur.regn;
                else
                        cur.fint = cur.clkin / (2 * cur.regn);
 
-               if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+               if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min)
                        continue;
 
                /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
-               for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+               for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) {
                        unsigned long a, b;
 
                        a = 2 * cur.regm * (cur.clkin/1000);
@@ -909,30 +1196,32 @@ retry:
                        if (cur.clkin4ddr > 1800 * 1000 * 1000)
                                break;
 
-                       /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3  < 173MHz */
-                       for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
-                                       ++cur.regm3) {
+                       /* dsi_pll_hsdiv_dispc_clk(MHz) =
+                        * DSIPHY(MHz) / regm_dispc  < 173MHz/186Mhz */
+                       for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max;
+                                       ++cur.regm_dispc) {
                                struct dispc_clock_info cur_dispc;
-                               cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3;
+                               cur.dsi_pll_hsdiv_dispc_clk =
+                                       cur.clkin4ddr / cur.regm_dispc;
 
                                /* this will narrow down the search a bit,
                                 * but still give pixclocks below what was
                                 * requested */
-                               if (cur.dsi1_pll_fclk  < req_pck)
+                               if (cur.dsi_pll_hsdiv_dispc_clk  < req_pck)
                                        break;
 
-                               if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
+                               if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
                                        continue;
 
                                if (min_fck_per_pck &&
-                                       cur.dsi1_pll_fclk <
+                                       cur.dsi_pll_hsdiv_dispc_clk <
                                                req_pck * min_fck_per_pck)
                                        continue;
 
                                match = 1;
 
                                dispc_find_clk_divs(is_tft, req_pck,
-                                               cur.dsi1_pll_fclk,
+                                               cur.dsi_pll_hsdiv_dispc_clk,
                                                &cur_dispc);
 
                                if (abs(cur_dispc.pck - req_pck) <
@@ -961,9 +1250,9 @@ found:
                return -EINVAL;
        }
 
-       /* DSI2_PLL_FCLK (regm4) is not used */
-       best.regm4 = 0;
-       best.dsi2_pll_fclk = 0;
+       /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
+       best.regm_dsi = 0;
+       best.dsi_pll_hsdiv_dsi_clk = 0;
 
        if (dsi_cinfo)
                *dsi_cinfo = best;
@@ -982,23 +1271,27 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
        int r = 0;
        u32 l;
        int f;
+       u8 regn_start, regn_end, regm_start, regm_end;
+       u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 
        DSSDBGF();
 
        dsi.current_cinfo.fint = cinfo->fint;
        dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
-       dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
-       dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+       dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk =
+                       cinfo->dsi_pll_hsdiv_dispc_clk;
+       dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk =
+                       cinfo->dsi_pll_hsdiv_dsi_clk;
 
        dsi.current_cinfo.regn = cinfo->regn;
        dsi.current_cinfo.regm = cinfo->regm;
-       dsi.current_cinfo.regm3 = cinfo->regm3;
-       dsi.current_cinfo.regm4 = cinfo->regm4;
+       dsi.current_cinfo.regm_dispc = cinfo->regm_dispc;
+       dsi.current_cinfo.regm_dsi = cinfo->regm_dsi;
 
        DSSDBG("DSI Fint %ld\n", cinfo->fint);
 
        DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
-                       cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
+                       cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
                        cinfo->clkin,
                        cinfo->highfreq);
 
@@ -1015,24 +1308,39 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
 
        DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
 
-       DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
-                       cinfo->regm3, cinfo->dsi1_pll_fclk);
-       DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
-                       cinfo->regm4, cinfo->dsi2_pll_fclk);
+       DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
+               dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+               dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+               cinfo->dsi_pll_hsdiv_dispc_clk);
+       DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
+               dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+               dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+               cinfo->dsi_pll_hsdiv_dsi_clk);
+
+       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
+       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
+       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
+                       &regm_dispc_end);
+       dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
+                       &regm_dsi_end);
 
        REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
 
        l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
        l = FLD_MOD(l, 1, 0, 0);                /* DSI_PLL_STOPMODE */
-       l = FLD_MOD(l, cinfo->regn - 1, 7, 1);  /* DSI_PLL_REGN */
-       l = FLD_MOD(l, cinfo->regm, 18, 8);     /* DSI_PLL_REGM */
-       l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0,
-                       22, 19);                /* DSI_CLOCK_DIV */
-       l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0,
-                       26, 23);                /* DSIPROTO_CLOCK_DIV */
+       /* DSI_PLL_REGN */
+       l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
+       /* DSI_PLL_REGM */
+       l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
+       /* DSI_CLOCK_DIV */
+       l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
+                       regm_dispc_start, regm_dispc_end);
+       /* DSIPROTO_CLOCK_DIV */
+       l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
+                       regm_dsi_start, regm_dsi_end);
        dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
 
-       BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
+       BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max);
        if (cinfo->fint < 1000000)
                f = 0x3;
        else if (cinfo->fint < 1250000)
@@ -1046,7 +1354,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
 
        l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
        l = FLD_MOD(l, f, 4, 1);                /* DSI_PLL_FREQSEL */
-       l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1,
+       l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
                        11, 11);                /* DSI_PLL_CLKSEL */
        l = FLD_MOD(l, cinfo->highfreq,
                        12, 12);                /* DSI_PLL_HIGHFREQ */
@@ -1101,6 +1409,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
 
        DSSDBG("PLL init\n");
 
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
+       /*
+        * HACK: this is just a quick hack to get the USE_DSI_PLL
+        * option working. USE_DSI_PLL is itself a big hack, and
+        * should be removed.
+        */
+       if (dsi.vdds_dsi_reg == NULL) {
+               struct regulator *vdds_dsi;
+
+               vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi");
+
+               if (IS_ERR(vdds_dsi)) {
+                       DSSERR("can't get VDDS_DSI regulator\n");
+                       return PTR_ERR(vdds_dsi);
+               }
+
+               dsi.vdds_dsi_reg = vdds_dsi;
+       }
+#endif
+
        enable_clocks(1);
        dsi_enable_pll_clock(1);
 
@@ -1162,6 +1490,10 @@ void dsi_dump_clocks(struct seq_file *s)
 {
        int clksel;
        struct dsi_clock_info *cinfo = &dsi.current_cinfo;
+       enum dss_clk_source dispc_clk_src, dsi_clk_src;
+
+       dispc_clk_src = dss_get_dispc_clk_source();
+       dsi_clk_src = dss_get_dsi_clk_source();
 
        enable_clocks(1);
 
@@ -1171,30 +1503,34 @@ void dsi_dump_clocks(struct seq_file *s)
 
        seq_printf(s,   "dsi pll source = %s\n",
                        clksel == 0 ?
-                       "dss2_alwon_fclk" : "pclkfree");
+                       "dss_sys_clk" : "pclkfree");
 
        seq_printf(s,   "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
 
        seq_printf(s,   "CLKIN4DDR\t%-16luregm %u\n",
                        cinfo->clkin4ddr, cinfo->regm);
 
-       seq_printf(s,   "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n",
-                       cinfo->dsi1_pll_fclk,
-                       cinfo->regm3,
-                       dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
+       seq_printf(s,   "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
+                       dss_get_generic_clk_source_name(dispc_clk_src),
+                       dss_feat_get_clk_source_name(dispc_clk_src),
+                       cinfo->dsi_pll_hsdiv_dispc_clk,
+                       cinfo->regm_dispc,
+                       dispc_clk_src == DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
-       seq_printf(s,   "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n",
-                       cinfo->dsi2_pll_fclk,
-                       cinfo->regm4,
-                       dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
+       seq_printf(s,   "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
+                       dss_get_generic_clk_source_name(dsi_clk_src),
+                       dss_feat_get_clk_source_name(dsi_clk_src),
+                       cinfo->dsi_pll_hsdiv_dsi_clk,
+                       cinfo->regm_dsi,
+                       dsi_clk_src == DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
        seq_printf(s,   "- DSI -\n");
 
-       seq_printf(s,   "dsi fclk source = %s\n",
-                       dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
-                       "dss1_alwon_fclk" : "dsi2_pll_fclk");
+       seq_printf(s,   "dsi fclk source = %s (%s)\n",
+                       dss_get_generic_clk_source_name(dsi_clk_src),
+                       dss_feat_get_clk_source_name(dsi_clk_src));
 
        seq_printf(s,   "DSI_FCLK\t%lu\n", dsi_fclk_rate());
 
@@ -1306,7 +1642,7 @@ void dsi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        DUMPREG(DSI_REVISION);
        DUMPREG(DSI_SYSCONFIG);
@@ -1378,7 +1714,7 @@ void dsi_dump_regs(struct seq_file *s)
        DUMPREG(DSI_PLL_CONFIGURATION1);
        DUMPREG(DSI_PLL_CONFIGURATION2);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
 }
 
@@ -1622,20 +1958,6 @@ static int _dsi_reset(void)
        return _dsi_wait_reset();
 }
 
-static void dsi_reset_tx_fifo(int channel)
-{
-       u32 mask;
-       u32 l;
-
-       /* set fifosize of the channel to 0, then return the old size */
-       l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE);
-
-       mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4);
-       dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask);
-
-       dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l);
-}
-
 static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
                enum fifo_size size3, enum fifo_size size4)
 {
@@ -1753,8 +2075,6 @@ static void dsi_vc_initial_config(int channel)
        r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
 
        dsi_write_reg(DSI_VC_CTRL(channel), r);
-
-       dsi.vc[channel].mode = DSI_VC_MODE_L4;
 }
 
 static int dsi_vc_config_l4(int channel)
@@ -1922,33 +2242,44 @@ static int dsi_vc_send_bta(int channel)
 
 int dsi_vc_send_bta_sync(int channel)
 {
+       DECLARE_COMPLETION_ONSTACK(completion);
        int r = 0;
        u32 err;
 
-       INIT_COMPLETION(dsi.bta_completion);
+       r = dsi_register_isr_vc(channel, dsi_completion_handler,
+                       &completion, DSI_VC_IRQ_BTA);
+       if (r)
+               goto err0;
 
-       dsi_vc_enable_bta_irq(channel);
+       r = dsi_register_isr(dsi_completion_handler, &completion,
+                       DSI_IRQ_ERROR_MASK);
+       if (r)
+               goto err1;
 
        r = dsi_vc_send_bta(channel);
        if (r)
-               goto err;
+               goto err2;
 
-       if (wait_for_completion_timeout(&dsi.bta_completion,
+       if (wait_for_completion_timeout(&completion,
                                msecs_to_jiffies(500)) == 0) {
                DSSERR("Failed to receive BTA\n");
                r = -EIO;
-               goto err;
+               goto err2;
        }
 
        err = dsi_get_errors();
        if (err) {
                DSSERR("Error while sending BTA: %x\n", err);
                r = -EIO;
-               goto err;
+               goto err2;
        }
-err:
-       dsi_vc_disable_bta_irq(channel);
-
+err2:
+       dsi_unregister_isr(dsi_completion_handler, &completion,
+                       DSI_IRQ_ERROR_MASK);
+err1:
+       dsi_unregister_isr_vc(channel, dsi_completion_handler,
+                       &completion, DSI_VC_IRQ_BTA);
+err0:
        return r;
 }
 EXPORT_SYMBOL(dsi_vc_send_bta_sync);
@@ -1961,7 +2292,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type,
 
        WARN_ON(!dsi_bus_is_locked());
 
-       data_id = data_type | channel << 6;
+       data_id = data_type | dsi.vc[channel].vc_id << 6;
 
        val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
                FLD_VAL(ecc, 31, 24);
@@ -2064,7 +2395,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
                return -EINVAL;
        }
 
-       data_id = data_type | channel << 6;
+       data_id = data_type | dsi.vc[channel].vc_id << 6;
 
        r = (data_id << 0) | (data << 8) | (ecc << 24);
 
@@ -2762,19 +3093,20 @@ static void dsi_te_timeout(unsigned long arg)
 }
 #endif
 
+static void dsi_framedone_bta_callback(void *data, u32 mask);
+
 static void dsi_handle_framedone(int error)
 {
        const int channel = dsi.update_channel;
 
-       cancel_delayed_work(&dsi.framedone_timeout_work);
+       dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
+                       NULL, DSI_VC_IRQ_BTA);
 
-       dsi_vc_disable_bta_irq(channel);
+       cancel_delayed_work(&dsi.framedone_timeout_work);
 
        /* SIDLEMODE back to smart-idle */
        dispc_enable_sidle();
 
-       dsi.bta_callback = NULL;
-
        if (dsi.te_enabled) {
                /* enable LP_RX_TO again after the TE */
                REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
@@ -2808,7 +3140,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
        dsi_handle_framedone(-ETIMEDOUT);
 }
 
-static void dsi_framedone_bta_callback(void)
+static void dsi_framedone_bta_callback(void *data, u32 mask)
 {
        dsi_handle_framedone(0);
 
@@ -2848,15 +3180,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
         * asynchronously.
         * */
 
-       dsi.bta_callback = dsi_framedone_bta_callback;
-
-       barrier();
-
-       dsi_vc_enable_bta_irq(channel);
+       r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
+                       NULL, DSI_VC_IRQ_BTA);
+       if (r) {
+               DSSERR("Failed to register BTA ISR\n");
+               dsi_handle_framedone(-EIO);
+               return;
+       }
 
        r = dsi_vc_send_bta(channel);
        if (r) {
                DSSERR("BTA after framedone failed\n");
+               dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
+                               NULL, DSI_VC_IRQ_BTA);
                dsi_handle_framedone(-EIO);
        }
 }
@@ -2984,12 +3320,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
        struct dsi_clock_info cinfo;
        int r;
 
-       /* we always use DSS2_FCK as input clock */
-       cinfo.use_dss2_fck = true;
+       /* we always use DSS_CLK_SYSCK as input clock */
+       cinfo.use_sys_clk = true;
        cinfo.regn  = dssdev->phy.dsi.div.regn;
        cinfo.regm  = dssdev->phy.dsi.div.regm;
-       cinfo.regm3 = dssdev->phy.dsi.div.regm3;
-       cinfo.regm4 = dssdev->phy.dsi.div.regm4;
+       cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc;
+       cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi;
        r = dsi_calc_clock_rates(dssdev, &cinfo);
        if (r) {
                DSSERR("Failed to calc dsi clocks\n");
@@ -3011,7 +3347,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
        int r;
        unsigned long long fck;
 
-       fck = dsi_get_dsi1_pll_rate();
+       fck = dsi_get_pll_hsdiv_dispc_rate();
 
        dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
        dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
@@ -3045,8 +3381,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
        if (r)
                goto err1;
 
-       dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
-       dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK);
+       dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
+       dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI);
 
        DSSDBG("PLL OK\n");
 
@@ -3082,8 +3418,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 err3:
        dsi_complexio_uninit();
 err2:
-       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
-       dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
+       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
+       dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
 err1:
        dsi_pll_uninit();
 err0:
@@ -3099,8 +3435,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
        dsi_vc_enable(2, 0);
        dsi_vc_enable(3, 0);
 
-       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
-       dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
+       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
+       dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
        dsi_complexio_uninit();
        dsi_pll_uninit();
 }
@@ -3220,29 +3556,107 @@ int dsi_init_display(struct omap_dss_device *dssdev)
        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
                OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
 
-       dsi.vc[0].dssdev = dssdev;
-       dsi.vc[1].dssdev = dssdev;
+       if (dsi.vdds_dsi_reg == NULL) {
+               struct regulator *vdds_dsi;
+
+               vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi");
+
+               if (IS_ERR(vdds_dsi)) {
+                       DSSERR("can't get VDDS_DSI regulator\n");
+                       return PTR_ERR(vdds_dsi);
+               }
+
+               dsi.vdds_dsi_reg = vdds_dsi;
+       }
 
        return 0;
 }
 
-void dsi_wait_dsi1_pll_active(void)
+int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) {
+               if (!dsi.vc[i].dssdev) {
+                       dsi.vc[i].dssdev = dssdev;
+                       *channel = i;
+                       return 0;
+               }
+       }
+
+       DSSERR("cannot get VC for display %s", dssdev->name);
+       return -ENOSPC;
+}
+EXPORT_SYMBOL(omap_dsi_request_vc);
+
+int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
+{
+       if (vc_id < 0 || vc_id > 3) {
+               DSSERR("VC ID out of range\n");
+               return -EINVAL;
+       }
+
+       if (channel < 0 || channel > 3) {
+               DSSERR("Virtual Channel out of range\n");
+               return -EINVAL;
+       }
+
+       if (dsi.vc[channel].dssdev != dssdev) {
+               DSSERR("Virtual Channel not allocated to display %s\n",
+                       dssdev->name);
+               return -EINVAL;
+       }
+
+       dsi.vc[channel].vc_id = vc_id;
+
+       return 0;
+}
+EXPORT_SYMBOL(omap_dsi_set_vc_id);
+
+void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel)
+{
+       if ((channel >= 0 && channel <= 3) &&
+               dsi.vc[channel].dssdev == dssdev) {
+               dsi.vc[channel].dssdev = NULL;
+               dsi.vc[channel].vc_id = 0;
+       }
+}
+EXPORT_SYMBOL(omap_dsi_release_vc);
+
+void dsi_wait_pll_hsdiv_dispc_active(void)
 {
        if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
-               DSSERR("DSI1 PLL clock not active\n");
+               DSSERR("%s (%s) not active\n",
+                       dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+                       dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
 }
 
-void dsi_wait_dsi2_pll_active(void)
+void dsi_wait_pll_hsdiv_dsi_active(void)
 {
        if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
-               DSSERR("DSI2 PLL clock not active\n");
+               DSSERR("%s (%s) not active\n",
+                       dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+                       dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
+}
+
+static void dsi_calc_clock_param_ranges(void)
+{
+       dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
+       dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
+       dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
+       dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
+       dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
+       dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
+       dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
-int dsi_init(struct platform_device *pdev)
+static int dsi_init(struct platform_device *pdev)
 {
        u32 rev;
-       int r;
+       int r, i;
+       struct resource *dsi_mem;
 
+       spin_lock_init(&dsi.irq_lock);
        spin_lock_init(&dsi.errors_lock);
        dsi.errors = 0;
 
@@ -3251,8 +3665,6 @@ int dsi_init(struct platform_device *pdev)
        dsi.irq_stats.last_reset = jiffies;
 #endif
 
-       init_completion(&dsi.bta_completion);
-
        mutex_init(&dsi.lock);
        sema_init(&dsi.bus_lock, 1);
 
@@ -3268,24 +3680,45 @@ int dsi_init(struct platform_device *pdev)
        dsi.te_timer.function = dsi_te_timeout;
        dsi.te_timer.data = 0;
 #endif
-       dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+       dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0);
+       if (!dsi_mem) {
+               DSSERR("can't get IORESOURCE_MEM DSI\n");
+               r = -EINVAL;
+               goto err1;
+       }
+       dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem));
        if (!dsi.base) {
                DSSERR("can't ioremap DSI\n");
                r = -ENOMEM;
                goto err1;
        }
+       dsi.irq = platform_get_irq(dsi.pdev, 0);
+       if (dsi.irq < 0) {
+               DSSERR("platform_get_irq failed\n");
+               r = -ENODEV;
+               goto err2;
+       }
 
-       dsi.vdds_dsi_reg = dss_get_vdds_dsi();
-       if (IS_ERR(dsi.vdds_dsi_reg)) {
-               DSSERR("can't get VDDS_DSI regulator\n");
-               r = PTR_ERR(dsi.vdds_dsi_reg);
+       r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED,
+               "OMAP DSI1", dsi.pdev);
+       if (r < 0) {
+               DSSERR("request_irq failed\n");
                goto err2;
        }
 
+       /* DSI VCs initialization */
+       for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) {
+               dsi.vc[i].mode = DSI_VC_MODE_L4;
+               dsi.vc[i].dssdev = NULL;
+               dsi.vc[i].vc_id = 0;
+       }
+
+       dsi_calc_clock_param_ranges();
+
        enable_clocks(1);
 
        rev = dsi_read_reg(DSI_REVISION);
-       printk(KERN_INFO "OMAP DSI rev %d.%d\n",
+       dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
        enable_clocks(0);
@@ -3298,8 +3731,14 @@ err1:
        return r;
 }
 
-void dsi_exit(void)
+static void dsi_exit(void)
 {
+       if (dsi.vdds_dsi_reg != NULL) {
+               regulator_put(dsi.vdds_dsi_reg);
+               dsi.vdds_dsi_reg = NULL;
+       }
+
+       free_irq(dsi.irq, dsi.pdev);
        iounmap(dsi.base);
 
        destroy_workqueue(dsi.workqueue);
@@ -3307,3 +3746,41 @@ void dsi_exit(void)
        DSSDBG("omap_dsi_exit\n");
 }
 
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *pdev)
+{
+       int r;
+       dsi.pdev = pdev;
+       r = dsi_init(pdev);
+       if (r) {
+               DSSERR("Failed to initialize DSI\n");
+               goto err_dsi;
+       }
+err_dsi:
+       return r;
+}
+
+static int omap_dsi1hw_remove(struct platform_device *pdev)
+{
+       dsi_exit();
+       return 0;
+}
+
+static struct platform_driver omap_dsi1hw_driver = {
+       .probe          = omap_dsi1hw_probe,
+       .remove         = omap_dsi1hw_remove,
+       .driver         = {
+               .name   = "omapdss_dsi1",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int dsi_init_platform_driver(void)
+{
+       return platform_driver_register(&omap_dsi1hw_driver);
+}
+
+void dsi_uninit_platform_driver(void)
+{
+       return platform_driver_unregister(&omap_dsi1hw_driver);
+}
index 77c3621..3f1fee6 100644 (file)
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
 
 #include <plat/display.h>
+#include <plat/clock.h>
 #include "dss.h"
-
-#define DSS_BASE                       0x48050000
+#include "dss_features.h"
 
 #define DSS_SZ_REGS                    SZ_512
 
@@ -59,9 +58,17 @@ struct dss_reg {
        dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
 
 static struct {
+       struct platform_device *pdev;
        void __iomem    *base;
+       int             ctx_id;
 
        struct clk      *dpll4_m4_ck;
+       struct clk      *dss_ick;
+       struct clk      *dss_fck;
+       struct clk      *dss_sys_clk;
+       struct clk      *dss_tv_fck;
+       struct clk      *dss_video_fck;
+       unsigned        num_clks_enabled;
 
        unsigned long   cache_req_pck;
        unsigned long   cache_prate;
@@ -70,10 +77,22 @@ static struct {
 
        enum dss_clk_source dsi_clk_source;
        enum dss_clk_source dispc_clk_source;
+       enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
+static const char * const dss_generic_clk_source_names[] = {
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]       = "DSI_PLL_HSDIV_DISPC",
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]         = "DSI_PLL_HSDIV_DSI",
+       [DSS_CLK_SRC_FCK]                       = "DSS_FCK",
+};
+
+static void dss_clk_enable_all_no_ctx(void);
+static void dss_clk_disable_all_no_ctx(void);
+static void dss_clk_enable_no_ctx(enum dss_clock clks);
+static void dss_clk_disable_no_ctx(enum dss_clock clks);
+
 static int _omap_dss_wait_reset(void);
 
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -99,10 +118,11 @@ void dss_save_context(void)
        SR(SYSCONFIG);
        SR(CONTROL);
 
-#ifdef CONFIG_OMAP2_DSS_SDI
-       SR(SDI_CONTROL);
-       SR(PLL_CONTROL);
-#endif
+       if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+                       OMAP_DISPLAY_TYPE_SDI) {
+               SR(SDI_CONTROL);
+               SR(PLL_CONTROL);
+       }
 }
 
 void dss_restore_context(void)
@@ -113,10 +133,11 @@ void dss_restore_context(void)
        RR(SYSCONFIG);
        RR(CONTROL);
 
-#ifdef CONFIG_OMAP2_DSS_SDI
-       RR(SDI_CONTROL);
-       RR(PLL_CONTROL);
-#endif
+       if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+                       OMAP_DISPLAY_TYPE_SDI) {
+               RR(SDI_CONTROL);
+               RR(PLL_CONTROL);
+       }
 }
 
 #undef SR
@@ -209,66 +230,96 @@ void dss_sdi_disable(void)
        REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
 }
 
+const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src)
+{
+       return dss_generic_clk_source_names[clk_src];
+}
+
 void dss_dump_clocks(struct seq_file *s)
 {
        unsigned long dpll4_ck_rate;
        unsigned long dpll4_m4_ck_rate;
+       const char *fclk_name, *fclk_real_name;
+       unsigned long fclk_rate;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-       dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        seq_printf(s, "- DSS -\n");
 
-       seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
+       fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK);
+       fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK);
+       fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
 
-       if (cpu_is_omap3630())
-               seq_printf(s, "dss1_alwon_fclk = %lu / %lu  = %lu\n",
-                       dpll4_ck_rate,
-                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                       dss_clk_get_rate(DSS_CLK_FCK1));
-       else
-               seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
-                       dpll4_ck_rate,
-                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                       dss_clk_get_rate(DSS_CLK_FCK1));
+       if (dss.dpll4_m4_ck) {
+               dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+               dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
+
+               seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               if (cpu_is_omap3630() || cpu_is_omap44xx())
+                       seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
+                                       fclk_name, fclk_real_name,
+                                       dpll4_ck_rate,
+                                       dpll4_ck_rate / dpll4_m4_ck_rate,
+                                       fclk_rate);
+               else
+                       seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
+                                       fclk_name, fclk_real_name,
+                                       dpll4_ck_rate,
+                                       dpll4_ck_rate / dpll4_m4_ck_rate,
+                                       fclk_rate);
+       } else {
+               seq_printf(s, "%s (%s) = %lu\n",
+                               fclk_name, fclk_real_name,
+                               fclk_rate);
+       }
+
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 }
 
 void dss_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        DUMPREG(DSS_REVISION);
        DUMPREG(DSS_SYSCONFIG);
        DUMPREG(DSS_SYSSTATUS);
        DUMPREG(DSS_IRQSTATUS);
        DUMPREG(DSS_CONTROL);
-       DUMPREG(DSS_SDI_CONTROL);
-       DUMPREG(DSS_PLL_CONTROL);
-       DUMPREG(DSS_SDI_STATUS);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+                       OMAP_DISPLAY_TYPE_SDI) {
+               DUMPREG(DSS_SDI_CONTROL);
+               DUMPREG(DSS_PLL_CONTROL);
+               DUMPREG(DSS_SDI_STATUS);
+       }
+
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
 }
 
 void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
 {
        int b;
+       u8 start, end;
+
+       switch (clk_src) {
+       case DSS_CLK_SRC_FCK:
+               b = 0;
+               break;
+       case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+               b = 1;
+               dsi_wait_pll_hsdiv_dispc_active();
+               break;
+       default:
+               BUG();
+       }
 
-       BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
-                       clk_src != DSS_SRC_DSS1_ALWON_FCLK);
-
-       b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
-
-       if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
-               dsi_wait_dsi1_pll_active();
+       dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
 
-       REG_FLD_MOD(DSS_CONTROL, b, 0, 0);      /* DISPC_CLK_SWITCH */
+       REG_FLD_MOD(DSS_CONTROL, b, start, end);        /* DISPC_CLK_SWITCH */
 
        dss.dispc_clk_source = clk_src;
 }
@@ -277,19 +328,51 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
 {
        int b;
 
-       BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
-                       clk_src != DSS_SRC_DSS1_ALWON_FCLK);
-
-       b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
-
-       if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
-               dsi_wait_dsi2_pll_active();
+       switch (clk_src) {
+       case DSS_CLK_SRC_FCK:
+               b = 0;
+               break;
+       case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
+               b = 1;
+               dsi_wait_pll_hsdiv_dsi_active();
+               break;
+       default:
+               BUG();
+       }
 
        REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
 
        dss.dsi_clk_source = clk_src;
 }
 
+void dss_select_lcd_clk_source(enum omap_channel channel,
+               enum dss_clk_source clk_src)
+{
+       int b, ix, pos;
+
+       if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+               return;
+
+       switch (clk_src) {
+       case DSS_CLK_SRC_FCK:
+               b = 0;
+               break;
+       case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+               BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
+               b = 1;
+               dsi_wait_pll_hsdiv_dispc_active();
+               break;
+       default:
+               BUG();
+       }
+
+       pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
+       REG_FLD_MOD(DSS_CONTROL, b, pos, pos);  /* LCDx_CLK_SWITCH */
+
+       ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+       dss.lcd_clk_source[ix] = clk_src;
+}
+
 enum dss_clk_source dss_get_dispc_clk_source(void)
 {
        return dss.dispc_clk_source;
@@ -300,34 +383,52 @@ enum dss_clk_source dss_get_dsi_clk_source(void)
        return dss.dsi_clk_source;
 }
 
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
+{
+       int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+       return dss.lcd_clk_source[ix];
+}
+
 /* calculate clock rates using dividers in cinfo */
 int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 {
-       unsigned long prate;
+       if (dss.dpll4_m4_ck) {
+               unsigned long prate;
+               u16 fck_div_max = 16;
 
-       if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
-                                               cinfo->fck_div == 0)
-               return -EINVAL;
+               if (cpu_is_omap3630() || cpu_is_omap44xx())
+                       fck_div_max = 32;
+
+               if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
+                       return -EINVAL;
 
-       prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+               prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 
-       cinfo->fck = prate / cinfo->fck_div;
+               cinfo->fck = prate / cinfo->fck_div;
+       } else {
+               if (cinfo->fck_div != 0)
+                       return -EINVAL;
+               cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+       }
 
        return 0;
 }
 
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
-       unsigned long prate;
-       int r;
+       if (dss.dpll4_m4_ck) {
+               unsigned long prate;
+               int r;
 
-       if (cpu_is_omap34xx()) {
                prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
                DSSDBG("dpll4_m4 = %ld\n", prate);
 
                r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
                if (r)
                        return r;
+       } else {
+               if (cinfo->fck_div != 0)
+                       return -EINVAL;
        }
 
        DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
@@ -337,12 +438,14 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 
 int dss_get_clock_div(struct dss_clock_info *cinfo)
 {
-       cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
+       cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
 
-       if (cpu_is_omap34xx()) {
+       if (dss.dpll4_m4_ck) {
                unsigned long prate;
+
                prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-               if (cpu_is_omap3630())
+
+               if (cpu_is_omap3630() || cpu_is_omap44xx())
                        cinfo->fck_div = prate / (cinfo->fck);
                else
                        cinfo->fck_div = prate / (cinfo->fck / 2);
@@ -355,7 +458,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo)
 
 unsigned long dss_get_dpll4_rate(void)
 {
-       if (cpu_is_omap34xx())
+       if (dss.dpll4_m4_ck)
                return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
        else
                return 0;
@@ -369,16 +472,18 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
        struct dss_clock_info best_dss;
        struct dispc_clock_info best_dispc;
 
-       unsigned long fck;
+       unsigned long fck, max_dss_fck;
 
-       u16 fck_div;
+       u16 fck_div, fck_div_max = 16;
 
        int match = 0;
        int min_fck_per_pck;
 
        prate = dss_get_dpll4_rate();
 
-       fck = dss_clk_get_rate(DSS_CLK_FCK1);
+       max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+       fck = dss_clk_get_rate(DSS_CLK_FCK);
        if (req_pck == dss.cache_req_pck &&
                        ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
                         dss.cache_dss_cinfo.fck == fck)) {
@@ -391,7 +496,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
        min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
 
        if (min_fck_per_pck &&
-               req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+               req_pck * min_fck_per_pck > max_dss_fck) {
                DSSERR("Requested pixel clock not possible with the current "
                                "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
                                "the constraint off.\n");
@@ -402,10 +507,10 @@ retry:
        memset(&best_dss, 0, sizeof(best_dss));
        memset(&best_dispc, 0, sizeof(best_dispc));
 
-       if (cpu_is_omap24xx()) {
+       if (dss.dpll4_m4_ck == NULL) {
                struct dispc_clock_info cur_dispc;
                /* XXX can we change the clock on omap2? */
-               fck = dss_clk_get_rate(DSS_CLK_FCK1);
+               fck = dss_clk_get_rate(DSS_CLK_FCK);
                fck_div = 1;
 
                dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -417,17 +522,19 @@ retry:
                best_dispc = cur_dispc;
 
                goto found;
-       } else if (cpu_is_omap34xx()) {
-               for (fck_div = (cpu_is_omap3630() ? 32 : 16);
-                                       fck_div > 0; --fck_div) {
+       } else {
+               if (cpu_is_omap3630() || cpu_is_omap44xx())
+                       fck_div_max = 32;
+
+               for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
                        struct dispc_clock_info cur_dispc;
 
-                       if (cpu_is_omap3630())
+                       if (fck_div_max == 32)
                                fck = prate / fck_div;
                        else
                                fck = prate / fck_div * 2;
 
-                       if (fck > DISPC_MAX_FCK)
+                       if (fck > max_dss_fck)
                                continue;
 
                        if (min_fck_per_pck &&
@@ -450,8 +557,6 @@ retry:
                                        goto found;
                        }
                }
-       } else {
-               BUG();
        }
 
 found:
@@ -482,31 +587,6 @@ found:
        return 0;
 }
 
-
-
-static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
-{
-       dispc_irq_handler();
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
-{
-       u32 irqstatus;
-
-       irqstatus = dss_read_reg(DSS_IRQSTATUS);
-
-       if (irqstatus & (1<<0)) /* DISPC_IRQ */
-               dispc_irq_handler();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       if (irqstatus & (1<<1)) /* DSI_IRQ */
-               dsi_irq_handler();
-#endif
-
-       return IRQ_HANDLED;
-}
-
 static int _omap_dss_wait_reset(void)
 {
        int t = 0;
@@ -549,34 +629,45 @@ void dss_set_dac_pwrdn_bgz(bool enable)
        REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
 }
 
-int dss_init(bool skip_init)
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
+{
+       REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
+}
+
+static int dss_init(void)
 {
        int r;
        u32 rev;
+       struct resource *dss_mem;
+       struct clk *dpll4_m4_ck;
 
-       dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
+       dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+       if (!dss_mem) {
+               DSSERR("can't get IORESOURCE_MEM DSS\n");
+               r = -EINVAL;
+               goto fail0;
+       }
+       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
        if (!dss.base) {
                DSSERR("can't ioremap DSS\n");
                r = -ENOMEM;
                goto fail0;
        }
 
-       if (!skip_init) {
-               /* disable LCD and DIGIT output. This seems to fix the synclost
-                * problem that we get, if the bootloader starts the DSS and
-                * the kernel resets it */
-               omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+       /* disable LCD and DIGIT output. This seems to fix the synclost
+        * problem that we get, if the bootloader starts the DSS and
+        * the kernel resets it */
+       omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
 
-               /* We need to wait here a bit, otherwise we sometimes start to
-                * get synclost errors, and after that only power cycle will
-                * restore DSS functionality. I have no idea why this happens.
-                * And we have to wait _before_ resetting the DSS, but after
-                * enabling clocks.
-                */
-               msleep(50);
+       /* We need to wait here a bit, otherwise we sometimes start to
+        * get synclost errors, and after that only power cycle will
+        * restore DSS functionality. I have no idea why this happens.
+        * And we have to wait _before_ resetting the DSS, but after
+        * enabling clocks.
+        */
+       msleep(50);
 
-               _omap_dss_reset();
-       }
+       _omap_dss_reset();
 
        /* autoidle */
        REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
@@ -589,29 +680,30 @@ int dss_init(bool skip_init)
        REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
        REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
 #endif
-
-       r = request_irq(INT_24XX_DSS_IRQ,
-                       cpu_is_omap24xx()
-                       ? dss_irq_handler_omap2
-                       : dss_irq_handler_omap3,
-                       0, "OMAP DSS", NULL);
-
-       if (r < 0) {
-               DSSERR("omap2 dss: request_irq failed\n");
-               goto fail1;
-       }
-
        if (cpu_is_omap34xx()) {
-               dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-               if (IS_ERR(dss.dpll4_m4_ck)) {
+               dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+               if (IS_ERR(dpll4_m4_ck)) {
                        DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(dss.dpll4_m4_ck);
-                       goto fail2;
+                       r = PTR_ERR(dpll4_m4_ck);
+                       goto fail1;
                }
+       } else if (cpu_is_omap44xx()) {
+               dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+               if (IS_ERR(dpll4_m4_ck)) {
+                       DSSERR("Failed to get dpll4_m4_ck\n");
+                       r = PTR_ERR(dpll4_m4_ck);
+                       goto fail1;
+               }
+       } else { /* omap24xx */
+               dpll4_m4_ck = NULL;
        }
 
-       dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
-       dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
+       dss.dpll4_m4_ck = dpll4_m4_ck;
+
+       dss.dsi_clk_source = DSS_CLK_SRC_FCK;
+       dss.dispc_clk_source = DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
 
        dss_save_context();
 
@@ -621,21 +713,416 @@ int dss_init(bool skip_init)
 
        return 0;
 
-fail2:
-       free_irq(INT_24XX_DSS_IRQ, NULL);
 fail1:
        iounmap(dss.base);
 fail0:
        return r;
 }
 
-void dss_exit(void)
+static void dss_exit(void)
 {
-       if (cpu_is_omap34xx())
+       if (dss.dpll4_m4_ck)
                clk_put(dss.dpll4_m4_ck);
 
-       free_irq(INT_24XX_DSS_IRQ, NULL);
-
        iounmap(dss.base);
 }
 
+/* CONTEXT */
+static int dss_get_ctx_id(void)
+{
+       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
+       int r;
+
+       if (!pdata->board_data->get_last_off_on_transaction_id)
+               return 0;
+       r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
+       if (r < 0) {
+               dev_err(&dss.pdev->dev, "getting transaction ID failed, "
+                               "will force context restore\n");
+               r = -1;
+       }
+       return r;
+}
+
+int dss_need_ctx_restore(void)
+{
+       int id = dss_get_ctx_id();
+
+       if (id < 0 || id != dss.ctx_id) {
+               DSSDBG("ctx id %d -> id %d\n",
+                               dss.ctx_id, id);
+               dss.ctx_id = id;
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static void save_all_ctx(void)
+{
+       DSSDBG("save context\n");
+
+       dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+
+       dss_save_context();
+       dispc_save_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+       dsi_save_context();
+#endif
+
+       dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+}
+
+static void restore_all_ctx(void)
+{
+       DSSDBG("restore context\n");
+
+       dss_clk_enable_all_no_ctx();
+
+       dss_restore_context();
+       dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+       dsi_restore_context();
+#endif
+
+       dss_clk_disable_all_no_ctx();
+}
+
+static int dss_get_clock(struct clk **clock, const char *clk_name)
+{
+       struct clk *clk;
+
+       clk = clk_get(&dss.pdev->dev, clk_name);
+
+       if (IS_ERR(clk)) {
+               DSSERR("can't get clock %s", clk_name);
+               return PTR_ERR(clk);
+       }
+
+       *clock = clk;
+
+       DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
+
+       return 0;
+}
+
+static int dss_get_clocks(void)
+{
+       int r;
+       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
+
+       dss.dss_ick = NULL;
+       dss.dss_fck = NULL;
+       dss.dss_sys_clk = NULL;
+       dss.dss_tv_fck = NULL;
+       dss.dss_video_fck = NULL;
+
+       r = dss_get_clock(&dss.dss_ick, "ick");
+       if (r)
+               goto err;
+
+       r = dss_get_clock(&dss.dss_fck, "fck");
+       if (r)
+               goto err;
+
+       if (!pdata->opt_clock_available) {
+               r = -ENODEV;
+               goto err;
+       }
+
+       if (pdata->opt_clock_available("sys_clk")) {
+               r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
+               if (r)
+                       goto err;
+       }
+
+       if (pdata->opt_clock_available("tv_clk")) {
+               r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
+               if (r)
+                       goto err;
+       }
+
+       if (pdata->opt_clock_available("video_clk")) {
+               r = dss_get_clock(&dss.dss_video_fck, "video_clk");
+               if (r)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       if (dss.dss_ick)
+               clk_put(dss.dss_ick);
+       if (dss.dss_fck)
+               clk_put(dss.dss_fck);
+       if (dss.dss_sys_clk)
+               clk_put(dss.dss_sys_clk);
+       if (dss.dss_tv_fck)
+               clk_put(dss.dss_tv_fck);
+       if (dss.dss_video_fck)
+               clk_put(dss.dss_video_fck);
+
+       return r;
+}
+
+static void dss_put_clocks(void)
+{
+       if (dss.dss_video_fck)
+               clk_put(dss.dss_video_fck);
+       if (dss.dss_tv_fck)
+               clk_put(dss.dss_tv_fck);
+       if (dss.dss_sys_clk)
+               clk_put(dss.dss_sys_clk);
+       clk_put(dss.dss_fck);
+       clk_put(dss.dss_ick);
+}
+
+unsigned long dss_clk_get_rate(enum dss_clock clk)
+{
+       switch (clk) {
+       case DSS_CLK_ICK:
+               return clk_get_rate(dss.dss_ick);
+       case DSS_CLK_FCK:
+               return clk_get_rate(dss.dss_fck);
+       case DSS_CLK_SYSCK:
+               return clk_get_rate(dss.dss_sys_clk);
+       case DSS_CLK_TVFCK:
+               return clk_get_rate(dss.dss_tv_fck);
+       case DSS_CLK_VIDFCK:
+               return clk_get_rate(dss.dss_video_fck);
+       }
+
+       BUG();
+       return 0;
+}
+
+static unsigned count_clk_bits(enum dss_clock clks)
+{
+       unsigned num_clks = 0;
+
+       if (clks & DSS_CLK_ICK)
+               ++num_clks;
+       if (clks & DSS_CLK_FCK)
+               ++num_clks;
+       if (clks & DSS_CLK_SYSCK)
+               ++num_clks;
+       if (clks & DSS_CLK_TVFCK)
+               ++num_clks;
+       if (clks & DSS_CLK_VIDFCK)
+               ++num_clks;
+
+       return num_clks;
+}
+
+static void dss_clk_enable_no_ctx(enum dss_clock clks)
+{
+       unsigned num_clks = count_clk_bits(clks);
+
+       if (clks & DSS_CLK_ICK)
+               clk_enable(dss.dss_ick);
+       if (clks & DSS_CLK_FCK)
+               clk_enable(dss.dss_fck);
+       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
+               clk_enable(dss.dss_sys_clk);
+       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+               clk_enable(dss.dss_tv_fck);
+       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+               clk_enable(dss.dss_video_fck);
+
+       dss.num_clks_enabled += num_clks;
+}
+
+void dss_clk_enable(enum dss_clock clks)
+{
+       bool check_ctx = dss.num_clks_enabled == 0;
+
+       dss_clk_enable_no_ctx(clks);
+
+       /*
+        * HACK: On omap4 the registers may not be accessible right after
+        * enabling the clocks. At some point this will be handled by
+        * pm_runtime, but for the time begin this should make things work.
+        */
+       if (cpu_is_omap44xx() && check_ctx)
+               udelay(10);
+
+       if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
+               restore_all_ctx();
+}
+
+static void dss_clk_disable_no_ctx(enum dss_clock clks)
+{
+       unsigned num_clks = count_clk_bits(clks);
+
+       if (clks & DSS_CLK_ICK)
+               clk_disable(dss.dss_ick);
+       if (clks & DSS_CLK_FCK)
+               clk_disable(dss.dss_fck);
+       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
+               clk_disable(dss.dss_sys_clk);
+       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+               clk_disable(dss.dss_tv_fck);
+       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+               clk_disable(dss.dss_video_fck);
+
+       dss.num_clks_enabled -= num_clks;
+}
+
+void dss_clk_disable(enum dss_clock clks)
+{
+       if (cpu_is_omap34xx()) {
+               unsigned num_clks = count_clk_bits(clks);
+
+               BUG_ON(dss.num_clks_enabled < num_clks);
+
+               if (dss.num_clks_enabled == num_clks)
+                       save_all_ctx();
+       }
+
+       dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_enable_all_no_ctx(void)
+{
+       enum dss_clock clks;
+
+       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+       if (cpu_is_omap34xx())
+               clks |= DSS_CLK_VIDFCK;
+       dss_clk_enable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all_no_ctx(void)
+{
+       enum dss_clock clks;
+
+       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+       if (cpu_is_omap34xx())
+               clks |= DSS_CLK_VIDFCK;
+       dss_clk_disable_no_ctx(clks);
+}
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+/* CLOCKS */
+static void core_dump_clocks(struct seq_file *s)
+{
+       int i;
+       struct clk *clocks[5] = {
+               dss.dss_ick,
+               dss.dss_fck,
+               dss.dss_sys_clk,
+               dss.dss_tv_fck,
+               dss.dss_video_fck
+       };
+
+       seq_printf(s, "- CORE -\n");
+
+       seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
+
+       for (i = 0; i < 5; i++) {
+               if (!clocks[i])
+                       continue;
+               seq_printf(s, "%-15s\t%lu\t%d\n",
+                               clocks[i]->name,
+                               clk_get_rate(clocks[i]),
+                               clocks[i]->usecount);
+       }
+}
+#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
+
+/* DEBUGFS */
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+void dss_debug_dump_clocks(struct seq_file *s)
+{
+       core_dump_clocks(s);
+       dss_dump_clocks(s);
+       dispc_dump_clocks(s);
+#ifdef CONFIG_OMAP2_DSS_DSI
+       dsi_dump_clocks(s);
+#endif
+}
+#endif
+
+
+/* DSS HW IP initialisation */
+static int omap_dsshw_probe(struct platform_device *pdev)
+{
+       int r;
+
+       dss.pdev = pdev;
+
+       r = dss_get_clocks();
+       if (r)
+               goto err_clocks;
+
+       dss_clk_enable_all_no_ctx();
+
+       dss.ctx_id = dss_get_ctx_id();
+       DSSDBG("initial ctx id %u\n", dss.ctx_id);
+
+       r = dss_init();
+       if (r) {
+               DSSERR("Failed to initialize DSS\n");
+               goto err_dss;
+       }
+
+       r = dpi_init();
+       if (r) {
+               DSSERR("Failed to initialize DPI\n");
+               goto err_dpi;
+       }
+
+       r = sdi_init();
+       if (r) {
+               DSSERR("Failed to initialize SDI\n");
+               goto err_sdi;
+       }
+
+       dss_clk_disable_all_no_ctx();
+       return 0;
+err_sdi:
+       dpi_exit();
+err_dpi:
+       dss_exit();
+err_dss:
+       dss_clk_disable_all_no_ctx();
+       dss_put_clocks();
+err_clocks:
+       return r;
+}
+
+static int omap_dsshw_remove(struct platform_device *pdev)
+{
+
+       dss_exit();
+
+       /*
+        * As part of hwmod changes, DSS is not the only controller of dss
+        * clocks; hwmod framework itself will also enable clocks during hwmod
+        * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
+        * need to disable clocks if their usecounts > 1.
+        */
+       WARN_ON(dss.num_clks_enabled > 0);
+
+       dss_put_clocks();
+       return 0;
+}
+
+static struct platform_driver omap_dsshw_driver = {
+       .probe          = omap_dsshw_probe,
+       .remove         = omap_dsshw_remove,
+       .driver         = {
+               .name   = "omapdss_dss",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int dss_init_platform_driver(void)
+{
+       return platform_driver_register(&omap_dsshw_driver);
+}
+
+void dss_uninit_platform_driver(void)
+{
+       return platform_driver_unregister(&omap_dsshw_driver);
+}
index b394951..c2f582b 100644 (file)
@@ -97,8 +97,6 @@ extern unsigned int dss_debug;
 #define FLD_MOD(orig, val, start, end) \
        (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
 
-#define DISPC_MAX_FCK 173000000
-
 enum omap_burst_size {
        OMAP_DSS_BURST_4x32 = 0,
        OMAP_DSS_BURST_8x32 = 1,
@@ -112,17 +110,25 @@ enum omap_parallel_interface_mode {
 };
 
 enum dss_clock {
-       DSS_CLK_ICK     = 1 << 0,
-       DSS_CLK_FCK1    = 1 << 1,
-       DSS_CLK_FCK2    = 1 << 2,
-       DSS_CLK_54M     = 1 << 3,
-       DSS_CLK_96M     = 1 << 4,
+       DSS_CLK_ICK     = 1 << 0,       /* DSS_L3_ICLK and DSS_L4_ICLK */
+       DSS_CLK_FCK     = 1 << 1,       /* DSS1_ALWON_FCLK */
+       DSS_CLK_SYSCK   = 1 << 2,       /* DSS2_ALWON_FCLK */
+       DSS_CLK_TVFCK   = 1 << 3,       /* DSS_TV_FCLK */
+       DSS_CLK_VIDFCK  = 1 << 4,       /* DSS_96M_FCLK*/
 };
 
 enum dss_clk_source {
-       DSS_SRC_DSI1_PLL_FCLK,
-       DSS_SRC_DSI2_PLL_FCLK,
-       DSS_SRC_DSS1_ALWON_FCLK,
+       DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,        /* OMAP3: DSI1_PLL_FCLK
+                                                * OMAP4: PLL1_CLK1 */
+       DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,          /* OMAP3: DSI2_PLL_FCLK
+                                                * OMAP4: PLL1_CLK2 */
+       DSS_CLK_SRC_FCK,                        /* OMAP2/3: DSS1_ALWON_FCLK
+                                                * OMAP4: DSS_FCLK */
+};
+
+enum dss_hdmi_venc_clk_source_select {
+       DSS_VENC_TV_CLK = 0,
+       DSS_HDMI_M_PCLK = 1,
 };
 
 struct dss_clock_info {
@@ -148,36 +154,42 @@ struct dsi_clock_info {
        unsigned long fint;
        unsigned long clkin4ddr;
        unsigned long clkin;
-       unsigned long dsi1_pll_fclk;
-       unsigned long dsi2_pll_fclk;
-
+       unsigned long dsi_pll_hsdiv_dispc_clk;  /* OMAP3: DSI1_PLL_CLK
+                                                * OMAP4: PLLx_CLK1 */
+       unsigned long dsi_pll_hsdiv_dsi_clk;    /* OMAP3: DSI2_PLL_CLK
+                                                * OMAP4: PLLx_CLK2 */
        unsigned long lp_clk;
 
        /* dividers */
        u16 regn;
        u16 regm;
-       u16 regm3;
-       u16 regm4;
-
+       u16 regm_dispc; /* OMAP3: REGM3
+                        * OMAP4: REGM4 */
+       u16 regm_dsi;   /* OMAP3: REGM4
+                        * OMAP4: REGM5 */
        u16 lp_clk_div;
 
        u8 highfreq;
-       bool use_dss2_fck;
+       bool use_sys_clk;
+};
+
+/* HDMI PLL structure */
+struct hdmi_pll_info {
+       u16 regn;
+       u16 regm;
+       u32 regmf;
+       u16 regm2;
+       u16 regsd;
+       u16 dcofreq;
 };
 
 struct seq_file;
 struct platform_device;
 
 /* core */
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
-void dss_dump_clocks(struct seq_file *s);
 struct bus_type *dss_get_bus(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_sdi(void);
-struct regulator *dss_get_vdda_dac(void);
 
 /* display */
 int dss_suspend_all_devices(void);
@@ -214,13 +226,23 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
 void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 
 /* DSS */
-int dss_init(bool skip_init);
-void dss_exit(void);
+int dss_init_platform_driver(void);
+void dss_uninit_platform_driver(void);
 
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
 void dss_save_context(void);
 void dss_restore_context(void);
+void dss_clk_enable(enum dss_clock clks);
+void dss_clk_disable(enum dss_clock clks);
+unsigned long dss_clk_get_rate(enum dss_clock clk);
+int dss_need_ctx_restore(void);
+const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src);
+void dss_dump_clocks(struct seq_file *s);
 
 void dss_dump_regs(struct seq_file *s);
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+void dss_debug_dump_clocks(struct seq_file *s);
+#endif
 
 void dss_sdi_init(u8 datapairs);
 int dss_sdi_enable(void);
@@ -228,8 +250,11 @@ void dss_sdi_disable(void);
 
 void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
 void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
+void dss_select_lcd_clk_source(enum omap_channel channel,
+               enum dss_clk_source clk_src);
 enum dss_clk_source dss_get_dispc_clk_source(void);
 enum dss_clk_source dss_get_dsi_clk_source(void);
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
 
 void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
@@ -244,11 +269,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 
 /* SDI */
 #ifdef CONFIG_OMAP2_DSS_SDI
-int sdi_init(bool skip_init);
+int sdi_init(void);
 void sdi_exit(void);
 int sdi_init_display(struct omap_dss_device *display);
 #else
-static inline int sdi_init(bool skip_init)
+static inline int sdi_init(void)
 {
        return 0;
 }
@@ -259,8 +284,8 @@ static inline void sdi_exit(void)
 
 /* DSI */
 #ifdef CONFIG_OMAP2_DSS_DSI
-int dsi_init(struct platform_device *pdev);
-void dsi_exit(void);
+int dsi_init_platform_driver(void);
+void dsi_uninit_platform_driver(void);
 
 void dsi_dump_clocks(struct seq_file *s);
 void dsi_dump_irqs(struct seq_file *s);
@@ -271,7 +296,7 @@ void dsi_restore_context(void);
 
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
-unsigned long dsi_get_dsi1_pll_rate(void);
+unsigned long dsi_get_pll_hsdiv_dispc_rate(void);
 int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo);
 int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
                struct dsi_clock_info *cinfo,
@@ -282,31 +307,36 @@ void dsi_pll_uninit(void);
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
                u32 fifo_size, enum omap_burst_size *burst_size,
                u32 *fifo_low, u32 *fifo_high);
-void dsi_wait_dsi1_pll_active(void);
-void dsi_wait_dsi2_pll_active(void);
+void dsi_wait_pll_hsdiv_dispc_active(void);
+void dsi_wait_pll_hsdiv_dsi_active(void);
 #else
-static inline int dsi_init(struct platform_device *pdev)
+static inline int dsi_init_platform_driver(void)
 {
        return 0;
 }
-static inline void dsi_exit(void)
+static inline void dsi_uninit_platform_driver(void)
 {
 }
-static inline void dsi_wait_dsi1_pll_active(void)
+static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void)
 {
+       WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
+       return 0;
 }
-static inline void dsi_wait_dsi2_pll_active(void)
+static inline void dsi_wait_pll_hsdiv_dispc_active(void)
+{
+}
+static inline void dsi_wait_pll_hsdiv_dsi_active(void)
 {
 }
 #endif
 
 /* DPI */
 #ifdef CONFIG_OMAP2_DSS_DPI
-int dpi_init(struct platform_device *pdev);
+int dpi_init(void);
 void dpi_exit(void);
 int dpi_init_display(struct omap_dss_device *dssdev);
 #else
-static inline int dpi_init(struct platform_device *pdev)
+static inline int dpi_init(void)
 {
        return 0;
 }
@@ -316,8 +346,8 @@ static inline void dpi_exit(void)
 #endif
 
 /* DISPC */
-int dispc_init(void);
-void dispc_exit(void);
+int dispc_init_platform_driver(void);
+void dispc_uninit_platform_driver(void);
 void dispc_dump_clocks(struct seq_file *s);
 void dispc_dump_irqs(struct seq_file *s);
 void dispc_dump_regs(struct seq_file *s);
@@ -350,6 +380,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
 void dispc_set_channel_out(enum omap_plane plane,
                enum omap_channel channel_out);
 
+void dispc_enable_gamma_table(bool enable);
 int dispc_setup_plane(enum omap_plane plane,
                      u32 paddr, u16 screen_width,
                      u16 pos_x, u16 pos_y,
@@ -409,24 +440,50 @@ int dispc_get_clock_div(enum omap_channel channel,
 
 /* VENC */
 #ifdef CONFIG_OMAP2_DSS_VENC
-int venc_init(struct platform_device *pdev);
-void venc_exit(void);
+int venc_init_platform_driver(void);
+void venc_uninit_platform_driver(void);
 void venc_dump_regs(struct seq_file *s);
 int venc_init_display(struct omap_dss_device *display);
 #else
-static inline int venc_init(struct platform_device *pdev)
+static inline int venc_init_platform_driver(void)
+{
+       return 0;
+}
+static inline void venc_uninit_platform_driver(void)
+{
+}
+#endif
+
+/* HDMI */
+#ifdef CONFIG_OMAP4_DSS_HDMI
+int hdmi_init_platform_driver(void);
+void hdmi_uninit_platform_driver(void);
+int hdmi_init_display(struct omap_dss_device *dssdev);
+#else
+static inline int hdmi_init_display(struct omap_dss_device *dssdev)
+{
+       return 0;
+}
+static inline int hdmi_init_platform_driver(void)
 {
        return 0;
 }
-static inline void venc_exit(void)
+static inline void hdmi_uninit_platform_driver(void)
 {
 }
 #endif
+int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
+int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
+                                       struct omap_video_timings *timings);
+int hdmi_panel_init(void);
+void hdmi_panel_exit(void);
 
 /* RFBI */
 #ifdef CONFIG_OMAP2_DSS_RFBI
-int rfbi_init(void);
-void rfbi_exit(void);
+int rfbi_init_platform_driver(void);
+void rfbi_uninit_platform_driver(void);
 void rfbi_dump_regs(struct seq_file *s);
 
 int rfbi_configure(int rfbi_module, int bpp, int lines);
@@ -437,11 +494,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
 unsigned long rfbi_get_max_tx_rate(void);
 int rfbi_init_display(struct omap_dss_device *display);
 #else
-static inline int rfbi_init(void)
+static inline int rfbi_init_platform_driver(void)
 {
        return 0;
 }
-static inline void rfbi_exit(void)
+static inline void rfbi_uninit_platform_driver(void)
 {
 }
 #endif
index cf3ef69..aa16222 100644 (file)
 #include <plat/display.h>
 #include <plat/cpu.h>
 
+#include "dss.h"
 #include "dss_features.h"
 
 /* Defines a generic omap register field */
 struct dss_reg_field {
-       enum dss_feat_reg_field id;
        u8 start, end;
 };
 
+struct dss_param_range {
+       int min, max;
+};
+
 struct omap_dss_features {
        const struct dss_reg_field *reg_fields;
        const int num_reg_fields;
@@ -43,28 +47,67 @@ struct omap_dss_features {
        const int num_ovls;
        const enum omap_display_type *supported_displays;
        const enum omap_color_mode *supported_color_modes;
+       const char * const *clksrc_names;
+       const struct dss_param_range *dss_params;
 };
 
 /* This struct is assigned to one of the below during initialization */
 static struct omap_dss_features *omap_current_dss_features;
 
 static const struct dss_reg_field omap2_dss_reg_fields[] = {
-       { FEAT_REG_FIRHINC, 11, 0 },
-       { FEAT_REG_FIRVINC, 27, 16 },
-       { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 },
-       { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 },
-       { FEAT_REG_FIFOSIZE, 8, 0 },
+       [FEAT_REG_FIRHINC]                      = { 11, 0 },
+       [FEAT_REG_FIRVINC]                      = { 27, 16 },
+       [FEAT_REG_FIFOLOWTHRESHOLD]             = { 8, 0 },
+       [FEAT_REG_FIFOHIGHTHRESHOLD]            = { 24, 16 },
+       [FEAT_REG_FIFOSIZE]                     = { 8, 0 },
+       [FEAT_REG_HORIZONTALACCU]               = { 9, 0 },
+       [FEAT_REG_VERTICALACCU]                 = { 25, 16 },
+       [FEAT_REG_DISPC_CLK_SWITCH]             = { 0, 0 },
+       [FEAT_REG_DSIPLL_REGN]                  = { 0, 0 },
+       [FEAT_REG_DSIPLL_REGM]                  = { 0, 0 },
+       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 0, 0 },
+       [FEAT_REG_DSIPLL_REGM_DSI]              = { 0, 0 },
 };
 
 static const struct dss_reg_field omap3_dss_reg_fields[] = {
-       { FEAT_REG_FIRHINC, 12, 0 },
-       { FEAT_REG_FIRVINC, 28, 16 },
-       { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 },
-       { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 },
-       { FEAT_REG_FIFOSIZE, 10, 0 },
+       [FEAT_REG_FIRHINC]                      = { 12, 0 },
+       [FEAT_REG_FIRVINC]                      = { 28, 16 },
+       [FEAT_REG_FIFOLOWTHRESHOLD]             = { 11, 0 },
+       [FEAT_REG_FIFOHIGHTHRESHOLD]            = { 27, 16 },
+       [FEAT_REG_FIFOSIZE]                     = { 10, 0 },
+       [FEAT_REG_HORIZONTALACCU]               = { 9, 0 },
+       [FEAT_REG_VERTICALACCU]                 = { 25, 16 },
+       [FEAT_REG_DISPC_CLK_SWITCH]             = { 0, 0 },
+       [FEAT_REG_DSIPLL_REGN]                  = { 7, 1 },
+       [FEAT_REG_DSIPLL_REGM]                  = { 18, 8 },
+       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 22, 19 },
+       [FEAT_REG_DSIPLL_REGM_DSI]              = { 26, 23 },
+};
+
+static const struct dss_reg_field omap4_dss_reg_fields[] = {
+       [FEAT_REG_FIRHINC]                      = { 12, 0 },
+       [FEAT_REG_FIRVINC]                      = { 28, 16 },
+       [FEAT_REG_FIFOLOWTHRESHOLD]             = { 15, 0 },
+       [FEAT_REG_FIFOHIGHTHRESHOLD]            = { 31, 16 },
+       [FEAT_REG_FIFOSIZE]                     = { 15, 0 },
+       [FEAT_REG_HORIZONTALACCU]               = { 10, 0 },
+       [FEAT_REG_VERTICALACCU]                 = { 26, 16 },
+       [FEAT_REG_DISPC_CLK_SWITCH]             = { 9, 8 },
+       [FEAT_REG_DSIPLL_REGN]                  = { 8, 1 },
+       [FEAT_REG_DSIPLL_REGM]                  = { 20, 9 },
+       [FEAT_REG_DSIPLL_REGM_DISPC]            = { 25, 21 },
+       [FEAT_REG_DSIPLL_REGM_DSI]              = { 30, 26 },
 };
 
 static const enum omap_display_type omap2_dss_supported_displays[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap3430_dss_supported_displays[] = {
        /* OMAP_DSS_CHANNEL_LCD */
        OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
        OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
@@ -73,10 +116,10 @@ static const enum omap_display_type omap2_dss_supported_displays[] = {
        OMAP_DISPLAY_TYPE_VENC,
 };
 
-static const enum omap_display_type omap3_dss_supported_displays[] = {
+static const enum omap_display_type omap3630_dss_supported_displays[] = {
        /* OMAP_DSS_CHANNEL_LCD */
        OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-       OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+       OMAP_DISPLAY_TYPE_DSI,
 
        /* OMAP_DSS_CHANNEL_DIGIT */
        OMAP_DISPLAY_TYPE_VENC,
@@ -87,7 +130,7 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
        OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
 
        /* OMAP_DSS_CHANNEL_DIGIT */
-       OMAP_DISPLAY_TYPE_VENC,
+       OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
 
        /* OMAP_DSS_CHANNEL_LCD2 */
        OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
@@ -134,6 +177,54 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
        OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
 };
 
+static const char * const omap2_dss_clk_source_names[] = {
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]       = "N/A",
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]         = "N/A",
+       [DSS_CLK_SRC_FCK]                       = "DSS_FCLK1",
+};
+
+static const char * const omap3_dss_clk_source_names[] = {
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]       = "DSI1_PLL_FCLK",
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]         = "DSI2_PLL_FCLK",
+       [DSS_CLK_SRC_FCK]                       = "DSS1_ALWON_FCLK",
+};
+
+static const char * const omap4_dss_clk_source_names[] = {
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]       = "PLL1_CLK1",
+       [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]         = "PLL1_CLK2",
+       [DSS_CLK_SRC_FCK]                       = "DSS_FCLK",
+};
+
+static const struct dss_param_range omap2_dss_param_range[] = {
+       [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
+       [FEAT_PARAM_DSIPLL_REGN]                = { 0, 0 },
+       [FEAT_PARAM_DSIPLL_REGM]                = { 0, 0 },
+       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, 0 },
+       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, 0 },
+       [FEAT_PARAM_DSIPLL_FINT]                = { 0, 0 },
+       [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, 0 },
+};
+
+static const struct dss_param_range omap3_dss_param_range[] = {
+       [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
+       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 7) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 11) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 4) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 4) - 1 },
+       [FEAT_PARAM_DSIPLL_FINT]                = { 750000, 2100000 },
+       [FEAT_PARAM_DSIPLL_LPDIV]               = { 1, (1 << 13) - 1},
+};
+
+static const struct dss_param_range omap4_dss_param_range[] = {
+       [FEAT_PARAM_DSS_FCK]                    = { 0, 186000000 },
+       [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 8) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 12) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 5) - 1 },
+       [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
+       [FEAT_PARAM_DSIPLL_FINT]                = { 500000, 2500000 },
+       [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
+};
+
 /* OMAP2 DSS Features */
 static struct omap_dss_features omap2_dss_features = {
        .reg_fields = omap2_dss_reg_fields,
@@ -141,12 +232,15 @@ static struct omap_dss_features omap2_dss_features = {
 
        .has_feature    =
                FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL |
-               FEAT_PCKFREEENABLE | FEAT_FUNCGATED,
+               FEAT_PCKFREEENABLE | FEAT_FUNCGATED |
+               FEAT_ROWREPEATENABLE | FEAT_RESIZECONF,
 
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap2_dss_supported_displays,
        .supported_color_modes = omap2_dss_supported_color_modes,
+       .clksrc_names = omap2_dss_clk_source_names,
+       .dss_params = omap2_dss_param_range,
 };
 
 /* OMAP3 DSS Features */
@@ -157,12 +251,15 @@ static struct omap_dss_features omap3430_dss_features = {
        .has_feature    =
                FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-               FEAT_FUNCGATED,
+               FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
+               FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF,
 
        .num_mgrs = 2,
        .num_ovls = 3,
-       .supported_displays = omap3_dss_supported_displays,
+       .supported_displays = omap3430_dss_supported_displays,
        .supported_color_modes = omap3_dss_supported_color_modes,
+       .clksrc_names = omap3_dss_clk_source_names,
+       .dss_params = omap3_dss_param_range,
 };
 
 static struct omap_dss_features omap3630_dss_features = {
@@ -172,27 +269,34 @@ static struct omap_dss_features omap3630_dss_features = {
        .has_feature    =
                FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-               FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED,
+               FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
+               FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
+               FEAT_RESIZECONF,
 
        .num_mgrs = 2,
        .num_ovls = 3,
-       .supported_displays = omap3_dss_supported_displays,
+       .supported_displays = omap3630_dss_supported_displays,
        .supported_color_modes = omap3_dss_supported_color_modes,
+       .clksrc_names = omap3_dss_clk_source_names,
+       .dss_params = omap3_dss_param_range,
 };
 
 /* OMAP4 DSS Features */
 static struct omap_dss_features omap4_dss_features = {
-       .reg_fields = omap3_dss_reg_fields,
-       .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+       .reg_fields = omap4_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
 
        .has_feature    =
                FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
-               FEAT_MGR_LCD2,
+               FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
+               FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC,
 
        .num_mgrs = 3,
        .num_ovls = 3,
        .supported_displays = omap4_dss_supported_displays,
        .supported_color_modes = omap3_dss_supported_color_modes,
+       .clksrc_names = omap4_dss_clk_source_names,
+       .dss_params = omap4_dss_param_range,
 };
 
 /* Functions returning values related to a DSS feature */
@@ -206,6 +310,16 @@ int dss_feat_get_num_ovls(void)
        return omap_current_dss_features->num_ovls;
 }
 
+unsigned long dss_feat_get_param_min(enum dss_range_param param)
+{
+       return omap_current_dss_features->dss_params[param].min;
+}
+
+unsigned long dss_feat_get_param_max(enum dss_range_param param)
+{
+       return omap_current_dss_features->dss_params[param].max;
+}
+
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
 {
        return omap_current_dss_features->supported_displays[channel];
@@ -223,6 +337,11 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
                        color_mode;
 }
 
+const char *dss_feat_get_clk_source_name(enum dss_clk_source id)
+{
+       return omap_current_dss_features->clksrc_names[id];
+}
+
 /* DSS has_feature check */
 bool dss_has_feature(enum dss_feat_id id)
 {
index b9c70be..12e9c4e 100644 (file)
@@ -22,6 +22,7 @@
 
 #define MAX_DSS_MANAGERS       3
 #define MAX_DSS_OVERLAYS       3
+#define MAX_DSS_LCD_MANAGERS   2
 
 /* DSS has feature id */
 enum dss_feat_id {
@@ -33,6 +34,12 @@ enum dss_feat_id {
        FEAT_PCKFREEENABLE      = 1 << 5,
        FEAT_FUNCGATED          = 1 << 6,
        FEAT_MGR_LCD2           = 1 << 7,
+       FEAT_LINEBUFFERSPLIT    = 1 << 8,
+       FEAT_ROWREPEATENABLE    = 1 << 9,
+       FEAT_RESIZECONF         = 1 << 10,
+       /* Independent core clk divider */
+       FEAT_CORE_CLK_DIV       = 1 << 11,
+       FEAT_LCD_CLK_SRC        = 1 << 12,
 };
 
 /* DSS register field id */
@@ -42,15 +49,35 @@ enum dss_feat_reg_field {
        FEAT_REG_FIFOHIGHTHRESHOLD,
        FEAT_REG_FIFOLOWTHRESHOLD,
        FEAT_REG_FIFOSIZE,
+       FEAT_REG_HORIZONTALACCU,
+       FEAT_REG_VERTICALACCU,
+       FEAT_REG_DISPC_CLK_SWITCH,
+       FEAT_REG_DSIPLL_REGN,
+       FEAT_REG_DSIPLL_REGM,
+       FEAT_REG_DSIPLL_REGM_DISPC,
+       FEAT_REG_DSIPLL_REGM_DSI,
+};
+
+enum dss_range_param {
+       FEAT_PARAM_DSS_FCK,
+       FEAT_PARAM_DSIPLL_REGN,
+       FEAT_PARAM_DSIPLL_REGM,
+       FEAT_PARAM_DSIPLL_REGM_DISPC,
+       FEAT_PARAM_DSIPLL_REGM_DSI,
+       FEAT_PARAM_DSIPLL_FINT,
+       FEAT_PARAM_DSIPLL_LPDIV,
 };
 
 /* DSS Feature Functions */
 int dss_feat_get_num_mgrs(void);
 int dss_feat_get_num_ovls(void);
+unsigned long dss_feat_get_param_min(enum dss_range_param param);
+unsigned long dss_feat_get_param_max(enum dss_range_param param);
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
 bool dss_feat_color_mode_supported(enum omap_plane plane,
                enum omap_color_mode color_mode);
+const char *dss_feat_get_clk_source_name(enum dss_clk_source id);
 
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
new file mode 100644 (file)
index 0000000..0d44f07
--- /dev/null
@@ -0,0 +1,1332 @@
+/*
+ * hdmi.c
+ *
+ * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ *     Mythri pk <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "HDMI"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <plat/display.h>
+
+#include "dss.h"
+#include "hdmi.h"
+
+static struct {
+       struct mutex lock;
+       struct omap_display_platform_data *pdata;
+       struct platform_device *pdev;
+       void __iomem *base_wp;  /* HDMI wrapper */
+       int code;
+       int mode;
+       u8 edid[HDMI_EDID_MAX_LENGTH];
+       u8 edid_set;
+       bool custom_set;
+       struct hdmi_config cfg;
+} hdmi;
+
+/*
+ * Logic for the below structure :
+ * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
+ * There is a correspondence between CEA/VESA timing and code, please
+ * refer to section 6.3 in HDMI 1.3 specification for timing code.
+ *
+ * In the below structure, cea_vesa_timings corresponds to all OMAP4
+ * supported CEA and VESA timing values.code_cea corresponds to the CEA
+ * code, It is used to get the timing from cea_vesa_timing array.Similarly
+ * with code_vesa. Code_index is used for back mapping, that is once EDID
+ * is read from the TV, EDID is parsed to find the timing values and then
+ * map it to corresponding CEA or VESA index.
+ */
+
+static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = {
+       { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0},
+       { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1},
+       { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1},
+       { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0},
+       { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0},
+       { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0},
+       { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0},
+       { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1},
+       { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1},
+       { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1},
+       { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0},
+       { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0},
+       { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1},
+       { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0},
+       { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1},
+       /* VESA From Here */
+       { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0},
+       { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1},
+       { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1},
+       { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0},
+       { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0},
+       { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1},
+       { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1},
+       { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1},
+       { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0},
+       { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0},
+       { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0},
+       { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0},
+       { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1},
+       { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1},
+       { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1},
+       { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1},
+       { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1},
+       { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1},
+       { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}
+};
+
+/*
+ * This is a static mapping array which maps the timing values
+ * with corresponding CEA / VESA code
+ */
+static const int code_index[OMAP_HDMI_TIMINGS_NB] = {
+       1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32,
+       /* <--15 CEA 17--> vesa*/
+       4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A,
+       0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B
+};
+
+/*
+ * This is reverse static mapping which maps the CEA / VESA code
+ * to the corresponding timing values
+ */
+static const int code_cea[39] = {
+       -1,  0,  3,  3,  2,  8,  5,  5, -1, -1,
+       -1, -1, -1, -1, -1, -1,  9, 10, 10,  1,
+       7,   6,  6, -1, -1, -1, -1, -1, -1, 11,
+       11, 12, 14, -1, -1, 13, 13,  4,  4
+};
+
+static const int code_vesa[85] = {
+       -1, -1, -1, -1, 15, -1, -1, -1, -1, 16,
+       -1, -1, -1, -1, 17, -1, 23, -1, -1, -1,
+       -1, -1, 29, 18, -1, -1, -1, 32, 19, -1,
+       -1, -1, 21, -1, -1, 22, -1, -1, -1, 20,
+       -1, 30, 24, -1, -1, -1, -1, 25, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, 31, 26, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, 27, 28, -1, 33};
+
+static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
+
+static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
+{
+       __raw_writel(val, hdmi.base_wp + idx.idx);
+}
+
+static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
+{
+       return __raw_readl(hdmi.base_wp + idx.idx);
+}
+
+static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
+                               int b2, int b1, u32 val)
+{
+       u32 t = 0;
+       while (val != REG_GET(idx, b2, b1)) {
+               udelay(1);
+               if (t++ > 10000)
+                       return !val;
+       }
+       return val;
+}
+
+int hdmi_init_display(struct omap_dss_device *dssdev)
+{
+       DSSDBG("init_display\n");
+
+       return 0;
+}
+
+static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
+               struct hdmi_pll_info *fmt, u16 sd)
+{
+       u32 r;
+
+       /* PLL start always use manual mode */
+       REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+
+       r = hdmi_read_reg(PLLCTRL_CFG1);
+       r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
+       r = FLD_MOD(r, fmt->regn, 8, 1);  /* CFG1_PLL_REGN */
+
+       hdmi_write_reg(PLLCTRL_CFG1, r);
+
+       r = hdmi_read_reg(PLLCTRL_CFG2);
+
+       r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
+       r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
+       r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
+
+       if (dcofreq) {
+               /* divider programming for frequency beyond 1000Mhz */
+               REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
+               r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
+       } else {
+               r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
+       }
+
+       hdmi_write_reg(PLLCTRL_CFG2, r);
+
+       r = hdmi_read_reg(PLLCTRL_CFG4);
+       r = FLD_MOD(r, fmt->regm2, 24, 18);
+       r = FLD_MOD(r, fmt->regmf, 17, 0);
+
+       hdmi_write_reg(PLLCTRL_CFG4, r);
+
+       /* go now */
+       REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
+
+       /* wait for bit change */
+       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
+               DSSERR("PLL GO bit not set\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Wait till the lock bit is set in PLL status */
+       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+               DSSWARN("cannot lock PLL\n");
+               DSSWARN("CFG1 0x%x\n",
+                       hdmi_read_reg(PLLCTRL_CFG1));
+               DSSWARN("CFG2 0x%x\n",
+                       hdmi_read_reg(PLLCTRL_CFG2));
+               DSSWARN("CFG4 0x%x\n",
+                       hdmi_read_reg(PLLCTRL_CFG4));
+               return -ETIMEDOUT;
+       }
+
+       DSSDBG("PLL locked!\n");
+
+       return 0;
+}
+
+/* PHY_PWR_CMD */
+static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
+{
+       /* Command for power control of HDMI PHY */
+       REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
+
+       /* Status of the power control of HDMI PHY */
+       if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
+               DSSERR("Failed to set PHY power mode to %d\n", val);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+/* PLL_PWR_CMD */
+static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
+{
+       /* Command for power control of HDMI PLL */
+       REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
+
+       /* wait till PHY_PWR_STATUS is set */
+       if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
+               DSSERR("Failed to set PHY_PWR_STATUS\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int hdmi_pll_reset(void)
+{
+       /* SYSRESET  controlled by power FSM */
+       REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+
+       /* READ 0x0 reset is in progress */
+       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
+               DSSERR("Failed to sysreset PLL\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int hdmi_phy_init(void)
+{
+       u16 r = 0;
+
+       r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
+       if (r)
+               return r;
+
+       r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
+       if (r)
+               return r;
+
+       /*
+        * Read address 0 in order to get the SCP reset done completed
+        * Dummy access performed to make sure reset is done
+        */
+       hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
+
+       /*
+        * Write to phy address 0 to configure the clock
+        * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
+        */
+       REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+
+       /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
+       hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+
+       /* Setup max LDO voltage */
+       REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+
+       /* Write to phy address 3 to change the polarity control */
+       REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+
+       return 0;
+}
+
+static int hdmi_wait_softreset(void)
+{
+       /* reset W1 */
+       REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
+
+       /* wait till SOFTRESET == 0 */
+       if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
+               DSSERR("sysconfig reset failed\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int hdmi_pll_program(struct hdmi_pll_info *fmt)
+{
+       u16 r = 0;
+       enum hdmi_clk_refsel refsel;
+
+       /* wait for wrapper reset */
+       r = hdmi_wait_softreset();
+       if (r)
+               return r;
+
+       r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+       if (r)
+               return r;
+
+       r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+       if (r)
+               return r;
+
+       r = hdmi_pll_reset();
+       if (r)
+               return r;
+
+       refsel = HDMI_REFSEL_SYSCLK;
+
+       r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static void hdmi_phy_off(void)
+{
+       hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
+}
+
+static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+{
+       u32 i, j;
+       char checksum = 0;
+       u32 offset = 0;
+
+       /* Turn on CLK for DDC */
+       REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
+
+       /*
+        * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
+        * right shifted values( The behavior is not consistent and seen only
+        * with some TV's)
+        */
+       usleep_range(800, 1000);
+
+       if (!ext) {
+               /* Clk SCL Devices */
+               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+
+               /* HDMI_CORE_DDC_STATUS_IN_PROG */
+               if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
+                                               4, 4, 0) != 0) {
+                       DSSERR("Failed to program DDC\n");
+                       return -ETIMEDOUT;
+               }
+
+               /* Clear FIFO */
+               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+               /* HDMI_CORE_DDC_STATUS_IN_PROG */
+               if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
+                                               4, 4, 0) != 0) {
+                       DSSERR("Failed to program DDC\n");
+                       return -ETIMEDOUT;
+               }
+
+       } else {
+               if (ext % 2 != 0)
+                       offset = 0x80;
+       }
+
+       /* Load Segment Address Register */
+       REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
+
+       /* Load Slave Address Register */
+       REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+
+       /* Load Offset Address Register */
+       REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+
+       /* Load Byte Count */
+       REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+       REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+
+       /* Set DDC_CMD */
+       if (ext)
+               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+       else
+               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+
+       /* HDMI_CORE_DDC_STATUS_BUS_LOW */
+       if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
+               DSSWARN("I2C Bus Low?\n");
+               return -EIO;
+       }
+       /* HDMI_CORE_DDC_STATUS_NO_ACK */
+       if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
+               DSSWARN("I2C No Ack\n");
+               return -EIO;
+       }
+
+       i = ext * 128;
+       j = 0;
+       while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) ||
+                       (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) &&
+                       j < 128) {
+
+               if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
+                       /* FIFO not empty */
+                       pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
+                       j++;
+               }
+       }
+
+       for (j = 0; j < 128; j++)
+               checksum += pedid[j];
+
+       if (checksum != 0) {
+               DSSERR("E-EDID checksum failed!!\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int read_edid(u8 *pedid, u16 max_length)
+{
+       int r = 0, n = 0, i = 0;
+       int max_ext_blocks = (max_length / 128) - 1;
+
+       r = hdmi_core_ddc_edid(pedid, 0);
+       if (r) {
+               return r;
+       } else {
+               n = pedid[0x7e];
+
+               /*
+                * README: need to comply with max_length set by the caller.
+                * Better implementation should be to allocate necessary
+                * memory to store EDID according to nb_block field found
+                * in first block
+                */
+               if (n > max_ext_blocks)
+                       n = max_ext_blocks;
+
+               for (i = 1; i <= n; i++) {
+                       r = hdmi_core_ddc_edid(pedid, i);
+                       if (r)
+                               return r;
+               }
+       }
+       return 0;
+}
+
+static int get_timings_index(void)
+{
+       int code;
+
+       if (hdmi.mode == 0)
+               code = code_vesa[hdmi.code];
+       else
+               code = code_cea[hdmi.code];
+
+       if (code == -1) {
+               /* HDMI code 4 corresponds to 640 * 480 VGA */
+               hdmi.code = 4;
+               /* DVI mode 1 corresponds to HDMI 0 to DVI */
+               hdmi.mode = HDMI_DVI;
+
+               code = code_vesa[hdmi.code];
+       }
+       return code;
+}
+
+static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
+{
+       int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
+       int timing_vsync = 0, timing_hsync = 0;
+       struct omap_video_timings temp;
+       struct hdmi_cm cm = {-1};
+       DSSDBG("hdmi_get_code\n");
+
+       for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) {
+               temp = cea_vesa_timings[i].timings;
+               if ((temp.pixel_clock == timing->pixel_clock) &&
+                       (temp.x_res == timing->x_res) &&
+                       (temp.y_res == timing->y_res)) {
+
+                       temp_hsync = temp.hfp + temp.hsw + temp.hbp;
+                       timing_hsync = timing->hfp + timing->hsw + timing->hbp;
+                       temp_vsync = temp.vfp + temp.vsw + temp.vbp;
+                       timing_vsync = timing->vfp + timing->vsw + timing->vbp;
+
+                       DSSDBG("temp_hsync = %d , temp_vsync = %d"
+                               "timing_hsync = %d, timing_vsync = %d\n",
+                               temp_hsync, temp_hsync,
+                               timing_hsync, timing_vsync);
+
+                       if ((temp_hsync == timing_hsync) &&
+                                       (temp_vsync == timing_vsync)) {
+                               code = i;
+                               cm.code = code_index[i];
+                               if (code < 14)
+                                       cm.mode = HDMI_HDMI;
+                               else
+                                       cm.mode = HDMI_DVI;
+                               DSSDBG("Hdmi_code = %d mode = %d\n",
+                                        cm.code, cm.mode);
+                               break;
+                        }
+               }
+       }
+
+       return cm;
+}
+
+static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
+               struct omap_video_timings *timings)
+{
+       /* X and Y resolution */
+       timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
+                        edid[current_descriptor_addrs + 2]);
+       timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
+                        edid[current_descriptor_addrs + 5]);
+
+       timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
+                               edid[current_descriptor_addrs]);
+
+       timings->pixel_clock = 10 * timings->pixel_clock;
+
+       /* HORIZONTAL FRONT PORCH */
+       timings->hfp = edid[current_descriptor_addrs + 8] |
+                       ((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
+       /* HORIZONTAL SYNC WIDTH */
+       timings->hsw = edid[current_descriptor_addrs + 9] |
+                       ((edid[current_descriptor_addrs + 11] & 0x30) << 4);
+       /* HORIZONTAL BACK PORCH */
+       timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
+                       edid[current_descriptor_addrs + 3]) -
+                       (timings->hfp + timings->hsw);
+       /* VERTICAL FRONT PORCH */
+       timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
+                       ((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
+       /* VERTICAL SYNC WIDTH */
+       timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
+                       ((edid[current_descriptor_addrs + 11] & 0x03) << 4);
+       /* VERTICAL BACK PORCH */
+       timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
+                       edid[current_descriptor_addrs + 6]) -
+                       (timings->vfp + timings->vsw);
+
+}
+
+/* Description : This function gets the resolution information from EDID */
+static void get_edid_timing_data(u8 *edid)
+{
+       u8 count;
+       u16 current_descriptor_addrs;
+       struct hdmi_cm cm;
+       struct omap_video_timings edid_timings;
+
+       /* seach block 0, there are 4 DTDs arranged in priority order */
+       for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
+               current_descriptor_addrs =
+                       EDID_DESCRIPTOR_BLOCK0_ADDRESS +
+                       count * EDID_TIMING_DESCRIPTOR_SIZE;
+               get_horz_vert_timing_info(current_descriptor_addrs,
+                               edid, &edid_timings);
+               cm = hdmi_get_code(&edid_timings);
+               DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
+                       count, cm.code, cm.mode);
+               if (cm.code == -1) {
+                       continue;
+               } else {
+                       hdmi.code = cm.code;
+                       hdmi.mode = cm.mode;
+                       DSSDBG("code = %d , mode = %d\n",
+                               hdmi.code, hdmi.mode);
+                       return;
+               }
+       }
+       if (edid[0x7e] != 0x00) {
+               for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
+                       count++) {
+                       current_descriptor_addrs =
+                       EDID_DESCRIPTOR_BLOCK1_ADDRESS +
+                       count * EDID_TIMING_DESCRIPTOR_SIZE;
+                       get_horz_vert_timing_info(current_descriptor_addrs,
+                                               edid, &edid_timings);
+                       cm = hdmi_get_code(&edid_timings);
+                       DSSDBG("Block1[%d] value matches code = %d, mode = %d",
+                               count, cm.code, cm.mode);
+                       if (cm.code == -1) {
+                               continue;
+                       } else {
+                               hdmi.code = cm.code;
+                               hdmi.mode = cm.mode;
+                               DSSDBG("code = %d , mode = %d\n",
+                                       hdmi.code, hdmi.mode);
+                               return;
+                       }
+               }
+       }
+
+       DSSINFO("no valid timing found , falling back to VGA\n");
+       hdmi.code = 4; /* setting default value of 640 480 VGA */
+       hdmi.mode = HDMI_DVI;
+}
+
+static void hdmi_read_edid(struct omap_video_timings *dp)
+{
+       int ret = 0, code;
+
+       memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
+
+       if (!hdmi.edid_set)
+               ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
+
+       if (!ret) {
+               if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
+                       /* search for timings of default resolution */
+                       get_edid_timing_data(hdmi.edid);
+                       hdmi.edid_set = true;
+               }
+       } else {
+               DSSWARN("failed to read E-EDID\n");
+       }
+
+       if (!hdmi.edid_set) {
+               DSSINFO("fallback to VGA\n");
+               hdmi.code = 4; /* setting default value of 640 480 VGA */
+               hdmi.mode = HDMI_DVI;
+       }
+
+       code = get_timings_index();
+
+       *dp = cea_vesa_timings[code].timings;
+}
+
+static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
+                       struct hdmi_core_infoframe_avi *avi_cfg,
+                       struct hdmi_core_packet_enable_repeat *repeat_cfg)
+{
+       DSSDBG("Enter hdmi_core_init\n");
+
+       /* video core */
+       video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
+       video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
+       video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
+       video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
+       video_cfg->hdmi_dvi = HDMI_DVI;
+       video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
+
+       /* info frame */
+       avi_cfg->db1_format = 0;
+       avi_cfg->db1_active_info = 0;
+       avi_cfg->db1_bar_info_dv = 0;
+       avi_cfg->db1_scan_info = 0;
+       avi_cfg->db2_colorimetry = 0;
+       avi_cfg->db2_aspect_ratio = 0;
+       avi_cfg->db2_active_fmt_ar = 0;
+       avi_cfg->db3_itc = 0;
+       avi_cfg->db3_ec = 0;
+       avi_cfg->db3_q_range = 0;
+       avi_cfg->db3_nup_scaling = 0;
+       avi_cfg->db4_videocode = 0;
+       avi_cfg->db5_pixel_repeat = 0;
+       avi_cfg->db6_7_line_eoftop = 0 ;
+       avi_cfg->db8_9_line_sofbottom = 0;
+       avi_cfg->db10_11_pixel_eofleft = 0;
+       avi_cfg->db12_13_pixel_sofright = 0;
+
+       /* packet enable and repeat */
+       repeat_cfg->audio_pkt = 0;
+       repeat_cfg->audio_pkt_repeat = 0;
+       repeat_cfg->avi_infoframe = 0;
+       repeat_cfg->avi_infoframe_repeat = 0;
+       repeat_cfg->gen_cntrl_pkt = 0;
+       repeat_cfg->gen_cntrl_pkt_repeat = 0;
+       repeat_cfg->generic_pkt = 0;
+       repeat_cfg->generic_pkt_repeat = 0;
+}
+
+static void hdmi_core_powerdown_disable(void)
+{
+       DSSDBG("Enter hdmi_core_powerdown_disable\n");
+       REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_release(void)
+{
+       DSSDBG("Enter hdmi_core_swreset_release\n");
+       REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_assert(void)
+{
+       DSSDBG("Enter hdmi_core_swreset_assert\n");
+       REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+}
+
+/* DSS_HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
+{
+       u32 r = 0;
+
+       /* sys_ctrl1 default configuration not tunable */
+       r = hdmi_read_reg(HDMI_CORE_CTRL1);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
+       hdmi_write_reg(HDMI_CORE_CTRL1, r);
+
+       REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+
+       /* Vid_Mode */
+       r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
+
+       /* dither truncation configuration */
+       if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
+               r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
+               r = FLD_MOD(r, 1, 5, 5);
+       } else {
+               r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
+               r = FLD_MOD(r, 0, 5, 5);
+       }
+       hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
+
+       /* HDMI_Ctrl */
+       r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
+       r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
+       r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
+       r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
+       hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
+
+       /* TMDS_CTRL */
+       REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
+               cfg->tclk_sel_clkmult, 6, 5);
+}
+
+static void hdmi_core_aux_infoframe_avi_config(
+               struct hdmi_core_infoframe_avi info_avi)
+{
+       u32 val;
+       char sum = 0, checksum = 0;
+
+       sum += 0x82 + 0x002 + 0x00D;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
+
+       val = (info_avi.db1_format << 5) |
+               (info_avi.db1_active_info << 4) |
+               (info_avi.db1_bar_info_dv << 2) |
+               (info_avi.db1_scan_info);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
+       sum += val;
+
+       val = (info_avi.db2_colorimetry << 6) |
+               (info_avi.db2_aspect_ratio << 4) |
+               (info_avi.db2_active_fmt_ar);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
+       sum += val;
+
+       val = (info_avi.db3_itc << 7) |
+               (info_avi.db3_ec << 4) |
+               (info_avi.db3_q_range << 2) |
+               (info_avi.db3_nup_scaling);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
+       sum += val;
+
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
+       sum += info_avi.db4_videocode;
+
+       val = info_avi.db5_pixel_repeat;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
+       sum += val;
+
+       val = info_avi.db6_7_line_eoftop & 0x00FF;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
+       sum += val;
+
+       val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
+       sum += val;
+
+       val = info_avi.db8_9_line_sofbottom & 0x00FF;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
+       sum += val;
+
+       val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
+       sum += val;
+
+       val = info_avi.db10_11_pixel_eofleft & 0x00FF;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
+       sum += val;
+
+       val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
+       sum += val;
+
+       val = info_avi.db12_13_pixel_sofright & 0x00FF;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
+       sum += val;
+
+       val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
+       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
+       sum += val;
+
+       checksum = 0x100 - sum;
+       hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
+}
+
+static void hdmi_core_av_packet_config(
+               struct hdmi_core_packet_enable_repeat repeat_cfg)
+{
+       /* enable/repeat the infoframe */
+       hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
+               (repeat_cfg.audio_pkt << 5) |
+               (repeat_cfg.audio_pkt_repeat << 4) |
+               (repeat_cfg.avi_infoframe << 1) |
+               (repeat_cfg.avi_infoframe_repeat));
+
+       /* enable/repeat the packet */
+       hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
+               (repeat_cfg.gen_cntrl_pkt << 3) |
+               (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
+               (repeat_cfg.generic_pkt << 1) |
+               (repeat_cfg.generic_pkt_repeat));
+}
+
+static void hdmi_wp_init(struct omap_video_timings *timings,
+                       struct hdmi_video_format *video_fmt,
+                       struct hdmi_video_interface *video_int)
+{
+       DSSDBG("Enter hdmi_wp_init\n");
+
+       timings->hbp = 0;
+       timings->hfp = 0;
+       timings->hsw = 0;
+       timings->vbp = 0;
+       timings->vfp = 0;
+       timings->vsw = 0;
+
+       video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
+       video_fmt->y_res = 0;
+       video_fmt->x_res = 0;
+
+       video_int->vsp = 0;
+       video_int->hsp = 0;
+
+       video_int->interlacing = 0;
+       video_int->tm = 0; /* HDMI_TIMING_SLAVE */
+
+}
+
+static void hdmi_wp_video_start(bool start)
+{
+       REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
+}
+
+static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
+       struct omap_video_timings *timings, struct hdmi_config *param)
+{
+       DSSDBG("Enter hdmi_wp_video_init_format\n");
+
+       video_fmt->y_res = param->timings.timings.y_res;
+       video_fmt->x_res = param->timings.timings.x_res;
+
+       timings->hbp = param->timings.timings.hbp;
+       timings->hfp = param->timings.timings.hfp;
+       timings->hsw = param->timings.timings.hsw;
+       timings->vbp = param->timings.timings.vbp;
+       timings->vfp = param->timings.timings.vfp;
+       timings->vsw = param->timings.timings.vsw;
+}
+
+static void hdmi_wp_video_config_format(
+               struct hdmi_video_format *video_fmt)
+{
+       u32 l = 0;
+
+       REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
+
+       l |= FLD_VAL(video_fmt->y_res, 31, 16);
+       l |= FLD_VAL(video_fmt->x_res, 15, 0);
+       hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
+}
+
+static void hdmi_wp_video_config_interface(
+               struct hdmi_video_interface *video_int)
+{
+       u32 r;
+       DSSDBG("Enter hdmi_wp_video_config_interface\n");
+
+       r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
+       r = FLD_MOD(r, video_int->vsp, 7, 7);
+       r = FLD_MOD(r, video_int->hsp, 6, 6);
+       r = FLD_MOD(r, video_int->interlacing, 3, 3);
+       r = FLD_MOD(r, video_int->tm, 1, 0);
+       hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
+}
+
+static void hdmi_wp_video_config_timing(
+               struct omap_video_timings *timings)
+{
+       u32 timing_h = 0;
+       u32 timing_v = 0;
+
+       DSSDBG("Enter hdmi_wp_video_config_timing\n");
+
+       timing_h |= FLD_VAL(timings->hbp, 31, 20);
+       timing_h |= FLD_VAL(timings->hfp, 19, 8);
+       timing_h |= FLD_VAL(timings->hsw, 7, 0);
+       hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
+
+       timing_v |= FLD_VAL(timings->vbp, 31, 20);
+       timing_v |= FLD_VAL(timings->vfp, 19, 8);
+       timing_v |= FLD_VAL(timings->vsw, 7, 0);
+       hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
+}
+
+static void hdmi_basic_configure(struct hdmi_config *cfg)
+{
+       /* HDMI */
+       struct omap_video_timings video_timing;
+       struct hdmi_video_format video_format;
+       struct hdmi_video_interface video_interface;
+       /* HDMI core */
+       struct hdmi_core_infoframe_avi avi_cfg;
+       struct hdmi_core_video_config v_core_cfg;
+       struct hdmi_core_packet_enable_repeat repeat_cfg;
+
+       hdmi_wp_init(&video_timing, &video_format,
+               &video_interface);
+
+       hdmi_core_init(&v_core_cfg,
+               &avi_cfg,
+               &repeat_cfg);
+
+       hdmi_wp_video_init_format(&video_format,
+                       &video_timing, cfg);
+
+       hdmi_wp_video_config_timing(&video_timing);
+
+       /* video config */
+       video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+
+       hdmi_wp_video_config_format(&video_format);
+
+       video_interface.vsp = cfg->timings.vsync_pol;
+       video_interface.hsp = cfg->timings.hsync_pol;
+       video_interface.interlacing = cfg->interlace;
+       video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
+
+       hdmi_wp_video_config_interface(&video_interface);
+
+       /*
+        * configure core video part
+        * set software reset in the core
+        */
+       hdmi_core_swreset_assert();
+
+       /* power down off */
+       hdmi_core_powerdown_disable();
+
+       v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
+       v_core_cfg.hdmi_dvi = cfg->cm.mode;
+
+       hdmi_core_video_config(&v_core_cfg);
+
+       /* release software reset in the core */
+       hdmi_core_swreset_release();
+
+       /*
+        * configure packet
+        * info frame video see doc CEA861-D page 65
+        */
+       avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
+       avi_cfg.db1_active_info =
+               HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
+       avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
+       avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
+       avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
+       avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
+       avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
+       avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
+       avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
+       avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
+       avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
+       avi_cfg.db4_videocode = cfg->cm.code;
+       avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
+       avi_cfg.db6_7_line_eoftop = 0;
+       avi_cfg.db8_9_line_sofbottom = 0;
+       avi_cfg.db10_11_pixel_eofleft = 0;
+       avi_cfg.db12_13_pixel_sofright = 0;
+
+       hdmi_core_aux_infoframe_avi_config(avi_cfg);
+
+       /* enable/repeat the infoframe */
+       repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
+       repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
+       /* wakeup */
+       repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
+       repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
+       hdmi_core_av_packet_config(repeat_cfg);
+}
+
+static void update_hdmi_timings(struct hdmi_config *cfg,
+               struct omap_video_timings *timings, int code)
+{
+       cfg->timings.timings.x_res = timings->x_res;
+       cfg->timings.timings.y_res = timings->y_res;
+       cfg->timings.timings.hbp = timings->hbp;
+       cfg->timings.timings.hfp = timings->hfp;
+       cfg->timings.timings.hsw = timings->hsw;
+       cfg->timings.timings.vbp = timings->vbp;
+       cfg->timings.timings.vfp = timings->vfp;
+       cfg->timings.timings.vsw = timings->vsw;
+       cfg->timings.timings.pixel_clock = timings->pixel_clock;
+       cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol;
+       cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
+}
+
+static void hdmi_compute_pll(unsigned long clkin, int phy,
+       int n, struct hdmi_pll_info *pi)
+{
+       unsigned long refclk;
+       u32 mf;
+
+       /*
+        * Input clock is predivided by N + 1
+        * out put of which is reference clk
+        */
+       refclk = clkin / (n + 1);
+       pi->regn = n;
+
+       /*
+        * multiplier is pixel_clk/ref_clk
+        * Multiplying by 100 to avoid fractional part removal
+        */
+       pi->regm = (phy * 100/(refclk))/100;
+       pi->regm2 = 1;
+
+       /*
+        * fractional multiplier is remainder of the difference between
+        * multiplier and actual phy(required pixel clock thus should be
+        * multiplied by 2^18(262144) divided by the reference clock
+        */
+       mf = (phy - pi->regm * refclk) * 262144;
+       pi->regmf = mf/(refclk);
+
+       /*
+        * Dcofreq should be set to 1 if required pixel clock
+        * is greater than 1000MHz
+        */
+       pi->dcofreq = phy > 1000 * 100;
+       pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10;
+
+       DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
+       DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
+}
+
+static void hdmi_enable_clocks(int enable)
+{
+       if (enable)
+               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
+                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+       else
+               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
+                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+}
+
+static int hdmi_power_on(struct omap_dss_device *dssdev)
+{
+       int r, code = 0;
+       struct hdmi_pll_info pll_data;
+       struct omap_video_timings *p;
+       int clkin, n, phy;
+
+       hdmi_enable_clocks(1);
+
+       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+
+       p = &dssdev->panel.timings;
+
+       DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
+               dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+
+       if (!hdmi.custom_set) {
+               DSSDBG("Read EDID as no EDID is not set on poweron\n");
+               hdmi_read_edid(p);
+       }
+       code = get_timings_index();
+       dssdev->panel.timings = cea_vesa_timings[code].timings;
+       update_hdmi_timings(&hdmi.cfg, p, code);
+
+       clkin = 3840; /* 38.4 MHz */
+       n = 15; /* this is a constant for our math */
+       phy = p->pixel_clock;
+
+       hdmi_compute_pll(clkin, phy, n, &pll_data);
+
+       hdmi_wp_video_start(0);
+
+       /* config the PLL and PHY first */
+       r = hdmi_pll_program(&pll_data);
+       if (r) {
+               DSSDBG("Failed to lock PLL\n");
+               goto err;
+       }
+
+       r = hdmi_phy_init();
+       if (r) {
+               DSSDBG("Failed to start PHY\n");
+               goto err;
+       }
+
+       hdmi.cfg.cm.mode = hdmi.mode;
+       hdmi.cfg.cm.code = hdmi.code;
+       hdmi_basic_configure(&hdmi.cfg);
+
+       /* Make selection of HDMI in DSS */
+       dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+       /* Select the dispc clock source as PRCM clock, to ensure that it is not
+        * DSI PLL source as the clock selected by DSI PLL might not be
+        * sufficient for the resolution selected / that can be changed
+        * dynamically by user. This can be moved to single location , say
+        * Boardfile.
+        */
+       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
+
+       /* bypass TV gamma table */
+       dispc_enable_gamma_table(0);
+
+       /* tv size */
+       dispc_set_digit_size(dssdev->panel.timings.x_res,
+                       dssdev->panel.timings.y_res);
+
+       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
+
+       hdmi_wp_video_start(1);
+
+       return 0;
+err:
+       hdmi_enable_clocks(0);
+       return -EIO;
+}
+
+static void hdmi_power_off(struct omap_dss_device *dssdev)
+{
+       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+
+       hdmi_wp_video_start(0);
+       hdmi_phy_off();
+       hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+       hdmi_enable_clocks(0);
+
+       hdmi.edid_set = 0;
+}
+
+int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
+                                       struct omap_video_timings *timings)
+{
+       struct hdmi_cm cm;
+
+       cm = hdmi_get_code(timings);
+       if (cm.code == -1) {
+               DSSERR("Invalid timing entered\n");
+               return -EINVAL;
+       }
+
+       return 0;
+
+}
+
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
+{
+       struct hdmi_cm cm;
+
+       hdmi.custom_set = 1;
+       cm = hdmi_get_code(&dssdev->panel.timings);
+       hdmi.code = cm.code;
+       hdmi.mode = cm.mode;
+       omapdss_hdmi_display_enable(dssdev);
+       hdmi.custom_set = 0;
+}
+
+int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       DSSDBG("ENTER hdmi_display_enable\n");
+
+       mutex_lock(&hdmi.lock);
+
+       r = omap_dss_start_device(dssdev);
+       if (r) {
+               DSSERR("failed to start device\n");
+               goto err0;
+       }
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r) {
+                       DSSERR("failed to enable GPIO's\n");
+                       goto err1;
+               }
+       }
+
+       r = hdmi_power_on(dssdev);
+       if (r) {
+               DSSERR("failed to power on device\n");
+               goto err2;
+       }
+
+       mutex_unlock(&hdmi.lock);
+       return 0;
+
+err2:
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+err1:
+       omap_dss_stop_device(dssdev);
+err0:
+       mutex_unlock(&hdmi.lock);
+       return r;
+}
+
+void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
+{
+       DSSDBG("Enter hdmi_display_disable\n");
+
+       mutex_lock(&hdmi.lock);
+
+       hdmi_power_off(dssdev);
+
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       omap_dss_stop_device(dssdev);
+
+       mutex_unlock(&hdmi.lock);
+}
+
+/* HDMI HW IP initialisation */
+static int omapdss_hdmihw_probe(struct platform_device *pdev)
+{
+       struct resource *hdmi_mem;
+
+       hdmi.pdata = pdev->dev.platform_data;
+       hdmi.pdev = pdev;
+
+       mutex_init(&hdmi.lock);
+
+       hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+       if (!hdmi_mem) {
+               DSSERR("can't get IORESOURCE_MEM HDMI\n");
+               return -EINVAL;
+       }
+
+       /* Base address taken from platform */
+       hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
+       if (!hdmi.base_wp) {
+               DSSERR("can't ioremap WP\n");
+               return -ENOMEM;
+       }
+
+       hdmi_panel_init();
+
+       return 0;
+}
+
+static int omapdss_hdmihw_remove(struct platform_device *pdev)
+{
+       hdmi_panel_exit();
+
+       iounmap(hdmi.base_wp);
+
+       return 0;
+}
+
+static struct platform_driver omapdss_hdmihw_driver = {
+       .probe          = omapdss_hdmihw_probe,
+       .remove         = omapdss_hdmihw_remove,
+       .driver         = {
+               .name   = "omapdss_hdmi",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int hdmi_init_platform_driver(void)
+{
+       return platform_driver_register(&omapdss_hdmihw_driver);
+}
+
+void hdmi_uninit_platform_driver(void)
+{
+       return platform_driver_unregister(&omapdss_hdmihw_driver);
+}
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
new file mode 100644 (file)
index 0000000..9887ab9
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * hdmi.h
+ *
+ * HDMI driver definition for TI OMAP4 processors.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _OMAP4_DSS_HDMI_H_
+#define _OMAP4_DSS_HDMI_H_
+
+#include <linux/string.h>
+#include <plat/display.h>
+
+#define HDMI_WP                0x0
+#define HDMI_CORE_SYS          0x400
+#define HDMI_CORE_AV           0x900
+#define HDMI_PLLCTRL           0x200
+#define HDMI_PHY               0x300
+
+struct hdmi_reg { u16 idx; };
+
+#define HDMI_REG(idx)                  ((const struct hdmi_reg) { idx })
+
+/* HDMI Wrapper */
+#define HDMI_WP_REG(idx)                       HDMI_REG(HDMI_WP + idx)
+
+#define HDMI_WP_REVISION                       HDMI_WP_REG(0x0)
+#define HDMI_WP_SYSCONFIG                      HDMI_WP_REG(0x10)
+#define HDMI_WP_IRQSTATUS_RAW                  HDMI_WP_REG(0x24)
+#define HDMI_WP_IRQSTATUS                      HDMI_WP_REG(0x28)
+#define HDMI_WP_PWR_CTRL                       HDMI_WP_REG(0x40)
+#define HDMI_WP_IRQENABLE_SET                  HDMI_WP_REG(0x2C)
+#define HDMI_WP_VIDEO_CFG                      HDMI_WP_REG(0x50)
+#define HDMI_WP_VIDEO_SIZE                     HDMI_WP_REG(0x60)
+#define HDMI_WP_VIDEO_TIMING_H                 HDMI_WP_REG(0x68)
+#define HDMI_WP_VIDEO_TIMING_V                 HDMI_WP_REG(0x6C)
+#define HDMI_WP_WP_CLK                         HDMI_WP_REG(0x70)
+
+/* HDMI IP Core System */
+#define HDMI_CORE_SYS_REG(idx)                 HDMI_REG(HDMI_CORE_SYS + idx)
+
+#define HDMI_CORE_SYS_VND_IDL                  HDMI_CORE_SYS_REG(0x0)
+#define HDMI_CORE_SYS_DEV_IDL                  HDMI_CORE_SYS_REG(0x8)
+#define HDMI_CORE_SYS_DEV_IDH                  HDMI_CORE_SYS_REG(0xC)
+#define HDMI_CORE_SYS_DEV_REV                  HDMI_CORE_SYS_REG(0x10)
+#define HDMI_CORE_SYS_SRST                     HDMI_CORE_SYS_REG(0x14)
+#define HDMI_CORE_CTRL1                        HDMI_CORE_SYS_REG(0x20)
+#define HDMI_CORE_SYS_SYS_STAT                 HDMI_CORE_SYS_REG(0x24)
+#define HDMI_CORE_SYS_VID_ACEN                 HDMI_CORE_SYS_REG(0x124)
+#define HDMI_CORE_SYS_VID_MODE                 HDMI_CORE_SYS_REG(0x128)
+#define HDMI_CORE_SYS_INTR_STATE               HDMI_CORE_SYS_REG(0x1C0)
+#define HDMI_CORE_SYS_INTR1                    HDMI_CORE_SYS_REG(0x1C4)
+#define HDMI_CORE_SYS_INTR2                    HDMI_CORE_SYS_REG(0x1C8)
+#define HDMI_CORE_SYS_INTR3                    HDMI_CORE_SYS_REG(0x1CC)
+#define HDMI_CORE_SYS_INTR4                    HDMI_CORE_SYS_REG(0x1D0)
+#define HDMI_CORE_SYS_UMASK1                   HDMI_CORE_SYS_REG(0x1D4)
+#define HDMI_CORE_SYS_TMDS_CTRL                HDMI_CORE_SYS_REG(0x208)
+#define HDMI_CORE_SYS_DE_DLY                   HDMI_CORE_SYS_REG(0xC8)
+#define HDMI_CORE_SYS_DE_CTRL                  HDMI_CORE_SYS_REG(0xCC)
+#define HDMI_CORE_SYS_DE_TOP                   HDMI_CORE_SYS_REG(0xD0)
+#define HDMI_CORE_SYS_DE_CNTL                  HDMI_CORE_SYS_REG(0xD8)
+#define HDMI_CORE_SYS_DE_CNTH                  HDMI_CORE_SYS_REG(0xDC)
+#define HDMI_CORE_SYS_DE_LINL                  HDMI_CORE_SYS_REG(0xE0)
+#define HDMI_CORE_SYS_DE_LINH_1                HDMI_CORE_SYS_REG(0xE4)
+#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC        0x1
+#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC        0x1
+#define HDMI_CORE_CTRL1_BSEL_24BITBUS          0x1
+#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE        0x1
+
+/* HDMI DDC E-DID */
+#define HDMI_CORE_DDC_CMD                      HDMI_CORE_SYS_REG(0x3CC)
+#define HDMI_CORE_DDC_STATUS                   HDMI_CORE_SYS_REG(0x3C8)
+#define HDMI_CORE_DDC_ADDR                     HDMI_CORE_SYS_REG(0x3B4)
+#define HDMI_CORE_DDC_OFFSET                   HDMI_CORE_SYS_REG(0x3BC)
+#define HDMI_CORE_DDC_COUNT1                   HDMI_CORE_SYS_REG(0x3C0)
+#define HDMI_CORE_DDC_COUNT2                   HDMI_CORE_SYS_REG(0x3C4)
+#define HDMI_CORE_DDC_DATA                     HDMI_CORE_SYS_REG(0x3D0)
+#define HDMI_CORE_DDC_SEGM                     HDMI_CORE_SYS_REG(0x3B8)
+
+/* HDMI IP Core Audio Video */
+#define HDMI_CORE_AV_REG(idx)                  HDMI_REG(HDMI_CORE_AV + idx)
+
+#define HDMI_CORE_AV_HDMI_CTRL                 HDMI_CORE_AV_REG(0xBC)
+#define HDMI_CORE_AV_DPD                       HDMI_CORE_AV_REG(0xF4)
+#define HDMI_CORE_AV_PB_CTRL1                  HDMI_CORE_AV_REG(0xF8)
+#define HDMI_CORE_AV_PB_CTRL2                  HDMI_CORE_AV_REG(0xFC)
+#define HDMI_CORE_AV_AVI_TYPE                  HDMI_CORE_AV_REG(0x100)
+#define HDMI_CORE_AV_AVI_VERS                  HDMI_CORE_AV_REG(0x104)
+#define HDMI_CORE_AV_AVI_LEN                   HDMI_CORE_AV_REG(0x108)
+#define HDMI_CORE_AV_AVI_CHSUM                 HDMI_CORE_AV_REG(0x10C)
+#define HDMI_CORE_AV_AVI_DBYTE(n)              HDMI_CORE_AV_REG(n * 4 + 0x110)
+#define HDMI_CORE_AV_AVI_DBYTE_NELEMS          HDMI_CORE_AV_REG(15)
+#define HDMI_CORE_AV_SPD_DBYTE                 HDMI_CORE_AV_REG(0x190)
+#define HDMI_CORE_AV_SPD_DBYTE_NELEMS          HDMI_CORE_AV_REG(27)
+#define HDMI_CORE_AV_MPEG_DBYTE                HDMI_CORE_AV_REG(0x290)
+#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS         HDMI_CORE_AV_REG(27)
+#define HDMI_CORE_AV_GEN_DBYTE                 HDMI_CORE_AV_REG(0x300)
+#define HDMI_CORE_AV_GEN_DBYTE_NELEMS          HDMI_CORE_AV_REG(31)
+#define HDMI_CORE_AV_GEN2_DBYTE                HDMI_CORE_AV_REG(0x380)
+#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS         HDMI_CORE_AV_REG(31)
+#define HDMI_CORE_AV_ACR_CTRL                  HDMI_CORE_AV_REG(0x4)
+#define HDMI_CORE_AV_FREQ_SVAL                 HDMI_CORE_AV_REG(0x8)
+#define HDMI_CORE_AV_N_SVAL1                   HDMI_CORE_AV_REG(0xC)
+#define HDMI_CORE_AV_N_SVAL2                   HDMI_CORE_AV_REG(0x10)
+#define HDMI_CORE_AV_N_SVAL3                   HDMI_CORE_AV_REG(0x14)
+#define HDMI_CORE_AV_CTS_SVAL1                 HDMI_CORE_AV_REG(0x18)
+#define HDMI_CORE_AV_CTS_SVAL2                 HDMI_CORE_AV_REG(0x1C)
+#define HDMI_CORE_AV_CTS_SVAL3                 HDMI_CORE_AV_REG(0x20)
+#define HDMI_CORE_AV_CTS_HVAL1                 HDMI_CORE_AV_REG(0x24)
+#define HDMI_CORE_AV_CTS_HVAL2                 HDMI_CORE_AV_REG(0x28)
+#define HDMI_CORE_AV_CTS_HVAL3                 HDMI_CORE_AV_REG(0x2C)
+#define HDMI_CORE_AV_AUD_MODE                  HDMI_CORE_AV_REG(0x50)
+#define HDMI_CORE_AV_SPDIF_CTRL                HDMI_CORE_AV_REG(0x54)
+#define HDMI_CORE_AV_HW_SPDIF_FS               HDMI_CORE_AV_REG(0x60)
+#define HDMI_CORE_AV_SWAP_I2S                  HDMI_CORE_AV_REG(0x64)
+#define HDMI_CORE_AV_SPDIF_ERTH                HDMI_CORE_AV_REG(0x6C)
+#define HDMI_CORE_AV_I2S_IN_MAP                HDMI_CORE_AV_REG(0x70)
+#define HDMI_CORE_AV_I2S_IN_CTRL               HDMI_CORE_AV_REG(0x74)
+#define HDMI_CORE_AV_I2S_CHST0                 HDMI_CORE_AV_REG(0x78)
+#define HDMI_CORE_AV_I2S_CHST1                 HDMI_CORE_AV_REG(0x7C)
+#define HDMI_CORE_AV_I2S_CHST2                 HDMI_CORE_AV_REG(0x80)
+#define HDMI_CORE_AV_I2S_CHST4                 HDMI_CORE_AV_REG(0x84)
+#define HDMI_CORE_AV_I2S_CHST5                 HDMI_CORE_AV_REG(0x88)
+#define HDMI_CORE_AV_ASRC                      HDMI_CORE_AV_REG(0x8C)
+#define HDMI_CORE_AV_I2S_IN_LEN                HDMI_CORE_AV_REG(0x90)
+#define HDMI_CORE_AV_HDMI_CTRL                 HDMI_CORE_AV_REG(0xBC)
+#define HDMI_CORE_AV_AUDO_TXSTAT               HDMI_CORE_AV_REG(0xC0)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1          HDMI_CORE_AV_REG(0xCC)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2          HDMI_CORE_AV_REG(0xD0)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3          HDMI_CORE_AV_REG(0xD4)
+#define HDMI_CORE_AV_TEST_TXCTRL               HDMI_CORE_AV_REG(0xF0)
+#define HDMI_CORE_AV_DPD                       HDMI_CORE_AV_REG(0xF4)
+#define HDMI_CORE_AV_PB_CTRL1                  HDMI_CORE_AV_REG(0xF8)
+#define HDMI_CORE_AV_PB_CTRL2                  HDMI_CORE_AV_REG(0xFC)
+#define HDMI_CORE_AV_AVI_TYPE                  HDMI_CORE_AV_REG(0x100)
+#define HDMI_CORE_AV_AVI_VERS                  HDMI_CORE_AV_REG(0x104)
+#define HDMI_CORE_AV_AVI_LEN                   HDMI_CORE_AV_REG(0x108)
+#define HDMI_CORE_AV_AVI_CHSUM                 HDMI_CORE_AV_REG(0x10C)
+#define HDMI_CORE_AV_SPD_TYPE                  HDMI_CORE_AV_REG(0x180)
+#define HDMI_CORE_AV_SPD_VERS                  HDMI_CORE_AV_REG(0x184)
+#define HDMI_CORE_AV_SPD_LEN                   HDMI_CORE_AV_REG(0x188)
+#define HDMI_CORE_AV_SPD_CHSUM                 HDMI_CORE_AV_REG(0x18C)
+#define HDMI_CORE_AV_MPEG_TYPE                 HDMI_CORE_AV_REG(0x280)
+#define HDMI_CORE_AV_MPEG_VERS                 HDMI_CORE_AV_REG(0x284)
+#define HDMI_CORE_AV_MPEG_LEN                  HDMI_CORE_AV_REG(0x288)
+#define HDMI_CORE_AV_MPEG_CHSUM                HDMI_CORE_AV_REG(0x28C)
+#define HDMI_CORE_AV_CP_BYTE1                  HDMI_CORE_AV_REG(0x37C)
+#define HDMI_CORE_AV_CEC_ADDR_ID               HDMI_CORE_AV_REG(0x3FC)
+#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE          0x4
+#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE         0x4
+#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE         0x4
+#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE          0x4
+
+/* PLL */
+#define HDMI_PLL_REG(idx)                      HDMI_REG(HDMI_PLLCTRL + idx)
+
+#define PLLCTRL_PLL_CONTROL                    HDMI_PLL_REG(0x0)
+#define PLLCTRL_PLL_STATUS                     HDMI_PLL_REG(0x4)
+#define PLLCTRL_PLL_GO                         HDMI_PLL_REG(0x8)
+#define PLLCTRL_CFG1                           HDMI_PLL_REG(0xC)
+#define PLLCTRL_CFG2                           HDMI_PLL_REG(0x10)
+#define PLLCTRL_CFG3                           HDMI_PLL_REG(0x14)
+#define PLLCTRL_CFG4                           HDMI_PLL_REG(0x20)
+
+/* HDMI PHY */
+#define HDMI_PHY_REG(idx)                      HDMI_REG(HDMI_PHY + idx)
+
+#define HDMI_TXPHY_TX_CTRL                     HDMI_PHY_REG(0x0)
+#define HDMI_TXPHY_DIGITAL_CTRL                HDMI_PHY_REG(0x4)
+#define HDMI_TXPHY_POWER_CTRL                  HDMI_PHY_REG(0x8)
+#define HDMI_TXPHY_PAD_CFG_CTRL                HDMI_PHY_REG(0xC)
+
+/* HDMI EDID Length  */
+#define HDMI_EDID_MAX_LENGTH                   256
+#define EDID_TIMING_DESCRIPTOR_SIZE            0x12
+#define EDID_DESCRIPTOR_BLOCK0_ADDRESS         0x36
+#define EDID_DESCRIPTOR_BLOCK1_ADDRESS         0x80
+#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR     4
+#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR     4
+
+#define OMAP_HDMI_TIMINGS_NB                   34
+
+#define REG_FLD_MOD(idx, val, start, end) \
+       hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end))
+#define REG_GET(idx, start, end) \
+       FLD_GET(hdmi_read_reg(idx), start, end)
+
+/* HDMI timing structure */
+struct hdmi_timings {
+       struct omap_video_timings timings;
+       int vsync_pol;
+       int hsync_pol;
+};
+
+enum hdmi_phy_pwr {
+       HDMI_PHYPWRCMD_OFF = 0,
+       HDMI_PHYPWRCMD_LDOON = 1,
+       HDMI_PHYPWRCMD_TXON = 2
+};
+
+enum hdmi_pll_pwr {
+       HDMI_PLLPWRCMD_ALLOFF = 0,
+       HDMI_PLLPWRCMD_PLLONLY = 1,
+       HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
+       HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
+};
+
+enum hdmi_clk_refsel {
+       HDMI_REFSEL_PCLK = 0,
+       HDMI_REFSEL_REF1 = 1,
+       HDMI_REFSEL_REF2 = 2,
+       HDMI_REFSEL_SYSCLK = 3
+};
+
+enum hdmi_core_inputbus_width {
+       HDMI_INPUT_8BIT = 0,
+       HDMI_INPUT_10BIT = 1,
+       HDMI_INPUT_12BIT = 2
+};
+
+enum hdmi_core_dither_trunc {
+       HDMI_OUTPUTTRUNCATION_8BIT = 0,
+       HDMI_OUTPUTTRUNCATION_10BIT = 1,
+       HDMI_OUTPUTTRUNCATION_12BIT = 2,
+       HDMI_OUTPUTDITHER_8BIT = 3,
+       HDMI_OUTPUTDITHER_10BIT = 4,
+       HDMI_OUTPUTDITHER_12BIT = 5
+};
+
+enum hdmi_core_deepcolor_ed {
+       HDMI_DEEPCOLORPACKECTDISABLE = 0,
+       HDMI_DEEPCOLORPACKECTENABLE = 1
+};
+
+enum hdmi_core_packet_mode {
+       HDMI_PACKETMODERESERVEDVALUE = 0,
+       HDMI_PACKETMODE24BITPERPIXEL = 4,
+       HDMI_PACKETMODE30BITPERPIXEL = 5,
+       HDMI_PACKETMODE36BITPERPIXEL = 6,
+       HDMI_PACKETMODE48BITPERPIXEL = 7
+};
+
+enum hdmi_core_hdmi_dvi {
+       HDMI_DVI = 0,
+       HDMI_HDMI = 1
+};
+
+enum hdmi_core_tclkselclkmult {
+       HDMI_FPLL05IDCK = 0,
+       HDMI_FPLL10IDCK = 1,
+       HDMI_FPLL20IDCK = 2,
+       HDMI_FPLL40IDCK = 3
+};
+
+enum hdmi_core_packet_ctrl {
+       HDMI_PACKETENABLE = 1,
+       HDMI_PACKETDISABLE = 0,
+       HDMI_PACKETREPEATON = 1,
+       HDMI_PACKETREPEATOFF = 0
+};
+
+/* INFOFRAME_AVI_ definitions */
+enum hdmi_core_infoframe {
+       HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
+       HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
+       HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
+       HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
+       HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON =  1,
+       HDMI_INFOFRAME_AVI_DB1B_NO = 0,
+       HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
+       HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
+       HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
+       HDMI_INFOFRAME_AVI_DB1S_0 = 0,
+       HDMI_INFOFRAME_AVI_DB1S_1 = 1,
+       HDMI_INFOFRAME_AVI_DB1S_2 = 2,
+       HDMI_INFOFRAME_AVI_DB2C_NO = 0,
+       HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
+       HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
+       HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
+       HDMI_INFOFRAME_AVI_DB2M_NO = 0,
+       HDMI_INFOFRAME_AVI_DB2M_43 = 1,
+       HDMI_INFOFRAME_AVI_DB2M_169 = 2,
+       HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
+       HDMI_INFOFRAME_AVI_DB2R_43 = 9,
+       HDMI_INFOFRAME_AVI_DB2R_169 = 10,
+       HDMI_INFOFRAME_AVI_DB2R_149 = 11,
+       HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
+       HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
+       HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
+       HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
+       HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
+       HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
+       HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
+       HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
+       HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
+       HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
+       HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
+       HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
+       HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
+       HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
+       HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
+       HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
+       HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
+       HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
+       HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
+       HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
+       HDMI_INFOFRAME_AVI_DB5PR_10 = 9
+};
+
+enum hdmi_packing_mode {
+       HDMI_PACK_10b_RGB_YUV444 = 0,
+       HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
+       HDMI_PACK_20b_YUV422 = 2,
+       HDMI_PACK_ALREADYPACKED = 7
+};
+
+struct hdmi_core_video_config {
+       enum hdmi_core_inputbus_width   ip_bus_width;
+       enum hdmi_core_dither_trunc     op_dither_truc;
+       enum hdmi_core_deepcolor_ed     deep_color_pkt;
+       enum hdmi_core_packet_mode      pkt_mode;
+       enum hdmi_core_hdmi_dvi         hdmi_dvi;
+       enum hdmi_core_tclkselclkmult   tclk_sel_clkmult;
+};
+
+/*
+ * Refer to section 8.2 in HDMI 1.3 specification for
+ * details about infoframe databytes
+ */
+struct hdmi_core_infoframe_avi {
+       u8      db1_format;
+               /* Y0, Y1 rgb,yCbCr */
+       u8      db1_active_info;
+               /* A0  Active information Present */
+       u8      db1_bar_info_dv;
+               /* B0, B1 Bar info data valid */
+       u8      db1_scan_info;
+               /* S0, S1 scan information */
+       u8      db2_colorimetry;
+               /* C0, C1 colorimetry */
+       u8      db2_aspect_ratio;
+               /* M0, M1 Aspect ratio (4:3, 16:9) */
+       u8      db2_active_fmt_ar;
+               /* R0...R3 Active format aspect ratio */
+       u8      db3_itc;
+               /* ITC IT content. */
+       u8      db3_ec;
+               /* EC0, EC1, EC2 Extended colorimetry */
+       u8      db3_q_range;
+               /* Q1, Q0 Quantization range */
+       u8      db3_nup_scaling;
+               /* SC1, SC0 Non-uniform picture scaling */
+       u8      db4_videocode;
+               /* VIC0..6 Video format identification */
+       u8      db5_pixel_repeat;
+               /* PR0..PR3 Pixel repetition factor */
+       u16     db6_7_line_eoftop;
+               /* Line number end of top bar */
+       u16     db8_9_line_sofbottom;
+               /* Line number start of bottom bar */
+       u16     db10_11_pixel_eofleft;
+               /* Pixel number end of left bar */
+       u16     db12_13_pixel_sofright;
+               /* Pixel number start of right bar */
+};
+
+struct hdmi_core_packet_enable_repeat {
+       u32     audio_pkt;
+       u32     audio_pkt_repeat;
+       u32     avi_infoframe;
+       u32     avi_infoframe_repeat;
+       u32     gen_cntrl_pkt;
+       u32     gen_cntrl_pkt_repeat;
+       u32     generic_pkt;
+       u32     generic_pkt_repeat;
+};
+
+struct hdmi_video_format {
+       enum hdmi_packing_mode  packing_mode;
+       u32                     y_res;  /* Line per panel */
+       u32                     x_res;  /* pixel per line */
+};
+
+struct hdmi_video_interface {
+       int     vsp;    /* Vsync polarity */
+       int     hsp;    /* Hsync polarity */
+       int     interlacing;
+       int     tm;     /* Timing mode */
+};
+
+struct hdmi_cm {
+       int     code;
+       int     mode;
+};
+
+struct hdmi_config {
+       struct hdmi_timings timings;
+       u16     interlace;
+       struct hdmi_cm cm;
+};
+
+#endif
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
new file mode 100644 (file)
index 0000000..ffb5de9
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * hdmi_omap4_panel.c
+ *
+ * HDMI library support functions for TI OMAP4 processors.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors:    Mythri P k <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <plat/display.h>
+
+#include "dss.h"
+
+static struct {
+       struct mutex hdmi_lock;
+} hdmi;
+
+
+static int hdmi_panel_probe(struct omap_dss_device *dssdev)
+{
+       DSSDBG("ENTER hdmi_panel_probe\n");
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT |
+                       OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
+
+       /*
+        * Initialize the timings to 640 * 480
+        * This is only for framebuffer update not for TV timing setting
+        * Setting TV timing will be done only on enable
+        */
+       dssdev->panel.timings.x_res = 640;
+       dssdev->panel.timings.y_res = 480;
+
+       DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
+               dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+       return 0;
+}
+
+static void hdmi_panel_remove(struct omap_dss_device *dssdev)
+{
+
+}
+
+static int hdmi_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+       DSSDBG("ENTER hdmi_panel_enable\n");
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+               r = -EINVAL;
+               goto err;
+       }
+
+       r = omapdss_hdmi_display_enable(dssdev);
+       if (r) {
+               DSSERR("failed to power on\n");
+               goto err;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+err:
+       mutex_unlock(&hdmi.hdmi_lock);
+
+       return r;
+}
+
+static void hdmi_panel_disable(struct omap_dss_device *dssdev)
+{
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               omapdss_hdmi_display_disable(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&hdmi.hdmi_lock);
+}
+
+static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+               r = -EINVAL;
+               goto err;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+       omapdss_hdmi_display_disable(dssdev);
+
+err:
+       mutex_unlock(&hdmi.hdmi_lock);
+
+       return r;
+}
+
+static int hdmi_panel_resume(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+               r = -EINVAL;
+               goto err;
+       }
+
+       r = omapdss_hdmi_display_enable(dssdev);
+       if (r) {
+               DSSERR("failed to power on\n");
+               goto err;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+err:
+       mutex_unlock(&hdmi.hdmi_lock);
+
+       return r;
+}
+
+static void hdmi_get_timings(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings)
+{
+       mutex_lock(&hdmi.hdmi_lock);
+
+       *timings = dssdev->panel.timings;
+
+       mutex_unlock(&hdmi.hdmi_lock);
+}
+
+static void hdmi_set_timings(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings)
+{
+       DSSDBG("hdmi_set_timings\n");
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       dssdev->panel.timings = *timings;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               /* turn the hdmi off and on to get new timings to use */
+               omapdss_hdmi_display_disable(dssdev);
+               omapdss_hdmi_display_set_timing(dssdev);
+       }
+
+       mutex_unlock(&hdmi.hdmi_lock);
+}
+
+static int hdmi_check_timings(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings)
+{
+       int r = 0;
+
+       DSSDBG("hdmi_check_timings\n");
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       r = omapdss_hdmi_display_check_timing(dssdev, timings);
+       if (r) {
+               DSSERR("Timing cannot be applied\n");
+               goto err;
+       }
+err:
+       mutex_unlock(&hdmi.hdmi_lock);
+       return r;
+}
+
+static struct omap_dss_driver hdmi_driver = {
+       .probe          = hdmi_panel_probe,
+       .remove         = hdmi_panel_remove,
+       .enable         = hdmi_panel_enable,
+       .disable        = hdmi_panel_disable,
+       .suspend        = hdmi_panel_suspend,
+       .resume         = hdmi_panel_resume,
+       .get_timings    = hdmi_get_timings,
+       .set_timings    = hdmi_set_timings,
+       .check_timings  = hdmi_check_timings,
+       .driver                 = {
+               .name   = "hdmi_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int hdmi_panel_init(void)
+{
+       mutex_init(&hdmi.hdmi_lock);
+
+       omap_dss_register_driver(&hdmi_driver);
+
+       return 0;
+}
+
+void hdmi_panel_exit(void)
+{
+       omap_dss_unregister_driver(&hdmi_driver);
+
+}
index 172d4e6..bcd37ec 100644 (file)
@@ -515,6 +515,8 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
 
        if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
                irq = DISPC_IRQ_EVSYNC_ODD;
+       } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) {
+               irq = DISPC_IRQ_EVSYNC_EVEN;
        } else {
                if (mgr->id == OMAP_DSS_CHANNEL_LCD)
                        irq = DISPC_IRQ_VSYNC;
@@ -536,7 +538,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
+                       || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
                if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
@@ -613,7 +616,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
+                       || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
                if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
@@ -1377,6 +1381,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                case OMAP_DISPLAY_TYPE_DBI:
                case OMAP_DISPLAY_TYPE_SDI:
                case OMAP_DISPLAY_TYPE_VENC:
+               case OMAP_DISPLAY_TYPE_HDMI:
                        default_get_overlay_fifo_thresholds(ovl->id, size,
                                        &oc->burst_size, &oc->fifo_low,
                                        &oc->fifo_high);
@@ -1394,7 +1399,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        }
 
        r = 0;
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        if (!dss_cache.irq_enabled) {
                u32 mask;
 
@@ -1407,7 +1412,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                dss_cache.irq_enabled = true;
        }
        configure_dispc();
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        spin_unlock_irqrestore(&dss_cache.lock, flags);
 
index 456efef..f1aca6d 100644 (file)
@@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 
        ovl->manager = mgr;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        /* XXX: on manual update display, in auto update mode, a bug happens
         * here. When an overlay is first enabled on LCD, then it's disabled,
         * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
@@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
         * but I don't understand how or why. */
        msleep(40);
        dispc_set_channel_out(ovl->id, mgr->id);
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        return 0;
 }
@@ -679,7 +679,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
                        lcd2_mgr->set_device(lcd2_mgr, dssdev);
                        mgr = lcd2_mgr;
                }
-       } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
+       } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
+                       && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
                if (!lcd_mgr->device || force) {
                        if (lcd_mgr->device)
                                lcd_mgr->unset_device(lcd_mgr);
@@ -688,7 +689,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
                }
        }
 
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
+                       || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                if (!tv_mgr->device || force) {
                        if (tv_mgr->device)
                                tv_mgr->unset_device(tv_mgr);
index 10a2ffe..5ea17f4 100644 (file)
@@ -36,8 +36,6 @@
 #include <plat/display.h>
 #include "dss.h"
 
-#define RFBI_BASE               0x48050800
-
 struct rfbi_reg { u16 idx; };
 
 #define RFBI_REG(idx)          ((const struct rfbi_reg) { idx })
@@ -100,6 +98,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t);
 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
 
 static struct {
+       struct platform_device *pdev;
        void __iomem    *base;
 
        unsigned long   l4_khz;
@@ -142,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
 static void rfbi_enable_clocks(bool enable)
 {
        if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 }
 
 void omap_rfbi_write_command(const void *buf, u32 len)
@@ -497,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void)
        };
 
        l4_rate = rfbi.l4_khz / 1000;
-       dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
+       dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000;
 
        for (i = 0; i < ARRAY_SIZE(ftab); i++) {
                /* Use a window instead of an exact match, to account
@@ -922,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        DUMPREG(RFBI_REVISION);
        DUMPREG(RFBI_SYSCONFIG);
@@ -953,54 +952,10 @@ void rfbi_dump_regs(struct seq_file *s)
        DUMPREG(RFBI_VSYNC_WIDTH);
        DUMPREG(RFBI_HSYNC_WIDTH);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
 }
 
-int rfbi_init(void)
-{
-       u32 rev;
-       u32 l;
-
-       spin_lock_init(&rfbi.cmd_lock);
-
-       init_completion(&rfbi.cmd_done);
-       atomic_set(&rfbi.cmd_fifo_full, 0);
-       atomic_set(&rfbi.cmd_pending, 0);
-
-       rfbi.base = ioremap(RFBI_BASE, SZ_256);
-       if (!rfbi.base) {
-               DSSERR("can't ioremap RFBI\n");
-               return -ENOMEM;
-       }
-
-       rfbi_enable_clocks(1);
-
-       msleep(10);
-
-       rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
-
-       /* Enable autoidle and smart-idle */
-       l = rfbi_read_reg(RFBI_SYSCONFIG);
-       l |= (1 << 0) | (2 << 3);
-       rfbi_write_reg(RFBI_SYSCONFIG, l);
-
-       rev = rfbi_read_reg(RFBI_REVISION);
-       printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
-              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-       rfbi_enable_clocks(0);
-
-       return 0;
-}
-
-void rfbi_exit(void)
-{
-       DSSDBG("rfbi_exit\n");
-
-       iounmap(rfbi.base);
-}
-
 int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
@@ -1056,3 +1011,74 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
        return 0;
 }
+
+/* RFBI HW IP initialisation */
+static int omap_rfbihw_probe(struct platform_device *pdev)
+{
+       u32 rev;
+       u32 l;
+       struct resource *rfbi_mem;
+
+       rfbi.pdev = pdev;
+
+       spin_lock_init(&rfbi.cmd_lock);
+
+       init_completion(&rfbi.cmd_done);
+       atomic_set(&rfbi.cmd_fifo_full, 0);
+       atomic_set(&rfbi.cmd_pending, 0);
+
+       rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
+       if (!rfbi_mem) {
+               DSSERR("can't get IORESOURCE_MEM RFBI\n");
+               return -EINVAL;
+       }
+       rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
+       if (!rfbi.base) {
+               DSSERR("can't ioremap RFBI\n");
+               return -ENOMEM;
+       }
+
+       rfbi_enable_clocks(1);
+
+       msleep(10);
+
+       rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+
+       /* Enable autoidle and smart-idle */
+       l = rfbi_read_reg(RFBI_SYSCONFIG);
+       l |= (1 << 0) | (2 << 3);
+       rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+       rev = rfbi_read_reg(RFBI_REVISION);
+       dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
+              FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+       rfbi_enable_clocks(0);
+
+       return 0;
+}
+
+static int omap_rfbihw_remove(struct platform_device *pdev)
+{
+       iounmap(rfbi.base);
+       return 0;
+}
+
+static struct platform_driver omap_rfbihw_driver = {
+       .probe          = omap_rfbihw_probe,
+       .remove         = omap_rfbihw_remove,
+       .driver         = {
+               .name   = "omapdss_rfbi",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int rfbi_init_platform_driver(void)
+{
+       return platform_driver_register(&omap_rfbihw_driver);
+}
+
+void rfbi_uninit_platform_driver(void)
+{
+       return platform_driver_unregister(&omap_rfbihw_driver);
+}
index b64adf7..54a53e6 100644 (file)
@@ -30,7 +30,6 @@
 #include "dss.h"
 
 static struct {
-       bool skip_init;
        bool update_enabled;
        struct regulator *vdds_sdi_reg;
 } sdi;
@@ -68,9 +67,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err1;
 
-       /* In case of skip_init sdi_init has already enabled the clocks */
-       if (!sdi.skip_init)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        sdi_basic_init(dssdev);
 
@@ -80,14 +77,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
 
-       if (!sdi.skip_init) {
-               r = dss_calc_clock_div(1, t->pixel_clock * 1000,
-                               &dss_cinfo, &dispc_cinfo);
-       } else {
-               r = dss_get_clock_div(&dss_cinfo);
-               r = dispc_get_clock_div(dssdev->manager->id, &dispc_cinfo);
-       }
-
+       r = dss_calc_clock_div(1, t->pixel_clock * 1000,
+                       &dss_cinfo, &dispc_cinfo);
        if (r)
                goto err2;
 
@@ -116,21 +107,17 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err2;
 
-       if (!sdi.skip_init) {
-               dss_sdi_init(dssdev->phy.sdi.datapairs);
-               r = dss_sdi_enable();
-               if (r)
-                       goto err1;
-               mdelay(2);
-       }
+       dss_sdi_init(dssdev->phy.sdi.datapairs);
+       r = dss_sdi_enable();
+       if (r)
+               goto err1;
+       mdelay(2);
 
        dssdev->manager->enable(dssdev->manager);
 
-       sdi.skip_init = 0;
-
        return 0;
 err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
        regulator_disable(sdi.vdds_sdi_reg);
 err1:
        omap_dss_stop_device(dssdev);
@@ -145,7 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 
        dss_sdi_disable();
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        regulator_disable(sdi.vdds_sdi_reg);
 
@@ -157,25 +144,24 @@ int sdi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("SDI init\n");
 
+       if (sdi.vdds_sdi_reg == NULL) {
+               struct regulator *vdds_sdi;
+
+               vdds_sdi = dss_get_vdds_sdi();
+
+               if (IS_ERR(vdds_sdi)) {
+                       DSSERR("can't get VDDS_SDI regulator\n");
+                       return PTR_ERR(vdds_sdi);
+               }
+
+               sdi.vdds_sdi_reg = vdds_sdi;
+       }
+
        return 0;
 }
 
-int sdi_init(bool skip_init)
+int sdi_init(void)
 {
-       /* we store this for first display enable, then clear it */
-       sdi.skip_init = skip_init;
-
-       sdi.vdds_sdi_reg = dss_get_vdds_sdi();
-       if (IS_ERR(sdi.vdds_sdi_reg)) {
-               DSSERR("can't get VDDS_SDI regulator\n");
-               return PTR_ERR(sdi.vdds_sdi_reg);
-       }
-       /*
-        * Enable clocks already here, otherwise there would be a toggle
-        * of them until sdi_display_enable is called.
-        */
-       if (skip_init)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
        return 0;
 }
 
index eff3505..8e35a5b 100644 (file)
@@ -39,8 +39,6 @@
 
 #include "dss.h"
 
-#define VENC_BASE      0x48050C00
-
 /* Venc registers */
 #define VENC_REV_ID                            0x00
 #define VENC_STATUS                            0x04
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = {
 EXPORT_SYMBOL(omap_dss_ntsc_timings);
 
 static struct {
+       struct platform_device *pdev;
        void __iomem *base;
        struct mutex venc_lock;
        u32 wss_data;
@@ -381,11 +380,11 @@ static void venc_reset(void)
 static void venc_enable_clocks(int enable)
 {
        if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
-                               DSS_CLK_96M);
+               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+                               DSS_CLK_VIDFCK);
        else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
-                               DSS_CLK_96M);
+               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+                               DSS_CLK_VIDFCK);
 }
 
 static const struct venc_config *venc_timings_to_config(
@@ -641,50 +640,23 @@ static struct omap_dss_driver venc_driver = {
 };
 /* driver end */
 
-
-
-int venc_init(struct platform_device *pdev)
+int venc_init_display(struct omap_dss_device *dssdev)
 {
-       u8 rev_id;
+       DSSDBG("init_display\n");
 
-       mutex_init(&venc.venc_lock);
+       if (venc.vdda_dac_reg == NULL) {
+               struct regulator *vdda_dac;
 
-       venc.wss_data = 0;
+               vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac");
 
-       venc.base = ioremap(VENC_BASE, SZ_1K);
-       if (!venc.base) {
-               DSSERR("can't ioremap VENC\n");
-               return -ENOMEM;
-       }
+               if (IS_ERR(vdda_dac)) {
+                       DSSERR("can't get VDDA_DAC regulator\n");
+                       return PTR_ERR(vdda_dac);
+               }
 
-       venc.vdda_dac_reg = dss_get_vdda_dac();
-       if (IS_ERR(venc.vdda_dac_reg)) {
-               iounmap(venc.base);
-               DSSERR("can't get VDDA_DAC regulator\n");
-               return PTR_ERR(venc.vdda_dac_reg);
+               venc.vdda_dac_reg = vdda_dac;
        }
 
-       venc_enable_clocks(1);
-
-       rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
-       printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
-
-       venc_enable_clocks(0);
-
-       return omap_dss_register_driver(&venc_driver);
-}
-
-void venc_exit(void)
-{
-       omap_dss_unregister_driver(&venc_driver);
-
-       iounmap(venc.base);
-}
-
-int venc_init_display(struct omap_dss_device *dssdev)
-{
-       DSSDBG("init_display\n");
-
        return 0;
 }
 
@@ -740,3 +712,73 @@ void venc_dump_regs(struct seq_file *s)
 
 #undef DUMPREG
 }
+
+/* VENC HW IP initialisation */
+static int omap_venchw_probe(struct platform_device *pdev)
+{
+       u8 rev_id;
+       struct resource *venc_mem;
+
+       venc.pdev = pdev;
+
+       mutex_init(&venc.venc_lock);
+
+       venc.wss_data = 0;
+
+       venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
+       if (!venc_mem) {
+               DSSERR("can't get IORESOURCE_MEM VENC\n");
+               return -EINVAL;
+       }
+       venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
+       if (!venc.base) {
+               DSSERR("can't ioremap VENC\n");
+               return -ENOMEM;
+       }
+
+       venc_enable_clocks(1);
+
+       rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+       dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
+
+       venc_enable_clocks(0);
+
+       return omap_dss_register_driver(&venc_driver);
+}
+
+static int omap_venchw_remove(struct platform_device *pdev)
+{
+       if (venc.vdda_dac_reg != NULL) {
+               regulator_put(venc.vdda_dac_reg);
+               venc.vdda_dac_reg = NULL;
+       }
+       omap_dss_unregister_driver(&venc_driver);
+
+       iounmap(venc.base);
+       return 0;
+}
+
+static struct platform_driver omap_venchw_driver = {
+       .probe          = omap_venchw_probe,
+       .remove         = omap_venchw_remove,
+       .driver         = {
+               .name   = "omapdss_venc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int venc_init_platform_driver(void)
+{
+       if (cpu_is_omap44xx())
+               return 0;
+
+       return platform_driver_register(&omap_venchw_driver);
+}
+
+void venc_uninit_platform_driver(void)
+{
+       if (cpu_is_omap44xx())
+               return;
+
+       return platform_driver_unregister(&omap_venchw_driver);
+}
index 65149b2..aa33386 100644 (file)
@@ -1,5 +1,5 @@
 menuconfig FB_OMAP2
-        tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
+        tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
         depends on FB && OMAP2_DSS
 
        select OMAP2_VRAM
@@ -8,10 +8,10 @@ menuconfig FB_OMAP2
         select FB_CFB_COPYAREA
         select FB_CFB_IMAGEBLIT
         help
-          Frame buffer driver for OMAP2/3 based boards.
+         Frame buffer driver for OMAP2+ based boards.
 
 config FB_OMAP2_DEBUG_SUPPORT
-       bool "Debug support for OMAP2/3 FB"
+        bool "Debug support for OMAP2+ FB"
        default y
        depends on FB_OMAP2
        help
index 4fdab8e..505ec66 100644 (file)
@@ -2090,7 +2090,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
 {
        int r;
        u8 bpp;
-       struct omap_video_timings timings;
+       struct omap_video_timings timings, temp_timings;
 
        r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
        if (r)
@@ -2100,14 +2100,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
        fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
        ++fbdev->num_bpp_overrides;
 
-       if (!display->driver->check_timings || !display->driver->set_timings)
-               return -EINVAL;
+       if (display->driver->check_timings) {
+               r = display->driver->check_timings(display, &timings);
+               if (r)
+                       return r;
+       } else {
+               /* If check_timings is not present compare xres and yres */
+               if (display->driver->get_timings) {
+                       display->driver->get_timings(display, &temp_timings);
 
-       r = display->driver->check_timings(display, &timings);
-       if (r)
-               return r;
+                       if (temp_timings.x_res != timings.x_res ||
+                               temp_timings.y_res != timings.y_res)
+                               return -EINVAL;
+               }
+       }
 
-       display->driver->set_timings(display, &timings);
+       if (display->driver->set_timings)
+                       display->driver->set_timings(display, &timings);
 
        return 0;
 }