aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-dvi.c363
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c747
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c594
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-taal.c125
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile2
-rw-r--r--drivers/video/omap2/dss/core.c4
-rw-r--r--drivers/video/omap2/dss/dispc.c1700
-rw-r--r--drivers/video/omap2/dss/dispc.h57
-rw-r--r--drivers/video/omap2/dss/display.c31
-rw-r--r--drivers/video/omap2/dss/dpi.c28
-rw-r--r--drivers/video/omap2/dss/dsi.c929
-rw-r--r--drivers/video/omap2/dss/dss.c18
-rw-r--r--drivers/video/omap2/dss/dss.h156
-rw-r--r--drivers/video/omap2/dss/dss_features.c130
-rw-r--r--drivers/video/omap2/dss/dss_features.h17
-rw-r--r--drivers/video/omap2/dss/hdmi.c1260
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c (renamed from drivers/video/omap2/dss/hdmi_omap4_panel.c)68
-rw-r--r--drivers/video/omap2/dss/manager.c191
-rw-r--r--drivers/video/omap2/dss/overlay.c122
-rw-r--r--drivers/video/omap2/dss/rfbi.c45
-rw-r--r--drivers/video/omap2/dss/sdi.c19
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h138
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c1239
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h (renamed from drivers/video/omap2/dss/hdmi.h)400
-rw-r--r--drivers/video/omap2/dss/venc.c27
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c134
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c6
33 files changed, 5812 insertions, 3174 deletions
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 609a28073178..8d8e1fe1901c 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
Supports LCD Panel used in TI SDP3430 and EVM boards,
OMAP3517 EVM boards and CM-T35.
+config PANEL_DVI
+ tristate "DVI output"
+ depends on OMAP2_DSS_DPI
+ help
+ Driver for external monitors, connected via DVI. The driver uses i2c
+ to read EDID information from the monitor.
+
config PANEL_LGPHILIPS_LB035Q02
tristate "LG.Philips LB035Q02 LCD Panel"
depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS_DPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
LCD Panel used in TI's SDP3430 and EVM boards
config PANEL_NEC_NL8048HL11_01B
tristate "NEC NL8048HL11-01B Panel"
depends on OMAP2_DSS_DPI
+ depends on SPI
+ depends on BACKLIGHT_CLASS_DEVICE
help
This NEC NL8048HL11-01B panel is TFT LCD
used in the Zoom2/3/3630 sdp boards.
+config PANEL_PICODLP
+ tristate "TI PICO DLP mini-projector"
+ depends on OMAP2_DSS && I2C
+ help
+ A mini-projector used in TI's SDP4430 and EVM boards
+ For more info please visit http://www.dlp.com/projector/
+
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
help
Taal DSI command mode panel from TPO.
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
config PANEL_ACX565AKM
tristate "ACX565AKM Panel"
depends on OMAP2_DSS_SDI && SPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
This is the LCD panel used on Nokia N900
+
+config PANEL_N8X0
+ tristate "N8X0 Panel"
+ depends on OMAP2_DSS_RFBI && SPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ This is the LCD panel used on Nokia N8x0
endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 0f601ab3abf4..fbfafc6eebb4 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,11 @@
obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
+obj-$(CONFIG_PANEL_DVI) += panel-dvi.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
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c
new file mode 100644
index 000000000000..03eb14af33e0
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-dvi.c
@@ -0,0 +1,363 @@
+/*
+ * DVI output support
+ *
+ * Copyright (C) 2011 Texas Instruments Inc
+ * Author: Tomi Valkeinen <tomi.valkeinen@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/module.h>
+#include <linux/slab.h>
+#include <video/omapdss.h>
+#include <linux/i2c.h>
+#include <drm/drm_edid.h>
+
+#include <video/omap-panel-dvi.h>
+
+static const struct omap_video_timings panel_dvi_default_timings = {
+ .x_res = 640,
+ .y_res = 480,
+
+ .pixel_clock = 23500,
+
+ .hfp = 48,
+ .hsw = 32,
+ .hbp = 80,
+
+ .vfp = 3,
+ .vsw = 4,
+ .vbp = 7,
+};
+
+struct panel_drv_data {
+ struct omap_dss_device *dssdev;
+
+ struct mutex lock;
+};
+
+static inline struct panel_dvi_platform_data
+*get_pdata(const struct omap_dss_device *dssdev)
+{
+ return dssdev->data;
+}
+
+static int panel_dvi_power_on(struct omap_dss_device *dssdev)
+{
+ struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ int r;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ r = omapdss_dpi_display_enable(dssdev);
+ if (r)
+ goto err0;
+
+ if (pdata->platform_enable) {
+ r = pdata->platform_enable(dssdev);
+ if (r)
+ goto err1;
+ }
+
+ return 0;
+err1:
+ omapdss_dpi_display_disable(dssdev);
+err0:
+ return r;
+}
+
+static void panel_dvi_power_off(struct omap_dss_device *dssdev)
+{
+ struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ if (pdata->platform_disable)
+ pdata->platform_disable(dssdev);
+
+ omapdss_dpi_display_disable(dssdev);
+}
+
+static int panel_dvi_probe(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata;
+
+ ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ dssdev->panel.timings = panel_dvi_default_timings;
+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
+
+ ddata->dssdev = dssdev;
+ mutex_init(&ddata->lock);
+
+ dev_set_drvdata(&dssdev->dev, ddata);
+
+ return 0;
+}
+
+static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&ddata->lock);
+
+ dev_set_drvdata(&dssdev->dev, NULL);
+
+ mutex_unlock(&ddata->lock);
+
+ kfree(ddata);
+}
+
+static int panel_dvi_enable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ mutex_lock(&ddata->lock);
+
+ r = panel_dvi_power_on(dssdev);
+ if (r == 0)
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ mutex_unlock(&ddata->lock);
+
+ return r;
+}
+
+static void panel_dvi_disable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&ddata->lock);
+
+ panel_dvi_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ mutex_unlock(&ddata->lock);
+}
+
+static int panel_dvi_suspend(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&ddata->lock);
+
+ panel_dvi_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static int panel_dvi_resume(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ mutex_lock(&ddata->lock);
+
+ r = panel_dvi_power_on(dssdev);
+ if (r == 0)
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ mutex_unlock(&ddata->lock);
+
+ return r;
+}
+
+static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&ddata->lock);
+ dpi_set_timings(dssdev, timings);
+ mutex_unlock(&ddata->lock);
+}
+
+static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&ddata->lock);
+ *timings = dssdev->panel.timings;
+ mutex_unlock(&ddata->lock);
+}
+
+static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ mutex_lock(&ddata->lock);
+ r = dpi_check_timings(dssdev, timings);
+ mutex_unlock(&ddata->lock);
+
+ return r;
+}
+
+
+static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
+ unsigned char *buf, u16 count, u8 offset)
+{
+ int r, retries;
+
+ for (retries = 3; retries > 0; retries--) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &offset,
+ }, {
+ .addr = DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = count,
+ .buf = buf,
+ }
+ };
+
+ r = i2c_transfer(adapter, msgs, 2);
+ if (r == 2)
+ return 0;
+
+ if (r != -EAGAIN)
+ break;
+ }
+
+ return r < 0 ? r : -EIO;
+}
+
+static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
+ u8 *edid, int len)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+ struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct i2c_adapter *adapter;
+ int r, l, bytes_read;
+
+ mutex_lock(&ddata->lock);
+
+ if (pdata->i2c_bus_num == 0) {
+ r = -ENODEV;
+ goto err;
+ }
+
+ adapter = i2c_get_adapter(pdata->i2c_bus_num);
+ if (!adapter) {
+ dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
+ pdata->i2c_bus_num);
+ r = -EINVAL;
+ goto err;
+ }
+
+ l = min(EDID_LENGTH, len);
+ r = panel_dvi_ddc_read(adapter, edid, l, 0);
+ if (r)
+ goto err;
+
+ bytes_read = l;
+
+ /* if there are extensions, read second block */
+ if (len > EDID_LENGTH && edid[0x7e] > 0) {
+ l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+ r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
+ l, EDID_LENGTH);
+ if (r)
+ goto err;
+
+ bytes_read += l;
+ }
+
+ mutex_unlock(&ddata->lock);
+
+ return bytes_read;
+
+err:
+ mutex_unlock(&ddata->lock);
+ return r;
+}
+
+static bool panel_dvi_detect(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+ struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+ struct i2c_adapter *adapter;
+ unsigned char out;
+ int r;
+
+ mutex_lock(&ddata->lock);
+
+ if (pdata->i2c_bus_num == 0)
+ goto out;
+
+ adapter = i2c_get_adapter(pdata->i2c_bus_num);
+ if (!adapter)
+ goto out;
+
+ r = panel_dvi_ddc_read(adapter, &out, 1, 0);
+
+ mutex_unlock(&ddata->lock);
+
+ return r == 0;
+
+out:
+ mutex_unlock(&ddata->lock);
+ return true;
+}
+
+static struct omap_dss_driver panel_dvi_driver = {
+ .probe = panel_dvi_probe,
+ .remove = __exit_p(panel_dvi_remove),
+
+ .enable = panel_dvi_enable,
+ .disable = panel_dvi_disable,
+ .suspend = panel_dvi_suspend,
+ .resume = panel_dvi_resume,
+
+ .set_timings = panel_dvi_set_timings,
+ .get_timings = panel_dvi_get_timings,
+ .check_timings = panel_dvi_check_timings,
+
+ .read_edid = panel_dvi_read_edid,
+ .detect = panel_dvi_detect,
+
+ .driver = {
+ .name = "dvi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init panel_dvi_init(void)
+{
+ return omap_dss_register_driver(&panel_dvi_driver);
+}
+
+static void __exit panel_dvi_exit(void)
+{
+ omap_dss_unregister_driver(&panel_dvi_driver);
+}
+
+module_init(panel_dvi_init);
+module_exit(panel_dvi_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75653fb..519c47d2057f 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -58,30 +58,6 @@ struct panel_config {
/* Panel configurations */
static struct panel_config generic_dpi_panels[] = {
- /* Generic Panel */
- {
- {
- .x_res = 640,
- .y_res = 480,
-
- .pixel_clock = 23500,
-
- .hfp = 48,
- .hsw = 32,
- .hbp = 80,
-
- .vfp = 3,
- .vsw = 4,
- .vbp = 7,
- },
- .acbi = 0x0,
- .acb = 0x0,
- .config = OMAP_DSS_LCD_TFT,
- .power_on_delay = 0,
- .power_off_delay = 0,
- .name = "generic",
- },
-
/* Sharp LQ043T1DG01 */
{
{
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "powertip_ph480272t",
},
+
+ /* Innolux AT070TN83 */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 40000,
+
+ .hsw = 48,
+ .hfp = 1,
+ .hbp = 1,
+
+ .vsw = 3,
+ .vfp = 12,
+ .vbp = 25,
+ },
+ .acbi = 0x0,
+ .acb = 0x28,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "innolux_at070tn83",
+ },
+
+ /* NEC NL2432DR22-11B */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 5400,
+
+ .hsw = 3,
+ .hfp = 3,
+ .hbp = 39,
+
+ .vsw = 1,
+ .vfp = 2,
+ .vbp = 7,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .name = "nec_nl2432dr22-11b",
+ },
+
+ /* Unknown panel used in OMAP H4 */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 6250,
+
+ .hsw = 15,
+ .hfp = 15,
+ .hbp = 60,
+
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 1,
+ },
+ .config = OMAP_DSS_LCD_TFT,
+
+ .name = "h4",
+ },
+
+ /* Unknown panel used in Samsung OMAP2 Apollon */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 6250,
+
+ .hsw = 41,
+ .hfp = 2,
+ .hbp = 2,
+
+ .vsw = 10,
+ .vfp = 2,
+ .vbp = 2,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+
+ .name = "apollon",
+ },
};
struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
new file mode 100644
index 000000000000..150e8bae35a1
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -0,0 +1,747 @@
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-n8x0.h>
+
+#define BLIZZARD_REV_CODE 0x00
+#define BLIZZARD_CONFIG 0x02
+#define BLIZZARD_PLL_DIV 0x04
+#define BLIZZARD_PLL_LOCK_RANGE 0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
+#define BLIZZARD_PLL_MODE 0x0c
+#define BLIZZARD_CLK_SRC 0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
+#define BLIZZARD_MEM_BANK0_STATUS 0x14
+#define BLIZZARD_PANEL_CONFIGURATION 0x28
+#define BLIZZARD_HDISP 0x2a
+#define BLIZZARD_HNDP 0x2c
+#define BLIZZARD_VDISP0 0x2e
+#define BLIZZARD_VDISP1 0x30
+#define BLIZZARD_VNDP 0x32
+#define BLIZZARD_HSW 0x34
+#define BLIZZARD_VSW 0x38
+#define BLIZZARD_DISPLAY_MODE 0x68
+#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
+#define BLIZZARD_POWER_SAVE 0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD 0x00
+#define BLIZZARD_SRC_BLT_LCD 0x06
+
+#define BLIZZARD_COLOR_RGB565 0x01
+#define BLIZZARD_COLOR_YUV420 0x09
+
+#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
+
+#define MIPID_CMD_READ_DISP_ID 0x04
+#define MIPID_CMD_READ_RED 0x06
+#define MIPID_CMD_READ_GREEN 0x07
+#define MIPID_CMD_READ_BLUE 0x08
+#define MIPID_CMD_READ_DISP_STATUS 0x09
+#define MIPID_CMD_RDDSDR 0x0F
+#define MIPID_CMD_SLEEP_IN 0x10
+#define MIPID_CMD_SLEEP_OUT 0x11
+#define MIPID_CMD_DISP_OFF 0x28
+#define MIPID_CMD_DISP_ON 0x29
+
+static struct panel_drv_data {
+ struct mutex lock;
+
+ struct omap_dss_device *dssdev;
+ struct spi_device *spidev;
+ struct backlight_device *bldev;
+
+ int blizzard_ver;
+} s_drv_data;
+
+
+static inline
+struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
+{
+ return dssdev->data;
+}
+
+static inline
+struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
+{
+ return &s_drv_data;
+}
+
+
+static inline void blizzard_cmd(u8 cmd)
+{
+ omap_rfbi_write_command(&cmd, 1);
+}
+
+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
+{
+ omap_rfbi_write_command(&cmd, 1);
+ omap_rfbi_write_data(buf, len);
+}
+
+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
+{
+ omap_rfbi_write_command(&cmd, 1);
+ omap_rfbi_read_data(buf, len);
+}
+
+static u8 blizzard_read_reg(u8 cmd)
+{
+ u8 data;
+ blizzard_read(cmd, &data, 1);
+ return data;
+}
+
+static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
+ int x, int y, int w, int h)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ u8 tmp[18];
+ int x_end, y_end;
+
+ x_end = x + w - 1;
+ y_end = y + h - 1;
+
+ tmp[0] = x;
+ tmp[1] = x >> 8;
+ tmp[2] = y;
+ tmp[3] = y >> 8;
+ tmp[4] = x_end;
+ tmp[5] = x_end >> 8;
+ tmp[6] = y_end;
+ tmp[7] = y_end >> 8;
+
+ /* scaling? */
+ tmp[8] = x;
+ tmp[9] = x >> 8;
+ tmp[10] = y;
+ tmp[11] = y >> 8;
+ tmp[12] = x_end;
+ tmp[13] = x_end >> 8;
+ tmp[14] = y_end;
+ tmp[15] = y_end >> 8;
+
+ tmp[16] = BLIZZARD_COLOR_RGB565;
+
+ if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
+ tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+ else
+ tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
+ BLIZZARD_SRC_WRITE_LCD :
+ BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+ omap_rfbi_configure(dssdev, 16, 8);
+
+ blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
+
+ omap_rfbi_configure(dssdev, 16, 16);
+}
+
+static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
+ int wlen, u8 *rbuf, int rlen)
+{
+ struct spi_message m;
+ struct spi_transfer *x, xfer[4];
+ u16 w;
+ int r;
+
+ spi_message_init(&m);
+
+ memset(xfer, 0, sizeof(xfer));
+ x = &xfer[0];
+
+ cmd &= 0xff;
+ x->tx_buf = &cmd;
+ x->bits_per_word = 9;
+ x->len = 2;
+ spi_message_add_tail(x, &m);
+
+ if (wlen) {
+ x++;
+ x->tx_buf = wbuf;
+ x->len = wlen;
+ x->bits_per_word = 9;
+ spi_message_add_tail(x, &m);
+ }
+
+ if (rlen) {
+ x++;
+ x->rx_buf = &w;
+ x->len = 1;
+ spi_message_add_tail(x, &m);
+
+ if (rlen > 1) {
+ /* Arrange for the extra clock before the first
+ * data bit.
+ */
+ x->bits_per_word = 9;
+ x->len = 2;
+
+ x++;
+ x->rx_buf = &rbuf[1];
+ x->len = rlen - 1;
+ spi_message_add_tail(x, &m);
+ }
+ }
+
+ r = spi_sync(spi, &m);
+ if (r < 0)
+ dev_dbg(&spi->dev, "spi_sync %d\n", r);
+
+ if (rlen)
+ rbuf[0] = w & 0xff;
+}
+
+static inline void mipid_cmd(struct spi_device *spi, int cmd)
+{
+ mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void mipid_write(struct spi_device *spi,
+ int reg, const u8 *buf, int len)
+{
+ mipid_transfer(spi, reg, buf, len, NULL, 0);
+}
+
+static inline void mipid_read(struct spi_device *spi,
+ int reg, u8 *buf, int len)
+{
+ mipid_transfer(spi, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct spi_device *spi, int data_lines)
+{
+ u16 par;
+
+ switch (data_lines) {
+ case 16:
+ par = 0x150;
+ break;
+ case 18:
+ par = 0x160;
+ break;
+ case 24:
+ par = 0x170;
+ break;
+ }
+
+ mipid_write(spi, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct spi_device *spi)
+{
+ u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+ mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
+}
+
+static void send_display_on(struct spi_device *spi)
+{
+ mipid_cmd(spi, MIPID_CMD_DISP_ON);
+}
+
+static void send_display_off(struct spi_device *spi)
+{
+ mipid_cmd(spi, MIPID_CMD_DISP_OFF);
+}
+
+static void send_sleep_out(struct spi_device *spi)
+{
+ mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
+ msleep(120);
+}
+
+static void send_sleep_in(struct spi_device *spi)
+{
+ mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
+ msleep(50);
+}
+
+static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
+{
+ int r;
+ struct panel_n8x0_data *bdata = get_board_data(dssdev);
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ struct spi_device *spi = ddata->spidev;
+ u8 rev, conf;
+ u8 display_id[3];
+ const char *panel_name;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ gpio_direction_output(bdata->ctrl_pwrdown, 1);
+
+ if (bdata->platform_enable) {
+ r = bdata->platform_enable(dssdev);
+ if (r)
+ goto err_plat_en;
+ }
+
+ r = omapdss_rfbi_display_enable(dssdev);
+ if (r)
+ goto err_rfbi_en;
+
+ rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+ conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+ switch (rev & 0xfc) {
+ case 0x9c:
+ ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
+ dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ case 0xa4:
+ ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
+ dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+ break;
+ default:
+ dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
+ r = -ENODEV;
+ goto err_inv_chip;
+ }
+
+ /* panel */
+
+ gpio_direction_output(bdata->panel_reset, 1);
+
+ mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
+ dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
+ display_id[0], display_id[1], display_id[2]);
+
+ switch (display_id[0]) {
+ case 0x45:
+ panel_name = "lph8923";
+ break;
+ case 0x83:
+ panel_name = "ls041y3";
+ break;
+ default:
+ dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
+ display_id[0]);
+ r = -ENODEV;
+ goto err_inv_panel;
+ }
+
+ dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
+ panel_name, display_id[1]);
+
+ send_sleep_out(spi);
+ send_init_string(spi);
+ set_data_lines(spi, 24);
+ send_display_on(spi);
+
+ return 0;
+
+err_inv_panel:
+ /*
+ * HACK: we should turn off the panel here, but there is some problem
+ * with the initialization sequence, and we fail to init the panel if we
+ * have turned it off
+ */
+ /* gpio_direction_output(bdata->panel_reset, 0); */
+err_inv_chip:
+ omapdss_rfbi_display_disable(dssdev);
+err_rfbi_en:
+ if (bdata->platform_disable)
+ bdata->platform_disable(dssdev);
+err_plat_en:
+ gpio_direction_output(bdata->ctrl_pwrdown, 0);
+ return r;
+}
+
+static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
+{
+ struct panel_n8x0_data *bdata = get_board_data(dssdev);
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ struct spi_device *spi = ddata->spidev;
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ send_display_off(spi);
+ send_sleep_in(spi);
+
+ if (bdata->platform_disable)
+ bdata->platform_disable(dssdev);
+
+ /*
+ * HACK: we should turn off the panel here, but there is some problem
+ * with the initialization sequence, and we fail to init the panel if we
+ * have turned it off
+ */
+ /* gpio_direction_output(bdata->panel_reset, 0); */
+ gpio_direction_output(bdata->ctrl_pwrdown, 0);
+ omapdss_rfbi_display_disable(dssdev);
+}
+
+static const struct rfbi_timings n8x0_panel_timings = {
+ .cs_on_time = 0,
+
+ .we_on_time = 9000,
+ .we_off_time = 18000,
+ .we_cycle_time = 36000,
+
+ .re_on_time = 9000,
+ .re_off_time = 27000,
+ .re_cycle_time = 36000,
+
+ .access_time = 27000,
+ .cs_off_time = 36000,
+
+ .cs_pulse_width = 0,
+};
+
+static int n8x0_bl_update_status(struct backlight_device *dev)
+{
+ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
+ struct panel_n8x0_data *bdata = get_board_data(dssdev);
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ int r;
+ int level;
+
+ mutex_lock(&ddata->lock);
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ level = dev->props.brightness;
+ else
+ level = 0;
+
+ dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
+
+ if (!bdata->set_backlight)
+ r = -EINVAL;
+ else
+ r = bdata->set_backlight(dssdev, level);
+
+ mutex_unlock(&ddata->lock);
+
+ return r;
+}
+
+static int n8x0_bl_get_intensity(struct backlight_device *dev)
+{
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ return dev->props.brightness;
+
+ return 0;
+}
+
+static const struct backlight_ops n8x0_bl_ops = {
+ .get_brightness = n8x0_bl_get_intensity,
+ .update_status = n8x0_bl_update_status,
+};
+
+static int n8x0_panel_probe(struct omap_dss_device *dssdev)
+{
+ struct panel_n8x0_data *bdata = get_board_data(dssdev);
+ struct panel_drv_data *ddata;
+ struct backlight_device *bldev;
+ struct backlight_properties props;
+ int r;
+
+ dev_dbg(&dssdev->dev, "probe\n");
+
+ if (!bdata)
+ return -EINVAL;
+
+ s_drv_data.dssdev = dssdev;
+
+ ddata = &s_drv_data;
+
+ mutex_init(&ddata->lock);
+
+ dssdev->panel.config = OMAP_DSS_LCD_TFT;
+ dssdev->panel.timings.x_res = 800;
+ dssdev->panel.timings.y_res = 480;
+ dssdev->ctrl.pixel_size = 16;
+ dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
+
+ memset(&props, 0, sizeof(props));
+ props.max_brightness = 127;
+ props.type = BACKLIGHT_PLATFORM;
+ bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
+ dssdev, &n8x0_bl_ops, &props);
+ if (IS_ERR(bldev)) {
+ r = PTR_ERR(bldev);
+ dev_err(&dssdev->dev, "register backlight failed\n");
+ return r;
+ }
+
+ ddata->bldev = bldev;
+
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
+ bldev->props.brightness = 127;
+
+ n8x0_bl_update_status(bldev);
+
+ return 0;
+}
+
+static void n8x0_panel_remove(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ struct backlight_device *bldev;
+
+ dev_dbg(&dssdev->dev, "remove\n");
+
+ bldev = ddata->bldev;
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ n8x0_bl_update_status(bldev);
+ backlight_device_unregister(bldev);
+
+ dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+static int n8x0_panel_enable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ int r;
+
+ dev_dbg(&dssdev->dev, "enable\n");
+
+ mutex_lock(&ddata->lock);
+
+ rfbi_bus_lock();
+
+ r = n8x0_panel_power_on(dssdev);
+
+ rfbi_bus_unlock();
+
+ if (r) {
+ mutex_unlock(&ddata->lock);
+ return r;
+ }
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static void n8x0_panel_disable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+ dev_dbg(&dssdev->dev, "disable\n");
+
+ mutex_lock(&ddata->lock);
+
+ rfbi_bus_lock();
+
+ n8x0_panel_power_off(dssdev);
+
+ rfbi_bus_unlock();
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+ mutex_unlock(&ddata->lock);
+}
+
+static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+ dev_dbg(&dssdev->dev, "suspend\n");
+
+ mutex_lock(&ddata->lock);
+
+ rfbi_bus_lock();
+
+ n8x0_panel_power_off(dssdev);
+
+ rfbi_bus_unlock();
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static int n8x0_panel_resume(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+ int r;
+
+ dev_dbg(&dssdev->dev, "resume\n");
+
+ mutex_lock(&ddata->lock);
+
+ rfbi_bus_lock();
+
+ r = n8x0_panel_power_on(dssdev);
+
+ rfbi_bus_unlock();
+
+ if (r) {
+ mutex_unlock(&ddata->lock);
+ return r;
+ }
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ *timings = dssdev->panel.timings;
+}
+
+static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres)
+{
+ *xres = dssdev->panel.timings.x_res;
+ *yres = dssdev->panel.timings.y_res;
+}
+
+static void update_done(void *data)
+{
+ rfbi_bus_unlock();
+}
+
+static int n8x0_panel_update(struct omap_dss_device *dssdev,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+ dev_dbg(&dssdev->dev, "update\n");
+
+ mutex_lock(&ddata->lock);
+ rfbi_bus_lock();
+
+ omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
+
+ blizzard_ctrl_setup_update(dssdev, x, y, w, h);
+
+ omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
+
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static int n8x0_panel_sync(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+ dev_dbg(&dssdev->dev, "sync\n");
+
+ mutex_lock(&ddata->lock);
+ rfbi_bus_lock();
+ rfbi_bus_unlock();
+ mutex_unlock(&ddata->lock);
+
+ return 0;
+}
+
+static struct omap_dss_driver n8x0_panel_driver = {
+ .probe = n8x0_panel_probe,
+ .remove = n8x0_panel_remove,
+
+ .enable = n8x0_panel_enable,
+ .disable = n8x0_panel_disable,
+ .suspend = n8x0_panel_suspend,
+ .resume = n8x0_panel_resume,
+
+ .update = n8x0_panel_update,
+ .sync = n8x0_panel_sync,
+
+ .get_resolution = n8x0_panel_get_resolution,
+ .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+ .get_timings = n8x0_panel_get_timings,
+
+ .driver = {
+ .name = "n8x0_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+/* PANEL */
+
+static int mipid_spi_probe(struct spi_device *spi)
+{
+ dev_dbg(&spi->dev, "mipid_spi_probe\n");
+
+ spi->mode = SPI_MODE_0;
+
+ s_drv_data.spidev = spi;
+
+ return 0;
+}
+
+static int mipid_spi_remove(struct spi_device *spi)
+{
+ dev_dbg(&spi->dev, "mipid_spi_remove\n");
+ return 0;
+}
+
+static struct spi_driver mipid_spi_driver = {
+ .driver = {
+ .name = "lcd_mipid",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = mipid_spi_probe,
+ .remove = __devexit_p(mipid_spi_remove),
+};
+
+static int __init n8x0_panel_drv_init(void)
+{
+ int r;
+
+ r = spi_register_driver(&mipid_spi_driver);
+ if (r) {
+ pr_err("n8x0_panel: spi driver registration failed\n");
+ return r;
+ }
+
+ r = omap_dss_register_driver(&n8x0_panel_driver);
+ if (r) {
+ pr_err("n8x0_panel: dss driver registration failed\n");
+ spi_unregister_driver(&mipid_spi_driver);
+ return r;
+ }
+
+ return 0;
+}
+
+static void __exit n8x0_panel_drv_exit(void)
+{
+ spi_unregister_driver(&mipid_spi_driver);
+
+ omap_dss_unregister_driver(&n8x0_panel_driver);
+}
+
+module_init(n8x0_panel_drv_init);
+module_exit(n8x0_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
new file mode 100644
index 000000000000..98ebdaddab5a
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -0,0 +1,594 @@
+/*
+ * picodlp panel driver
+ * picodlp_i2c_driver: i2c_client driver
+ *
+ * Copyright (C) 2009-2011 Texas Instruments
+ * Author: Mythri P K <mythripk@ti.com>
+ * Mayuresh Janorkar <mayur@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/module.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-picodlp.h>
+
+#include "panel-picodlp.h"
+
+struct picodlp_data {
+ struct mutex lock;
+ struct i2c_client *picodlp_i2c_client;
+};
+
+static struct i2c_board_info picodlp_i2c_board_info = {
+ I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
+};
+
+struct picodlp_i2c_data {
+ struct mutex xfer_lock;
+};
+
+static struct i2c_device_id picodlp_i2c_id[] = {
+ { "picodlp_i2c_driver", 0 },
+};
+
+struct picodlp_i2c_command {
+ u8 reg;
+ u32 value;
+};
+
+static struct omap_video_timings pico_ls_timings = {
+ .x_res = 864,
+ .y_res = 480,
+ .hsw = 7,
+ .hfp = 11,
+ .hbp = 7,
+
+ .pixel_clock = 19200,
+
+ .vsw = 2,
+ .vfp = 3,
+ .vbp = 14,
+};
+
+static inline struct picodlp_panel_data
+ *get_panel_data(const struct omap_dss_device *dssdev)
+{
+ return (struct picodlp_panel_data *) dssdev->data;
+}
+
+static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
+{
+ u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
+ struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
+ struct i2c_msg msg[2];
+
+ mutex_lock(&picodlp_i2c_data->xfer_lock);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = read_cmd;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 4;
+ msg[1].buf = data;
+
+ i2c_transfer(client->adapter, msg, 2);
+ mutex_unlock(&picodlp_i2c_data->xfer_lock);
+ return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
+}
+
+static int picodlp_i2c_write_block(struct i2c_client *client,
+ u8 *data, int len)
+{
+ struct i2c_msg msg;
+ int i, r, msg_count = 1;
+
+ struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
+
+ if (len < 1 || len > 32) {
+ dev_err(&client->dev,
+ "too long syn_write_block len %d\n", len);
+ return -EIO;
+ }
+ mutex_lock(&picodlp_i2c_data->xfer_lock);
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = len;
+ msg.buf = data;
+ r = i2c_transfer(client->adapter, &msg, msg_count);
+ mutex_unlock(&picodlp_i2c_data->xfer_lock);
+
+ /*
+ * i2c_transfer returns:
+ * number of messages sent in case of success
+ * a negative error number in case of failure
+ */
+ if (r != msg_count)
+ goto err;
+
+ /* In case of success */
+ for (i = 0; i < len; i++)
+ dev_dbg(&client->dev,
+ "addr %x bw 0x%02x[%d]: 0x%02x\n",
+ client->addr, data[0] + i, i, data[i]);
+
+ return 0;
+err:
+ dev_err(&client->dev, "picodlp_i2c_write error\n");
+ return r;
+}
+
+static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
+{
+ u8 data[5];
+ int i;
+
+ data[0] = reg;
+ for (i = 1; i < 5; i++)
+ data[i] = (value >> (32 - (i) * 8)) & 0xFF;
+
+ return picodlp_i2c_write_block(client, data, 5);
+}
+
+static int picodlp_i2c_write_array(struct i2c_client *client,
+ const struct picodlp_i2c_command commands[],
+ int count)
+{
+ int i, r = 0;
+ for (i = 0; i < count; i++) {
+ r = picodlp_i2c_write(client, commands[i].reg,
+ commands[i].value);
+ if (r)
+ return r;
+ }
+ return r;
+}
+
+static int picodlp_wait_for_dma_done(struct i2c_client *client)
+{
+ u8 trial = 100;
+
+ do {
+ msleep(1);
+ if (!trial--)
+ return -ETIMEDOUT;
+ } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
+
+ return 0;
+}
+
+/**
+ * picodlp_i2c_init: i2c_initialization routine
+ * client: i2c_client for communication
+ *
+ * return
+ * 0 : Success, no error
+ * error code : Failure
+ */
+static int picodlp_i2c_init(struct i2c_client *client)
+{
+ int r;
+ static const struct picodlp_i2c_command init_cmd_set1[] = {
+ {SOFT_RESET, 1},
+ {DMD_PARK_TRIGGER, 1},
+ {MISC_REG, 5},
+ {SEQ_CONTROL, 0},
+ {SEQ_VECTOR, 0x100},
+ {DMD_BLOCK_COUNT, 7},
+ {DMD_VCC_CONTROL, 0x109},
+ {DMD_PARK_PULSE_COUNT, 0xA},
+ {DMD_PARK_PULSE_WIDTH, 0xB},
+ {DMD_PARK_DELAY, 0x2ED},
+ {DMD_SHADOW_ENABLE, 0},
+ {FLASH_OPCODE, 0xB},
+ {FLASH_DUMMY_BYTES, 1},
+ {FLASH_ADDR_BYTES, 3},
+ {PBC_CONTROL, 0},
+ {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
+ {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
+ {CMT_SPLASH_LUT_START_ADDR, 0},
+ {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
+ {PBC_CONTROL, 1},
+ };
+
+ static const struct picodlp_i2c_command init_cmd_set2[] = {
+ {PBC_CONTROL, 0},
+ {CMT_SPLASH_LUT_DEST_SELECT, 0},
+ {PBC_CONTROL, 0},
+ {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
+ {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
+ {SEQ_RESET_LUT_START_ADDR, 0},
+ {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
+ {PBC_CONTROL, 1},
+ };
+
+ static const struct picodlp_i2c_command init_cmd_set3[] = {
+ {PBC_CONTROL, 0},
+ {SEQ_RESET_LUT_DEST_SELECT, 0},
+ {PBC_CONTROL, 0},
+ {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
+ {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
+ {SEQ_RESET_LUT_START_ADDR, 0},
+ {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
+ {PBC_CONTROL, 1},
+ };
+
+ static const struct picodlp_i2c_command init_cmd_set4[] = {
+ {PBC_CONTROL, 0},
+ {SEQ_RESET_LUT_DEST_SELECT, 0},
+ {SDC_ENABLE, 1},
+ {AGC_CTRL, 7},
+ {CCA_C1A, 0x100},
+ {CCA_C1B, 0x0},
+ {CCA_C1C, 0x0},
+ {CCA_C2A, 0x0},
+ {CCA_C2B, 0x100},
+ {CCA_C2C, 0x0},
+ {CCA_C3A, 0x0},
+ {CCA_C3B, 0x0},
+ {CCA_C3C, 0x100},
+ {CCA_C7A, 0x100},
+ {CCA_C7B, 0x100},
+ {CCA_C7C, 0x100},
+ {CCA_ENABLE, 1},
+ {CPU_IF_MODE, 1},
+ {SHORT_FLIP, 1},
+ {CURTAIN_CONTROL, 0},
+ {DMD_PARK_TRIGGER, 0},
+ {R_DRIVE_CURRENT, 0x298},
+ {G_DRIVE_CURRENT, 0x298},
+ {B_DRIVE_CURRENT, 0x298},
+ {RGB_DRIVER_ENABLE, 7},
+ {SEQ_CONTROL, 0},
+ {ACTGEN_CONTROL, 0x10},
+ {SEQUENCE_MODE, SEQ_LOCK},
+ {DATA_FORMAT, RGB888},
+ {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
+ {INPUT_SOURCE, PARALLEL_RGB},
+ {CPU_IF_SYNC_METHOD, 1},
+ {SEQ_CONTROL, 1}
+ };
+
+ r = picodlp_i2c_write_array(client, init_cmd_set1,
+ ARRAY_SIZE(init_cmd_set1));
+ if (r)
+ return r;
+
+ r = picodlp_wait_for_dma_done(client);
+ if (r)
+ return r;
+
+ r = picodlp_i2c_write_array(client, init_cmd_set2,
+ ARRAY_SIZE(init_cmd_set2));
+ if (r)
+ return r;
+
+ r = picodlp_wait_for_dma_done(client);
+ if (r)
+ return r;
+
+ r = picodlp_i2c_write_array(client, init_cmd_set3,
+ ARRAY_SIZE(init_cmd_set3));
+ if (r)
+ return r;
+
+ r = picodlp_wait_for_dma_done(client);
+ if (r)
+ return r;
+
+ r = picodlp_i2c_write_array(client, init_cmd_set4,
+ ARRAY_SIZE(init_cmd_set4));
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int picodlp_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct picodlp_i2c_data *picodlp_i2c_data;
+
+ picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
+
+ if (!picodlp_i2c_data)
+ return -ENOMEM;
+
+ mutex_init(&picodlp_i2c_data->xfer_lock);
+ i2c_set_clientdata(client, picodlp_i2c_data);
+
+ return 0;
+}
+
+static int picodlp_i2c_remove(struct i2c_client *client)
+{
+ struct picodlp_i2c_data *picodlp_i2c_data =
+ i2c_get_clientdata(client);
+ kfree(picodlp_i2c_data);
+ return 0;
+}
+
+static struct i2c_driver picodlp_i2c_driver = {
+ .driver = {
+ .name = "picodlp_i2c_driver",
+ },
+ .probe = picodlp_i2c_probe,
+ .remove = picodlp_i2c_remove,
+ .id_table = picodlp_i2c_id,
+};
+
+static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
+{
+ int r, trial = 100;
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+ struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+
+ if (dssdev->platform_enable) {
+ r = dssdev->platform_enable(dssdev);
+ if (r)
+ return r;
+ }
+
+ gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
+ msleep(1);
+ gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
+
+ while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
+ if (!trial--) {
+ dev_err(&dssdev->dev, "emu_done signal not"
+ " going high\n");
+ return -ETIMEDOUT;
+ }
+ msleep(5);
+ }
+ /*
+ * As per dpp2600 programming guide,
+ * it is required to sleep for 1000ms after emu_done signal goes high
+ * then only i2c commands can be successfully sent to dpp2600
+ */
+ msleep(1000);
+ r = omapdss_dpi_display_enable(dssdev);
+ if (r) {
+ dev_err(&dssdev->dev, "failed to enable DPI\n");
+ goto err1;
+ }
+
+ r = picodlp_i2c_init(picod->picodlp_i2c_client);
+ if (r)
+ goto err;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return r;
+err:
+ omapdss_dpi_display_disable(dssdev);
+err1:
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ return r;
+}
+
+static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
+{
+ struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+
+ omapdss_dpi_display_disable(dssdev);
+
+ gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
+ gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+}
+
+static int picodlp_panel_probe(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod;
+ struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+ struct i2c_adapter *adapter;
+ struct i2c_client *picodlp_i2c_client;
+ int r = 0, picodlp_adapter_id;
+
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
+ OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
+ dssdev->panel.acb = 0x0;
+ dssdev->panel.timings = pico_ls_timings;
+
+ picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
+ if (!picod)
+ return -ENOMEM;
+
+ mutex_init(&picod->lock);
+
+ picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
+
+ adapter = i2c_get_adapter(picodlp_adapter_id);
+ if (!adapter) {
+ dev_err(&dssdev->dev, "can't get i2c adapter\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
+ if (!picodlp_i2c_client) {
+ dev_err(&dssdev->dev, "can't add i2c device::"
+ " picodlp_i2c_client is NULL\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ picod->picodlp_i2c_client = picodlp_i2c_client;
+
+ dev_set_drvdata(&dssdev->dev, picod);
+ return r;
+err:
+ kfree(picod);
+ return r;
+}
+
+static void picodlp_panel_remove(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+ i2c_unregister_device(picod->picodlp_i2c_client);
+ dev_set_drvdata(&dssdev->dev, NULL);
+ dev_dbg(&dssdev->dev, "removing picodlp panel\n");
+
+ kfree(picod);
+}
+
+static int picodlp_panel_enable(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
+
+ mutex_lock(&picod->lock);
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+ mutex_unlock(&picod->lock);
+ return -EINVAL;
+ }
+
+ r = picodlp_panel_power_on(dssdev);
+ mutex_unlock(&picod->lock);
+
+ return r;
+}
+
+static void picodlp_panel_disable(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&picod->lock);
+ /* Turn off DLP Power */
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ picodlp_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+ mutex_unlock(&picod->lock);
+
+ dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
+}
+
+static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+ mutex_lock(&picod->lock);
+ /* Turn off DLP Power */
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ mutex_unlock(&picod->lock);
+ dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
+ " panel is not ACTIVE\n");
+ return -EINVAL;
+ }
+
+ picodlp_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+ mutex_unlock(&picod->lock);
+
+ dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
+ return 0;
+}
+
+static int picodlp_panel_resume(struct omap_dss_device *dssdev)
+{
+ struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ mutex_lock(&picod->lock);
+ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+ mutex_unlock(&picod->lock);
+ dev_err(&dssdev->dev, "unable to resume picodlp panel,"
+ " panel is not ACTIVE\n");
+ return -EINVAL;
+ }
+
+ r = picodlp_panel_power_on(dssdev);
+ mutex_unlock(&picod->lock);
+ dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
+ return r;
+}
+
+static void picodlp_get_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres)
+{
+ *xres = dssdev->panel.timings.x_res;
+ *yres = dssdev->panel.timings.y_res;
+}
+
+static struct omap_dss_driver picodlp_driver = {
+ .probe = picodlp_panel_probe,
+ .remove = picodlp_panel_remove,
+
+ .enable = picodlp_panel_enable,
+ .disable = picodlp_panel_disable,
+
+ .get_resolution = picodlp_get_resolution,
+
+ .suspend = picodlp_panel_suspend,
+ .resume = picodlp_panel_resume,
+
+ .driver = {
+ .name = "picodlp_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init picodlp_init(void)
+{
+ int r = 0;
+
+ r = i2c_add_driver(&picodlp_i2c_driver);
+ if (r) {
+ printk(KERN_WARNING "picodlp_i2c_driver" \
+ " registration failed\n");
+ return r;
+ }
+
+ r = omap_dss_register_driver(&picodlp_driver);
+ if (r)
+ i2c_del_driver(&picodlp_i2c_driver);
+
+ return r;
+}
+
+static void __exit picodlp_exit(void)
+{
+ i2c_del_driver(&picodlp_i2c_driver);
+ omap_dss_unregister_driver(&picodlp_driver);
+}
+
+module_init(picodlp_init);
+module_exit(picodlp_exit);
+
+MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
+MODULE_DESCRIPTION("picodlp driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
new file mode 100644
index 000000000000..a34b431a7267
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-picodlp.h
@@ -0,0 +1,288 @@
+/*
+ * Header file required by picodlp panel driver
+ *
+ * Copyright (C) 2009-2011 Texas Instruments
+ * Author: 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/>.
+*/
+
+#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H
+#define __OMAP2_DISPLAY_PANEL_PICODLP_H
+
+/* Commands used for configuring picodlp panel */
+
+#define MAIN_STATUS 0x03
+#define PBC_CONTROL 0x08
+#define INPUT_SOURCE 0x0B
+#define INPUT_RESOLUTION 0x0C
+#define DATA_FORMAT 0x0D
+#define IMG_ROTATION 0x0E
+#define LONG_FLIP 0x0F
+#define SHORT_FLIP 0x10
+#define TEST_PAT_SELECT 0x11
+#define R_DRIVE_CURRENT 0x12
+#define G_DRIVE_CURRENT 0x13
+#define B_DRIVE_CURRENT 0x14
+#define READ_REG_SELECT 0x15
+#define RGB_DRIVER_ENABLE 0x16
+
+#define CPU_IF_MODE 0x18
+#define FRAME_RATE 0x19
+#define CPU_IF_SYNC_METHOD 0x1A
+#define CPU_IF_SOF 0x1B
+#define CPU_IF_EOF 0x1C
+#define CPU_IF_SLEEP 0x1D
+
+#define SEQUENCE_MODE 0x1E
+#define SOFT_RESET 0x1F
+#define FRONT_END_RESET 0x21
+#define AUTO_PWR_ENABLE 0x22
+
+#define VSYNC_LINE_DELAY 0x23
+#define CPU_PI_HORIZ_START 0x24
+#define CPU_PI_VERT_START 0x25
+#define CPU_PI_HORIZ_WIDTH 0x26
+#define CPU_PI_VERT_HEIGHT 0x27
+
+#define PIXEL_MASK_CROP 0x28
+#define CROP_FIRST_LINE 0x29
+#define CROP_LAST_LINE 0x2A
+#define CROP_FIRST_PIXEL 0x2B
+#define CROP_LAST_PIXEL 0x2C
+#define DMD_PARK_TRIGGER 0x2D
+
+#define MISC_REG 0x30
+
+/* AGC registers */
+#define AGC_CTRL 0x50
+#define AGC_CLIPPED_PIXS 0x55
+#define AGC_BRIGHT_PIXS 0x56
+#define AGC_BG_PIXS 0x57
+#define AGC_SAFETY_MARGIN 0x17
+
+/* Color Coordinate Adjustment registers */
+#define CCA_ENABLE 0x5E
+#define CCA_C1A 0x5F
+#define CCA_C1B 0x60
+#define CCA_C1C 0x61
+#define CCA_C2A 0x62
+#define CCA_C2B 0x63
+#define CCA_C2C 0x64
+#define CCA_C3A 0x65
+#define CCA_C3B 0x66
+#define CCA_C3C 0x67
+#define CCA_C7A 0x71
+#define CCA_C7B 0x72
+#define CCA_C7C 0x73
+
+/**
+ * DLP Pico Processor 2600 comes with flash
+ * We can do DMA operations from flash for accessing Look Up Tables
+ */
+#define DMA_STATUS 0x100
+#define FLASH_ADDR_BYTES 0x74
+#define FLASH_DUMMY_BYTES 0x75
+#define FLASH_WRITE_BYTES 0x76
+#define FLASH_READ_BYTES 0x77
+#define FLASH_OPCODE 0x78
+#define FLASH_START_ADDR 0x79
+#define FLASH_DUMMY2 0x7A
+#define FLASH_WRITE_DATA 0x7B
+
+#define TEMPORAL_DITH_DISABLE 0x7E
+#define SEQ_CONTROL 0x82
+#define SEQ_VECTOR 0x83
+
+/* DMD is Digital Micromirror Device */
+#define DMD_BLOCK_COUNT 0x84
+#define DMD_VCC_CONTROL 0x86
+#define DMD_PARK_PULSE_COUNT 0x87
+#define DMD_PARK_PULSE_WIDTH 0x88
+#define DMD_PARK_DELAY 0x89
+#define DMD_SHADOW_ENABLE 0x8E
+#define SEQ_STATUS 0x8F
+#define FLASH_CLOCK_CONTROL 0x98
+#define DMD_PARK 0x2D
+
+#define SDRAM_BIST_ENABLE 0x46
+#define DDR_DRIVER_STRENGTH 0x9A
+#define SDC_ENABLE 0x9D
+#define SDC_BUFF_SWAP_DISABLE 0xA3
+#define CURTAIN_CONTROL 0xA6
+#define DDR_BUS_SWAP_ENABLE 0xA7
+#define DMD_TRC_ENABLE 0xA8
+#define DMD_BUS_SWAP_ENABLE 0xA9
+
+#define ACTGEN_ENABLE 0xAE
+#define ACTGEN_CONTROL 0xAF
+#define ACTGEN_HORIZ_BP 0xB0
+#define ACTGEN_VERT_BP 0xB1
+
+/* Look Up Table access */
+#define CMT_SPLASH_LUT_START_ADDR 0xFA
+#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
+#define CMT_SPLASH_LUT_DATA 0xFC
+#define SEQ_RESET_LUT_START_ADDR 0xFD
+#define SEQ_RESET_LUT_DEST_SELECT 0xFE
+#define SEQ_RESET_LUT_DATA 0xFF
+
+/* Input source definitions */
+#define PARALLEL_RGB 0
+#define INT_TEST_PATTERN 1
+#define SPLASH_SCREEN 2
+#define CPU_INTF 3
+#define BT656 4
+
+/* Standard input resolution definitions */
+#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
+#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
+#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
+
+/* Standard data format definitions */
+#define RGB565 0
+#define RGB666 1
+#define RGB888 2
+
+/* Test Pattern definitions */
+#define TPG_CHECKERBOARD 0
+#define TPG_BLACK 1
+#define TPG_WHITE 2
+#define TPG_RED 3
+#define TPG_BLUE 4
+#define TPG_GREEN 5
+#define TPG_VLINES_BLACK 6
+#define TPG_HLINES_BLACK 7
+#define TPG_VLINES_ALT 8
+#define TPG_HLINES_ALT 9
+#define TPG_DIAG_LINES 10
+#define TPG_GREYRAMP_VERT 11
+#define TPG_GREYRAMP_HORIZ 12
+#define TPG_ANSI_CHECKERBOARD 13
+
+/* sequence mode definitions */
+#define SEQ_FREE_RUN 0
+#define SEQ_LOCK 1
+
+/* curtain color definitions */
+#define CURTAIN_BLACK 0
+#define CURTAIN_RED 1
+#define CURTAIN_GREEN 2
+#define CURTAIN_BLUE 3
+#define CURTAIN_YELLOW 4
+#define CURTAIN_MAGENTA 5
+#define CURTAIN_CYAN 6
+#define CURTAIN_WHITE 7
+
+/* LUT definitions */
+#define CMT_LUT_NONE 0
+#define CMT_LUT_GREEN 1
+#define CMT_LUT_RED 2
+#define CMT_LUT_BLUE 3
+#define CMT_LUT_ALL 4
+#define SPLASH_LUT 5
+
+#define SEQ_LUT_NONE 0
+#define SEQ_DRC_LUT_0 1
+#define SEQ_DRC_LUT_1 2
+#define SEQ_DRC_LUT_2 3
+#define SEQ_DRC_LUT_3 4
+#define SEQ_SEQ_LUT 5
+#define SEQ_DRC_LUT_ALL 6
+#define WPC_PROGRAM_LUT 7
+
+#define BITSTREAM_START_ADDR 0x00000000
+#define BITSTREAM_SIZE 0x00040000
+
+#define WPC_FW_0_START_ADDR 0x00040000
+#define WPC_FW_0_SIZE 0x00000ce8
+
+#define SEQUENCE_0_START_ADDR 0x00044000
+#define SEQUENCE_0_SIZE 0x00001000
+
+#define SEQUENCE_1_START_ADDR 0x00045000
+#define SEQUENCE_1_SIZE 0x00000d10
+
+#define SEQUENCE_2_START_ADDR 0x00046000
+#define SEQUENCE_2_SIZE 0x00000d10
+
+#define SEQUENCE_3_START_ADDR 0x00047000
+#define SEQUENCE_3_SIZE 0x00000d10
+
+#define SEQUENCE_4_START_ADDR 0x00048000
+#define SEQUENCE_4_SIZE 0x00000d10
+
+#define SEQUENCE_5_START_ADDR 0x00049000
+#define SEQUENCE_5_SIZE 0x00000d10
+
+#define SEQUENCE_6_START_ADDR 0x0004a000
+#define SEQUENCE_6_SIZE 0x00000d10
+
+#define CMT_LUT_0_START_ADDR 0x0004b200
+#define CMT_LUT_0_SIZE 0x00000600
+
+#define CMT_LUT_1_START_ADDR 0x0004b800
+#define CMT_LUT_1_SIZE 0x00000600
+
+#define CMT_LUT_2_START_ADDR 0x0004be00
+#define CMT_LUT_2_SIZE 0x00000600
+
+#define CMT_LUT_3_START_ADDR 0x0004c400
+#define CMT_LUT_3_SIZE 0x00000600
+
+#define CMT_LUT_4_START_ADDR 0x0004ca00
+#define CMT_LUT_4_SIZE 0x00000600
+
+#define CMT_LUT_5_START_ADDR 0x0004d000
+#define CMT_LUT_5_SIZE 0x00000600
+
+#define CMT_LUT_6_START_ADDR 0x0004d600
+#define CMT_LUT_6_SIZE 0x00000600
+
+#define DRC_TABLE_0_START_ADDR 0x0004dc00
+#define DRC_TABLE_0_SIZE 0x00000100
+
+#define SPLASH_0_START_ADDR 0x0004dd00
+#define SPLASH_0_SIZE 0x00032280
+
+#define SEQUENCE_7_START_ADDR 0x00080000
+#define SEQUENCE_7_SIZE 0x00000d10
+
+#define SEQUENCE_8_START_ADDR 0x00081800
+#define SEQUENCE_8_SIZE 0x00000d10
+
+#define SEQUENCE_9_START_ADDR 0x00083000
+#define SEQUENCE_9_SIZE 0x00000d10
+
+#define CMT_LUT_7_START_ADDR 0x0008e000
+#define CMT_LUT_7_SIZE 0x00000600
+
+#define CMT_LUT_8_START_ADDR 0x0008e800
+#define CMT_LUT_8_SIZE 0x00000600
+
+#define CMT_LUT_9_START_ADDR 0x0008f000
+#define CMT_LUT_9_SIZE 0x00000600
+
+#define SPLASH_1_START_ADDR 0x0009a000
+#define SPLASH_1_SIZE 0x00032280
+
+#define SPLASH_2_START_ADDR 0x000cd000
+#define SPLASH_2_SIZE 0x00032280
+
+#define SPLASH_3_START_ADDR 0x00100000
+#define SPLASH_3_SIZE 0x00032280
+
+#define OPT_SPLASH_0_START_ADDR 0x00134000
+#define OPT_SPLASH_0_SIZE 0x000cb100
+
+#endif
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4e888ac09b3f..80c3f6ab1a94 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -35,26 +35,12 @@
#include <video/omapdss.h>
#include <video/omap-panel-nokia-dsi.h>
+#include <video/mipi_display.h>
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
#define DCS_READ_NUM_ERRORS 0x05
-#define DCS_READ_POWER_MODE 0x0a
-#define DCS_READ_MADCTL 0x0b
-#define DCS_READ_PIXEL_FORMAT 0x0c
-#define DCS_RDDSDR 0x0f
-#define DCS_SLEEP_IN 0x10
-#define DCS_SLEEP_OUT 0x11
-#define DCS_DISPLAY_OFF 0x28
-#define DCS_DISPLAY_ON 0x29
-#define DCS_COLUMN_ADDR 0x2a
-#define DCS_PAGE_ADDR 0x2b
-#define DCS_MEMORY_WRITE 0x2c
-#define DCS_TEAR_OFF 0x34
-#define DCS_TEAR_ON 0x35
-#define DCS_MEM_ACC_CTRL 0x36
-#define DCS_PIXEL_FORMAT 0x3a
#define DCS_BRIGHTNESS 0x51
#define DCS_CTRL_DISPLAY 0x53
#define DCS_WRITE_CABC 0x55
@@ -222,8 +208,6 @@ struct taal_data {
struct delayed_work te_timeout_work;
- bool use_dsi_bl;
-
bool cabc_broken;
unsigned cabc_mode;
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
hw_guard_wait(td);
- cmd = DCS_SLEEP_IN;
+ cmd = MIPI_DCS_ENTER_SLEEP_MODE;
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
if (r)
return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
hw_guard_wait(td);
- r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
+ r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
if (r)
return r;
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
u8 mode;
int b5, b6, b7;
- r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
if (r)
return r;
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
mode &= ~((1<<7) | (1<<6) | (1<<5));
mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
- return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
+ return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
}
static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
u16 y2 = y + h - 1;
u8 buf[5];
- buf[0] = DCS_COLUMN_ADDR;
+ buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
buf[1] = (x1 >> 8) & 0xff;
buf[2] = (x1 >> 0) & 0xff;
buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
if (r)
return r;
- buf[0] = DCS_PAGE_ADDR;
+ buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
buf[1] = (y1 >> 8) & 0xff;
buf[2] = (y1 >> 0) & 0xff;
buf[3] = (y2 >> 8) & 0xff;
@@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
int level;
@@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
mutex_lock(&td->lock);
- if (td->use_dsi_bl) {
- if (td->enabled) {
- dsi_bus_lock(dssdev);
+ if (td->enabled) {
+ dsi_bus_lock(dssdev);
- r = taal_wake_up(dssdev);
- if (!r)
- r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
- dsi_bus_unlock(dssdev);
- } else {
- r = 0;
- }
+ dsi_bus_unlock(dssdev);
} else {
- if (!panel_data->set_backlight)
- r = -EINVAL;
- else
- r = panel_data->set_backlight(dssdev, level);
+ r = 0;
}
mutex_unlock(&td->lock);
@@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
{
struct backlight_properties props;
struct taal_data *td;
- struct backlight_device *bldev;
+ struct backlight_device *bldev = NULL;
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL;
int r, i;
@@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings = panel_config->timings;
- dssdev->ctrl.pixel_size = 24;
+ dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
td = kzalloc(sizeof(*td), GFP_KERNEL);
if (!td) {
@@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
- /* if no platform set_backlight() defined, presume DSI backlight
- * control */
- memset(&props, 0, sizeof(struct backlight_properties));
- if (!panel_data->set_backlight)
- td->use_dsi_bl = true;
-
- if (td->use_dsi_bl)
+ if (panel_data->use_dsi_backlight) {
+ memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = 255;
- else
- props.max_brightness = 127;
-
- props.type = BACKLIGHT_RAW;
- bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
- dssdev, &taal_bl_ops, &props);
- if (IS_ERR(bldev)) {
- r = PTR_ERR(bldev);
- goto err_bl;
- }
- td->bldev = bldev;
+ props.type = BACKLIGHT_RAW;
+ bldev = backlight_device_register(dev_name(&dssdev->dev),
+ &dssdev->dev, dssdev, &taal_bl_ops, &props);
+ if (IS_ERR(bldev)) {
+ r = PTR_ERR(bldev);
+ goto err_bl;
+ }
+
+ td->bldev = bldev;
- bldev->props.fb_blank = FB_BLANK_UNBLANK;
- bldev->props.power = FB_BLANK_UNBLANK;
- if (td->use_dsi_bl)
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = 255;
- else
- bldev->props.brightness = 127;
- taal_bl_update_status(bldev);
+ taal_bl_update_status(bldev);
+ }
if (panel_data->use_ext_te) {
int gpio = panel_data->ext_te_gpio;
@@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
gpio_direction_input(gpio);
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING,
"taal vsync", dssdev);
if (r) {
@@ -1111,7 +1078,8 @@ err_irq:
if (panel_data->use_ext_te)
gpio_free(panel_data->ext_te_gpio);
err_gpio:
- backlight_device_unregister(bldev);
+ if (bldev != NULL)
+ backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(td->workqueue);
err_wq:
@@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
}
bldev = td->bldev;
- bldev->props.power = FB_BLANK_POWERDOWN;
- taal_bl_update_status(bldev);
- backlight_device_unregister(bldev);
+ if (bldev != NULL) {
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ taal_bl_update_status(bldev);
+ backlight_device_unregister(bldev);
+ }
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
@@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if (r)
goto err;
- r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
+ MIPI_DCS_PIXEL_FMT_24BIT);
if (r)
goto err;
@@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
goto err;
}
- r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
if (r)
goto err;
@@ -1246,7 +1217,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(td, DCS_DISPLAY_OFF);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
if (!r)
r = taal_sleep_in(td);
@@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
int r;
if (enable)
- r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
else
- r = taal_dcs_write_0(td, DCS_TEAR_OFF);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
if (!panel_data->use_ext_te)
omapdss_dsi_enable_te(dssdev, enable);
@@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1880,7 +1851,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(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
if (r)
goto err;
}
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 0d12524db14b..7be7c06a249e 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,5 +1,5 @@
menuconfig OMAP2_DSS
- tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
+ tristate "OMAP2+ Display Subsystem support"
depends on ARCH_OMAP2PLUS
help
OMAP2+ Display Subsystem support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 10d9d3bb3e24..bd34ac5b2026 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -6,4 +6,4 @@ 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
+ hdmi_panel.o ti_hdmi_4xxx_ip.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 76821fefce9a..86ec12e16c7c 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -145,6 +145,10 @@ static int dss_initialize_debugfs(void)
debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
&venc_dump_regs, &dss_debug_fops);
#endif
+#ifdef CONFIG_OMAP4_DSS_HDMI
+ debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
+ &hdmi_dump_regs, &dss_debug_fops);
+#endif
return 0;
}
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 0f3961a1ce26..6892cfd2e3b7 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -106,7 +106,7 @@ static struct {
int irq;
struct clk *dss_clk;
- u32 fifo_size[3];
+ u32 fifo_size[MAX_DSS_OVERLAYS];
spinlock_t irq_lock;
u32 irq_error_mask;
@@ -171,172 +171,98 @@ static int dispc_get_ctx_loss_count(void)
static void dispc_save_context(void)
{
- int i;
+ int i, j;
DSSDBG("dispc_save_context\n");
SR(IRQENABLE);
SR(CONTROL);
SR(CONFIG);
- SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
- SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
- SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
- SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
SR(LINE_NUMBER);
- SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
- SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
- SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
- SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
SR(GLOBAL_ALPHA);
- SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
- SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
SR(CONTROL2);
- SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
- SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
- SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
- SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
- SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
- SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
- SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
SR(CONFIG2);
}
- SR(OVL_BA0(OMAP_DSS_GFX));
- SR(OVL_BA1(OMAP_DSS_GFX));
- SR(OVL_POSITION(OMAP_DSS_GFX));
- SR(OVL_SIZE(OMAP_DSS_GFX));
- SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
- SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
- SR(OVL_ROW_INC(OMAP_DSS_GFX));
- SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
- SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
- SR(OVL_TABLE_BA(OMAP_DSS_GFX));
+ for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+ SR(DEFAULT_COLOR(i));
+ SR(TRANS_COLOR(i));
+ SR(SIZE_MGR(i));
+ if (i == OMAP_DSS_CHANNEL_DIGIT)
+ continue;
+ SR(TIMING_H(i));
+ SR(TIMING_V(i));
+ SR(POL_FREQ(i));
+ SR(DIVISORo(i));
- SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
- SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
- SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
+ SR(DATA_CYCLE1(i));
+ SR(DATA_CYCLE2(i));
+ SR(DATA_CYCLE3(i));
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
- if (dss_has_feature(FEAT_MGR_LCD2)) {
if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+ SR(CPR_COEF_R(i));
+ SR(CPR_COEF_G(i));
+ SR(CPR_COEF_B(i));
}
-
- SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
- SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
- SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_GFX));
-
- /* VID1 */
- SR(OVL_BA0(OMAP_DSS_VIDEO1));
- SR(OVL_BA1(OMAP_DSS_VIDEO1));
- SR(OVL_POSITION(OMAP_DSS_VIDEO1));
- SR(OVL_SIZE(OMAP_DSS_VIDEO1));
- SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
- SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
- SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
- SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
- SR(OVL_FIR(OMAP_DSS_VIDEO1));
- SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
- SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
- SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
-
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 5; i++)
- SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
- SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
- SR(OVL_FIR2(OMAP_DSS_VIDEO1));
- SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
- SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
- }
- if (dss_has_feature(FEAT_ATTR2))
- SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
-
- /* VID2 */
- SR(OVL_BA0(OMAP_DSS_VIDEO2));
- SR(OVL_BA1(OMAP_DSS_VIDEO2));
- SR(OVL_POSITION(OMAP_DSS_VIDEO2));
- SR(OVL_SIZE(OMAP_DSS_VIDEO2));
- SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
- SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
- SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
- SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
- SR(OVL_FIR(OMAP_DSS_VIDEO2));
- SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
- SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
- SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
+ for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+ SR(OVL_BA0(i));
+ SR(OVL_BA1(i));
+ SR(OVL_POSITION(i));
+ SR(OVL_SIZE(i));
+ SR(OVL_ATTRIBUTES(i));
+ SR(OVL_FIFO_THRESHOLD(i));
+ SR(OVL_ROW_INC(i));
+ SR(OVL_PIXEL_INC(i));
+ if (dss_has_feature(FEAT_PRELOAD))
+ SR(OVL_PRELOAD(i));
+ if (i == OMAP_DSS_GFX) {
+ SR(OVL_WINDOW_SKIP(i));
+ SR(OVL_TABLE_BA(i));
+ continue;
+ }
+ SR(OVL_FIR(i));
+ SR(OVL_PICTURE_SIZE(i));
+ SR(OVL_ACCU0(i));
+ SR(OVL_ACCU1(i));
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_H(i, j));
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_HV(i, j));
- for (i = 0; i < 5; i++)
- SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 5; j++)
+ SR(OVL_CONV_COEF(i, j));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ if (dss_has_feature(FEAT_FIR_COEF_V)) {
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_V(i, j));
+ }
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
- SR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
- SR(OVL_FIR2(OMAP_DSS_VIDEO2));
- SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
- SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
+ if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+ SR(OVL_BA0_UV(i));
+ SR(OVL_BA1_UV(i));
+ SR(OVL_FIR2(i));
+ SR(OVL_ACCU2_0(i));
+ SR(OVL_ACCU2_1(i));
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_H2(i, j));
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_HV2(i, j));
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ SR(OVL_FIR_COEF_V2(i, j));
+ }
+ if (dss_has_feature(FEAT_ATTR2))
+ SR(OVL_ATTRIBUTES2(i));
}
- if (dss_has_feature(FEAT_ATTR2))
- SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
SR(DIVISOR);
@@ -349,7 +275,7 @@ static void dispc_save_context(void)
static void dispc_restore_context(void)
{
- int i, ctx;
+ int i, j, ctx;
DSSDBG("dispc_restore_context\n");
@@ -367,165 +293,89 @@ static void dispc_restore_context(void)
/*RR(IRQENABLE);*/
/*RR(CONTROL);*/
RR(CONFIG);
- RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
- RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
- RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
- RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
RR(LINE_NUMBER);
- RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
- RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
- RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
- RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
RR(GLOBAL_ALPHA);
- RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
- RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
- RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
- RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
- RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
- RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
- RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
- RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
+ if (dss_has_feature(FEAT_MGR_LCD2))
RR(CONFIG2);
- }
-
- RR(OVL_BA0(OMAP_DSS_GFX));
- RR(OVL_BA1(OMAP_DSS_GFX));
- RR(OVL_POSITION(OMAP_DSS_GFX));
- RR(OVL_SIZE(OMAP_DSS_GFX));
- RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
- RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
- RR(OVL_ROW_INC(OMAP_DSS_GFX));
- RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
- RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
- RR(OVL_TABLE_BA(OMAP_DSS_GFX));
-
- RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
- RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
- RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
+ for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+ RR(DEFAULT_COLOR(i));
+ RR(TRANS_COLOR(i));
+ RR(SIZE_MGR(i));
+ if (i == OMAP_DSS_CHANNEL_DIGIT)
+ continue;
+ RR(TIMING_H(i));
+ RR(TIMING_V(i));
+ RR(POL_FREQ(i));
+ RR(DIVISORo(i));
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
- RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
- RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
+ RR(DATA_CYCLE1(i));
+ RR(DATA_CYCLE2(i));
+ RR(DATA_CYCLE3(i));
if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+ RR(CPR_COEF_R(i));
+ RR(CPR_COEF_G(i));
+ RR(CPR_COEF_B(i));
}
}
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_GFX));
-
- /* VID1 */
- RR(OVL_BA0(OMAP_DSS_VIDEO1));
- RR(OVL_BA1(OMAP_DSS_VIDEO1));
- RR(OVL_POSITION(OMAP_DSS_VIDEO1));
- RR(OVL_SIZE(OMAP_DSS_VIDEO1));
- RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
- RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
- RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
- RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
- RR(OVL_FIR(OMAP_DSS_VIDEO1));
- RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
- RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
- RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
-
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 5; i++)
- RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
- RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
- RR(OVL_FIR2(OMAP_DSS_VIDEO1));
- RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
- RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
-
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
- }
- if (dss_has_feature(FEAT_ATTR2))
- RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
-
- /* VID2 */
- RR(OVL_BA0(OMAP_DSS_VIDEO2));
- RR(OVL_BA1(OMAP_DSS_VIDEO2));
- RR(OVL_POSITION(OMAP_DSS_VIDEO2));
- RR(OVL_SIZE(OMAP_DSS_VIDEO2));
- RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
- RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
- RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
- RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
- RR(OVL_FIR(OMAP_DSS_VIDEO2));
- RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
- RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
- RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
+ for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+ RR(OVL_BA0(i));
+ RR(OVL_BA1(i));
+ RR(OVL_POSITION(i));
+ RR(OVL_SIZE(i));
+ RR(OVL_ATTRIBUTES(i));
+ RR(OVL_FIFO_THRESHOLD(i));
+ RR(OVL_ROW_INC(i));
+ RR(OVL_PIXEL_INC(i));
+ if (dss_has_feature(FEAT_PRELOAD))
+ RR(OVL_PRELOAD(i));
+ if (i == OMAP_DSS_GFX) {
+ RR(OVL_WINDOW_SKIP(i));
+ RR(OVL_TABLE_BA(i));
+ continue;
+ }
+ RR(OVL_FIR(i));
+ RR(OVL_PICTURE_SIZE(i));
+ RR(OVL_ACCU0(i));
+ RR(OVL_ACCU1(i));
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_H(i, j));
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_HV(i, j));
- for (i = 0; i < 5; i++)
- RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 5; j++)
+ RR(OVL_CONV_COEF(i, j));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ if (dss_has_feature(FEAT_FIR_COEF_V)) {
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_V(i, j));
+ }
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
- RR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
- RR(OVL_FIR2(OMAP_DSS_VIDEO2));
- RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
- RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
+ if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+ RR(OVL_BA0_UV(i));
+ RR(OVL_BA1_UV(i));
+ RR(OVL_FIR2(i));
+ RR(OVL_ACCU2_0(i));
+ RR(OVL_ACCU2_1(i));
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_H2(i, j));
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_HV2(i, j));
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
+ for (j = 0; j < 8; j++)
+ RR(OVL_FIR_COEF_V2(i, j));
+ }
+ if (dss_has_feature(FEAT_ATTR2))
+ RR(OVL_ATTRIBUTES2(i));
}
- if (dss_has_feature(FEAT_ATTR2))
- RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
RR(DIVISOR);
@@ -570,13 +420,28 @@ void dispc_runtime_put(void)
WARN_ON(r < 0);
}
+static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
+{
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
+ channel == OMAP_DSS_CHANNEL_LCD2)
+ return true;
+ else
+ return false;
+}
+
+static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
+{
+ struct omap_overlay_manager *mgr =
+ omap_dss_get_overlay_manager(channel);
-bool dispc_go_busy(enum omap_channel channel)
+ return mgr ? mgr->device : NULL;
+}
+
+bool dispc_mgr_go_busy(enum omap_channel channel)
{
int bit;
- if (channel == OMAP_DSS_CHANNEL_LCD ||
- channel == OMAP_DSS_CHANNEL_LCD2)
+ if (dispc_mgr_is_lcd(channel))
bit = 5; /* GOLCD */
else
bit = 6; /* GODIGIT */
@@ -587,13 +452,12 @@ bool dispc_go_busy(enum omap_channel channel)
return REG_GET(DISPC_CONTROL, bit, bit) == 1;
}
-void dispc_go(enum omap_channel channel)
+void dispc_mgr_go(enum omap_channel channel)
{
int bit;
bool enable_bit, go_bit;
- if (channel == OMAP_DSS_CHANNEL_LCD ||
- channel == OMAP_DSS_CHANNEL_LCD2)
+ if (dispc_mgr_is_lcd(channel))
bit = 0; /* LCDENABLE */
else
bit = 1; /* DIGITALENABLE */
@@ -607,8 +471,7 @@ void dispc_go(enum omap_channel channel)
if (!enable_bit)
return;
- if (channel == OMAP_DSS_CHANNEL_LCD ||
- channel == OMAP_DSS_CHANNEL_LCD2)
+ if (dispc_mgr_is_lcd(channel))
bit = 5; /* GOLCD */
else
bit = 6; /* GODIGIT */
@@ -632,43 +495,44 @@ void dispc_go(enum omap_channel channel)
REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
}
-static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
{
dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
}
-static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
{
dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
}
-static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
{
dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
}
-static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
{
BUG_ON(plane == OMAP_DSS_GFX);
dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
}
-static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
+ u32 value)
{
BUG_ON(plane == OMAP_DSS_GFX);
dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
}
-static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
{
BUG_ON(plane == OMAP_DSS_GFX);
dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
}
-static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
+static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
int vscaleup, int five_taps,
enum omap_color_component color_comp)
{
@@ -769,11 +633,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
| FLD_VAL(v_coef[i].vc2, 31, 24);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
- _dispc_write_firh_reg(plane, i, h);
- _dispc_write_firhv_reg(plane, i, hv);
+ dispc_ovl_write_firh_reg(plane, i, h);
+ dispc_ovl_write_firhv_reg(plane, i, hv);
} else {
- _dispc_write_firh2_reg(plane, i, h);
- _dispc_write_firhv2_reg(plane, i, hv);
+ dispc_ovl_write_firh2_reg(plane, i, h);
+ dispc_ovl_write_firhv2_reg(plane, i, hv);
}
}
@@ -784,15 +648,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
v = FLD_VAL(v_coef[i].vc00, 7, 0)
| FLD_VAL(v_coef[i].vc22, 15, 8);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
- _dispc_write_firv_reg(plane, i, v);
+ dispc_ovl_write_firv_reg(plane, i, v);
else
- _dispc_write_firv2_reg(plane, i, v);
+ dispc_ovl_write_firv2_reg(plane, i, v);
}
}
}
static void _dispc_setup_color_conv_coef(void)
{
+ int i;
const struct color_conv_coef {
int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
int full_range;
@@ -806,65 +671,54 @@ static void _dispc_setup_color_conv_coef(void)
ct = &ctbl_bt601_5;
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
- CVAL(ct->rcr, ct->ry));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
- CVAL(ct->gy, ct->rcb));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
- CVAL(ct->gcb, ct->gcr));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
- CVAL(ct->bcr, ct->by));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
- CVAL(0, ct->bcb));
-
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
- CVAL(ct->rcr, ct->ry));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
- CVAL(ct->gy, ct->rcb));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
- CVAL(ct->gcb, ct->gcr));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
- CVAL(ct->bcr, ct->by));
- dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
- CVAL(0, ct->bcb));
+ for (i = 1; i < dss_feat_get_num_ovls(); i++) {
+ dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
+ CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
+ CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
+ CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
+ CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
+ CVAL(0, ct->bcb));
-#undef CVAL
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
+ 11, 11);
+ }
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
- ct->full_range, 11, 11);
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
- ct->full_range, 11, 11);
+#undef CVAL
}
-static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
{
dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
}
-static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
{
dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
}
-static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
{
dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
}
-static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
{
dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
}
-static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
+static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)
{
u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
dispc_write_reg(DISPC_OVL_POSITION(plane), val);
}
-static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height)
{
u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
@@ -874,7 +728,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
}
-static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
{
u32 val;
@@ -885,44 +739,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
dispc_write_reg(DISPC_OVL_SIZE(plane), val);
}
-static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder)
{
- if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
return;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
- plane == OMAP_DSS_VIDEO1)
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
+}
+
+static void dispc_ovl_enable_zorder_planes(void)
+{
+ int i;
+
+ if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
return;
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
+ for (i = 0; i < dss_feat_get_num_ovls(); i++)
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
}
-static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable)
{
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
return;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
- plane == OMAP_DSS_VIDEO1)
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
+}
+
+static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+{
+ static const unsigned shifts[] = { 0, 8, 16, 24, };
+ int shift;
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
return;
- if (plane == OMAP_DSS_GFX)
- REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
- else if (plane == OMAP_DSS_VIDEO2)
- REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
+ shift = shifts[plane];
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
}
-static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
{
dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
}
-static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
+static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
{
dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
}
-static void _dispc_set_color_mode(enum omap_plane plane,
+static void dispc_ovl_set_color_mode(enum omap_plane plane,
enum omap_color_mode color_mode)
{
u32 m = 0;
@@ -1003,7 +874,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-void dispc_set_channel_out(enum omap_plane plane,
+static void dispc_ovl_set_channel_out(enum omap_plane plane,
enum omap_channel channel)
{
int shift;
@@ -1016,6 +887,7 @@ void dispc_set_channel_out(enum omap_plane plane,
break;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
+ case OMAP_DSS_VIDEO3:
shift = 16;
break;
default:
@@ -1050,24 +922,13 @@ void dispc_set_channel_out(enum omap_plane plane,
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
-static void dispc_set_burst_size(enum omap_plane plane,
+static void dispc_ovl_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size)
{
+ static const unsigned shifts[] = { 6, 14, 14, 14, };
int shift;
- switch (plane) {
- case OMAP_DSS_GFX:
- shift = 6;
- break;
- case OMAP_DSS_VIDEO1:
- case OMAP_DSS_VIDEO2:
- shift = 14;
- break;
- default:
- BUG();
- return;
- }
-
+ shift = shifts[plane];
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
}
@@ -1078,10 +939,10 @@ static void dispc_configure_burst_sizes(void)
/* Configure burst size always to maximum size */
for (i = 0; i < omap_dss_get_num_overlays(); ++i)
- dispc_set_burst_size(i, burst_size);
+ dispc_ovl_set_burst_size(i, burst_size);
}
-u32 dispc_get_burst_size(enum omap_plane plane)
+u32 dispc_ovl_get_burst_size(enum omap_plane plane)
{
unsigned unit = dss_feat_get_burst_size_unit();
/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1102,7 +963,7 @@ void dispc_enable_gamma_table(bool enable)
REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
}
-void dispc_enable_cpr(enum omap_channel channel, bool enable)
+void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
{
u16 reg;
@@ -1116,12 +977,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable)
REG_FLD_MOD(reg, enable, 15, 15);
}
-void dispc_set_cpr_coef(enum omap_channel channel,
+void dispc_mgr_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs)
{
u32 coef_r, coef_g, coef_b;
- if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
+ if (!dispc_mgr_is_lcd(channel))
return;
coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
@@ -1136,7 +997,7 @@ void dispc_set_cpr_coef(enum omap_channel channel,
dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
}
-static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
{
u32 val;
@@ -1147,19 +1008,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
-void dispc_enable_replication(enum omap_plane plane, bool enable)
+static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
{
- int bit;
-
- if (plane == OMAP_DSS_GFX)
- bit = 5;
- else
- bit = 10;
+ static const unsigned shifts[] = { 5, 10, 10, 10 };
+ int shift;
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
+ shift = shifts[plane];
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
}
-void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
+void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
{
u32 val;
BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
@@ -1186,19 +1044,20 @@ static void dispc_read_plane_fifo_sizes(void)
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
- for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+ for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
size *= unit;
dispc.fifo_size[plane] = size;
}
}
-u32 dispc_get_plane_fifo_size(enum omap_plane plane)
+u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
{
return dispc.fifo_size[plane];
}
-void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
+static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low,
+ u32 high)
{
u8 hi_start, hi_end, lo_start, lo_end;
u32 unit;
@@ -1233,7 +1092,7 @@ void dispc_enable_fifomerge(bool enable)
REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
}
-static void _dispc_set_fir(enum omap_plane plane,
+static void dispc_ovl_set_fir(enum omap_plane plane,
int hinc, int vinc,
enum omap_color_component color_comp)
{
@@ -1256,7 +1115,7 @@ static void _dispc_set_fir(enum omap_plane plane,
}
}
-static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
{
u32 val;
u8 hor_start, hor_end, vert_start, vert_end;
@@ -1270,7 +1129,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
}
-static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
{
u32 val;
u8 hor_start, hor_end, vert_start, vert_end;
@@ -1284,7 +1143,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
}
-static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
+ int vaccu)
{
u32 val;
@@ -1292,7 +1152,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
}
-static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
+ int vaccu)
{
u32 val;
@@ -1300,7 +1161,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
}
-static void _dispc_set_scale_param(enum omap_plane plane,
+static void dispc_ovl_set_scale_param(enum omap_plane plane,
u16 orig_width, u16 orig_height,
u16 out_width, u16 out_height,
bool five_taps, u8 rotation,
@@ -1312,15 +1173,16 @@ static void _dispc_set_scale_param(enum omap_plane plane,
hscaleup = orig_width <= out_width;
vscaleup = orig_height <= out_height;
- _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
+ dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
+ color_comp);
fir_hinc = 1024 * orig_width / out_width;
fir_vinc = 1024 * orig_height / out_height;
- _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
+ dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
}
-static void _dispc_set_scaling_common(enum omap_plane plane,
+static void dispc_ovl_set_scaling_common(enum omap_plane plane,
u16 orig_width, u16 orig_height,
u16 out_width, u16 out_height,
bool ilace, bool five_taps,
@@ -1331,7 +1193,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
int accu1 = 0;
u32 l;
- _dispc_set_scale_param(plane, orig_width, orig_height,
+ dispc_ovl_set_scale_param(plane, orig_width, orig_height,
out_width, out_height, five_taps,
rotation, DISPC_COLOR_COMPONENT_RGB_Y);
l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -1370,11 +1232,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
}
}
- _dispc_set_vid_accu0(plane, 0, accu0);
- _dispc_set_vid_accu1(plane, 0, accu1);
+ dispc_ovl_set_vid_accu0(plane, 0, accu0);
+ dispc_ovl_set_vid_accu1(plane, 0, accu1);
}
-static void _dispc_set_scaling_uv(enum omap_plane plane,
+static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
u16 orig_width, u16 orig_height,
u16 out_width, u16 out_height,
bool ilace, bool five_taps,
@@ -1422,7 +1284,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
if (out_height != orig_height)
scale_y = true;
- _dispc_set_scale_param(plane, orig_width, orig_height,
+ dispc_ovl_set_scale_param(plane, orig_width, orig_height,
out_width, out_height, five_taps,
rotation, DISPC_COLOR_COMPONENT_UV);
@@ -1433,11 +1295,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
/* set V scaling */
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
- _dispc_set_vid_accu2_0(plane, 0x80, 0);
- _dispc_set_vid_accu2_1(plane, 0x80, 0);
+ dispc_ovl_set_vid_accu2_0(plane, 0x80, 0);
+ dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);
}
-static void _dispc_set_scaling(enum omap_plane plane,
+static void dispc_ovl_set_scaling(enum omap_plane plane,
u16 orig_width, u16 orig_height,
u16 out_width, u16 out_height,
bool ilace, bool five_taps,
@@ -1446,14 +1308,14 @@ static void _dispc_set_scaling(enum omap_plane plane,
{
BUG_ON(plane == OMAP_DSS_GFX);
- _dispc_set_scaling_common(plane,
+ dispc_ovl_set_scaling_common(plane,
orig_width, orig_height,
out_width, out_height,
ilace, five_taps,
fieldmode, color_mode,
rotation);
- _dispc_set_scaling_uv(plane,
+ dispc_ovl_set_scaling_uv(plane,
orig_width, orig_height,
out_width, out_height,
ilace, five_taps,
@@ -1461,7 +1323,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
rotation);
}
-static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
bool mirroring, enum omap_color_mode color_mode)
{
bool row_repeat = false;
@@ -1789,12 +1651,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
enum omap_color_mode color_mode)
{
u32 fclk = 0;
- /* FIXME venc pclk? */
- u64 tmp, pclk = dispc_pclk_rate(channel);
+ u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
if (height > out_height) {
- /* FIXME get real display PPL */
- unsigned int ppl = 800;
+ struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
+ unsigned int ppl = dssdev->panel.timings.x_res;
tmp = pclk * height * out_width;
do_div(tmp, 2 * out_height * ppl);
@@ -1846,114 +1707,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
else
vf = 1;
- /* FIXME venc pclk? */
- return dispc_pclk_rate(channel) * vf * hf;
+ return dispc_mgr_pclk_rate(channel) * vf * hf;
}
-int dispc_setup_plane(enum omap_plane plane,
- u32 paddr, u16 screen_width,
- u16 pos_x, u16 pos_y,
- u16 width, u16 height,
+static int dispc_ovl_calc_scaling(enum omap_plane plane,
+ enum omap_channel channel, u16 width, u16 height,
u16 out_width, u16 out_height,
- enum omap_color_mode color_mode,
- bool ilace,
- enum omap_dss_rotation_type rotation_type,
- u8 rotation, bool mirror,
- u8 global_alpha, u8 pre_mult_alpha,
- enum omap_channel channel, u32 puv_addr)
-{
- const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
- bool five_taps = 0;
- bool fieldmode = 0;
- int cconv = 0;
- unsigned offset0, offset1;
- s32 row_inc;
- s32 pix_inc;
- u16 frame_height = height;
- unsigned int field_offset = 0;
+ enum omap_color_mode color_mode, bool *five_taps)
+{
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+ unsigned long fclk = 0;
- DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
- "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
- plane, paddr, screen_width, pos_x, pos_y,
- width, height,
- out_width, out_height,
- ilace, color_mode,
- rotation, mirror, channel);
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ if (width != out_width || height != out_height)
+ return -EINVAL;
+ else
+ return 0;
+ }
- if (paddr == 0)
+ if (out_width < width / maxdownscale ||
+ out_width > width * 8)
return -EINVAL;
- if (ilace && height == out_height)
- fieldmode = 1;
+ if (out_height < height / maxdownscale ||
+ out_height > height * 8)
+ return -EINVAL;
- if (ilace) {
- if (fieldmode)
- height /= 2;
- pos_y /= 2;
- out_height /= 2;
+ /* Must use 5-tap filter? */
+ *five_taps = height > out_height * 2;
- DSSDBG("adjusting for ilace: height %d, pos_y %d, "
- "out_height %d\n",
- height, pos_y, out_height);
+ if (!*five_taps) {
+ fclk = calc_fclk(channel, width, height, out_width,
+ out_height);
+
+ /* Try 5-tap filter if 3-tap fclk is too high */
+ if (cpu_is_omap34xx() && height > out_height &&
+ fclk > dispc_fclk_rate())
+ *five_taps = true;
}
- if (!dss_feat_color_mode_supported(plane, color_mode))
+ if (width > (2048 >> *five_taps)) {
+ DSSERR("failed to set up scaling, fclk too low\n");
return -EINVAL;
+ }
- if (plane == OMAP_DSS_GFX) {
- if (width != out_width || height != out_height)
- return -EINVAL;
- } else {
- /* video plane */
+ if (*five_taps)
+ fclk = calc_fclk_five_taps(channel, width, height,
+ out_width, out_height, color_mode);
- unsigned long fclk = 0;
+ DSSDBG("required fclk rate = %lu Hz\n", fclk);
+ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
- if (out_width < width / maxdownscale ||
- out_width > width * 8)
- return -EINVAL;
+ if (!fclk || fclk > dispc_fclk_rate()) {
+ DSSERR("failed to set up scaling, "
+ "required fclk rate = %lu Hz, "
+ "current fclk rate = %lu Hz\n",
+ fclk, dispc_fclk_rate());
+ return -EINVAL;
+ }
- if (out_height < height / maxdownscale ||
- out_height > height * 8)
- return -EINVAL;
+ return 0;
+}
- if (color_mode == OMAP_DSS_COLOR_YUV2 ||
- color_mode == OMAP_DSS_COLOR_UYVY ||
- color_mode == OMAP_DSS_COLOR_NV12)
- cconv = 1;
+int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+ bool ilace, enum omap_channel channel, bool replication,
+ u32 fifo_low, u32 fifo_high)
+{
+ struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ bool five_taps = false;
+ bool fieldmode = 0;
+ int r, cconv = 0;
+ unsigned offset0, offset1;
+ s32 row_inc;
+ s32 pix_inc;
+ u16 frame_height = oi->height;
+ unsigned int field_offset = 0;
- /* Must use 5-tap filter? */
- five_taps = height > out_height * 2;
+ DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+ "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d "
+ "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr,
+ oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+ oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+ oi->mirror, ilace, channel, replication, fifo_low, fifo_high);
- if (!five_taps) {
- fclk = calc_fclk(channel, width, height, out_width,
- out_height);
+ if (oi->paddr == 0)
+ return -EINVAL;
- /* Try 5-tap filter if 3-tap fclk is too high */
- if (cpu_is_omap34xx() && height > out_height &&
- fclk > dispc_fclk_rate())
- five_taps = true;
- }
+ if (ilace && oi->height == oi->out_height)
+ fieldmode = 1;
- if (width > (2048 >> five_taps)) {
- DSSERR("failed to set up scaling, fclk too low\n");
- return -EINVAL;
- }
+ if (ilace) {
+ if (fieldmode)
+ oi->height /= 2;
+ oi->pos_y /= 2;
+ oi->out_height /= 2;
- if (five_taps)
- fclk = calc_fclk_five_taps(channel, width, height,
- out_width, out_height, color_mode);
+ DSSDBG("adjusting for ilace: height %d, pos_y %d, "
+ "out_height %d\n",
+ oi->height, oi->pos_y, oi->out_height);
+ }
- DSSDBG("required fclk rate = %lu Hz\n", fclk);
- DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+ if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+ return -EINVAL;
- if (!fclk || fclk > dispc_fclk_rate()) {
- DSSERR("failed to set up scaling, "
- "required fclk rate = %lu Hz, "
- "current fclk rate = %lu Hz\n",
- fclk, dispc_fclk_rate());
- return -EINVAL;
- }
- }
+ r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
+ oi->out_width, oi->out_height, oi->color_mode,
+ &five_taps);
+ if (r)
+ return r;
+
+ if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
+ oi->color_mode == OMAP_DSS_COLOR_UYVY ||
+ oi->color_mode == OMAP_DSS_COLOR_NV12)
+ cconv = 1;
if (ilace && !fieldmode) {
/*
@@ -1963,69 +1830,76 @@ int dispc_setup_plane(enum omap_plane plane,
* so the integer part must be added to the base address of the
* bottom field.
*/
- if (!height || height == out_height)
+ if (!oi->height || oi->height == oi->out_height)
field_offset = 0;
else
- field_offset = height / out_height / 2;
+ field_offset = oi->height / oi->out_height / 2;
}
/* Fields are independent but interleaved in memory. */
if (fieldmode)
field_offset = 1;
- if (rotation_type == OMAP_DSS_ROT_DMA)
- calc_dma_rotation_offset(rotation, mirror,
- screen_width, width, frame_height, color_mode,
- fieldmode, field_offset,
+ if (oi->rotation_type == OMAP_DSS_ROT_DMA)
+ calc_dma_rotation_offset(oi->rotation, oi->mirror,
+ oi->screen_width, oi->width, frame_height,
+ oi->color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc);
else
- calc_vrfb_rotation_offset(rotation, mirror,
- screen_width, width, frame_height, color_mode,
- fieldmode, field_offset,
+ calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
+ oi->screen_width, oi->width, frame_height,
+ oi->color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc);
DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
offset0, offset1, row_inc, pix_inc);
- _dispc_set_color_mode(plane, color_mode);
+ dispc_ovl_set_color_mode(plane, oi->color_mode);
- _dispc_set_plane_ba0(plane, paddr + offset0);
- _dispc_set_plane_ba1(plane, paddr + offset1);
+ dispc_ovl_set_ba0(plane, oi->paddr + offset0);
+ dispc_ovl_set_ba1(plane, oi->paddr + offset1);
- if (OMAP_DSS_COLOR_NV12 == color_mode) {
- _dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
- _dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
+ if (OMAP_DSS_COLOR_NV12 == oi->color_mode) {
+ dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0);
+ dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);
}
- _dispc_set_row_inc(plane, row_inc);
- _dispc_set_pix_inc(plane, pix_inc);
+ dispc_ovl_set_row_inc(plane, row_inc);
+ dispc_ovl_set_pix_inc(plane, pix_inc);
- DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
- out_width, out_height);
+ DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
+ oi->height, oi->out_width, oi->out_height);
- _dispc_set_plane_pos(plane, pos_x, pos_y);
+ dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
- _dispc_set_pic_size(plane, width, height);
+ dispc_ovl_set_pic_size(plane, oi->width, oi->height);
- if (plane != OMAP_DSS_GFX) {
- _dispc_set_scaling(plane, width, height,
- out_width, out_height,
+ if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
+ dispc_ovl_set_scaling(plane, oi->width, oi->height,
+ oi->out_width, oi->out_height,
ilace, five_taps, fieldmode,
- color_mode, rotation);
- _dispc_set_vid_size(plane, out_width, out_height);
- _dispc_set_vid_color_conv(plane, cconv);
+ oi->color_mode, oi->rotation);
+ dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height);
+ dispc_ovl_set_vid_color_conv(plane, cconv);
}
- _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+ dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
+ oi->color_mode);
+
+ dispc_ovl_set_zorder(plane, oi->zorder);
+ dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
+ dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
- _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
- _dispc_setup_global_alpha(plane, global_alpha);
+ dispc_ovl_set_channel_out(plane, channel);
+
+ dispc_ovl_enable_replication(plane, replication);
+ dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
return 0;
}
-int dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_ovl_enable(enum omap_plane plane, bool enable)
{
DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2048,7 +1922,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable)
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
}
-static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
{
struct completion frame_done_completion;
bool is_on;
@@ -2095,14 +1969,19 @@ static void _enable_digit_out(bool enable)
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
}
-static void dispc_enable_digit_out(bool enable)
+static void dispc_mgr_enable_digit_out(bool enable)
{
struct completion frame_done_completion;
- int r;
+ enum dss_hdmi_venc_clk_source_select src;
+ int r, i;
+ u32 irq_mask;
+ int num_irqs;
if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
return;
+ src = dss_get_hdmi_venc_clk_source();
+
if (enable) {
unsigned long flags;
/* When we enable digit output, we'll get an extra digit
@@ -2119,43 +1998,47 @@ static void dispc_enable_digit_out(bool enable)
* wait for the extra sync losts */
init_completion(&frame_done_completion);
+ if (src == DSS_HDMI_M_PCLK && enable == false) {
+ irq_mask = DISPC_IRQ_FRAMEDONETV;
+ num_irqs = 1;
+ } else {
+ irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+ /* XXX I understand from TRM that we should only wait for the
+ * current field to complete. But it seems we have to wait for
+ * both fields */
+ num_irqs = 2;
+ }
+
r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
- DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+ irq_mask);
if (r)
- DSSERR("failed to register EVSYNC isr\n");
+ DSSERR("failed to register %x isr\n", irq_mask);
_enable_digit_out(enable);
- /* XXX I understand from TRM that we should only wait for the
- * current field to complete. But it seems we have to wait
- * for both fields */
- if (!wait_for_completion_timeout(&frame_done_completion,
- msecs_to_jiffies(100)))
- DSSERR("timeout waiting for EVSYNC\n");
-
- if (!wait_for_completion_timeout(&frame_done_completion,
- msecs_to_jiffies(100)))
- DSSERR("timeout waiting for EVSYNC\n");
+ for (i = 0; i < num_irqs; ++i) {
+ if (!wait_for_completion_timeout(&frame_done_completion,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for digit out to %s\n",
+ enable ? "start" : "stop");
+ }
- r = omap_dispc_unregister_isr(dispc_disable_isr,
- &frame_done_completion,
- DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+ r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
+ irq_mask);
if (r)
- DSSERR("failed to unregister EVSYNC isr\n");
+ DSSERR("failed to unregister %x isr\n", irq_mask);
if (enable) {
unsigned long flags;
spin_lock_irqsave(&dispc.irq_lock, flags);
- dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
- if (dss_has_feature(FEAT_MGR_LCD2))
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+ dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc.irq_lock, flags);
}
}
-bool dispc_is_channel_enabled(enum omap_channel channel)
+bool dispc_mgr_is_enabled(enum omap_channel channel)
{
if (channel == OMAP_DSS_CHANNEL_LCD)
return !!REG_GET(DISPC_CONTROL, 0, 0);
@@ -2167,13 +2050,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel)
BUG();
}
-void dispc_enable_channel(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
{
- if (channel == OMAP_DSS_CHANNEL_LCD ||
- channel == OMAP_DSS_CHANNEL_LCD2)
- dispc_enable_lcd_out(channel, enable);
+ if (dispc_mgr_is_lcd(channel))
+ dispc_mgr_enable_lcd_out(channel, enable);
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
- dispc_enable_digit_out(enable);
+ dispc_mgr_enable_digit_out(enable);
else
BUG();
}
@@ -2202,7 +2084,7 @@ void dispc_pck_free_enable(bool enable)
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
}
-void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
+void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
{
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
@@ -2211,7 +2093,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
}
-void dispc_set_lcd_display_type(enum omap_channel channel,
+void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
enum omap_lcd_display_type type)
{
int mode;
@@ -2242,12 +2124,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
}
-void dispc_set_default_color(enum omap_channel channel, u32 color)
+void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
{
dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
}
-u32 dispc_get_default_color(enum omap_channel channel)
+u32 dispc_mgr_get_default_color(enum omap_channel channel)
{
u32 l;
@@ -2260,7 +2142,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
return l;
}
-void dispc_set_trans_key(enum omap_channel ch,
+void dispc_mgr_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key)
{
@@ -2274,7 +2156,7 @@ void dispc_set_trans_key(enum omap_channel ch,
dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
}
-void dispc_get_trans_key(enum omap_channel ch,
+void dispc_mgr_get_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type *type,
u32 *trans_key)
{
@@ -2293,7 +2175,7 @@ void dispc_get_trans_key(enum omap_channel ch,
*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
}
-void dispc_enable_trans_key(enum omap_channel ch, bool enable)
+void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
{
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
@@ -2302,39 +2184,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
else /* OMAP_DSS_CHANNEL_LCD2 */
REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
}
-void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
+
+void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
{
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
return;
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
- else /* OMAP_DSS_CHANNEL_LCD2 */
- REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
}
-bool dispc_alpha_blending_enabled(enum omap_channel ch)
+
+bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)
{
bool enabled;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
return false;
if (ch == OMAP_DSS_CHANNEL_LCD)
enabled = REG_GET(DISPC_CONFIG, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
enabled = REG_GET(DISPC_CONFIG, 19, 19);
- else if (ch == OMAP_DSS_CHANNEL_LCD2)
- enabled = REG_GET(DISPC_CONFIG2, 18, 18);
else
BUG();
return enabled;
}
-
-bool dispc_trans_key_enabled(enum omap_channel ch)
+bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
{
bool enabled;
@@ -2351,7 +2230,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
}
-void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
{
int code;
@@ -2379,46 +2258,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
}
-void dispc_set_parallel_interface_mode(enum omap_channel channel,
- enum omap_parallel_interface_mode mode)
+void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
{
u32 l;
- int stallmode;
- int gpout0 = 1;
- int gpout1;
+ int gpout0, gpout1;
switch (mode) {
- case OMAP_DSS_PARALLELMODE_BYPASS:
- stallmode = 0;
- gpout1 = 1;
+ case DSS_IO_PAD_MODE_RESET:
+ gpout0 = 0;
+ gpout1 = 0;
break;
-
- case OMAP_DSS_PARALLELMODE_RFBI:
- stallmode = 1;
+ case DSS_IO_PAD_MODE_RFBI:
+ gpout0 = 1;
gpout1 = 0;
break;
-
- case OMAP_DSS_PARALLELMODE_DSI:
- stallmode = 1;
+ case DSS_IO_PAD_MODE_BYPASS:
+ gpout0 = 1;
gpout1 = 1;
break;
-
default:
BUG();
return;
}
- if (channel == OMAP_DSS_CHANNEL_LCD2) {
- l = dispc_read_reg(DISPC_CONTROL2);
- l = FLD_MOD(l, stallmode, 11, 11);
- dispc_write_reg(DISPC_CONTROL2, l);
- } else {
- l = dispc_read_reg(DISPC_CONTROL);
- l = FLD_MOD(l, stallmode, 11, 11);
- l = FLD_MOD(l, gpout0, 15, 15);
- l = FLD_MOD(l, gpout1, 16, 16);
- dispc_write_reg(DISPC_CONTROL, l);
- }
+ l = dispc_read_reg(DISPC_CONTROL);
+ l = FLD_MOD(l, gpout0, 15, 15);
+ l = FLD_MOD(l, gpout1, 16, 16);
+ dispc_write_reg(DISPC_CONTROL, l);
+}
+
+void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+{
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
+ REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11);
+ else
+ REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
}
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2452,7 +2326,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
timings->vfp, timings->vbp);
}
-static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
+static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
int hfp, int hbp, int vsw, int vfp, int vbp)
{
u32 timing_h, timing_v;
@@ -2476,7 +2350,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
}
/* change name to mode? */
-void dispc_set_lcd_timings(enum omap_channel channel,
+void dispc_mgr_set_lcd_timings(enum omap_channel channel,
struct omap_video_timings *timings)
{
unsigned xtot, ytot;
@@ -2487,11 +2361,11 @@ void dispc_set_lcd_timings(enum omap_channel channel,
timings->vfp, timings->vbp))
BUG();
- _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
+ _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp,
timings->hbp, timings->vsw, timings->vfp,
timings->vbp);
- dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
+ dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res);
xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
@@ -2509,17 +2383,17 @@ void dispc_set_lcd_timings(enum omap_channel channel,
DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
}
-static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
+static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
u16 pck_div)
{
BUG_ON(lck_div < 1);
- BUG_ON(pck_div < 2);
+ BUG_ON(pck_div < 1);
dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
}
-static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
+static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
int *pck_div)
{
u32 l;
@@ -2552,7 +2426,7 @@ unsigned long dispc_fclk_rate(void)
return r;
}
-unsigned long dispc_lclk_rate(enum omap_channel channel)
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
{
struct platform_device *dsidev;
int lcd;
@@ -2582,19 +2456,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
return r / lcd;
}
-unsigned long dispc_pclk_rate(enum omap_channel channel)
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
{
- int pcd;
unsigned long r;
- u32 l;
- l = dispc_read_reg(DISPC_DIVISORo(channel));
+ if (dispc_mgr_is_lcd(channel)) {
+ int pcd;
+ u32 l;
- pcd = FLD_GET(l, 7, 0);
+ l = dispc_read_reg(DISPC_DIVISORo(channel));
- r = dispc_lclk_rate(channel);
+ pcd = FLD_GET(l, 7, 0);
- return r / pcd;
+ r = dispc_mgr_lclk_rate(channel);
+
+ return r / pcd;
+ } else {
+ struct omap_dss_device *dssdev =
+ dispc_mgr_get_device(channel);
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_VENC:
+ return venc_get_pixel_clock();
+ case OMAP_DISPLAY_TYPE_HDMI:
+ return hdmi_get_pixel_clock();
+ default:
+ BUG();
+ }
+ }
}
void dispc_dump_clocks(struct seq_file *s)
@@ -2631,12 +2520,12 @@ void dispc_dump_clocks(struct seq_file *s)
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);
+ dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
- dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
+ dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
- dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
+ dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
if (dss_has_feature(FEAT_MGR_LCD2)) {
seq_printf(s, "- LCD2 -\n");
@@ -2646,12 +2535,12 @@ void dispc_dump_clocks(struct seq_file *s)
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);
+ dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
- dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
+ dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
- dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
+ dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
}
dispc_runtime_put();
@@ -2692,6 +2581,10 @@ void dispc_dump_irqs(struct seq_file *s)
PIS(VID1_END_WIN);
PIS(VID2_FIFO_UNDERFLOW);
PIS(VID2_END_WIN);
+ if (dss_feat_get_num_ovls() > 3) {
+ PIS(VID3_FIFO_UNDERFLOW);
+ PIS(VID3_END_WIN);
+ }
PIS(SYNC_LOST);
PIS(SYNC_LOST_DIGIT);
PIS(WAKEUP);
@@ -2707,11 +2600,26 @@ void dispc_dump_irqs(struct seq_file *s)
void dispc_dump_regs(struct seq_file *s)
{
+ int i, j;
+ const char *mgr_names[] = {
+ [OMAP_DSS_CHANNEL_LCD] = "LCD",
+ [OMAP_DSS_CHANNEL_DIGIT] = "TV",
+ [OMAP_DSS_CHANNEL_LCD2] = "LCD2",
+ };
+ const char *ovl_names[] = {
+ [OMAP_DSS_GFX] = "GFX",
+ [OMAP_DSS_VIDEO1] = "VID1",
+ [OMAP_DSS_VIDEO2] = "VID2",
+ [OMAP_DSS_VIDEO3] = "VID3",
+ };
+ const char **p_names;
+
#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
if (dispc_runtime_get())
return;
+ /* DISPC common registers */
DUMPREG(DISPC_REVISION);
DUMPREG(DISPC_SYSCONFIG);
DUMPREG(DISPC_SYSSTATUS);
@@ -2720,247 +2628,139 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_CONTROL);
DUMPREG(DISPC_CONFIG);
DUMPREG(DISPC_CAPABLE);
- DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
- DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
DUMPREG(DISPC_LINE_STATUS);
DUMPREG(DISPC_LINE_NUMBER);
- DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
DUMPREG(DISPC_GLOBAL_ALPHA);
- DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
- DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
DUMPREG(DISPC_CONTROL2);
DUMPREG(DISPC_CONFIG2);
- DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
- }
-
- DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
- DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
-
- DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
-
- if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
}
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
+
+#undef DUMPREG
+
+#define DISPC_REG(i, name) name(i)
+#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
+ 48 - strlen(#r) - strlen(p_names[i]), " ", \
+ dispc_read_reg(DISPC_REG(i, r)))
+
+ p_names = mgr_names;
+
+ /* DISPC channel specific registers */
+ for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+ DUMPREG(i, DISPC_DEFAULT_COLOR);
+ DUMPREG(i, DISPC_TRANS_COLOR);
+ DUMPREG(i, DISPC_SIZE_MGR);
+
+ if (i == OMAP_DSS_CHANNEL_DIGIT)
+ continue;
+
+ DUMPREG(i, DISPC_DEFAULT_COLOR);
+ DUMPREG(i, DISPC_TRANS_COLOR);
+ DUMPREG(i, DISPC_TIMING_H);
+ DUMPREG(i, DISPC_TIMING_V);
+ DUMPREG(i, DISPC_POL_FREQ);
+ DUMPREG(i, DISPC_DIVISORo);
+ DUMPREG(i, DISPC_SIZE_MGR);
+
+ DUMPREG(i, DISPC_DATA_CYCLE1);
+ DUMPREG(i, DISPC_DATA_CYCLE2);
+ DUMPREG(i, DISPC_DATA_CYCLE3);
if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+ DUMPREG(i, DISPC_CPR_COEF_R);
+ DUMPREG(i, DISPC_CPR_COEF_G);
+ DUMPREG(i, DISPC_CPR_COEF_B);
+ }
+ }
+
+ p_names = ovl_names;
+
+ for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+ DUMPREG(i, DISPC_OVL_BA0);
+ DUMPREG(i, DISPC_OVL_BA1);
+ DUMPREG(i, DISPC_OVL_POSITION);
+ DUMPREG(i, DISPC_OVL_SIZE);
+ DUMPREG(i, DISPC_OVL_ATTRIBUTES);
+ DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
+ DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
+ DUMPREG(i, DISPC_OVL_ROW_INC);
+ DUMPREG(i, DISPC_OVL_PIXEL_INC);
+ if (dss_has_feature(FEAT_PRELOAD))
+ DUMPREG(i, DISPC_OVL_PRELOAD);
+
+ if (i == OMAP_DSS_GFX) {
+ DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
+ DUMPREG(i, DISPC_OVL_TABLE_BA);
+ continue;
+ }
+
+ DUMPREG(i, DISPC_OVL_FIR);
+ DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
+ DUMPREG(i, DISPC_OVL_ACCU0);
+ DUMPREG(i, DISPC_OVL_ACCU1);
+ if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+ DUMPREG(i, DISPC_OVL_BA0_UV);
+ DUMPREG(i, DISPC_OVL_BA1_UV);
+ DUMPREG(i, DISPC_OVL_FIR2);
+ DUMPREG(i, DISPC_OVL_ACCU2_0);
+ DUMPREG(i, DISPC_OVL_ACCU2_1);
}
+ if (dss_has_feature(FEAT_ATTR2))
+ DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
+ if (dss_has_feature(FEAT_PRELOAD))
+ DUMPREG(i, DISPC_OVL_PRELOAD);
}
- if (dss_has_feature(FEAT_PRELOAD))
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
-
- DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1));
-
- DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2));
-
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7));
-
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7));
-
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7));
- }
- if (dss_has_feature(FEAT_ATTR2))
- DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
-
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2));
- DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2));
-
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7));
-
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7));
-
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7));
- }
- if (dss_has_feature(FEAT_ATTR2))
- DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
- if (dss_has_feature(FEAT_PRELOAD)) {
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+#undef DISPC_REG
+#undef DUMPREG
+
+#define DISPC_REG(plane, name, i) name(plane, i)
+#define DUMPREG(plane, name, i) \
+ seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
+ 46 - strlen(#name) - strlen(p_names[plane]), " ", \
+ dispc_read_reg(DISPC_REG(plane, name, i)))
+
+ /* Video pipeline coefficient registers */
+
+ /* start from OMAP_DSS_VIDEO1 */
+ for (i = 1; i < dss_feat_get_num_ovls(); i++) {
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
+
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
+
+ for (j = 0; j < 5; j++)
+ DUMPREG(i, DISPC_OVL_CONV_COEF, j);
+
+ if (dss_has_feature(FEAT_FIR_COEF_V)) {
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
+ }
+
+ if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
+
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
+
+ for (j = 0; j < 8; j++)
+ DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
+ }
}
dispc_runtime_put();
+
+#undef DISPC_REG
#undef DUMPREG
}
-static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
- bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
+static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff,
+ bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi,
+ u8 acb)
{
u32 l = 0;
@@ -2979,10 +2779,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
dispc_write_reg(DISPC_POL_FREQ(channel), l);
}
-void dispc_set_pol_freq(enum omap_channel channel,
+void dispc_mgr_set_pol_freq(enum omap_channel channel,
enum omap_panel_config config, u8 acbi, u8 acb)
{
- _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
+ _dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
(config & OMAP_DSS_LCD_RF) != 0,
(config & OMAP_DSS_LCD_IEO) != 0,
(config & OMAP_DSS_LCD_IPC) != 0,
@@ -2995,11 +2795,17 @@ void dispc_set_pol_freq(enum omap_channel channel,
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
struct dispc_clock_info *cinfo)
{
- u16 pcd_min = is_tft ? 2 : 3;
+ u16 pcd_min, pcd_max;
unsigned long best_pck;
u16 best_ld, cur_ld;
u16 best_pd, cur_pd;
+ pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+ pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+
+ if (!is_tft)
+ pcd_min = 3;
+
best_pck = 0;
best_ld = 0;
best_pd = 0;
@@ -3007,7 +2813,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
unsigned long lck = fck / cur_ld;
- for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
+ for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
unsigned long pck = lck / cur_pd;
long old_delta = abs(best_pck - req_pck);
long new_delta = abs(pck - req_pck);
@@ -3042,7 +2848,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
{
if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
return -EINVAL;
- if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
+ if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
return -EINVAL;
cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
@@ -3051,18 +2857,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
return 0;
}
-int dispc_set_clock_div(enum omap_channel channel,
+int dispc_mgr_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo)
{
DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
- dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
+ dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
return 0;
}
-int dispc_get_clock_div(enum omap_channel channel,
+int dispc_mgr_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo)
{
unsigned long fck;
@@ -3207,6 +3013,8 @@ static void print_irq_status(u32 status)
PIS(OCP_ERR);
PIS(VID1_FIFO_UNDERFLOW);
PIS(VID2_FIFO_UNDERFLOW);
+ if (dss_feat_get_num_ovls() > 3)
+ PIS(VID3_FIFO_UNDERFLOW);
PIS(SYNC_LOST);
PIS(SYNC_LOST_DIGIT);
if (dss_has_feature(FEAT_MGR_LCD2))
@@ -3300,178 +3108,72 @@ static void dispc_error_worker(struct work_struct *work)
int i;
u32 errors;
unsigned long flags;
+ static const unsigned fifo_underflow_bits[] = {
+ DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+ };
+
+ static const unsigned sync_lost_bits[] = {
+ DISPC_IRQ_SYNC_LOST,
+ DISPC_IRQ_SYNC_LOST_DIGIT,
+ DISPC_IRQ_SYNC_LOST2,
+ };
spin_lock_irqsave(&dispc.irq_lock, flags);
errors = dispc.error_irqs;
dispc.error_irqs = 0;
spin_unlock_irqrestore(&dispc.irq_lock, flags);
- if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
- DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
- if (ovl->id == 0) {
- dispc_enable_plane(ovl->id, 0);
- dispc_go(ovl->manager->id);
- mdelay(50);
- break;
- }
- }
- }
-
- if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
- DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
- if (ovl->id == 1) {
- dispc_enable_plane(ovl->id, 0);
- dispc_go(ovl->manager->id);
- mdelay(50);
- break;
- }
- }
- }
-
- if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
- DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
+ dispc_runtime_get();
- if (ovl->id == 2) {
- dispc_enable_plane(ovl->id, 0);
- dispc_go(ovl->manager->id);
- mdelay(50);
- break;
- }
- }
- }
-
- if (errors & DISPC_IRQ_SYNC_LOST) {
- struct omap_overlay_manager *manager = NULL;
- bool enable = false;
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ unsigned bit;
- DSSERR("SYNC_LOST, disabling LCD\n");
+ ovl = omap_dss_get_overlay(i);
+ bit = fifo_underflow_bits[i];
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
- struct omap_overlay_manager *mgr;
- mgr = omap_dss_get_overlay_manager(i);
-
- if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
- manager = mgr;
- enable = mgr->device->state ==
- OMAP_DSS_DISPLAY_ACTIVE;
- mgr->device->driver->disable(mgr->device);
- break;
- }
- }
-
- if (manager) {
- struct omap_dss_device *dssdev = manager->device;
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
- if (ovl->id != 0 && ovl->manager == manager)
- dispc_enable_plane(ovl->id, 0);
- }
-
- dispc_go(manager->id);
+ if (bit & errors) {
+ DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+ ovl->name);
+ dispc_ovl_enable(ovl->id, false);
+ dispc_mgr_go(ovl->manager->id);
mdelay(50);
- if (enable)
- dssdev->driver->enable(dssdev);
}
}
- if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
- struct omap_overlay_manager *manager = NULL;
- bool enable = false;
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ unsigned bit;
- DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
+ mgr = omap_dss_get_overlay_manager(i);
+ bit = sync_lost_bits[i];
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
- struct omap_overlay_manager *mgr;
- mgr = omap_dss_get_overlay_manager(i);
+ if (bit & errors) {
+ struct omap_dss_device *dssdev = mgr->device;
+ bool enable;
- if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
- manager = mgr;
- enable = mgr->device->state ==
- OMAP_DSS_DISPLAY_ACTIVE;
- mgr->device->driver->disable(mgr->device);
- break;
- }
- }
+ DSSERR("SYNC_LOST on channel %s, restarting the output "
+ "with video overlays disabled\n",
+ mgr->name);
- if (manager) {
- struct omap_dss_device *dssdev = manager->device;
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
- if (ovl->id != 0 && ovl->manager == manager)
- dispc_enable_plane(ovl->id, 0);
- }
+ enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
+ dssdev->driver->disable(dssdev);
- dispc_go(manager->id);
- mdelay(50);
- if (enable)
- dssdev->driver->enable(dssdev);
- }
- }
-
- if (errors & DISPC_IRQ_SYNC_LOST2) {
- struct omap_overlay_manager *manager = NULL;
- bool enable = false;
-
- DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
-
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
- struct omap_overlay_manager *mgr;
- mgr = omap_dss_get_overlay_manager(i);
-
- if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
- manager = mgr;
- enable = mgr->device->state ==
- OMAP_DSS_DISPLAY_ACTIVE;
- mgr->device->driver->disable(mgr->device);
- break;
- }
- }
-
- if (manager) {
- struct omap_dss_device *dssdev = manager->device;
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(i);
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
- if (ovl->id != 0 && ovl->manager == manager)
- dispc_enable_plane(ovl->id, 0);
+ if (ovl->id != OMAP_DSS_GFX &&
+ ovl->manager == mgr)
+ dispc_ovl_enable(ovl->id, false);
}
- dispc_go(manager->id);
+ dispc_mgr_go(mgr->id);
mdelay(50);
+
if (enable)
dssdev->driver->enable(dssdev);
}
@@ -3482,9 +3184,7 @@ static void dispc_error_worker(struct work_struct *work)
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
struct omap_overlay_manager *mgr;
mgr = omap_dss_get_overlay_manager(i);
-
- if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
- mgr->device->driver->disable(mgr->device);
+ mgr->device->driver->disable(mgr->device);
}
}
@@ -3492,6 +3192,8 @@ static void dispc_error_worker(struct work_struct *work)
dispc.irq_error_mask |= errors;
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+ dispc_runtime_put();
}
int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
@@ -3586,6 +3288,8 @@ static void _omap_dispc_initialize_irq(void)
dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
if (dss_has_feature(FEAT_MGR_LCD2))
dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+ if (dss_feat_get_num_ovls() > 3)
+ dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
* so clear it */
@@ -3635,6 +3339,8 @@ static void _omap_dispc_initial_config(void)
dispc_read_plane_fifo_sizes();
dispc_configure_burst_sizes();
+
+ dispc_ovl_enable_zorder_planes();
}
/* DISPC HW IP initialisation */
@@ -3734,7 +3440,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
dispc_save_context();
- clk_disable(dispc.dss_clk);
dss_runtime_put();
return 0;
@@ -3748,7 +3453,6 @@ static int dispc_runtime_resume(struct device *dev)
if (r < 0)
return r;
- clk_enable(dispc.dss_clk);
dispc_restore_context();
return 0;
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 6c9ee0a0efb3..c06efc38983e 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
return 0x00BC;
case OMAP_DSS_VIDEO2:
return 0x014C;
+ case OMAP_DSS_VIDEO3:
+ return 0x0300;
default:
BUG();
}
@@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0000;
+ case OMAP_DSS_VIDEO3:
+ return 0x0008;
default:
BUG();
}
@@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0004;
+ case OMAP_DSS_VIDEO3:
+ return 0x000C;
default:
BUG();
}
@@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
return 0x0544;
case OMAP_DSS_VIDEO2:
return 0x04BC;
+ case OMAP_DSS_VIDEO3:
+ return 0x0310;
default:
BUG();
}
@@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
return 0x0548;
case OMAP_DSS_VIDEO2:
return 0x04C0;
+ case OMAP_DSS_VIDEO3:
+ return 0x0314;
default:
BUG();
}
@@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0008;
+ case OMAP_DSS_VIDEO3:
+ return 0x009C;
default:
BUG();
}
@@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x000C;
+ case OMAP_DSS_VIDEO3:
+ return 0x00A8;
default:
BUG();
}
@@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0010;
+ case OMAP_DSS_VIDEO3:
+ return 0x0070;
default:
BUG();
}
@@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
return 0x0568;
case OMAP_DSS_VIDEO2:
return 0x04DC;
+ case OMAP_DSS_VIDEO3:
+ return 0x032C;
default:
BUG();
}
@@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0014;
+ case OMAP_DSS_VIDEO3:
+ return 0x008C;
default:
BUG();
}
@@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0018;
+ case OMAP_DSS_VIDEO3:
+ return 0x0088;
default:
BUG();
}
@@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x001C;
+ case OMAP_DSS_VIDEO3:
+ return 0x00A4;
default:
BUG();
}
@@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0020;
+ case OMAP_DSS_VIDEO3:
+ return 0x0098;
default:
BUG();
}
@@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
return 0x0034;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
+ case OMAP_DSS_VIDEO3:
BUG();
default:
BUG();
@@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
return 0x0038;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
+ case OMAP_DSS_VIDEO3:
BUG();
default:
BUG();
@@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0024;
+ case OMAP_DSS_VIDEO3:
+ return 0x0090;
default:
BUG();
}
@@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
return 0x0580;
case OMAP_DSS_VIDEO2:
return 0x055C;
+ case OMAP_DSS_VIDEO3:
+ return 0x0424;
default:
BUG();
}
@@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0028;
+ case OMAP_DSS_VIDEO3:
+ return 0x0094;
default:
BUG();
}
@@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x002C;
+ case OMAP_DSS_VIDEO3:
+ return 0x0000;
default:
BUG();
}
@@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
return 0x0584;
case OMAP_DSS_VIDEO2:
return 0x0560;
+ case OMAP_DSS_VIDEO3:
+ return 0x0428;
default:
BUG();
}
@@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0030;
+ case OMAP_DSS_VIDEO3:
+ return 0x0004;
default:
BUG();
}
@@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
return 0x0588;
case OMAP_DSS_VIDEO2:
return 0x0564;
+ case OMAP_DSS_VIDEO3:
+ return 0x042C;
default:
BUG();
}
@@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0034 + i * 0x8;
+ case OMAP_DSS_VIDEO3:
+ return 0x0010 + i * 0x8;
default:
BUG();
}
@@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
return 0x058C + i * 0x8;
case OMAP_DSS_VIDEO2:
return 0x0568 + i * 0x8;
+ case OMAP_DSS_VIDEO3:
+ return 0x0430 + i * 0x8;
default:
BUG();
}
@@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0038 + i * 0x8;
+ case OMAP_DSS_VIDEO3:
+ return 0x0014 + i * 0x8;
default:
BUG();
}
@@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
return 0x0590 + i * 8;
case OMAP_DSS_VIDEO2:
return 0x056C + i * 0x8;
+ case OMAP_DSS_VIDEO3:
+ return 0x0434 + i * 0x8;
default:
BUG();
}
@@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
+ case OMAP_DSS_VIDEO3:
return 0x0074 + i * 0x4;
default:
BUG();
@@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
return 0x0124 + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x00B4 + i * 0x4;
+ case OMAP_DSS_VIDEO3:
+ return 0x0050 + i * 0x4;
default:
BUG();
}
@@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
return 0x05CC + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x05A8 + i * 0x4;
+ case OMAP_DSS_VIDEO3:
+ return 0x0470 + i * 0x4;
default:
BUG();
}
@@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
return 0x0174;
case OMAP_DSS_VIDEO2:
return 0x00E8;
+ case OMAP_DSS_VIDEO3:
+ return 0x00A0;
default:
BUG();
}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 94495e45ec5a..be331dc5a61b 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev,
const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
- int r, enabled;
+ int r;
+ bool enabled;
- r = kstrtoint(buf, 0, &enabled);
+ r = strtobool(buf, &enabled);
if (r)
return r;
- enabled = !!enabled;
-
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
if (enabled) {
r = dssdev->driver->enable(dssdev);
@@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
- int te, r;
+ int r;
+ bool te;
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
return -ENOENT;
- r = kstrtoint(buf, 0, &te);
+ r = strtobool(buf, &te);
if (r)
return r;
- te = !!te;
-
r = dssdev->driver->enable_te(dssdev, te);
if (r)
return r;
@@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
- int mirror, r;
+ int r;
+ bool mirror;
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
return -ENOENT;
- r = kstrtoint(buf, 0, &mirror);
+ r = strtobool(buf, &mirror);
if (r)
return r;
- mirror = !!mirror;
-
r = dssdev->driver->set_mirror(dssdev, mirror);
if (r)
return r;
@@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
return 16;
case OMAP_DISPLAY_TYPE_DBI:
- case OMAP_DISPLAY_TYPE_DSI:
if (dssdev->ctrl.pixel_size == 24)
return 24;
else
return 16;
+ case OMAP_DISPLAY_TYPE_DSI:
+ if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
+ return 24;
+ else
+ return 16;
case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_SDI:
case OMAP_DISPLAY_TYPE_HDMI:
@@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
bpp = 24;
break;
case OMAP_DISPLAY_TYPE_DBI:
- case OMAP_DISPLAY_TYPE_DSI:
bpp = dssdev->ctrl.pixel_size;
break;
+ case OMAP_DISPLAY_TYPE_DSI:
+ bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ break;
default:
BUG();
}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index f053b180ecd7..483888a85cfd 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
- r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
- if (r)
+ r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+ if (r) {
+ dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
return r;
+ }
*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
*lck_div = dispc_cinfo.lck_div;
@@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
if (r)
return r;
- r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+ r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
return r;
@@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
- dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
+ dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
@@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
t->pixel_clock = pck;
}
- dispc_set_lcd_timings(dssdev->manager->id, t);
+ dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
return 0;
}
@@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
- dispc_set_parallel_interface_mode(dssdev->manager->id,
- OMAP_DSS_PARALLELMODE_BYPASS);
- dispc_set_lcd_display_type(dssdev->manager->id, is_tft ?
+ dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
+ dispc_mgr_enable_stallmode(dssdev->manager->id, false);
+
+ dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ?
OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
- dispc_set_tft_data_lines(dssdev->manager->id,
+ dispc_mgr_set_tft_data_lines(dssdev->manager->id,
dssdev->phy.dpi.data_lines);
}
@@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
{
int r;
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ return -ENODEV;
+ }
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
}
dpi_set_mode(dssdev);
- dispc_go(dssdev->manager->id);
+ dispc_mgr_go(dssdev->manager->id);
dispc_runtime_put();
dss_runtime_put();
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 7adbbeb84334..43c04a9889c4 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -39,6 +39,7 @@
#include <linux/pm_runtime.h>
#include <video/omapdss.h>
+#include <video/mipi_display.h>
#include <plat/clock.h>
#include "dss.h"
@@ -131,7 +132,7 @@ struct dsi_reg { u16 idx; };
#define DSI_IRQ_TA_TIMEOUT (1 << 20)
#define DSI_IRQ_ERROR_MASK \
(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
- DSI_IRQ_TA_TIMEOUT)
+ DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
#define DSI_IRQ_CHANNEL_MASK 0xf
/* Virtual channel interrupts */
@@ -198,18 +199,6 @@ struct dsi_reg { u16 idx; };
DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
-#define DSI_DT_DCS_SHORT_WRITE_0 0x05
-#define DSI_DT_DCS_SHORT_WRITE_1 0x15
-#define DSI_DT_DCS_READ 0x06
-#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
-#define DSI_DT_NULL_PACKET 0x09
-#define DSI_DT_DCS_LONG_WRITE 0x39
-
-#define DSI_DT_RX_ACK_WITH_ERR 0x02
-#define DSI_DT_RX_DCS_LONG_READ 0x1c
-#define DSI_DT_RX_SHORT_READ_1 0x21
-#define DSI_DT_RX_SHORT_READ_2 0x22
-
typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
#define DSI_MAX_NR_ISRS 2
@@ -228,9 +217,9 @@ enum fifo_size {
DSI_FIFO_SIZE_128 = 4,
};
-enum dsi_vc_mode {
- DSI_VC_MODE_L4 = 0,
- DSI_VC_MODE_VP,
+enum dsi_vc_source {
+ DSI_VC_SOURCE_L4 = 0,
+ DSI_VC_SOURCE_VP,
};
enum dsi_lane {
@@ -274,7 +263,8 @@ struct dsi_data {
struct clk *dss_clk;
struct clk *sys_clk;
- void (*dsi_mux_pads)(bool enable);
+ int (*enable_pads)(int dsi_id, unsigned lane_mask);
+ void (*disable_pads)(int dsi_id, unsigned lane_mask);
struct dsi_clock_info current_cinfo;
@@ -282,7 +272,7 @@ struct dsi_data {
struct regulator *vdds_dsi_reg;
struct {
- enum dsi_vc_mode mode;
+ enum dsi_vc_source source;
struct omap_dss_device *dssdev;
enum fifo_size fifo_size;
int vc_id;
@@ -368,14 +358,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
return dsi_pdev_map[module];
}
-static int dsi_get_dsidev_id(struct platform_device *dsidev)
+static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
{
- /* TEMP: Pass 0 as the dsi module index till the time the dsi platform
- * device names aren't changed to the form "omapdss_dsi.0",
- * "omapdss_dsi.1" and so on */
- BUG_ON(dsidev->id != -1);
-
- return 0;
+ return dsidev->id;
}
static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -437,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev,
return value;
}
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+ switch (fmt) {
+ case OMAP_DSS_DSI_FMT_RGB888:
+ case OMAP_DSS_DSI_FMT_RGB666:
+ return 24;
+ case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+ return 18;
+ case OMAP_DSS_DSI_FMT_RGB565:
+ return 16;
+ default:
+ BUG();
+ }
+}
+
#ifdef DEBUG
static void dsi_perf_mark_setup(struct platform_device *dsidev)
{
@@ -453,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
static void dsi_perf_show(struct platform_device *dsidev, const char *name)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ struct omap_dss_device *dssdev = dsi->update_region.device;
ktime_t t, setup_time, trans_time;
u32 total_bytes;
u32 setup_us, trans_us, total_us;
@@ -476,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
total_bytes = dsi->update_region.w *
dsi->update_region.h *
- dsi->update_region.device->ctrl.pixel_size / 8;
+ dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
"%u bytes, %u kbytes/sec\n",
@@ -1287,7 +1288,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
* with DSS_SYS_CLK source also */
cinfo->highfreq = 0;
} else {
- cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
+ cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
if (cinfo->clkin < 32000000)
cinfo->highfreq = 0;
@@ -2360,6 +2361,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
return 0;
}
+static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
+{
+ unsigned lanes = 0;
+
+ if (dssdev->phy.dsi.clk_lane != 0)
+ lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
+ if (dssdev->phy.dsi.data1_lane != 0)
+ lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
+ if (dssdev->phy.dsi.data2_lane != 0)
+ lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
+ if (dssdev->phy.dsi.data3_lane != 0)
+ lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
+ if (dssdev->phy.dsi.data4_lane != 0)
+ lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
+
+ return lanes;
+}
+
static int dsi_cio_init(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -2370,8 +2389,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
DSSDBGF();
- if (dsi->dsi_mux_pads)
- dsi->dsi_mux_pads(true);
+ r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
+ if (r)
+ return r;
dsi_enable_scp_clk(dsidev);
@@ -2452,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_cio_timings(dsidev);
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ /* DDR_CLK_ALWAYS_ON */
+ REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
+ dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
+ }
+
dsi->ulps_enabled = false;
DSSDBG("CIO init done\n");
@@ -2467,19 +2493,21 @@ err_cio_pwr:
dsi_cio_disable_lane_override(dsidev);
err_scp_clk_dom:
dsi_disable_scp_clk(dsidev);
- if (dsi->dsi_mux_pads)
- dsi->dsi_mux_pads(false);
+ dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
return r;
}
-static void dsi_cio_uninit(struct platform_device *dsidev)
+static void dsi_cio_uninit(struct omap_dss_device *dssdev)
{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ /* DDR_CLK_ALWAYS_ON */
+ REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
dsi_disable_scp_clk(dsidev);
- if (dsi->dsi_mux_pads)
- dsi->dsi_mux_pads(false);
+ dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
}
static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2669,10 +2697,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
if (!dsi_vc_is_enabled(dsidev, channel))
return 0;
- switch (dsi->vc[channel].mode) {
- case DSI_VC_MODE_VP:
+ switch (dsi->vc[channel].source) {
+ case DSI_VC_SOURCE_VP:
return dsi_sync_vc_vp(dsidev, channel);
- case DSI_VC_MODE_L4:
+ case DSI_VC_SOURCE_L4:
return dsi_sync_vc_l4(dsidev, channel);
default:
BUG();
@@ -2726,43 +2754,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
}
-static int dsi_vc_config_l4(struct platform_device *dsidev, int channel)
+static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
+ enum dsi_vc_source source)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- if (dsi->vc[channel].mode == DSI_VC_MODE_L4)
- return 0;
-
- DSSDBGF("%d", channel);
-
- dsi_sync_vc(dsidev, channel);
-
- dsi_vc_enable(dsidev, channel, 0);
-
- /* VC_BUSY */
- if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
- DSSERR("vc(%d) busy when trying to config for L4\n", channel);
- return -EIO;
- }
-
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
-
- /* DCS_CMD_ENABLE */
- if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30);
-
- dsi_vc_enable(dsidev, channel, 1);
-
- dsi->vc[channel].mode = DSI_VC_MODE_L4;
-
- return 0;
-}
-
-static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- if (dsi->vc[channel].mode == DSI_VC_MODE_VP)
+ if (dsi->vc[channel].source == source)
return 0;
DSSDBGF("%d", channel);
@@ -2777,21 +2774,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
return -EIO;
}
- /* SOURCE, 1 = video port */
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1);
+ /* SOURCE, 0 = L4, 1 = video port */
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
/* DCS_CMD_ENABLE */
- if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30);
+ if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+ bool enable = source == DSI_VC_SOURCE_VP;
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
+ }
dsi_vc_enable(dsidev, channel, 1);
- dsi->vc[channel].mode = DSI_VC_MODE_VP;
+ dsi->vc[channel].source = source;
return 0;
}
-
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable)
{
@@ -2810,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
dsi_if_enable(dsidev, 1);
dsi_force_tx_stop_mode_io(dsidev);
+
+ /* start the DDR clock by sending a NULL packet */
+ if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
+ dsi_vc_send_null(dssdev, channel);
}
EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -2873,16 +2875,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
DSSERR("\trawval %#08x\n", val);
dt = FLD_GET(val, 5, 0);
- if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
u16 err = FLD_GET(val, 23, 8);
dsi_show_rx_ack_with_err(err);
- } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
DSSERR("\tDCS short response, 1 byte: %#x\n",
FLD_GET(val, 23, 8));
- } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
DSSERR("\tDCS short response, 2 byte: %#x\n",
FLD_GET(val, 23, 8));
- } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
DSSERR("\tDCS long response, len %d\n",
FLD_GET(val, 23, 8));
dsi_vc_flush_long_data(dsidev, channel);
@@ -3007,7 +3009,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
return -EINVAL;
}
- dsi_vc_config_l4(dsidev, channel);
+ dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
@@ -3066,7 +3068,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
channel,
data_type, data & 0xff, (data >> 8) & 0xff);
- dsi_vc_config_l4(dsidev, channel);
+ dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
DSSERR("ERROR FIFO FULL, aborting transfer\n");
@@ -3085,44 +3087,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- u8 nullpkg[] = {0, 0, 0, 0};
- return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg,
- 4, 0);
+ return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
+ 0, 0);
}
EXPORT_SYMBOL(dsi_vc_send_null);
-int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
- u8 *data, int len)
+static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
+ int channel, u8 *data, int len, enum dss_dsi_content_type type)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
int r;
- BUG_ON(len == 0);
-
- if (len == 1) {
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0,
- data[0], 0);
+ if (len == 0) {
+ BUG_ON(type == DSS_DSI_CONTENT_DCS);
+ r = dsi_vc_send_short(dsidev, channel,
+ MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
+ } else if (len == 1) {
+ r = dsi_vc_send_short(dsidev, channel,
+ type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
+ MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
} else if (len == 2) {
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1,
+ r = dsi_vc_send_short(dsidev, channel,
+ type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM,
data[0] | (data[1] << 8), 0);
} else {
- /* 0x39 = DCS Long Write */
- r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
- data, len, 0);
+ r = dsi_vc_send_long(dsidev, channel,
+ type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_GENERIC_LONG_WRITE :
+ MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
}
return r;
}
+
+int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len)
+{
+ return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+ DSS_DSI_CONTENT_DCS);
+}
EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
-int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
- int len)
+int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len)
+{
+ return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+ DSS_DSI_CONTENT_GENERIC);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
+
+static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
+ u8 *data, int len, enum dss_dsi_content_type type)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
int r;
- r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len);
+ r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type);
if (r)
goto err;
@@ -3140,18 +3164,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
return 0;
err:
- DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
+ DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
channel, data[0], len);
return r;
}
+
+int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+ int len)
+{
+ return dsi_vc_write_common(dssdev, channel, data, len,
+ DSS_DSI_CONTENT_DCS);
+}
EXPORT_SYMBOL(dsi_vc_dcs_write);
+int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+ int len)
+{
+ return dsi_vc_write_common(dssdev, channel, data, len,
+ DSS_DSI_CONTENT_GENERIC);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write);
+
int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
{
return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
}
EXPORT_SYMBOL(dsi_vc_dcs_write_0);
+int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel)
+{
+ return dsi_vc_generic_write(dssdev, channel, NULL, 0);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_0);
+
int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 param)
{
@@ -3162,25 +3207,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
}
EXPORT_SYMBOL(dsi_vc_dcs_write_1);
-int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 *buf, int buflen)
+int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
+ u8 param)
+{
+ return dsi_vc_generic_write(dssdev, channel, &param, 1);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_1);
+
+int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
+ u8 param1, u8 param2)
+{
+ u8 buf[2];
+ buf[0] = param1;
+ buf[1] = param2;
+ return dsi_vc_generic_write(dssdev, channel, buf, 2);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_2);
+
+static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
+ int channel, u8 dcs_cmd)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- u32 val;
- u8 dt;
int r;
if (dsi->debug_read)
- DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
+ DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
+ channel, dcs_cmd);
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0);
- if (r)
- goto err;
+ r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
+ if (r) {
+ DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
+ " failed\n", channel, dcs_cmd);
+ return r;
+ }
- r = dsi_vc_send_bta_sync(dssdev, channel);
- if (r)
- goto err;
+ return 0;
+}
+
+static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
+ int channel, u8 *reqdata, int reqlen)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ u16 data;
+ u8 data_type;
+ int r;
+
+ if (dsi->debug_read)
+ DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
+ channel, reqlen);
+
+ if (reqlen == 0) {
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
+ data = 0;
+ } else if (reqlen == 1) {
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+ data = reqdata[0];
+ } else if (reqlen == 2) {
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
+ data = reqdata[0] | (reqdata[1] << 8);
+ } else {
+ BUG();
+ }
+
+ r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
+ if (r) {
+ DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
+ " failed\n", channel, reqlen);
+ return r;
+ }
+
+ return 0;
+}
+
+static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
+ u8 *buf, int buflen, enum dss_dsi_content_type type)
+{
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ u32 val;
+ u8 dt;
+ int r;
/* RX_FIFO_NOT_EMPTY */
if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
@@ -3193,16 +3300,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
if (dsi->debug_read)
DSSDBG("\theader: %08x\n", val);
dt = FLD_GET(val, 5, 0);
- if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
u16 err = FLD_GET(val, 23, 8);
dsi_show_rx_ack_with_err(err);
r = -EIO;
goto err;
- } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
u8 data = FLD_GET(val, 15, 8);
if (dsi->debug_read)
- DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
+ DSSDBG("\t%s short response, 1 byte: %02x\n",
+ type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+ "DCS", data);
if (buflen < 1) {
r = -EIO;
@@ -3212,10 +3323,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
buf[0] = data;
return 1;
- } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
u16 data = FLD_GET(val, 23, 8);
if (dsi->debug_read)
- DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
+ DSSDBG("\t%s short response, 2 byte: %04x\n",
+ type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+ "DCS", data);
if (buflen < 2) {
r = -EIO;
@@ -3226,11 +3341,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
buf[1] = (data >> 8) & 0xff;
return 2;
- } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+ MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
+ MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
int w;
int len = FLD_GET(val, 23, 8);
if (dsi->debug_read)
- DSSDBG("\tDCS long response, len %d\n", len);
+ DSSDBG("\t%s long response, len %d\n",
+ type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+ "DCS", len);
if (len > buflen) {
r = -EIO;
@@ -3266,58 +3385,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
BUG();
err:
- DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n",
- channel, dcs_cmd);
+ DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
+ type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
+
return r;
+}
+int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
+ u8 *buf, int buflen)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ int r;
+
+ r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd);
+ if (r)
+ goto err;
+
+ r = dsi_vc_send_bta_sync(dssdev, channel);
+ if (r)
+ goto err;
+
+ r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+ DSS_DSI_CONTENT_DCS);
+ if (r < 0)
+ goto err;
+
+ if (r != buflen) {
+ r = -EIO;
+ goto err;
+ }
+
+ return 0;
+err:
+ DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
+ return r;
}
EXPORT_SYMBOL(dsi_vc_dcs_read);
-int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 *data)
+static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
+ u8 *reqdata, int reqlen, u8 *buf, int buflen)
{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
int r;
- r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1);
+ r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen);
+ if (r)
+ return r;
+
+ r = dsi_vc_send_bta_sync(dssdev, channel);
+ if (r)
+ return r;
+ r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+ DSS_DSI_CONTENT_GENERIC);
if (r < 0)
return r;
- if (r != 1)
- return -EIO;
+ if (r != buflen) {
+ r = -EIO;
+ return r;
+ }
return 0;
}
-EXPORT_SYMBOL(dsi_vc_dcs_read_1);
-int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
- u8 *data1, u8 *data2)
+int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
+ int buflen)
{
- u8 buf[2];
int r;
- r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2);
+ r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen);
+ if (r) {
+ DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel);
+ return r;
+ }
- if (r < 0)
+ return 0;
+}
+EXPORT_SYMBOL(dsi_vc_generic_read_0);
+
+int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
+ u8 *buf, int buflen)
+{
+ int r;
+
+ r = dsi_vc_generic_read(dssdev, channel, &param, 1, buf, buflen);
+ if (r) {
+ DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);
return r;
+ }
- if (r != 2)
- return -EIO;
+ return 0;
+}
+EXPORT_SYMBOL(dsi_vc_generic_read_1);
- *data1 = buf[0];
- *data2 = buf[1];
+int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
+ u8 param1, u8 param2, u8 *buf, int buflen)
+{
+ int r;
+ u8 reqdata[2];
+
+ reqdata[0] = param1;
+ reqdata[1] = param2;
+
+ r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen);
+ if (r) {
+ DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel);
+ return r;
+ }
return 0;
}
-EXPORT_SYMBOL(dsi_vc_dcs_read_2);
+EXPORT_SYMBOL(dsi_vc_generic_read_2);
int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
u16 len)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
- len, 0);
+ return dsi_vc_send_short(dsidev, channel,
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
}
EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
@@ -3508,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
ticks, x4 ? " x4" : "", x16 ? " x16" : "",
(total_ticks * 1000) / (fck / 1000 / 1000));
}
+
+static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ int num_line_buffers;
+
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+ struct omap_video_timings *timings = &dssdev->panel.timings;
+ /*
+ * Don't use line buffers if width is greater than the video
+ * port's line buffer size
+ */
+ if (line_buf_size <= timings->x_res * bpp / 8)
+ num_line_buffers = 0;
+ else
+ num_line_buffers = 2;
+ } else {
+ /* Use maximum number of line buffers in command mode */
+ num_line_buffers = 2;
+ }
+
+ /* LINE_BUFFER */
+ REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
+}
+
+static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol;
+ int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol;
+ int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol;
+ bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
+ bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+ u32 r;
+
+ r = dsi_read_reg(dsidev, DSI_CTRL);
+ r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */
+ r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */
+ r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */
+ r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */
+ r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */
+ r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */
+ r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */
+ dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
+static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
+ int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
+ int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
+ int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
+ u32 r;
+
+ /*
+ * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
+ * 1 = Long blanking packets are sent in corresponding blanking periods
+ */
+ r = dsi_read_reg(dsidev, DSI_CTRL);
+ r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */
+ r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */
+ r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */
+ r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */
+ dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
static int dsi_proto_config(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3530,7 +3786,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
- switch (dssdev->ctrl.pixel_size) {
+ switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
case 16:
buswidth = 0;
break;
@@ -3551,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
- r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
@@ -3562,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
dsi_write_reg(dsidev, DSI_CTRL, r);
+ dsi_config_vp_num_line_buffers(dssdev);
+
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ dsi_config_vp_sync_events(dssdev);
+ dsi_config_blanking_modes(dssdev);
+ }
+
dsi_vc_initial_config(dsidev, 0);
dsi_vc_initial_config(dsidev, 1);
dsi_vc_initial_config(dsidev, 2);
@@ -3580,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
unsigned ddr_clk_pre, ddr_clk_post;
unsigned enter_hs_mode_lat, exit_hs_mode_lat;
unsigned ths_eot;
+ int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
u32 r;
r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -3602,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
/* min 60ns + 52*UI */
tclk_post = ns2ddr(dsidev, 60) + 26;
- ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev));
+ ths_eot = DIV_ROUND_UP(4, ndl);
ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
4);
@@ -3632,162 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
enter_hs_mode_lat, exit_hs_mode_lat);
-}
-
-
-#define DSI_DECL_VARS \
- int __dsi_cb = 0; u32 __dsi_cv = 0;
-#define DSI_FLUSH(dsidev, ch) \
- if (__dsi_cb > 0) { \
- /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
- dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
- __dsi_cb = __dsi_cv = 0; \
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ /* TODO: Implement a video mode check_timings function */
+ int hsa = dssdev->panel.dsi_vm_data.hsa;
+ int hfp = dssdev->panel.dsi_vm_data.hfp;
+ int hbp = dssdev->panel.dsi_vm_data.hbp;
+ int vsa = dssdev->panel.dsi_vm_data.vsa;
+ int vfp = dssdev->panel.dsi_vm_data.vfp;
+ int vbp = dssdev->panel.dsi_vm_data.vbp;
+ int window_sync = dssdev->panel.dsi_vm_data.window_sync;
+ bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+ struct omap_video_timings *timings = &dssdev->panel.timings;
+ int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ int tl, t_he, width_bytes;
+
+ t_he = hsync_end ?
+ ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
+
+ width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+
+ /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
+ tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
+ DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
+
+ DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
+ hfp, hsync_end ? hsa : 0, tl);
+ DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
+ vsa, timings->y_res);
+
+ r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
+ r = FLD_MOD(r, hbp, 11, 0); /* HBP */
+ r = FLD_MOD(r, hfp, 23, 12); /* HFP */
+ r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */
+ dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
+
+ r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
+ r = FLD_MOD(r, vbp, 7, 0); /* VBP */
+ r = FLD_MOD(r, vfp, 15, 8); /* VFP */
+ r = FLD_MOD(r, vsa, 23, 16); /* VSA */
+ r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */
+ dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
+
+ r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
+ r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */
+ r = FLD_MOD(r, tl, 31, 16); /* TL */
+ dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
}
+}
-#define DSI_PUSH(dsidev, ch, data) \
- do { \
- __dsi_cv |= (data) << (__dsi_cb * 8); \
- /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
- if (++__dsi_cb > 3) \
- DSI_FLUSH(dsidev, ch); \
- } while (0)
-
-static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
- int x, int y, int w, int h)
+int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
{
- /* Note: supports only 24bit colors in 32bit container */
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- int first = 1;
- int fifo_stalls = 0;
- int max_dsi_packet_size;
- int max_data_per_packet;
- int max_pixels_per_packet;
- int pixels_left;
- int bytespp = dssdev->ctrl.pixel_size / 8;
- int scr_width;
- u32 __iomem *data;
- int start_offset;
- int horiz_inc;
- int current_x;
- struct omap_overlay *ovl;
-
- debug_irq = 0;
-
- DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
- x, y, w, h);
+ int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ u8 data_type;
+ u16 word_count;
- ovl = dssdev->manager->overlays[0];
-
- if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
- return -EINVAL;
-
- if (dssdev->ctrl.pixel_size != 24)
- return -EINVAL;
-
- scr_width = ovl->info.screen_width;
- data = ovl->info.vaddr;
-
- start_offset = scr_width * y + x;
- horiz_inc = scr_width - w;
- current_x = x;
-
- /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
- * in fifo */
-
- /* When using CPU, max long packet size is TX buffer size */
- max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4;
-
- /* we seem to get better perf if we divide the tx fifo to half,
- and while the other half is being sent, we fill the other half
- max_dsi_packet_size /= 2; */
-
- max_data_per_packet = max_dsi_packet_size - 4 - 1;
-
- max_pixels_per_packet = max_data_per_packet / bytespp;
-
- DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
-
- pixels_left = w * h;
+ switch (dssdev->panel.dsi_pix_fmt) {
+ case OMAP_DSS_DSI_FMT_RGB888:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB666:
+ data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB565:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+ break;
+ default:
+ BUG();
+ };
- DSSDBG("total pixels %d\n", pixels_left);
+ dsi_if_enable(dsidev, false);
+ dsi_vc_enable(dsidev, channel, false);
- data += start_offset;
+ /* MODE, 1 = video mode */
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
- while (pixels_left > 0) {
- /* 0x2c = write_memory_start */
- /* 0x3c = write_memory_continue */
- u8 dcs_cmd = first ? 0x2c : 0x3c;
- int pixels;
- DSI_DECL_VARS;
- first = 0;
+ word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
-#if 1
- /* using fifo not empty */
- /* TX_FIFO_NOT_EMPTY */
- while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) {
- fifo_stalls++;
- if (fifo_stalls > 0xfffff) {
- DSSERR("fifo stalls overflow, pixels left %d\n",
- pixels_left);
- dsi_if_enable(dsidev, 0);
- return -EIO;
- }
- udelay(1);
- }
-#elif 1
- /* using fifo emptiness */
- while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
- max_dsi_packet_size) {
- fifo_stalls++;
- if (fifo_stalls > 0xfffff) {
- DSSERR("fifo stalls overflow, pixels left %d\n",
- pixels_left);
- dsi_if_enable(dsidev, 0);
- return -EIO;
- }
- }
-#else
- while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS,
- 7, 0) + 1) * 4 == 0) {
- fifo_stalls++;
- if (fifo_stalls > 0xfffff) {
- DSSERR("fifo stalls overflow, pixels left %d\n",
- pixels_left);
- dsi_if_enable(dsidev, 0);
- return -EIO;
- }
- }
-#endif
- pixels = min(max_pixels_per_packet, pixels_left);
+ dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
- pixels_left -= pixels;
+ dsi_vc_enable(dsidev, channel, true);
+ dsi_if_enable(dsidev, true);
- dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE,
- 1 + pixels * bytespp, 0);
+ dssdev->manager->enable(dssdev->manager);
- DSI_PUSH(dsidev, 0, dcs_cmd);
+ return 0;
+}
+EXPORT_SYMBOL(dsi_video_mode_enable);
- while (pixels-- > 0) {
- u32 pix = __raw_readl(data++);
+void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff);
- DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff);
- DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff);
+ dsi_if_enable(dsidev, false);
+ dsi_vc_enable(dsidev, channel, false);
- current_x++;
- if (current_x == x+w) {
- current_x = x;
- data += horiz_inc;
- }
- }
+ /* MODE, 0 = command mode */
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
- DSI_FLUSH(dsidev, 0);
- }
+ dsi_vc_enable(dsidev, channel, true);
+ dsi_if_enable(dsidev, true);
- return 0;
+ dssdev->manager->disable(dssdev->manager);
}
+EXPORT_SYMBOL(dsi_video_mode_disable);
static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
@@ -3808,9 +4023,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
x, y, w, h);
- dsi_vc_config_vp(dsidev, channel);
+ dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
- bytespp = dssdev->ctrl.pixel_size / 8;
+ bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
bytespl = w * bytespp;
bytespf = bytespl * h;
@@ -3831,7 +4046,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
- dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
+ dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
packet_len, 0);
if (dsi->te_enabled)
@@ -3956,11 +4171,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
dsi_perf_mark_setup(dsidev);
- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
- dss_setup_partial_planes(dssdev, x, y, w, h,
- enlarge_update_area);
- dispc_set_lcd_size(dssdev->manager->id, *w, *h);
- }
+ dss_setup_partial_planes(dssdev, x, y, w, h,
+ enlarge_update_area);
+ dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
return 0;
}
@@ -3982,27 +4195,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
* see rather obscure HW error happening, as DSS halts. */
BUG_ON(x % 2 == 1);
- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
- dsi->framedone_callback = callback;
- dsi->framedone_data = data;
-
- dsi->update_region.x = x;
- dsi->update_region.y = y;
- dsi->update_region.w = w;
- dsi->update_region.h = h;
- dsi->update_region.device = dssdev;
-
- dsi_update_screen_dispc(dssdev, x, y, w, h);
- } else {
- int r;
+ dsi->framedone_callback = callback;
+ dsi->framedone_data = data;
- r = dsi_update_screen_l4(dssdev, x, y, w, h);
- if (r)
- return r;
+ dsi->update_region.x = x;
+ dsi->update_region.y = y;
+ dsi->update_region.w = w;
+ dsi->update_region.h = h;
+ dsi->update_region.device = dssdev;
- dsi_perf_show(dsidev, "L4");
- callback(0, data);
- }
+ dsi_update_screen_dispc(dssdev, x, y, w, h);
return 0;
}
@@ -4013,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update);
static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
{
int r;
- u32 irq;
-
- irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
- DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
- r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev,
- irq);
- if (r) {
- DSSERR("can't get FRAMEDONE irq\n");
- return r;
- }
-
- dispc_set_lcd_display_type(dssdev->manager->id,
- OMAP_DSS_LCD_DISPLAY_TFT);
-
- dispc_set_parallel_interface_mode(dssdev->manager->id,
- OMAP_DSS_PARALLELMODE_DSI);
- dispc_enable_fifohandcheck(dssdev->manager->id, 1);
-
- dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
-
- {
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ u32 irq;
struct omap_video_timings timings = {
.hsw = 1,
.hfp = 1,
@@ -4044,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
.vbp = 0,
};
- dispc_set_lcd_timings(dssdev->manager->id, &timings);
+ irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
+ DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
+
+ r = omap_dispc_register_isr(dsi_framedone_irq_callback,
+ (void *) dssdev, irq);
+ if (r) {
+ DSSERR("can't get FRAMEDONE irq\n");
+ return r;
+ }
+
+ dispc_mgr_enable_stallmode(dssdev->manager->id, true);
+ dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
+
+ dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings);
+ } else {
+ dispc_mgr_enable_stallmode(dssdev->manager->id, false);
+ dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0);
+
+ dispc_mgr_set_lcd_timings(dssdev->manager->id,
+ &dssdev->panel.timings);
}
+ dispc_mgr_set_lcd_display_type(dssdev->manager->id,
+ OMAP_DSS_LCD_DISPLAY_TFT);
+ dispc_mgr_set_tft_data_lines(dssdev->manager->id,
+ dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt));
return 0;
}
static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
{
- u32 irq;
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ u32 irq;
- irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
- DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
+ irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
+ DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
- omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev,
- irq);
+ omap_dispc_unregister_isr(dsi_framedone_irq_callback,
+ (void *) dssdev, irq);
+ }
}
static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4106,7 +4314,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
return r;
}
- r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+ r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r) {
DSSERR("Failed to set dispc clocks\n");
return r;
@@ -4166,10 +4374,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
return 0;
err3:
- dsi_cio_uninit(dsidev);
+ dsi_cio_uninit(dssdev);
err2:
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
+ dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+
err1:
dsi_pll_uninit(dsidev, true);
err0:
@@ -4195,7 +4405,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
- dsi_cio_uninit(dsidev);
+ dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+ dsi_cio_uninit(dssdev);
dsi_pll_uninit(dsidev, disconnect_lanes);
}
@@ -4211,6 +4422,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
mutex_lock(&dsi->lock);
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ r = -ENODEV;
+ goto err_start_dev;
+ }
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@@ -4307,9 +4524,10 @@ int dsi_init_display(struct omap_dss_device *dssdev)
DSSDBG("DSI init\n");
- /* XXX these should be figured out dynamically */
- dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
- OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
+ OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+ }
if (dsi->vdds_dsi_reg == NULL) {
struct regulator *vdds_dsi;
@@ -4435,10 +4653,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
dsi->dss_clk = clk;
- if (cpu_is_omap34xx() || cpu_is_omap3630())
- clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
- else
- clk = clk_get(&dsidev->dev, "sys_clk");
+ clk = clk_get(&dsidev->dev, "sys_clk");
if (IS_ERR(clk)) {
DSSERR("can't get sys_clk\n");
clk_put(dsi->dss_clk);
@@ -4462,7 +4677,7 @@ static void dsi_put_clocks(struct platform_device *dsidev)
}
/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int omap_dsihw_probe(struct platform_device *dsidev)
{
struct omap_display_platform_data *dss_plat_data;
struct omap_dss_board_info *board_info;
@@ -4483,7 +4698,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dss_plat_data = dsidev->dev.platform_data;
board_info = dss_plat_data->board_data;
- dsi->dsi_mux_pads = board_info->dsi_mux_pads;
+ dsi->enable_pads = board_info->dsi_enable_pads;
+ dsi->disable_pads = board_info->dsi_disable_pads;
spin_lock_init(&dsi->irq_lock);
spin_lock_init(&dsi->errors_lock);
@@ -4539,7 +4755,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
/* DSI VCs initialization */
for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
- dsi->vc[i].mode = DSI_VC_MODE_L4;
+ dsi->vc[i].source = DSI_VC_SOURCE_L4;
dsi->vc[i].dssdev = NULL;
dsi->vc[i].vc_id = 0;
}
@@ -4572,7 +4788,7 @@ err_alloc:
return r;
}
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static int omap_dsihw_remove(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4602,10 +4818,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
static int dsi_runtime_suspend(struct device *dev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
-
- clk_disable(dsi->dss_clk);
-
dispc_runtime_put();
dss_runtime_put();
@@ -4614,7 +4826,6 @@ static int dsi_runtime_suspend(struct device *dev)
static int dsi_runtime_resume(struct device *dev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
int r;
r = dss_runtime_get();
@@ -4625,8 +4836,6 @@ static int dsi_runtime_resume(struct device *dev)
if (r)
goto err_get_dispc;
- clk_enable(dsi->dss_clk);
-
return 0;
err_get_dispc:
@@ -4640,11 +4849,11 @@ static const struct dev_pm_ops dsi_pm_ops = {
.runtime_resume = dsi_runtime_resume,
};
-static struct platform_driver omap_dsi1hw_driver = {
- .probe = omap_dsi1hw_probe,
- .remove = omap_dsi1hw_remove,
+static struct platform_driver omap_dsihw_driver = {
+ .probe = omap_dsihw_probe,
+ .remove = omap_dsihw_remove,
.driver = {
- .name = "omapdss_dsi1",
+ .name = "omapdss_dsi",
.owner = THIS_MODULE,
.pm = &dsi_pm_ops,
},
@@ -4652,10 +4861,10 @@ static struct platform_driver omap_dsi1hw_driver = {
int dsi_init_platform_driver(void)
{
- return platform_driver_register(&omap_dsi1hw_driver);
+ return platform_driver_register(&omap_dsihw_driver);
}
void dsi_uninit_platform_driver(void)
{
- return platform_driver_unregister(&omap_dsi1hw_driver);
+ return platform_driver_unregister(&omap_dsihw_driver);
}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 0f9c3a6457a5..3e09726d32c7 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -639,6 +639,17 @@ 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 */
}
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
+{
+ enum omap_display_type displays;
+
+ displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+ if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
+ return DSS_VENC_TV_CLK;
+
+ return REG_GET(DSS_CONTROL, 15, 15);
+}
+
static int dss_get_clocks(void)
{
struct clk *clk;
@@ -691,11 +702,6 @@ static void dss_put_clocks(void)
clk_put(dss.dss_clk);
}
-struct clk *dss_get_ick(void)
-{
- return clk_get(&dss.pdev->dev, "ick");
-}
-
int dss_runtime_get(void)
{
int r;
@@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
dss_save_context();
- clk_disable(dss.dss_clk);
return 0;
}
static int dss_runtime_resume(struct device *dev)
{
- clk_enable(dss.dss_clk);
dss_restore_context();
return 0;
}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 9c94b1152c20..6308fc59fc9e 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -97,10 +97,10 @@ extern unsigned int dss_debug;
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
-enum omap_parallel_interface_mode {
- OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
- OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
- OMAP_DSS_PARALLELMODE_DSI,
+enum dss_io_pad_mode {
+ DSS_IO_PAD_MODE_RESET,
+ DSS_IO_PAD_MODE_RFBI,
+ DSS_IO_PAD_MODE_BYPASS,
};
enum dss_hdmi_venc_clk_source_select {
@@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select {
DSS_HDMI_M_PCLK = 1,
};
+enum dss_dsi_content_type {
+ DSS_DSI_CONTENT_DCS,
+ DSS_DSI_CONTENT_GENERIC,
+};
+
struct dss_clock_info {
/* rates that we get with dividers below */
unsigned long fck;
@@ -150,16 +155,6 @@ struct dsi_clock_info {
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;
@@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void);
int dss_runtime_get(void);
void dss_runtime_put(void);
-struct clk *dss_get_ick(void);
-
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
@@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
+
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo);
@@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev)
static inline void dsi_runtime_put(struct platform_device *dsidev)
{
}
+static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+ WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
+ return 0;
+}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -385,90 +386,71 @@ void dispc_disable_sidle(void);
void dispc_lcd_enable_signal_polarity(bool act_high);
void dispc_lcd_enable_signal(bool enable);
void dispc_pck_free_enable(bool enable);
-void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
-
-void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
void dispc_set_digit_size(u16 width, u16 height);
-u32 dispc_get_plane_fifo_size(enum omap_plane plane);
-void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_enable_fifomerge(bool enable);
-u32 dispc_get_burst_size(enum omap_plane plane);
-void dispc_enable_cpr(enum omap_channel channel, bool enable);
-void dispc_set_cpr_coef(enum omap_channel channel,
- struct omap_dss_cpr_coefs *coefs);
-
-void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
-void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
-void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
-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,
- u16 width, u16 height,
- u16 out_width, u16 out_height,
- enum omap_color_mode color_mode,
- bool ilace,
- enum omap_dss_rotation_type rotation_type,
- u8 rotation, bool mirror,
- u8 global_alpha, u8 pre_mult_alpha,
- enum omap_channel channel,
- u32 puv_addr);
-
-bool dispc_go_busy(enum omap_channel channel);
-void dispc_go(enum omap_channel channel);
-void dispc_enable_channel(enum omap_channel channel, bool enable);
-bool dispc_is_channel_enabled(enum omap_channel channel);
-int dispc_enable_plane(enum omap_plane plane, bool enable);
-void dispc_enable_replication(enum omap_plane plane, bool enable);
-
-void dispc_set_parallel_interface_mode(enum omap_channel channel,
- enum omap_parallel_interface_mode mode);
-void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_set_lcd_display_type(enum omap_channel channel,
- enum omap_lcd_display_type type);
void dispc_set_loadmode(enum omap_dss_load_mode mode);
-void dispc_set_default_color(enum omap_channel channel, u32 color);
-u32 dispc_get_default_color(enum omap_channel channel);
-void dispc_set_trans_key(enum omap_channel ch,
- enum omap_dss_trans_key_type type,
- u32 trans_key);
-void dispc_get_trans_key(enum omap_channel ch,
- enum omap_dss_trans_key_type *type,
- u32 *trans_key);
-void dispc_enable_trans_key(enum omap_channel ch, bool enable);
-void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
-bool dispc_trans_key_enabled(enum omap_channel ch);
-bool dispc_alpha_blending_enabled(enum omap_channel ch);
-
bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
-void dispc_set_lcd_timings(enum omap_channel channel,
- struct omap_video_timings *timings);
unsigned long dispc_fclk_rate(void);
-unsigned long dispc_lclk_rate(enum omap_channel channel);
-unsigned long dispc_pclk_rate(enum omap_channel channel);
-void dispc_set_pol_freq(enum omap_channel channel,
- enum omap_panel_config config, u8 acbi, u8 acb);
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
struct dispc_clock_info *cinfo);
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo);
-int dispc_set_clock_div(enum omap_channel channel,
+
+
+u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
+u32 dispc_ovl_get_burst_size(enum omap_plane plane);
+int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+ bool ilace, enum omap_channel channel, bool replication,
+ u32 fifo_low, u32 fifo_high);
+int dispc_ovl_enable(enum omap_plane plane, bool enable);
+
+
+void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
+void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
+void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
+void dispc_mgr_set_cpr_coef(enum omap_channel channel,
+ struct omap_dss_cpr_coefs *coefs);
+bool dispc_mgr_go_busy(enum omap_channel channel);
+void dispc_mgr_go(enum omap_channel channel);
+void dispc_mgr_enable(enum omap_channel channel, bool enable);
+bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
+void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
+void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
+void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
+void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
+ enum omap_lcd_display_type type);
+void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
+u32 dispc_mgr_get_default_color(enum omap_channel channel);
+void dispc_mgr_set_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type type,
+ u32 trans_key);
+void dispc_mgr_get_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type *type,
+ u32 *trans_key);
+void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
+void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
+bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
+bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
+void dispc_mgr_set_lcd_timings(enum omap_channel channel,
+ struct omap_video_timings *timings);
+void dispc_mgr_set_pol_freq(enum omap_channel channel,
+ enum omap_panel_config config, u8 acbi, u8 acb);
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
+int dispc_mgr_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
-int dispc_get_clock_div(enum omap_channel channel,
+int dispc_mgr_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
-
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
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);
+unsigned long venc_get_pixel_clock(void);
#else
static inline int venc_init_platform_driver(void)
{
@@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void)
static inline void venc_uninit_platform_driver(void)
{
}
+static inline unsigned long venc_get_pixel_clock(void)
+{
+ WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
+ return 0;
+}
#endif
/* HDMI */
@@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void)
int hdmi_init_platform_driver(void);
void hdmi_uninit_platform_driver(void);
int hdmi_init_display(struct omap_dss_device *dssdev);
+unsigned long hdmi_get_pixel_clock(void);
+void hdmi_dump_regs(struct seq_file *s);
#else
static inline int hdmi_init_display(struct omap_dss_device *dssdev)
{
@@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void)
static inline void hdmi_uninit_platform_driver(void)
{
}
+static inline unsigned long hdmi_get_pixel_clock(void)
+{
+ WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
+ return 0;
+}
#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 omapdss_hdmi_read_edid(u8 *buf, int len);
+bool omapdss_hdmi_detect(void);
int hdmi_panel_init(void);
void hdmi_panel_exit(void);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index b415c4ee621d..b402699168a5 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -47,6 +47,7 @@ struct omap_dss_features {
const int num_ovls;
const enum omap_display_type *supported_displays;
const enum omap_color_mode *supported_color_modes;
+ const enum omap_overlay_caps *overlay_caps;
const char * const *clksrc_names;
const struct dss_param_range *dss_params;
@@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
OMAP_DSS_COLOR_RGBX32,
+
+ /* OMAP_DSS_VIDEO3 */
+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+ OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+ OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+ OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+ OMAP_DSS_COLOR_RGBX32,
+};
+
+static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
+ /* OMAP_DSS_GFX */
+ 0,
+
+ /* OMAP_DSS_VIDEO1 */
+ OMAP_DSS_OVL_CAP_SCALE,
+
+ /* OMAP_DSS_VIDEO2 */
+ OMAP_DSS_OVL_CAP_SCALE,
+};
+
+static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
+ /* OMAP_DSS_GFX */
+ OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+
+ /* OMAP_DSS_VIDEO1 */
+ OMAP_DSS_OVL_CAP_SCALE,
+
+ /* OMAP_DSS_VIDEO2 */
+ OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+};
+
+static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
+ /* OMAP_DSS_GFX */
+ OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+
+ /* OMAP_DSS_VIDEO1 */
+ OMAP_DSS_OVL_CAP_SCALE,
+
+ /* OMAP_DSS_VIDEO2 */
+ OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+};
+
+static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
+ /* OMAP_DSS_GFX */
+ OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
+ OMAP_DSS_OVL_CAP_ZORDER,
+
+ /* OMAP_DSS_VIDEO1 */
+ OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+
+ /* OMAP_DSS_VIDEO2 */
+ OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+
+ /* OMAP_DSS_VIDEO3 */
+ OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+ OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
};
static const char * const omap2_dss_clk_source_names[] = {
@@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = {
static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
+ [FEAT_PARAM_DSS_PCD] = { 2, 255 },
[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 },
+ [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
};
static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
+ [FEAT_PARAM_DSS_PCD] = { 1, 255 },
[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},
+ [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
};
static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
+ [FEAT_PARAM_DSS_PCD] = { 1, 255 },
[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 },
+ [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
};
/* OMAP2 DSS Features */
@@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = {
.num_ovls = 3,
.supported_displays = omap2_dss_supported_displays,
.supported_color_modes = omap2_dss_supported_color_modes,
+ .overlay_caps = omap2_dss_overlay_caps,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range,
.buffer_size_unit = 1,
@@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
.has_feature =
- FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
+ FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
.num_mgrs = 2,
.num_ovls = 3,
.supported_displays = omap3430_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
+ .overlay_caps = omap3430_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
@@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
.has_feature =
- FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
+ FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
- FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
+ FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
.num_mgrs = 2,
.num_ovls = 3,
.supported_displays = omap3630_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
+ .overlay_caps = omap3630_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
@@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
- FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
- FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
+ FEAT_MGR_LCD2 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
- FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V |
+ FEAT_ALPHA_FREE_ZORDER,
.num_mgrs = 3,
- .num_ovls = 3,
+ .num_ovls = 4,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap4_dss_supported_color_modes,
+ .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
@@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
- FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
- FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
+ FEAT_MGR_LCD2 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
- FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
.num_mgrs = 3,
- .num_ovls = 3,
+ .num_ovls = 4,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap4_dss_supported_color_modes,
+ .overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
.burst_size_unit = 16,
};
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+/* HDMI OMAP4 Functions*/
+static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
+
+ .video_configure = ti_hdmi_4xxx_basic_configure,
+ .phy_enable = ti_hdmi_4xxx_phy_enable,
+ .phy_disable = ti_hdmi_4xxx_phy_disable,
+ .read_edid = ti_hdmi_4xxx_read_edid,
+ .detect = ti_hdmi_4xxx_detect,
+ .pll_enable = ti_hdmi_4xxx_pll_enable,
+ .pll_disable = ti_hdmi_4xxx_pll_disable,
+ .video_enable = ti_hdmi_4xxx_wp_video_start,
+ .dump_wrapper = ti_hdmi_4xxx_wp_dump,
+ .dump_core = ti_hdmi_4xxx_core_dump,
+ .dump_pll = ti_hdmi_4xxx_pll_dump,
+ .dump_phy = ti_hdmi_4xxx_phy_dump,
+
+};
+
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+{
+ if (cpu_is_omap44xx())
+ ip_data->ops = &omap4_hdmi_functions;
+}
+#endif
+
/* Functions returning values related to a DSS feature */
int dss_feat_get_num_mgrs(void)
{
@@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
return omap_current_dss_features->supported_color_modes[plane];
}
+enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
+{
+ return omap_current_dss_features->overlay_caps[plane];
+}
+
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode)
{
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index b7398cbcda5f..6a6c05dd45ce 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -20,16 +20,17 @@
#ifndef __OMAP2_DSS_FEATURES_H
#define __OMAP2_DSS_FEATURES_H
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+#include "ti_hdmi.h"
+#endif
+
#define MAX_DSS_MANAGERS 3
-#define MAX_DSS_OVERLAYS 3
+#define MAX_DSS_OVERLAYS 4
#define MAX_DSS_LCD_MANAGERS 2
#define MAX_NUM_DSI 2
/* DSS has feature id */
enum dss_feat_id {
- FEAT_GLOBAL_ALPHA = 1 << 0,
- FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
- FEAT_PRE_MULT_ALPHA = 1 << 2,
FEAT_LCDENABLEPOL = 1 << 3,
FEAT_LCDENABLESIGNAL = 1 << 4,
FEAT_PCKFREEENABLE = 1 << 5,
@@ -55,6 +56,8 @@ enum dss_feat_id {
FEAT_CPR = 1 << 23,
FEAT_PRELOAD = 1 << 24,
FEAT_FIR_COEF_V = 1 << 25,
+ FEAT_ALPHA_FIXED_ZORDER = 1 << 26,
+ FEAT_ALPHA_FREE_ZORDER = 1 << 27,
};
/* DSS register field id */
@@ -75,12 +78,14 @@ enum dss_feat_reg_field {
enum dss_range_param {
FEAT_PARAM_DSS_FCK,
+ FEAT_PARAM_DSS_PCD,
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,
+ FEAT_PARAM_DOWNSCALE,
};
/* DSS Feature Functions */
@@ -90,6 +95,7 @@ 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);
+enum omap_overlay_caps dss_feat_get_overlay_caps(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 omap_dss_clk_source id);
@@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void); /* in bytes */
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);
void dss_features_init(void);
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+#endif
#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 256f27a9064a..3262f0f1fa35 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -37,26 +37,41 @@
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#include <sound/soc.h>
#include <sound/pcm_params.h>
+#include "ti_hdmi_4xxx_ip.h"
#endif
+#include "ti_hdmi.h"
#include "dss.h"
-#include "hdmi.h"
#include "dss_features.h"
+#define HDMI_WP 0x0
+#define HDMI_CORE_SYS 0x400
+#define HDMI_CORE_AV 0x900
+#define HDMI_PLLCTRL 0x200
+#define HDMI_PHY 0x300
+
+/* HDMI EDID Length move this */
+#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 HDMI_DEFAULT_REGN 16
+#define HDMI_DEFAULT_REGM2 1
+
static struct {
struct mutex lock;
struct omap_display_platform_data *pdata;
struct platform_device *pdev;
- void __iomem *base_wp; /* HDMI wrapper */
+ struct hdmi_ip_data ip_data;
int code;
int mode;
- u8 edid[HDMI_EDID_MAX_LENGTH];
- u8 edid_set;
- bool custom_set;
- struct hdmi_config cfg;
struct clk *sys_clk;
- struct clk *hdmi_clk;
} hdmi;
/*
@@ -144,30 +159,6 @@ static const int code_vesa[85] = {
-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;
-}
-
static int hdmi_runtime_get(void)
{
int r;
@@ -193,304 +184,7 @@ 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_pll_program(struct hdmi_pll_info *fmt)
-{
- u16 r = 0;
- enum hdmi_clk_refsel refsel;
-
- 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;
- }
- }
+ dss_init_hdmi_ip_ops(&hdmi.ip_data);
return 0;
}
@@ -518,7 +212,7 @@ 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_video_timings temp;
struct hdmi_cm cm = {-1};
DSSDBG("hdmi_get_code\n");
@@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
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;
-
- /* search 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)
{
@@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
}
+unsigned long hdmi_get_pixel_clock(void)
+{
+ /* HDMI Pixel Clock in Mhz */
+ return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000;
+}
+
static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
struct hdmi_pll_info *pi)
{
@@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
* Input clock is predivided by N + 1
* out put of which is reference clk
*/
- pi->regn = dssdev->clocks.hdmi.regn;
- refclk = clkin / (pi->regn + 1);
+ if (dssdev->clocks.hdmi.regn == 0)
+ pi->regn = HDMI_DEFAULT_REGN;
+ else
+ pi->regn = dssdev->clocks.hdmi.regn;
+
+ refclk = clkin / pi->regn;
/*
* multiplier is pixel_clk/ref_clk
* Multiplying by 100 to avoid fractional part removal
*/
pi->regm = (phy * 100 / (refclk)) / 100;
- pi->regm2 = dssdev->clocks.hdmi.regm2;
+
+ if (dssdev->clocks.hdmi.regm2 == 0)
+ pi->regm2 = HDMI_DEFAULT_REGM2;
+ else
+ pi->regm2 = dssdev->clocks.hdmi.regm2;
/*
* fractional multiplier is remainder of the difference between
@@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
* is greater than 1000MHz
*/
pi->dcofreq = phy > 1000 * 100;
- pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10;
+ pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
+
+ /* Set the reference clock to sysclk reference */
+ pi->refsel = HDMI_REFSEL_SYSCLK;
DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
@@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
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;
unsigned long phy;
@@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
if (r)
return r;
- dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
p = &dssdev->panel.timings;
@@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
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);
+ update_hdmi_timings(&hdmi.ip_data.cfg, p, code);
phy = p->pixel_clock;
- hdmi_compute_pll(dssdev, phy, &pll_data);
+ hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
- hdmi_wp_video_start(0);
+ hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
- /* config the PLL and PHY first */
- r = hdmi_pll_program(&pll_data);
+ /* config the PLL and PHY hdmi_set_pll_pwrfirst */
+ r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
if (r) {
DSSDBG("Failed to lock PLL\n");
goto err;
}
- r = hdmi_phy_init();
+ r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
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);
+ hdmi.ip_data.cfg.cm.mode = hdmi.mode;
+ hdmi.ip_data.cfg.cm.code = hdmi.code;
+ hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
/* Make selection of HDMI in DSS */
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
@@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dispc_set_digit_size(dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
- dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
+ hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
- hdmi_wp_video_start(1);
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
return 0;
err:
@@ -1186,14 +397,12 @@ err:
static void hdmi_power_off(struct omap_dss_device *dssdev)
{
- dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
- hdmi_wp_video_start(0);
- hdmi_phy_off();
- hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+ hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
+ hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+ hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
hdmi_runtime_put();
-
- hdmi.edid_set = 0;
}
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
cm = hdmi_get_code(timings);
if (cm.code == -1) {
- DSSERR("Invalid timing entered\n");
return -EINVAL;
}
@@ -1215,12 +423,69 @@ 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;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ int r;
+
+ hdmi_power_off(dssdev);
+
+ r = hdmi_power_on(dssdev);
+ if (r)
+ DSSERR("failed to power on device\n");
+ }
+}
+
+void hdmi_dump_regs(struct seq_file *s)
+{
+ mutex_lock(&hdmi.lock);
+
+ if (hdmi_runtime_get())
+ return;
+
+ hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
+ hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
+ hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
+ hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
+
+ hdmi_runtime_put();
+ mutex_unlock(&hdmi.lock);
+}
+
+int omapdss_hdmi_read_edid(u8 *buf, int len)
+{
+ int r;
+
+ mutex_lock(&hdmi.lock);
+
+ r = hdmi_runtime_get();
+ BUG_ON(r);
+
+ r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
+
+ hdmi_runtime_put();
+ mutex_unlock(&hdmi.lock);
+
+ return r;
+}
+
+bool omapdss_hdmi_detect(void)
+{
+ int r;
+
+ mutex_lock(&hdmi.lock);
+
+ r = hdmi_runtime_get();
+ BUG_ON(r);
+
+ r = hdmi.ip_data.ops->detect(&hdmi.ip_data);
+
+ hdmi_runtime_put();
+ mutex_unlock(&hdmi.lock);
+
+ return r == 1;
}
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
@@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ r = -ENODEV;
+ goto err0;
+ }
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-static void hdmi_wp_audio_config_format(
- struct hdmi_audio_format *aud_fmt)
-{
- u32 r;
-
- DSSDBG("Enter hdmi_wp_audio_config_format\n");
-
- r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
- r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
- r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
- r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
- r = FLD_MOD(r, aud_fmt->type, 4, 4);
- r = FLD_MOD(r, aud_fmt->justification, 3, 3);
- r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
- r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
- r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
-}
-
-static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
-{
- u32 r;
-
- DSSDBG("Enter hdmi_wp_audio_config_dma\n");
-
- r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
- r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
- r = FLD_MOD(r, aud_dma->block_size, 7, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
-
- r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
- r = FLD_MOD(r, aud_dma->mode, 9, 9);
- r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
-}
-
-static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
-{
- u32 r;
-
- /* audio clock recovery parameters */
- r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
- r = FLD_MOD(r, cfg->use_mclk, 2, 2);
- r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
- r = FLD_MOD(r, cfg->cts_mode, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
-
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
-
- if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
- } else {
- /*
- * HDMI IP uses this configuration to divide the MCLK to
- * update CTS value.
- */
- REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
-
- /* Configure clock for audio packets */
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
- cfg->aud_par_busclk, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
- (cfg->aud_par_busclk >> 8), 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
- (cfg->aud_par_busclk >> 16), 7, 0);
- }
-
- /* Override of SPDIF sample frequency with value in I2S_CHST4 */
- REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
-
- /* I2S parameters */
- REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
-
- r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
- r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
- r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
- r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
- r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
- r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
- r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
- r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
- r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
-
- r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
- r = FLD_MOD(r, cfg->freq_sample, 7, 4);
- r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
- r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
-
- REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
-
- /* Audio channels and mode parameters */
- REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
- r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
- r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
- r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
- r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
- r = FLD_MOD(r, cfg->en_spdif, 1, 1);
- hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
-}
-
-static void hdmi_core_audio_infoframe_config(
- struct hdmi_core_infoframe_audio *info_aud)
-{
- u8 val;
- u8 sum = 0, checksum = 0;
-
- /*
- * Set audio info frame type, version and length as
- * described in HDMI 1.4a Section 8.2.2 specification.
- * Checksum calculation is defined in Section 5.3.5.
- */
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
- sum += 0x84 + 0x001 + 0x00a;
-
- val = (info_aud->db1_coding_type << 4)
- | (info_aud->db1_channel_count - 1);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
- sum += val;
-
- val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
- sum += val;
-
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
-
- val = info_aud->db4_channel_alloc;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
- sum += val;
-
- val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
- sum += val;
-
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
- checksum = 0x100 - sum;
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
-
- /*
- * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
- * is available.
- */
-}
-
-static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
-{
- u32 r;
- u32 deep_color = 0;
- u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
-
- if (n == NULL || cts == NULL)
- return -EINVAL;
- /*
- * Obtain current deep color configuration. This needed
- * to calculate the TMDS clock based on the pixel clock.
- */
- r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
- switch (r) {
- case 1: /* No deep color selected */
- deep_color = 100;
- break;
- case 2: /* 10-bit deep color selected */
- deep_color = 125;
- break;
- case 3: /* 12-bit deep color selected */
- deep_color = 150;
- break;
- default:
- return -EINVAL;
- }
-
- switch (sample_freq) {
- case 32000:
- if ((deep_color == 125) && ((pclk == 54054)
- || (pclk == 74250)))
- *n = 8192;
- else
- *n = 4096;
- break;
- case 44100:
- *n = 6272;
- break;
- case 48000:
- if ((deep_color == 125) && ((pclk == 54054)
- || (pclk == 74250)))
- *n = 8192;
- else
- *n = 6144;
- break;
- default:
- *n = 0;
- return -EINVAL;
- }
-
- /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
- *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
-
- return 0;
-}
-
-static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
+ struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
@@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
+ err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts);
if (err < 0)
return err;
@@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
audio_dma.fifo_threshold = 0x20; /* in number of samples */
- hdmi_wp_audio_config_dma(&audio_dma);
- hdmi_wp_audio_config_format(&audio_format);
+ hdmi_wp_audio_config_dma(ip_data, &audio_dma);
+ hdmi_wp_audio_config_format(ip_data, &audio_format);
/*
* I2S config
@@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
/* Use parallel audio interface */
core_cfg.en_parallel_aud_input = true;
- hdmi_core_audio_config(&core_cfg);
+ hdmi_core_audio_config(ip_data, &core_cfg);
/*
* Configure packet
@@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
aud_if_cfg.db5_downmix_inh = false;
aud_if_cfg.db5_lsv = 0;
- hdmi_core_audio_infoframe_config(&aud_if_cfg);
+ hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
return 0;
}
-static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- int err = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
- break;
- default:
- err = -EINVAL;
- }
- return err;
-}
-
static int hdmi_audio_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
hdmi.sys_clk = clk;
- clk = clk_get(&pdev->dev, "dss_48mhz_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get hdmi_clk\n");
- clk_put(hdmi.sys_clk);
- return PTR_ERR(clk);
- }
-
- hdmi.hdmi_clk = clk;
-
return 0;
}
@@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void)
{
if (hdmi.sys_clk)
clk_put(hdmi.sys_clk);
- if (hdmi.hdmi_clk)
- clk_put(hdmi.hdmi_clk);
}
/* HDMI HW IP initialisation */
@@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
}
/* Base address taken from platform */
- hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
- if (!hdmi.base_wp) {
+ hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
+ resource_size(hdmi_mem));
+ if (!hdmi.ip_data.base_wp) {
DSSERR("can't ioremap WP\n");
return -ENOMEM;
}
r = hdmi_get_clocks(pdev);
if (r) {
- iounmap(hdmi.base_wp);
+ iounmap(hdmi.ip_data.base_wp);
return r;
}
pm_runtime_enable(&pdev->dev);
+ hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
+ hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
+ hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
+ hdmi.ip_data.phy_offset = HDMI_PHY;
+
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
@@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
hdmi_put_clocks();
- iounmap(hdmi.base_wp);
+ iounmap(hdmi.ip_data.base_wp);
return 0;
}
static int hdmi_runtime_suspend(struct device *dev)
{
- clk_disable(hdmi.hdmi_clk);
clk_disable(hdmi.sys_clk);
dispc_runtime_put();
@@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev)
clk_enable(hdmi.sys_clk);
- clk_enable(hdmi.hdmi_clk);
return 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 7d4f2bd7c506..533d5dc634d2 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -1,5 +1,5 @@
/*
- * hdmi_omap4_panel.c
+ * hdmi_panel.c
*
* HDMI library support functions for TI OMAP4 processors.
*
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/module.h>
#include <video/omapdss.h>
+#include <linux/slab.h>
#include "dss.h"
@@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
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;
+ dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
dssdev->panel.timings.x_res,
@@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
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);
- }
+ omapdss_hdmi_display_set_timing(dssdev);
mutex_unlock(&hdmi.hdmi_lock);
}
@@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
mutex_lock(&hdmi.hdmi_lock);
r = omapdss_hdmi_display_check_timing(dssdev, timings);
- if (r) {
- DSSERR("Timing cannot be applied\n");
- goto err;
+
+ mutex_unlock(&hdmi.hdmi_lock);
+ return r;
+}
+
+static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
+{
+ int r;
+
+ mutex_lock(&hdmi.hdmi_lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ r = omapdss_hdmi_display_enable(dssdev);
+ if (r)
+ goto err;
+ }
+
+ r = omapdss_hdmi_read_edid(buf, len);
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ omapdss_hdmi_display_disable(dssdev);
+err:
+ mutex_unlock(&hdmi.hdmi_lock);
+
+ return r;
+}
+
+static bool hdmi_detect(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ mutex_lock(&hdmi.hdmi_lock);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ r = omapdss_hdmi_display_enable(dssdev);
+ if (r)
+ goto err;
}
+
+ r = omapdss_hdmi_detect();
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
+
return r;
}
@@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = {
.get_timings = hdmi_get_timings,
.set_timings = hdmi_set_timings,
.check_timings = hdmi_check_timings,
+ .read_edid = hdmi_read_edid,
+ .detect = hdmi_detect,
.driver = {
.name = "hdmi_panel",
.owner = THIS_MODULE,
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 13d72d5c714b..6e63845cc7d7 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -106,7 +106,7 @@ put_device:
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
+ return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
}
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
u32 color;
int r;
- if (sscanf(buf, "%d", &color) != 1)
- return -EINVAL;
+ r = kstrtouint(buf, 0, &color);
+ if (r)
+ return r;
mgr->get_manager_info(mgr, &info);
@@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
+ return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
}
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
u32 key_value;
int r;
- if (sscanf(buf, "%d", &key_value) != 1)
- return -EINVAL;
+ r = kstrtouint(buf, 0, &key_value);
+ if (r)
+ return r;
mgr->get_manager_info(mgr, &info);
@@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
- int enable;
+ bool enable;
int r;
- if (sscanf(buf, "%d", &enable) != 1)
- return -EINVAL;
+ r = strtobool(buf, &enable);
+ if (r)
+ return r;
mgr->get_manager_info(mgr, &info);
- info.trans_enabled = enable ? true : false;
+ info.trans_enabled = enable;
r = mgr->set_manager_info(mgr, &info);
if (r)
@@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
static ssize_t manager_alpha_blending_enabled_show(
struct omap_overlay_manager *mgr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
+ WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ mgr->info.partial_alpha_enabled);
}
static ssize_t manager_alpha_blending_enabled_store(
@@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store(
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
- int enable;
+ bool enable;
int r;
- if (sscanf(buf, "%d", &enable) != 1)
- return -EINVAL;
+ WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+ r = strtobool(buf, &enable);
+ if (r)
+ return r;
mgr->get_manager_info(mgr, &info);
- info.alpha_enabled = enable ? true : false;
+ info.partial_alpha_enabled = enable;
r = mgr->set_manager_info(mgr, &info);
if (r)
@@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
- int v;
int r;
bool enable;
if (!dss_has_feature(FEAT_CPR))
return -ENODEV;
- r = kstrtoint(buf, 0, &v);
+ r = strtobool(buf, &enable);
if (r)
return r;
- enable = !!v;
-
mgr->get_manager_info(mgr, &info);
if (info.cpr_enable == enable)
@@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
return -EINVAL;
}
+ /*
+ * Don't allow currently enabled displays to have the overlay manager
+ * pulled out from underneath them
+ */
+ if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
+ return -EINVAL;
+
mgr->device->manager = NULL;
mgr->device = NULL;
mgr->device_changed = true;
@@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane)
{
struct overlay_cache_data *c;
struct manager_cache_data *mc;
- struct omap_overlay_info *oi;
+ struct omap_overlay_info *oi, new_oi;
struct omap_overlay_manager_info *mi;
u16 outw, outh;
u16 x, y, w, h;
@@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane)
oi = &c->info;
if (!c->enabled) {
- dispc_enable_plane(plane, 0);
+ dispc_ovl_enable(plane, 0);
return 0;
}
@@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane)
/* If the overlay is outside the update region, disable it */
if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
x, y, outw, outh)) {
- dispc_enable_plane(plane, 0);
+ dispc_ovl_enable(plane, 0);
return 0;
}
@@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane)
}
}
- r = dispc_setup_plane(plane,
- paddr,
- oi->screen_width,
- x, y,
- w, h,
- outw, outh,
- oi->color_mode,
- c->ilace,
- oi->rotation_type,
- oi->rotation,
- oi->mirror,
- oi->global_alpha,
- oi->pre_mult_alpha,
- c->channel,
- oi->p_uv_addr);
+ new_oi = *oi;
+
+ /* update new_oi members which could have been possibly updated */
+ new_oi.pos_x = x;
+ new_oi.pos_y = y;
+ new_oi.width = w;
+ new_oi.height = h;
+ new_oi.out_width = outw;
+ new_oi.out_height = outh;
+ new_oi.paddr = paddr;
+ r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
+ c->replication, c->fifo_low, c->fifo_high);
if (r) {
/* this shouldn't happen */
- DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
- dispc_enable_plane(plane, 0);
+ DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
+ dispc_ovl_enable(plane, 0);
return r;
}
- dispc_enable_replication(plane, c->replication);
-
- dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
-
- dispc_enable_plane(plane, 1);
+ dispc_ovl_enable(plane, 1);
return 0;
}
@@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel)
/* picking info from the cache */
mi = &dss_cache.manager_cache[channel].info;
- dispc_set_default_color(channel, mi->default_color);
- dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
- dispc_enable_trans_key(channel, mi->trans_enabled);
- dispc_enable_alpha_blending(channel, mi->alpha_enabled);
+ dispc_mgr_set_default_color(channel, mi->default_color);
+ dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
+ dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
+ dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
if (dss_has_feature(FEAT_CPR)) {
- dispc_enable_cpr(channel, mi->cpr_enable);
- dispc_set_cpr_coef(channel, &mi->cpr_coefs);
+ dispc_mgr_enable_cpr(channel, mi->cpr_enable);
+ dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
}
}
@@ -992,7 +998,7 @@ static int configure_dispc(void)
busy = false;
for (i = 0; i < num_mgrs; i++) {
- mgr_busy[i] = dispc_go_busy(i);
+ mgr_busy[i] = dispc_mgr_go_busy(i);
mgr_go[i] = false;
}
@@ -1053,7 +1059,7 @@ static int configure_dispc(void)
* always be turned off after frame, and new settings will be
* taken in to use at next update */
if (!mc->manual_update)
- dispc_go(i);
+ dispc_mgr_go(i);
}
if (busy)
@@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
u32 irq_mask;
for (i = 0; i < num_mgrs; i++)
- mgr_busy[i] = dispc_go_busy(i);
+ mgr_busy[i] = dispc_mgr_go_busy(i);
spin_lock(&dss_cache.lock);
@@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
/* re-read busy flags */
for (i = 0; i < num_mgrs; i++)
- mgr_busy[i] = dispc_go_busy(i);
+ mgr_busy[i] = dispc_mgr_go_busy(i);
/* keep running as long as there are busy managers, so that
* we can collect overlay-applied information */
@@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
ovl = omap_dss_get_overlay(i);
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
oc = &dss_cache.overlay_cache[ovl->id];
+ if (ovl->manager_changed) {
+ ovl->manager_changed = false;
+ ovl->info_dirty = true;
+ }
+
if (!overlay_enabled(ovl)) {
if (oc->enabled) {
oc->enabled = false;
@@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
list_for_each_entry(mgr, &manager_list, list) {
struct omap_dss_device *dssdev;
- if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
- continue;
-
mc = &dss_cache.manager_cache[mgr->id];
if (mgr->device_changed) {
@@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
ovl = omap_dss_get_overlay(i);
- if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
- continue;
-
oc = &dss_cache.overlay_cache[ovl->id];
if (!oc->enabled)
@@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
dssdev = ovl->manager->device;
- size = dispc_get_plane_fifo_size(ovl->id);
+ size = dispc_ovl_get_fifo_size(ovl->id);
if (use_fifomerge)
size *= 3;
- burst_size = dispc_get_burst_size(ovl->id);
+ burst_size = dispc_ovl_get_burst_size(ovl->id);
switch (dssdev->type) {
case OMAP_DISPLAY_TYPE_DPI:
@@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
static int dss_check_manager(struct omap_overlay_manager *mgr)
{
- /* OMAP supports only graphics source transparency color key and alpha
- * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
-
- if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
- mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
- return -EINVAL;
+ if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
+ /*
+ * OMAP3 supports only graphics source transparency color key
+ * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
+ * Alpha Mode
+ */
+ if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled
+ && mgr->info.trans_key_type !=
+ OMAP_DSS_COLOR_KEY_GFX_DST)
+ return -EINVAL;
+ }
return 0;
}
@@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
static int dss_mgr_enable(struct omap_overlay_manager *mgr)
{
- dispc_enable_channel(mgr->id, 1);
+ dispc_mgr_enable(mgr->id, 1);
return 0;
}
static int dss_mgr_disable(struct omap_overlay_manager *mgr)
{
- dispc_enable_channel(mgr->id, 0);
+ dispc_mgr_enable(mgr->id, 0);
return 0;
}
@@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
mgr->enable = &dss_mgr_enable;
mgr->disable = &dss_mgr_disable;
- mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+ mgr->caps = 0;
mgr->supported_displays =
dss_feat_get_supported_displays(mgr->id);
@@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
}
}
-#ifdef L4_EXAMPLE
- {
- int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
- {
- DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
-
- return 0;
- }
-
- struct omap_overlay_manager *mgr;
- mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
-
- BUG_ON(mgr == NULL);
-
- mgr->name = "l4";
- mgr->supported_displays =
- OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
-
- mgr->set_device = &omap_dss_set_device;
- mgr->unset_device = &omap_dss_unset_device;
- mgr->apply = &omap_dss_mgr_apply_l4;
- mgr->set_manager_info = &omap_dss_mgr_set_info;
- mgr->get_manager_info = &omap_dss_mgr_get_info;
-
- dss_overlay_setup_l4_manager(mgr);
-
- omap_dss_add_overlay_manager(mgr);
-
- r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
- &pdev->dev.kobj, "managerl4");
-
- if (r)
- DSSERR("failed to create sysfs file\n");
- }
-#endif
-
return 0;
}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index c84380c53c39..ab8e40e48759 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
size_t size)
{
- int r, enable;
+ int r;
+ bool enable;
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
- r = kstrtoint(buf, 0, &enable);
+ r = strtobool(buf, &enable);
if (r)
return r;
- info.enabled = !!enable;
+ info.enabled = enable;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
return -ENODEV;
r = kstrtou8(buf, 0, &alpha);
@@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
ovl->get_overlay_info(ovl, &info);
- /* Video1 plane does not support global alpha
- * to always make it 255 completely opaque
- */
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
- ovl->id == OMAP_DSS_VIDEO1)
- info.global_alpha = 255;
- else
- info.global_alpha = alpha;
+ info.global_alpha = alpha;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+ return -ENODEV;
+
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
ovl->get_overlay_info(ovl, &info);
- /* only GFX and Video2 plane support pre alpha multiplied
- * set zero for Video1 plane
- */
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
- ovl->id == OMAP_DSS_VIDEO1)
- info.pre_mult_alpha = 0;
- else
- info.pre_mult_alpha = alpha;
+ info.pre_mult_alpha = alpha;
+
+ r = ovl->set_overlay_info(ovl, &info);
+ if (r)
+ return r;
+
+ if (ovl->manager) {
+ r = ovl->manager->apply(ovl->manager);
+ if (r)
+ return r;
+ }
+
+ return size;
+}
+
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+ const char *buf, size_t size)
+{
+ int r;
+ u8 zorder;
+ struct omap_overlay_info info;
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+ return -ENODEV;
+
+ r = kstrtou8(buf, 0, &zorder);
+ if (r)
+ return r;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ info.zorder = zorder;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
overlay_pre_mult_alpha_show,
overlay_pre_mult_alpha_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+ overlay_zorder_show, overlay_zorder_store);
static struct attribute *overlay_sysfs_attrs[] = {
&overlay_attr_name.attr,
@@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
&overlay_attr_enabled.attr,
&overlay_attr_global_alpha.attr,
&overlay_attr_pre_mult_alpha.attr,
+ &overlay_attr_zorder.attr,
NULL
};
@@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
struct omap_overlay_info *info;
u16 outw, outh;
u16 dw, dh;
+ int i;
if (!dssdev)
return 0;
@@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
return -EINVAL;
}
+ if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
+ if (info->zorder < 0 || info->zorder > 3) {
+ DSSERR("zorder out of range: %d\n",
+ info->zorder);
+ return -EINVAL;
+ }
+ /*
+ * Check that zorder doesn't match with zorder of any other
+ * overlay which is enabled and is also connected to the same
+ * manager
+ */
+ for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+ struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
+
+ if (tmp_ovl->id != ovl->id &&
+ tmp_ovl->manager == ovl->manager &&
+ tmp_ovl->info.enabled == true &&
+ tmp_ovl->info.zorder == info->zorder) {
+ DSSERR("%s and %s have same zorder: %d\n",
+ ovl->name, tmp_ovl->name, info->zorder);
+ return -EINVAL;
+ }
+ }
+ }
+
return 0;
}
@@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
}
ovl->manager = mgr;
+ ovl->manager_changed = true;
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
@@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
- dispc_set_channel_out(ovl->id, mgr->id);
return 0;
}
static int omap_dss_unset_manager(struct omap_overlay *ovl)
{
- int r;
-
if (!ovl->manager) {
DSSERR("failed to detach overlay: manager not set\n");
return -EINVAL;
@@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
return -EINVAL;
}
- r = ovl->wait_for_go(ovl);
- if (r)
- return r;
-
ovl->manager = NULL;
+ ovl->manager_changed = true;
return 0;
}
@@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev)
case 0:
ovl->name = "gfx";
ovl->id = OMAP_DSS_GFX;
- ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
+ ovl->info.zorder = 0;
break;
case 1:
ovl->name = "vid1";
ovl->id = OMAP_DSS_VIDEO1;
- ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
- OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
+ ovl->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
break;
case 2:
ovl->name = "vid2";
ovl->id = OMAP_DSS_VIDEO2;
- ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
- OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
+ ovl->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+ break;
+ case 3:
+ ovl->name = "vid3";
+ ovl->id = OMAP_DSS_VIDEO3;
+ ovl->info.global_alpha = 255;
+ ovl->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
break;
}
@@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev)
ovl->get_overlay_info = &dss_ovl_get_overlay_info;
ovl->wait_for_go = &dss_ovl_wait_for_go;
+ ovl->caps = dss_feat_get_overlay_caps(ovl->id);
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 39f4c597026a..1bd3703e42ff 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
- dispc_set_lcd_size(dssdev->manager->id, width, height);
+ dispc_mgr_set_lcd_size(dssdev->manager->id, width, height);
- dispc_enable_channel(dssdev->manager->id, true);
+ dispc_mgr_enable(dssdev->manager->id, true);
rfbi.framedone_callback = callback;
rfbi.framedone_callback_data = data;
@@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
if (*w == 0 || *h == 0)
return -EINVAL;
- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
- dss_setup_partial_planes(dssdev, x, y, w, h, true);
- dispc_set_lcd_size(dssdev->manager->id, *w, *h);
- }
+ dss_setup_partial_planes(dssdev, x, y, w, h, true);
+ dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
return 0;
}
@@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h,
void (*callback)(void *), void *data)
{
- if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
- rfbi_transfer_area(dssdev, w, h, callback, data);
- } else {
- struct omap_overlay *ovl;
- void __iomem *addr;
- int scr_width;
-
- ovl = dssdev->manager->overlays[0];
- scr_width = ovl->info.screen_width;
- addr = ovl->info.vaddr;
-
- omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
-
- callback(data);
- }
-
+ rfbi_transfer_area(dssdev, w, h, callback, data);
return 0;
}
EXPORT_SYMBOL(omap_rfbi_update);
@@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ return -ENODEV;
+ }
+
r = rfbi_runtime_get();
if (r)
return r;
@@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
goto err1;
}
- dispc_set_lcd_display_type(dssdev->manager->id,
+ dispc_mgr_set_lcd_display_type(dssdev->manager->id,
OMAP_DSS_LCD_DISPLAY_TFT);
- dispc_set_parallel_interface_mode(dssdev->manager->id,
- OMAP_DSS_PARALLELMODE_RFBI);
+ dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI);
+ dispc_mgr_enable_stallmode(dssdev->manager->id, true);
- dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
+ dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
rfbi_configure(dssdev->phy.rfbi.channel,
dssdev->ctrl.pixel_size,
@@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
msleep(10);
- if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
- clk = dss_get_ick();
- else
- clk = clk_get(&pdev->dev, "ick");
+ clk = clk_get(&pdev->dev, "ick");
if (IS_ERR(clk)) {
DSSERR("can't get ick\n");
r = PTR_ERR(clk);
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 3a688c871a45..695dc04cabba 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -35,13 +35,13 @@ static struct {
static void sdi_basic_init(struct omap_dss_device *dssdev)
{
- dispc_set_parallel_interface_mode(dssdev->manager->id,
- OMAP_DSS_PARALLELMODE_BYPASS);
+ dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
+ dispc_mgr_enable_stallmode(dssdev->manager->id, false);
- dispc_set_lcd_display_type(dssdev->manager->id,
+ dispc_mgr_set_lcd_display_type(dssdev->manager->id,
OMAP_DSS_LCD_DISPLAY_TFT);
- dispc_set_tft_data_lines(dssdev->manager->id, 24);
+ dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);
dispc_lcd_enable_signal_polarity(1);
}
@@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
unsigned long pck;
int r;
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ return -ENODEV;
+ }
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
/* 15.5.9.1.2 */
dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
- dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
+ dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
r = dss_calc_clock_div(1, t->pixel_clock * 1000,
@@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
}
- dispc_set_lcd_timings(dssdev->manager->id, t);
+ dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
r = dss_set_clock_div(&dss_cinfo);
if (r)
goto err_set_dss_clock_div;
- r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+ r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
goto err_set_dispc_clock_div;
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
new file mode 100644
index 000000000000..2c3443dabb14
--- /dev/null
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -0,0 +1,138 @@
+/*
+ * ti_hdmi.h
+ *
+ * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor.
+ *
+ * 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 _TI_HDMI_H
+#define _TI_HDMI_H
+
+struct hdmi_ip_data;
+
+enum hdmi_pll_pwr {
+ HDMI_PLLPWRCMD_ALLOFF = 0,
+ HDMI_PLLPWRCMD_PLLONLY = 1,
+ HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
+ HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
+};
+
+enum hdmi_core_hdmi_dvi {
+ HDMI_DVI = 0,
+ HDMI_HDMI = 1
+};
+
+enum hdmi_clk_refsel {
+ HDMI_REFSEL_PCLK = 0,
+ HDMI_REFSEL_REF1 = 1,
+ HDMI_REFSEL_REF2 = 2,
+ HDMI_REFSEL_SYSCLK = 3
+};
+
+struct hdmi_video_timings {
+ u16 x_res;
+ u16 y_res;
+ /* Unit: KHz */
+ u32 pixel_clock;
+ u16 hsw;
+ u16 hfp;
+ u16 hbp;
+ u16 vsw;
+ u16 vfp;
+ u16 vbp;
+};
+
+/* HDMI timing structure */
+struct hdmi_timings {
+ struct hdmi_video_timings timings;
+ int vsync_pol;
+ int hsync_pol;
+};
+
+struct hdmi_cm {
+ int code;
+ int mode;
+};
+
+struct hdmi_config {
+ struct hdmi_timings timings;
+ u16 interlace;
+ struct hdmi_cm cm;
+};
+
+/* HDMI PLL structure */
+struct hdmi_pll_info {
+ u16 regn;
+ u16 regm;
+ u32 regmf;
+ u16 regm2;
+ u16 regsd;
+ u16 dcofreq;
+ enum hdmi_clk_refsel refsel;
+};
+
+struct ti_hdmi_ip_ops {
+
+ void (*video_configure)(struct hdmi_ip_data *ip_data);
+
+ int (*phy_enable)(struct hdmi_ip_data *ip_data);
+
+ void (*phy_disable)(struct hdmi_ip_data *ip_data);
+
+ int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
+
+ bool (*detect)(struct hdmi_ip_data *ip_data);
+
+ int (*pll_enable)(struct hdmi_ip_data *ip_data);
+
+ void (*pll_disable)(struct hdmi_ip_data *ip_data);
+
+ void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
+
+ void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+ void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+ void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+ void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+};
+
+struct hdmi_ip_data {
+ void __iomem *base_wp; /* HDMI wrapper */
+ unsigned long core_sys_offset;
+ unsigned long core_av_offset;
+ unsigned long pll_offset;
+ unsigned long phy_offset;
+ const struct ti_hdmi_ip_ops *ops;
+ struct hdmi_config cfg;
+ struct hdmi_pll_info pll_data;
+};
+int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
+int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
+bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
+int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
new file mode 100644
index 000000000000..e1a6ce518af6
--- /dev/null
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -0,0 +1,1239 @@
+/*
+ * ti_hdmi_4xxx_ip.c
+ *
+ * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
+ * 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/>.
+ */
+
+#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 <linux/seq_file.h>
+
+#include "ti_hdmi_4xxx_ip.h"
+#include "dss.h"
+
+static inline void hdmi_write_reg(void __iomem *base_addr,
+ const u16 idx, u32 val)
+{
+ __raw_writel(val, base_addr + idx);
+}
+
+static inline u32 hdmi_read_reg(void __iomem *base_addr,
+ const u16 idx)
+{
+ return __raw_readl(base_addr + idx);
+}
+
+static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
+{
+ return ip_data->base_wp;
+}
+
+static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
+{
+ return ip_data->base_wp + ip_data->phy_offset;
+}
+
+static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
+{
+ return ip_data->base_wp + ip_data->pll_offset;
+}
+
+static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
+{
+ return ip_data->base_wp + ip_data->core_av_offset;
+}
+
+static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
+{
+ return ip_data->base_wp + ip_data->core_sys_offset;
+}
+
+static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
+ const u16 idx,
+ int b2, int b1, u32 val)
+{
+ u32 t = 0;
+ while (val != REG_GET(base_addr, idx, b2, b1)) {
+ udelay(1);
+ if (t++ > 10000)
+ return !val;
+ }
+ return val;
+}
+
+static int hdmi_pll_init(struct hdmi_ip_data *ip_data)
+{
+ u32 r;
+ void __iomem *pll_base = hdmi_pll_base(ip_data);
+ struct hdmi_pll_info *fmt = &ip_data->pll_data;
+
+ /* PLL start always use manual mode */
+ REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+
+ r = hdmi_read_reg(pll_base, PLLCTRL_CFG1);
+ r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
+ r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
+
+ hdmi_write_reg(pll_base, PLLCTRL_CFG1, r);
+
+ r = hdmi_read_reg(pll_base, 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 */
+ r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
+
+ if (fmt->dcofreq) {
+ /* divider programming for frequency beyond 1000Mhz */
+ REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 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(pll_base, PLLCTRL_CFG2, r);
+
+ r = hdmi_read_reg(pll_base, PLLCTRL_CFG4);
+ r = FLD_MOD(r, fmt->regm2, 24, 18);
+ r = FLD_MOD(r, fmt->regmf, 17, 0);
+
+ hdmi_write_reg(pll_base, PLLCTRL_CFG4, r);
+
+ /* go now */
+ REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0);
+
+ /* wait for bit change */
+ if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO,
+ 0, 0, 1) != 1) {
+ pr_err("PLL GO bit not set\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Wait till the lock bit is set in PLL status */
+ if (hdmi_wait_for_bit_change(pll_base,
+ PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+ pr_err("cannot lock PLL\n");
+ pr_err("CFG1 0x%x\n",
+ hdmi_read_reg(pll_base, PLLCTRL_CFG1));
+ pr_err("CFG2 0x%x\n",
+ hdmi_read_reg(pll_base, PLLCTRL_CFG2));
+ pr_err("CFG4 0x%x\n",
+ hdmi_read_reg(pll_base, PLLCTRL_CFG4));
+ return -ETIMEDOUT;
+ }
+
+ pr_debug("PLL locked!\n");
+
+ return 0;
+}
+
+/* PHY_PWR_CMD */
+static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
+{
+ /* Command for power control of HDMI PHY */
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
+
+ /* Status of the power control of HDMI PHY */
+ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
+ HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
+ pr_err("Failed to set PHY power mode to %d\n", val);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+/* PLL_PWR_CMD */
+static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
+{
+ /* Command for power control of HDMI PLL */
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
+
+ /* wait till PHY_PWR_STATUS is set */
+ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
+ 1, 0, val) != val) {
+ pr_err("Failed to set PLL_PWR_STATUS\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
+{
+ /* SYSRESET controlled by power FSM */
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+
+ /* READ 0x0 reset is in progress */
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+ PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
+ pr_err("Failed to sysreset PLL\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data)
+{
+ u16 r = 0;
+
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+ if (r)
+ return r;
+
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+ if (r)
+ return r;
+
+ r = hdmi_pll_reset(ip_data);
+ if (r)
+ return r;
+
+ r = hdmi_pll_init(ip_data);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
+{
+ hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+}
+
+int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
+{
+ u16 r = 0;
+ void __iomem *phy_base = hdmi_phy_base(ip_data);
+
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+ if (r)
+ return r;
+
+ r = hdmi_set_phy_pwr(ip_data, 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(phy_base, 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(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+
+ /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
+ hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+
+ /* Setup max LDO voltage */
+ REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+
+ /* Write to phy address 3 to change the polarity control */
+ REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+
+ return 0;
+}
+
+void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
+{
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+}
+
+static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
+{
+ void __iomem *base = hdmi_core_sys_base(ip_data);
+
+ /* Turn on CLK for DDC */
+ REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
+
+ /* IN_PROG */
+ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
+ /* Abort transaction */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
+ /* IN_PROG */
+ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+ 4, 4, 0) != 0) {
+ DSSERR("Timeout aborting DDC transaction\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ /* Clk SCL Devices */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_IN_PROG */
+ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+ 4, 4, 0) != 0) {
+ DSSERR("Timeout starting SCL clock\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Clear FIFO */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_IN_PROG */
+ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+ 4, 4, 0) != 0) {
+ DSSERR("Timeout clearing DDC fifo\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
+ u8 *pedid, int ext)
+{
+ void __iomem *base = hdmi_core_sys_base(ip_data);
+ u32 i;
+ char checksum;
+ u32 offset = 0;
+
+ /* HDMI_CORE_DDC_STATUS_IN_PROG */
+ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+ 4, 4, 0) != 0) {
+ DSSERR("Timeout waiting DDC to be ready\n");
+ return -ETIMEDOUT;
+ }
+
+ if (ext % 2 != 0)
+ offset = 0x80;
+
+ /* Load Segment Address Register */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
+
+ /* Load Slave Address Register */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+
+ /* Load Offset Address Register */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+
+ /* Load Byte Count */
+ REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+ REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+
+ /* Set DDC_CMD */
+ if (ext)
+ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+ else
+ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_BUS_LOW */
+ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
+ pr_err("I2C Bus Low?\n");
+ return -EIO;
+ }
+ /* HDMI_CORE_DDC_STATUS_NO_ACK */
+ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
+ pr_err("I2C No Ack\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < 0x80; ++i) {
+ int t;
+
+ /* IN_PROG */
+ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
+ DSSERR("operation stopped when reading edid\n");
+ return -EIO;
+ }
+
+ t = 0;
+ /* FIFO_EMPTY */
+ while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
+ if (t++ > 10000) {
+ DSSERR("timeout reading edid\n");
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+
+ pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
+ }
+
+ checksum = 0;
+ for (i = 0; i < 0x80; ++i)
+ checksum += pedid[i];
+
+ if (checksum != 0) {
+ pr_err("E-EDID checksum failed!!\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data,
+ u8 *edid, int len)
+{
+ int r, l;
+
+ if (len < 128)
+ return -EINVAL;
+
+ r = hdmi_core_ddc_init(ip_data);
+ if (r)
+ return r;
+
+ r = hdmi_core_ddc_edid(ip_data, edid, 0);
+ if (r)
+ return r;
+
+ l = 128;
+
+ if (len >= 128 * 2 && edid[0x7e] > 0) {
+ r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
+ if (r)
+ return r;
+ l += 128;
+ }
+
+ return l;
+}
+
+bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data)
+{
+ int r;
+
+ void __iomem *base = hdmi_core_sys_base(ip_data);
+
+ /* HPD */
+ r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1);
+
+ return r == 1;
+}
+
+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)
+{
+ pr_debug("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(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_powerdown_disable\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_swreset_release\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_swreset_assert\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+}
+
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_video_config *cfg)
+{
+ u32 r = 0;
+ void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+
+ /* sys_ctrl1 default configuration not tunable */
+ r = hdmi_read_reg(core_sys_base, 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(core_sys_base, HDMI_CORE_CTRL1, r);
+
+ REG_FLD_MOD(core_sys_base,
+ HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+
+ /* Vid_Mode */
+ r = hdmi_read_reg(core_sys_base, 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(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
+
+ /* HDMI_Ctrl */
+ r = hdmi_read_reg(hdmi_av_base(ip_data), 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_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
+
+ /* TMDS_CTRL */
+ REG_FLD_MOD(core_sys_base,
+ HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
+}
+
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_infoframe_avi info_avi)
+{
+ u32 val;
+ char sum = 0, checksum = 0;
+ void __iomem *av_base = hdmi_av_base(ip_data);
+
+ sum += 0x82 + 0x002 + 0x00D;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
+ hdmi_write_reg(av_base, 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(av_base, 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(av_base, 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(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
+ sum += val;
+
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
+ info_avi.db4_videocode);
+ sum += info_avi.db4_videocode;
+
+ val = info_avi.db5_pixel_repeat;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
+ sum += val;
+
+ val = info_avi.db6_7_line_eoftop & 0x00FF;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
+ sum += val;
+
+ val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
+ sum += val;
+
+ val = info_avi.db8_9_line_sofbottom & 0x00FF;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
+ sum += val;
+
+ val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
+ sum += val;
+
+ val = info_avi.db10_11_pixel_eofleft & 0x00FF;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
+ sum += val;
+
+ val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
+ sum += val;
+
+ val = info_avi.db12_13_pixel_sofright & 0x00FF;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
+ sum += val;
+
+ val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
+ sum += val;
+
+ checksum = 0x100 - sum;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
+}
+
+static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_packet_enable_repeat repeat_cfg)
+{
+ /* enable/repeat the infoframe */
+ hdmi_write_reg(hdmi_av_base(ip_data), 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_av_base(ip_data), 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)
+{
+ pr_debug("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 */
+
+}
+
+void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
+{
+ REG_FLD_MOD(hdmi_wp_base(ip_data), 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)
+{
+ pr_debug("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_ip_data *ip_data,
+ struct hdmi_video_format *video_fmt)
+{
+ u32 l = 0;
+
+ REG_FLD_MOD(hdmi_wp_base(ip_data), 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_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
+}
+
+static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
+ struct hdmi_video_interface *video_int)
+{
+ u32 r;
+ pr_debug("Enter hdmi_wp_video_config_interface\n");
+
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), 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_base(ip_data), HDMI_WP_VIDEO_CFG, r);
+}
+
+static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
+ struct omap_video_timings *timings)
+{
+ u32 timing_h = 0;
+ u32 timing_v = 0;
+
+ pr_debug("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_base(ip_data), 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_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
+}
+
+void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
+{
+ /* 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;
+ struct hdmi_config *cfg = &ip_data->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(ip_data, &video_timing);
+
+ /* video config */
+ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+
+ hdmi_wp_video_config_format(ip_data, &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(ip_data, &video_interface);
+
+ /*
+ * configure core video part
+ * set software reset in the core
+ */
+ hdmi_core_swreset_assert(ip_data);
+
+ /* power down off */
+ hdmi_core_powerdown_disable(ip_data);
+
+ v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
+ v_core_cfg.hdmi_dvi = cfg->cm.mode;
+
+ hdmi_core_video_config(ip_data, &v_core_cfg);
+
+ /* release software reset in the core */
+ hdmi_core_swreset_release(ip_data);
+
+ /*
+ * 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(ip_data, 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(ip_data, repeat_cfg);
+}
+
+void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\
+ hdmi_read_reg(hdmi_wp_base(ip_data), r))
+
+ DUMPREG(HDMI_WP_REVISION);
+ DUMPREG(HDMI_WP_SYSCONFIG);
+ DUMPREG(HDMI_WP_IRQSTATUS_RAW);
+ DUMPREG(HDMI_WP_IRQSTATUS);
+ DUMPREG(HDMI_WP_PWR_CTRL);
+ DUMPREG(HDMI_WP_IRQENABLE_SET);
+ DUMPREG(HDMI_WP_VIDEO_CFG);
+ DUMPREG(HDMI_WP_VIDEO_SIZE);
+ DUMPREG(HDMI_WP_VIDEO_TIMING_H);
+ DUMPREG(HDMI_WP_VIDEO_TIMING_V);
+ DUMPREG(HDMI_WP_WP_CLK);
+ DUMPREG(HDMI_WP_AUDIO_CFG);
+ DUMPREG(HDMI_WP_AUDIO_CFG2);
+ DUMPREG(HDMI_WP_AUDIO_CTRL);
+ DUMPREG(HDMI_WP_AUDIO_DATA);
+}
+
+void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
+ hdmi_read_reg(hdmi_pll_base(ip_data), r))
+
+ DUMPPLL(PLLCTRL_PLL_CONTROL);
+ DUMPPLL(PLLCTRL_PLL_STATUS);
+ DUMPPLL(PLLCTRL_PLL_GO);
+ DUMPPLL(PLLCTRL_CFG1);
+ DUMPPLL(PLLCTRL_CFG2);
+ DUMPPLL(PLLCTRL_CFG3);
+ DUMPPLL(PLLCTRL_CFG4);
+}
+
+void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+ int i;
+
+#define CORE_REG(i, name) name(i)
+#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
+ hdmi_read_reg(hdmi_pll_base(ip_data), r))
+#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
+ (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+ hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r)))
+
+ DUMPCORE(HDMI_CORE_SYS_VND_IDL);
+ DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
+ DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
+ DUMPCORE(HDMI_CORE_SYS_DEV_REV);
+ DUMPCORE(HDMI_CORE_SYS_SRST);
+ DUMPCORE(HDMI_CORE_CTRL1);
+ DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
+ DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
+ DUMPCORE(HDMI_CORE_SYS_VID_MODE);
+ DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
+ DUMPCORE(HDMI_CORE_SYS_INTR1);
+ DUMPCORE(HDMI_CORE_SYS_INTR2);
+ DUMPCORE(HDMI_CORE_SYS_INTR3);
+ DUMPCORE(HDMI_CORE_SYS_INTR4);
+ DUMPCORE(HDMI_CORE_SYS_UMASK1);
+ DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
+ DUMPCORE(HDMI_CORE_SYS_DE_DLY);
+ DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
+ DUMPCORE(HDMI_CORE_SYS_DE_TOP);
+ DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
+ DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
+ DUMPCORE(HDMI_CORE_SYS_DE_LINL);
+ DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
+
+ DUMPCORE(HDMI_CORE_DDC_CMD);
+ DUMPCORE(HDMI_CORE_DDC_STATUS);
+ DUMPCORE(HDMI_CORE_DDC_ADDR);
+ DUMPCORE(HDMI_CORE_DDC_OFFSET);
+ DUMPCORE(HDMI_CORE_DDC_COUNT1);
+ DUMPCORE(HDMI_CORE_DDC_COUNT2);
+ DUMPCORE(HDMI_CORE_DDC_DATA);
+ DUMPCORE(HDMI_CORE_DDC_SEGM);
+
+ DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
+ DUMPCORE(HDMI_CORE_AV_DPD);
+ DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
+ DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
+ DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
+ DUMPCORE(HDMI_CORE_AV_AVI_VERS);
+ DUMPCORE(HDMI_CORE_AV_AVI_LEN);
+ DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
+
+ for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE);
+
+ for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE);
+
+ for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE);
+
+ for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE);
+
+ for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE);
+
+ for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
+ DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE);
+
+ DUMPCORE(HDMI_CORE_AV_ACR_CTRL);
+ DUMPCORE(HDMI_CORE_AV_FREQ_SVAL);
+ DUMPCORE(HDMI_CORE_AV_N_SVAL1);
+ DUMPCORE(HDMI_CORE_AV_N_SVAL2);
+ DUMPCORE(HDMI_CORE_AV_N_SVAL3);
+ DUMPCORE(HDMI_CORE_AV_CTS_SVAL1);
+ DUMPCORE(HDMI_CORE_AV_CTS_SVAL2);
+ DUMPCORE(HDMI_CORE_AV_CTS_SVAL3);
+ DUMPCORE(HDMI_CORE_AV_CTS_HVAL1);
+ DUMPCORE(HDMI_CORE_AV_CTS_HVAL2);
+ DUMPCORE(HDMI_CORE_AV_CTS_HVAL3);
+ DUMPCORE(HDMI_CORE_AV_AUD_MODE);
+ DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL);
+ DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS);
+ DUMPCORE(HDMI_CORE_AV_SWAP_I2S);
+ DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH);
+ DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP);
+ DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL);
+ DUMPCORE(HDMI_CORE_AV_I2S_CHST0);
+ DUMPCORE(HDMI_CORE_AV_I2S_CHST1);
+ DUMPCORE(HDMI_CORE_AV_I2S_CHST2);
+ DUMPCORE(HDMI_CORE_AV_I2S_CHST4);
+ DUMPCORE(HDMI_CORE_AV_I2S_CHST5);
+ DUMPCORE(HDMI_CORE_AV_ASRC);
+ DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN);
+ DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
+ DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT);
+ DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
+ DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
+ DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
+ DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL);
+ DUMPCORE(HDMI_CORE_AV_DPD);
+ DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
+ DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
+ DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
+ DUMPCORE(HDMI_CORE_AV_AVI_VERS);
+ DUMPCORE(HDMI_CORE_AV_AVI_LEN);
+ DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
+ DUMPCORE(HDMI_CORE_AV_SPD_TYPE);
+ DUMPCORE(HDMI_CORE_AV_SPD_VERS);
+ DUMPCORE(HDMI_CORE_AV_SPD_LEN);
+ DUMPCORE(HDMI_CORE_AV_SPD_CHSUM);
+ DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE);
+ DUMPCORE(HDMI_CORE_AV_AUDIO_VERS);
+ DUMPCORE(HDMI_CORE_AV_AUDIO_LEN);
+ DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM);
+ DUMPCORE(HDMI_CORE_AV_MPEG_TYPE);
+ DUMPCORE(HDMI_CORE_AV_MPEG_VERS);
+ DUMPCORE(HDMI_CORE_AV_MPEG_LEN);
+ DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM);
+ DUMPCORE(HDMI_CORE_AV_CP_BYTE1);
+ DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID);
+}
+
+void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
+ hdmi_read_reg(hdmi_phy_base(ip_data), r))
+
+ DUMPPHY(HDMI_TXPHY_TX_CTRL);
+ DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
+ DUMPPHY(HDMI_TXPHY_POWER_CTRL);
+ DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
+}
+
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_format *aud_fmt)
+{
+ u32 r;
+
+ DSSDBG("Enter hdmi_wp_audio_config_format\n");
+
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG);
+ r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
+ r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+ r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
+ r = FLD_MOD(r, aud_fmt->type, 4, 4);
+ r = FLD_MOD(r, aud_fmt->justification, 3, 3);
+ r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
+ r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
+ r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
+}
+
+void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_dma *aud_dma)
+{
+ u32 r;
+
+ DSSDBG("Enter hdmi_wp_audio_config_dma\n");
+
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2);
+ r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
+ r = FLD_MOD(r, aud_dma->block_size, 7, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r);
+
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL);
+ r = FLD_MOD(r, aud_dma->mode, 9, 9);
+ r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
+}
+
+void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_audio_config *cfg)
+{
+ u32 r;
+ void __iomem *av_base = hdmi_av_base(ip_data);
+
+ /* audio clock recovery parameters */
+ r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
+ r = FLD_MOD(r, cfg->use_mclk, 2, 2);
+ r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
+ r = FLD_MOD(r, cfg->cts_mode, 0, 0);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
+
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
+
+ if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
+ REG_FLD_MOD(av_base,
+ HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
+ REG_FLD_MOD(av_base,
+ HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
+ } else {
+ /*
+ * HDMI IP uses this configuration to divide the MCLK to
+ * update CTS value.
+ */
+ REG_FLD_MOD(av_base,
+ HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+
+ /* Configure clock for audio packets */
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
+ cfg->aud_par_busclk, 7, 0);
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
+ (cfg->aud_par_busclk >> 8), 7, 0);
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
+ (cfg->aud_par_busclk >> 16), 7, 0);
+ }
+
+ /* Override of SPDIF sample frequency with value in I2S_CHST4 */
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
+ cfg->fs_override, 1, 1);
+
+ /* I2S parameters */
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4,
+ cfg->freq_sample, 3, 0);
+
+ r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
+ r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
+ r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
+ r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
+ r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
+ r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
+ r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
+ r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
+ r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
+
+ r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5);
+ r = FLD_MOD(r, cfg->freq_sample, 7, 4);
+ r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
+ r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r);
+
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
+ cfg->i2s_cfg.in_length_bits, 3, 0);
+
+ /* Audio channels and mode parameters */
+ REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
+ r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
+ r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
+ r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
+ r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
+ r = FLD_MOD(r, cfg->en_spdif, 1, 1);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
+}
+
+void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_infoframe_audio *info_aud)
+{
+ u8 val;
+ u8 sum = 0, checksum = 0;
+ void __iomem *av_base = hdmi_av_base(ip_data);
+
+ /*
+ * Set audio info frame type, version and length as
+ * described in HDMI 1.4a Section 8.2.2 specification.
+ * Checksum calculation is defined in Section 5.3.5.
+ */
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
+ sum += 0x84 + 0x001 + 0x00a;
+
+ val = (info_aud->db1_coding_type << 4)
+ | (info_aud->db1_channel_count - 1);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val);
+ sum += val;
+
+ val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val);
+ sum += val;
+
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
+
+ val = info_aud->db4_channel_alloc;
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val);
+ sum += val;
+
+ val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val);
+ sum += val;
+
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
+ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
+
+ checksum = 0x100 - sum;
+ hdmi_write_reg(av_base,
+ HDMI_CORE_AV_AUDIO_CHSUM, checksum);
+
+ /*
+ * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
+ * is available.
+ */
+}
+
+int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
+ u32 sample_freq, u32 *n, u32 *cts)
+{
+ u32 r;
+ u32 deep_color = 0;
+ u32 pclk = ip_data->cfg.timings.timings.pixel_clock;
+
+ if (n == NULL || cts == NULL)
+ return -EINVAL;
+ /*
+ * Obtain current deep color configuration. This needed
+ * to calculate the TMDS clock based on the pixel clock.
+ */
+ r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0);
+ switch (r) {
+ case 1: /* No deep color selected */
+ deep_color = 100;
+ break;
+ case 2: /* 10-bit deep color selected */
+ deep_color = 125;
+ break;
+ case 3: /* 12-bit deep color selected */
+ deep_color = 150;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (sample_freq) {
+ case 32000:
+ if ((deep_color == 125) && ((pclk == 54054)
+ || (pclk == 74250)))
+ *n = 8192;
+ else
+ *n = 4096;
+ break;
+ case 44100:
+ *n = 6272;
+ break;
+ case 48000:
+ if ((deep_color == 125) && ((pclk == 54054)
+ || (pclk == 74250)))
+ *n = 8192;
+ else
+ *n = 6144;
+ break;
+ default:
+ *n = 0;
+ return -EINVAL;
+ }
+
+ /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
+ *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
+
+ return 0;
+}
+
+int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
+ struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ int err = 0;
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 1, 31, 31);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 1, 30, 30);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 0, 30, 30);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 0, 31, 31);
+ break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+#endif
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index c885f9cb0659..204095632d27 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -1,7 +1,7 @@
/*
- * hdmi.h
+ * ti_hdmi_4xxx_ip.h
*
- * HDMI driver definition for TI OMAP4 processors.
+ * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
*
@@ -18,202 +18,177 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _OMAP4_DSS_HDMI_H_
-#define _OMAP4_DSS_HDMI_H_
+#ifndef _HDMI_TI_4xxx_H_
+#define _HDMI_TI_4xxx_H_
#include <linux/string.h>
#include <video/omapdss.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 })
+#include "ti_hdmi.h"
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#endif
/* 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)
-#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80)
-#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84)
-#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88)
-#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
+
+#define HDMI_WP_REVISION 0x0
+#define HDMI_WP_SYSCONFIG 0x10
+#define HDMI_WP_IRQSTATUS_RAW 0x24
+#define HDMI_WP_IRQSTATUS 0x28
+#define HDMI_WP_PWR_CTRL 0x40
+#define HDMI_WP_IRQENABLE_SET 0x2C
+#define HDMI_WP_VIDEO_CFG 0x50
+#define HDMI_WP_VIDEO_SIZE 0x60
+#define HDMI_WP_VIDEO_TIMING_H 0x68
+#define HDMI_WP_VIDEO_TIMING_V 0x6C
+#define HDMI_WP_WP_CLK 0x70
+#define HDMI_WP_AUDIO_CFG 0x80
+#define HDMI_WP_AUDIO_CFG2 0x84
+#define HDMI_WP_AUDIO_CTRL 0x88
+#define HDMI_WP_AUDIO_DATA 0x8C
/* 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_SYS_VND_IDL 0x0
+#define HDMI_CORE_SYS_DEV_IDL 0x8
+#define HDMI_CORE_SYS_DEV_IDH 0xC
+#define HDMI_CORE_SYS_DEV_REV 0x10
+#define HDMI_CORE_SYS_SRST 0x14
+#define HDMI_CORE_CTRL1 0x20
+#define HDMI_CORE_SYS_SYS_STAT 0x24
+#define HDMI_CORE_SYS_VID_ACEN 0x124
+#define HDMI_CORE_SYS_VID_MODE 0x128
+#define HDMI_CORE_SYS_INTR_STATE 0x1C0
+#define HDMI_CORE_SYS_INTR1 0x1C4
+#define HDMI_CORE_SYS_INTR2 0x1C8
+#define HDMI_CORE_SYS_INTR3 0x1CC
+#define HDMI_CORE_SYS_INTR4 0x1D0
+#define HDMI_CORE_SYS_UMASK1 0x1D4
+#define HDMI_CORE_SYS_TMDS_CTRL 0x208
+#define HDMI_CORE_SYS_DE_DLY 0xC8
+#define HDMI_CORE_SYS_DE_CTRL 0xCC
+#define HDMI_CORE_SYS_DE_TOP 0xD0
+#define HDMI_CORE_SYS_DE_CNTL 0xD8
+#define HDMI_CORE_SYS_DE_CNTH 0xDC
+#define HDMI_CORE_SYS_DE_LINL 0xE0
+#define HDMI_CORE_SYS_DE_LINH_1 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)
+#define HDMI_CORE_DDC_CMD 0x3CC
+#define HDMI_CORE_DDC_STATUS 0x3C8
+#define HDMI_CORE_DDC_ADDR 0x3B4
+#define HDMI_CORE_DDC_OFFSET 0x3BC
+#define HDMI_CORE_DDC_COUNT1 0x3C0
+#define HDMI_CORE_DDC_COUNT2 0x3C4
+#define HDMI_CORE_DDC_DATA 0x3D0
+#define HDMI_CORE_DDC_SEGM 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_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210)
-#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10)
-#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_AUDIO_TYPE HDMI_CORE_AV_REG(0x200)
-#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204)
-#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208)
-#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C)
-#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_HDMI_CTRL 0xBC
+#define HDMI_CORE_AV_DPD 0xF4
+#define HDMI_CORE_AV_PB_CTRL1 0xF8
+#define HDMI_CORE_AV_PB_CTRL2 0xFC
+#define HDMI_CORE_AV_AVI_TYPE 0x100
+#define HDMI_CORE_AV_AVI_VERS 0x104
+#define HDMI_CORE_AV_AVI_LEN 0x108
+#define HDMI_CORE_AV_AVI_CHSUM 0x10C
+#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
+#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
+#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
+#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
+#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
+#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
+#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
+#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
+#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
+#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
+#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
+#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
+#define HDMI_CORE_AV_ACR_CTRL 0x4
+#define HDMI_CORE_AV_FREQ_SVAL 0x8
+#define HDMI_CORE_AV_N_SVAL1 0xC
+#define HDMI_CORE_AV_N_SVAL2 0x10
+#define HDMI_CORE_AV_N_SVAL3 0x14
+#define HDMI_CORE_AV_CTS_SVAL1 0x18
+#define HDMI_CORE_AV_CTS_SVAL2 0x1C
+#define HDMI_CORE_AV_CTS_SVAL3 0x20
+#define HDMI_CORE_AV_CTS_HVAL1 0x24
+#define HDMI_CORE_AV_CTS_HVAL2 0x28
+#define HDMI_CORE_AV_CTS_HVAL3 0x2C
+#define HDMI_CORE_AV_AUD_MODE 0x50
+#define HDMI_CORE_AV_SPDIF_CTRL 0x54
+#define HDMI_CORE_AV_HW_SPDIF_FS 0x60
+#define HDMI_CORE_AV_SWAP_I2S 0x64
+#define HDMI_CORE_AV_SPDIF_ERTH 0x6C
+#define HDMI_CORE_AV_I2S_IN_MAP 0x70
+#define HDMI_CORE_AV_I2S_IN_CTRL 0x74
+#define HDMI_CORE_AV_I2S_CHST0 0x78
+#define HDMI_CORE_AV_I2S_CHST1 0x7C
+#define HDMI_CORE_AV_I2S_CHST2 0x80
+#define HDMI_CORE_AV_I2S_CHST4 0x84
+#define HDMI_CORE_AV_I2S_CHST5 0x88
+#define HDMI_CORE_AV_ASRC 0x8C
+#define HDMI_CORE_AV_I2S_IN_LEN 0x90
+#define HDMI_CORE_AV_HDMI_CTRL 0xBC
+#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4
+#define HDMI_CORE_AV_TEST_TXCTRL 0xF0
+#define HDMI_CORE_AV_DPD 0xF4
+#define HDMI_CORE_AV_PB_CTRL1 0xF8
+#define HDMI_CORE_AV_PB_CTRL2 0xFC
+#define HDMI_CORE_AV_AVI_TYPE 0x100
+#define HDMI_CORE_AV_AVI_VERS 0x104
+#define HDMI_CORE_AV_AVI_LEN 0x108
+#define HDMI_CORE_AV_AVI_CHSUM 0x10C
+#define HDMI_CORE_AV_SPD_TYPE 0x180
+#define HDMI_CORE_AV_SPD_VERS 0x184
+#define HDMI_CORE_AV_SPD_LEN 0x188
+#define HDMI_CORE_AV_SPD_CHSUM 0x18C
+#define HDMI_CORE_AV_AUDIO_TYPE 0x200
+#define HDMI_CORE_AV_AUDIO_VERS 0x204
+#define HDMI_CORE_AV_AUDIO_LEN 0x208
+#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
+#define HDMI_CORE_AV_MPEG_TYPE 0x280
+#define HDMI_CORE_AV_MPEG_VERS 0x284
+#define HDMI_CORE_AV_MPEG_LEN 0x288
+#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
+#define HDMI_CORE_AV_CP_BYTE1 0x37C
+#define HDMI_CORE_AV_CEC_ADDR_ID 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)
+#define PLLCTRL_PLL_CONTROL 0x0
+#define PLLCTRL_PLL_STATUS 0x4
+#define PLLCTRL_PLL_GO 0x8
+#define PLLCTRL_CFG1 0xC
+#define PLLCTRL_CFG2 0x10
+#define PLLCTRL_CFG3 0x14
+#define PLLCTRL_CFG4 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 HDMI_TXPHY_TX_CTRL 0x0
+#define HDMI_TXPHY_DIGITAL_CTRL 0x4
+#define HDMI_TXPHY_POWER_CTRL 0x8
+#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
-#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;
-};
+#define REG_FLD_MOD(base, idx, val, start, end) \
+ hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
+ val, start, end))
+#define REG_GET(base, idx, start, end) \
+ FLD_GET(hdmi_read_reg(base, idx), start, end)
enum hdmi_phy_pwr {
HDMI_PHYPWRCMD_OFF = 0,
@@ -221,20 +196,6 @@ enum hdmi_phy_pwr {
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,
@@ -263,11 +224,6 @@ enum hdmi_core_packet_mode {
HDMI_PACKETMODE48BITPERPIXEL = 7
};
-enum hdmi_core_hdmi_dvi {
- HDMI_DVI = 0,
- HDMI_HDMI = 1
-};
-
enum hdmi_core_tclkselclkmult {
HDMI_FPLL05IDCK = 0,
HDMI_FPLL10IDCK = 1,
@@ -495,40 +451,40 @@ struct hdmi_core_video_config {
* details about infoframe databytes
*/
struct hdmi_core_infoframe_avi {
+ /* Y0, Y1 rgb,yCbCr */
u8 db1_format;
- /* Y0, Y1 rgb,yCbCr */
+ /* A0 Active information Present */
u8 db1_active_info;
- /* A0 Active information Present */
+ /* B0, B1 Bar info data valid */
u8 db1_bar_info_dv;
- /* B0, B1 Bar info data valid */
+ /* S0, S1 scan information */
u8 db1_scan_info;
- /* S0, S1 scan information */
+ /* C0, C1 colorimetry */
u8 db2_colorimetry;
- /* C0, C1 colorimetry */
+ /* M0, M1 Aspect ratio (4:3, 16:9) */
u8 db2_aspect_ratio;
- /* M0, M1 Aspect ratio (4:3, 16:9) */
+ /* R0...R3 Active format aspect ratio */
u8 db2_active_fmt_ar;
- /* R0...R3 Active format aspect ratio */
+ /* ITC IT content. */
u8 db3_itc;
- /* ITC IT content. */
+ /* EC0, EC1, EC2 Extended colorimetry */
u8 db3_ec;
- /* EC0, EC1, EC2 Extended colorimetry */
+ /* Q1, Q0 Quantization range */
u8 db3_q_range;
- /* Q1, Q0 Quantization range */
+ /* SC1, SC0 Non-uniform picture scaling */
u8 db3_nup_scaling;
- /* SC1, SC0 Non-uniform picture scaling */
+ /* VIC0..6 Video format identification */
u8 db4_videocode;
- /* VIC0..6 Video format identification */
+ /* PR0..PR3 Pixel repetition factor */
u8 db5_pixel_repeat;
- /* PR0..PR3 Pixel repetition factor */
+ /* Line number end of top bar */
u16 db6_7_line_eoftop;
- /* Line number end of top bar */
+ /* Line number start of bottom bar */
u16 db8_9_line_sofbottom;
- /* Line number start of bottom bar */
+ /* Pixel number end of left bar */
u16 db10_11_pixel_eofleft;
- /* Pixel number end of left bar */
+ /* Pixel number start of right bar */
u16 db12_13_pixel_sofright;
- /* Pixel number start of right bar */
};
/*
* Refer to section 8.2 in HDMI 1.3 specification for
@@ -568,17 +524,6 @@ struct hdmi_video_interface {
int tm; /* Timing mode */
};
-struct hdmi_cm {
- int code;
- int mode;
-};
-
-struct hdmi_config {
- struct hdmi_timings timings;
- u16 interlace;
- struct hdmi_cm cm;
-};
-
struct hdmi_audio_format {
enum hdmi_stereo_channels stereo_channels;
u8 active_chnnls_msk;
@@ -628,4 +573,21 @@ struct hdmi_core_audio_config {
bool en_parallel_aud_input;
bool en_spdif;
};
+
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
+ struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai);
+int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
+ u32 sample_freq, u32 *n, u32 *cts);
+void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_infoframe_audio *info_aud);
+void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_audio_config *cfg);
+void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_dma *aud_dma);
+void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_format *aud_fmt);
+#endif
#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 173c66430dad..7533458ba4d2 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -295,7 +295,6 @@ static struct {
u32 wss_data;
struct regulator *vdda_dac_reg;
- struct clk *tv_clk;
struct clk *tv_dac_clk;
} venc;
@@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev)
regulator_disable(venc.vdda_dac_reg);
}
-
-
-
+unsigned long venc_get_pixel_clock(void)
+{
+ /* VENC Pixel Clock in Mhz */
+ return 13500000;
+}
/* driver */
static int venc_panel_probe(struct omap_dss_device *dssdev)
@@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
- clk = clk_get(&pdev->dev, "fck");
- if (IS_ERR(clk)) {
- DSSERR("can't get fck\n");
- return PTR_ERR(clk);
- }
-
- venc.tv_clk = clk;
-
if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
- if (cpu_is_omap34xx() || cpu_is_omap3630())
- clk = clk_get(&pdev->dev, "dss_96m_fck");
- else
- clk = clk_get(&pdev->dev, "tv_dac_clk");
+ clk = clk_get(&pdev->dev, "tv_dac_clk");
if (IS_ERR(clk)) {
DSSERR("can't get tv_dac_clk\n");
- clk_put(venc.tv_clk);
return PTR_ERR(clk);
}
} else {
@@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev)
static void venc_put_clocks(void)
{
- if (venc.tv_clk)
- clk_put(venc.tv_clk);
if (venc.tv_dac_clk)
clk_put(venc.tv_dac_clk);
}
@@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev)
{
if (venc.tv_dac_clk)
clk_disable(venc.tv_dac_clk);
- clk_disable(venc.tv_clk);
dispc_runtime_put();
dss_runtime_put();
@@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev)
if (r < 0)
goto err_get_dispc;
- clk_enable(venc.tv_clk);
if (venc.tv_dac_clk)
clk_enable(venc.tv_dac_clk);
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index aa33386c81ff..83d3fe7ec9ae 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,5 +1,5 @@
menuconfig FB_OMAP2
- tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
+ tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS
select OMAP2_VRAM
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 602b71a92d3c..70aa47de7146 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
static void omapfb_calc_addr(const struct omapfb_info *ofbi,
const struct fb_var_screeninfo *var,
const struct fb_fix_screeninfo *fix,
- int rotation, u32 *paddr, void __iomem **vaddr)
+ int rotation, u32 *paddr)
{
u32 data_start_p;
- void __iomem *data_start_v;
int offset;
- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
- data_start_v = NULL;
- } else {
+ else
data_start_p = omapfb_get_region_paddr(ofbi);
- data_start_v = omapfb_get_region_vaddr(ofbi);
- }
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
offset = calc_rotation_offset_dma(var, fix, rotation);
data_start_p += offset;
- data_start_v += offset;
if (offset)
DBG("offset %d, %d = %d\n",
var->xoffset, var->yoffset, offset);
- DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+ DBG("paddr %x\n", data_start_p);
*paddr = data_start_p;
- *vaddr = data_start_v;
}
/* setup overlay according to the fb */
@@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
struct fb_fix_screeninfo *fix = &fbi->fix;
enum omap_color_mode mode = 0;
u32 data_start_p = 0;
- void __iomem *data_start_v = NULL;
struct omap_overlay_info info;
int xres, yres;
int screen_width;
@@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
}
if (ofbi->region->size)
- omapfb_calc_addr(ofbi, var, fix, rotation,
- &data_start_p, &data_start_v);
+ omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
@@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
mirror = ofbi->mirror;
info.paddr = data_start_p;
- info.vaddr = data_start_v;
info.screen_width = screen_width;
info.width = xres;
info.height = yres;
@@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
return r;
}
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+ struct omap_video_timings *t)
+{
+ t->x_res = m->xres;
+ t->y_res = m->yres;
+ t->pixel_clock = PICOS2KHZ(m->pixclock);
+ t->hsw = m->hsync_len;
+ t->hfp = m->right_margin;
+ t->hbp = m->left_margin;
+ t->vsw = m->vsync_len;
+ t->vfp = m->lower_margin;
+ t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+ struct omap_video_timings *timings)
+{
+ struct fb_monspecs *specs;
+ u8 *edid;
+ int r, i, best_xres, best_idx, len;
+
+ if (!display->driver->read_edid)
+ return -ENODEV;
+
+ len = 0x80 * 2;
+ edid = kmalloc(len, GFP_KERNEL);
+
+ r = display->driver->read_edid(display, edid, len);
+ if (r < 0)
+ goto err1;
+
+ specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+ fb_edid_to_monspecs(edid, specs);
+
+ if (edid[126] > 0)
+ fb_edid_add_monspecs(edid + 0x80, specs);
+
+ best_xres = 0;
+ best_idx = -1;
+
+ for (i = 0; i < specs->modedb_len; ++i) {
+ struct fb_videomode *m;
+ struct omap_video_timings t;
+
+ m = &specs->modedb[i];
+
+ if (m->pixclock == 0)
+ continue;
+
+ /* skip repeated pixel modes */
+ if (m->xres == 2880 || m->xres == 1440)
+ continue;
+
+ fb_videomode_to_omap_timings(m, &t);
+
+ r = display->driver->check_timings(display, &t);
+ if (r == 0 && best_xres < m->xres) {
+ best_xres = m->xres;
+ best_idx = i;
+ }
+ }
+
+ if (best_xres == 0) {
+ r = -ENOENT;
+ goto err2;
+ }
+
+ fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+ r = 0;
+
+err2:
+ fb_destroy_modedb(specs->modedb);
+ kfree(specs);
+err1:
+ kfree(edid);
+
+ return r;
+}
+
static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
@@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev)
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
- dev_err(&pdev->dev, "no driver for display\n");
- r = -ENODEV;
+ dev_warn(&pdev->dev, "no driver for display: %s\n",
+ dssdev->name);
+ omap_dss_put_device(dssdev);
+ continue;
}
d = &fbdev->displays[fbdev->num_displays++];
@@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+ /* gfx overlay should be the default one. find a display
+ * connected to that, and use it as default display */
+ ovl = omap_dss_get_overlay(0);
+ if (ovl->manager && ovl->manager->device) {
+ def_display = ovl->manager->device;
+ } else {
+ dev_warn(&pdev->dev, "cannot find default display\n");
+ def_display = NULL;
+ }
+
if (def_mode && strlen(def_mode) > 0) {
if (omapfb_parse_def_modes(fbdev))
dev_warn(&pdev->dev, "cannot parse default modes\n");
+ } else if (def_display && def_display->driver->set_timings &&
+ def_display->driver->check_timings) {
+ struct omap_video_timings t;
+
+ r = omapfb_find_best_mode(def_display, &t);
+
+ if (r == 0)
+ def_display->driver->set_timings(def_display, &t);
}
r = omapfb_create_framebuffers(fbdev);
@@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
DBG("mgr->apply'ed\n");
- /* gfx overlay should be the default one. find a display
- * connected to that, and use it as default display */
- ovl = omap_dss_get_overlay(0);
- if (ovl->manager && ovl->manager->device) {
- def_display = ovl->manager->device;
- } else {
- dev_warn(&pdev->dev, "cannot find default display\n");
- def_display = NULL;
- }
-
if (def_display) {
r = omapfb_init_display(fbdev, def_display);
if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 153bf1aceebc..1694d5148f32 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
- int mirror;
+ bool mirror;
int r;
struct fb_var_screeninfo new_var;
- r = kstrtoint(buf, 0, &mirror);
+ r = strtobool(buf, &mirror);
if (r)
return r;
- mirror = !!mirror;
-
if (!lock_fb_info(fbi))
return -ENODEV;

Privacy Policy