summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@stericsson.com>2012-06-04 19:45:30 +0800
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-06-04 19:45:30 +0800
commit1cd04b2aba9f3b3468adf0789030240e032d8d3e (patch)
tree2e010c15b347b7acda9bc7a2ab4abca9d58043eb
parentcff72c10aa27e3a74eb5d5b7ceb7808d8c917d15 (diff)
parentb7086e0a1dec82bf7e8e96e17738151f0aee82fc (diff)
Merge topic branch 'video' into integration-linux-ux500
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/Kconfig2
-rw-r--r--arch/arm/mach-ux500/Kconfig-arch56
-rw-r--r--arch/arm/mach-ux500/board-mop500-mcde.c559
-rw-r--r--arch/arm/mach-ux500/board-u5500-mcde.c272
-rw-r--r--drivers/misc/Kconfig34
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/clonedev/Makefile5
-rw-r--r--drivers/misc/clonedev/clonedev.c312
-rw-r--r--drivers/misc/compdev/Makefile6
-rw-r--r--drivers/misc/compdev/compdev.c1381
-rw-r--r--drivers/misc/dispdev/Makefile1
-rw-r--r--drivers/misc/dispdev/dispdev.c659
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/av8100/Kconfig48
-rw-r--r--drivers/video/av8100/Makefile10
-rw-r--r--drivers/video/av8100/av8100.c4166
-rw-r--r--drivers/video/av8100/av8100_regs.h346
-rw-r--r--drivers/video/av8100/hdmi.c2479
-rw-r--r--drivers/video/av8100/hdmi_loc.h75
-rw-r--r--drivers/video/b2r2/Kconfig134
-rw-r--r--drivers/video/b2r2/Makefile15
-rw-r--r--drivers/video/b2r2/b2r2_api.c1643
-rw-r--r--drivers/video/b2r2/b2r2_blt_main.c2840
-rw-r--r--drivers/video/b2r2/b2r2_control.h33
-rw-r--r--drivers/video/b2r2/b2r2_core.c2763
-rw-r--r--drivers/video/b2r2/b2r2_core.h300
-rw-r--r--drivers/video/b2r2/b2r2_debug.c340
-rw-r--r--drivers/video/b2r2/b2r2_debug.h102
-rw-r--r--drivers/video/b2r2/b2r2_filters.c377
-rw-r--r--drivers/video/b2r2/b2r2_filters.h73
-rw-r--r--drivers/video/b2r2/b2r2_generic.c3206
-rw-r--r--drivers/video/b2r2/b2r2_generic.h51
-rw-r--r--drivers/video/b2r2/b2r2_global.h119
-rw-r--r--drivers/video/b2r2/b2r2_hw.h458
-rw-r--r--drivers/video/b2r2/b2r2_hw_convert.c747
-rw-r--r--drivers/video/b2r2/b2r2_hw_convert.h53
-rw-r--r--drivers/video/b2r2/b2r2_input_validation.c496
-rw-r--r--drivers/video/b2r2/b2r2_input_validation.h31
-rw-r--r--drivers/video/b2r2/b2r2_internal.h610
-rw-r--r--drivers/video/b2r2/b2r2_kernel_if.c37
-rw-r--r--drivers/video/b2r2/b2r2_mem_alloc.c669
-rw-r--r--drivers/video/b2r2/b2r2_mem_alloc.h161
-rw-r--r--drivers/video/b2r2/b2r2_node_gen.c83
-rw-r--r--drivers/video/b2r2/b2r2_node_split.c3033
-rw-r--r--drivers/video/b2r2/b2r2_node_split.h124
-rw-r--r--drivers/video/b2r2/b2r2_profiler/Makefile3
-rw-r--r--drivers/video/b2r2/b2r2_profiler/b2r2_profiler.c270
-rw-r--r--drivers/video/b2r2/b2r2_profiler_api.h66
-rw-r--r--drivers/video/b2r2/b2r2_profiler_socket.c107
-rw-r--r--drivers/video/b2r2/b2r2_profiler_socket.h22
-rw-r--r--drivers/video/b2r2/b2r2_structures.h226
-rw-r--r--drivers/video/b2r2/b2r2_timing.c22
-rw-r--r--drivers/video/b2r2/b2r2_timing.h22
-rw-r--r--drivers/video/b2r2/b2r2_utils.c1324
-rw-r--r--drivers/video/b2r2/b2r2_utils.h89
-rw-r--r--drivers/video/mcde/Kconfig96
-rw-r--r--drivers/video/mcde/Makefile23
-rw-r--r--drivers/video/mcde/display-ab8500.c494
-rw-r--r--drivers/video/mcde/display-av8100.c1656
-rw-r--r--drivers/video/mcde/display-fictive.c63
-rw-r--r--drivers/video/mcde/display-generic_dsi.c307
-rw-r--r--drivers/video/mcde/display-samsung_s6d16d0.c232
-rw-r--r--drivers/video/mcde/display-sony_acx424akp_dsi.c422
-rw-r--r--drivers/video/mcde/display-vuib500-dpi.c215
-rw-r--r--drivers/video/mcde/dsilink_regs.h2037
-rw-r--r--drivers/video/mcde/mcde_bus.c274
-rw-r--r--drivers/video/mcde/mcde_debugfs.c207
-rw-r--r--drivers/video/mcde/mcde_debugfs.h25
-rw-r--r--drivers/video/mcde/mcde_display.c366
-rw-r--r--drivers/video/mcde/mcde_dss.c445
-rw-r--r--drivers/video/mcde/mcde_fb.c898
-rw-r--r--drivers/video/mcde/mcde_hw.c3834
-rw-r--r--drivers/video/mcde/mcde_mod.c69
-rw-r--r--drivers/video/mcde/mcde_regs.h5096
-rw-r--r--firmware/Makefile1
-rw-r--r--firmware/av8100.fw.ihex1281
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/clonedev.h50
-rw-r--r--include/linux/compdev.h154
-rw-r--r--include/linux/dispdev.h66
-rw-r--r--include/video/Kbuild1
-rw-r--r--include/video/av8100.h549
-rw-r--r--include/video/b2r2_blt.h690
-rw-r--r--include/video/hdmi.h205
-rw-r--r--include/video/mcde.h400
-rw-r--r--include/video/mcde_display-ab8500.h24
-rw-r--r--include/video/mcde_display-av8100.h53
-rw-r--r--include/video/mcde_display-generic_dsi.h35
-rw-r--r--include/video/mcde_display-sony_acx424akp_dsi.h27
-rw-r--r--include/video/mcde_display-vuib500-dpi.h31
-rw-r--r--include/video/mcde_display.h143
-rw-r--r--include/video/mcde_dss.h81
-rw-r--r--include/video/mcde_fb.h65
94 files changed, 51686 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index a2af24dd3b9..5b81df73186 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -206,4 +206,6 @@ config UX500_DB_DUMP
source "arch/arm/mach-ux500/pm/Kconfig"
source "arch/arm/mach-ux500/test/Kconfig"
+source "arch/arm/mach-ux500/Kconfig-arch"
+
endif
diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch
new file mode 100644
index 00000000000..45fc2716814
--- /dev/null
+++ b/arch/arm/mach-ux500/Kconfig-arch
@@ -0,0 +1,56 @@
+config U8500_SECURE
+ bool "Support for running in Secure mode"
+ default n
+ help
+ Build the kernel to run in Secure mode.
+
+#Configuration for MCDE setup
+
+if FB_MCDE
+
+menu "Display setup"
+
+choice
+ prompt "TV output type"
+ default U8500_TV_OUTPUT_AV8100
+ help
+ Select the source of TV output to use
+
+config U8500_TV_OUTPUT_AV8100
+ bool "AV8100 (HDMI/CVBS)"
+ depends on MCDE_DISPLAY_AV8100
+
+config U8500_TV_OUTPUT_AB8500
+ bool "AB8500 (CVBS)"
+ depends on MCDE_DISPLAY_AB8500_DENC
+
+endchoice
+
+choice
+ prompt "Color depth"
+ depends on DISPLAY_GENERIC_PRIMARY
+ default MCDE_DISPLAY_PRIMARY_16BPP
+ help
+ Select color depth for primary display
+
+config MCDE_DISPLAY_PRIMARY_16BPP
+ bool "16 bpp"
+ help
+ 16 bpp color depth
+
+config MCDE_DISPLAY_PRIMARY_32BPP
+ bool "32 bpp"
+ help
+ 32 bpp color depth
+
+endchoice
+
+config DISPLAY_AV8100_TRIPPLE_BUFFER
+ bool "Enable tripple buffer for HDMI display"
+ depends on MCDE_DISPLAY_AV8100
+ help
+ Say yes to enable tripple buffer. You'll get double buffer otherwise
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c
new file mode 100644
index 00000000000..3d8c8fc4852
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-mcde.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <linux/workqueue.h>
+#include <linux/dispdev.h>
+#include <linux/compdev.h>
+#include <asm/mach-types.h>
+#include <linux/clk.h>
+#include <mach/devices.h>
+#include <video/av8100.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-vuib500-dpi.h>
+#include <video/mcde_display-sony_acx424akp_dsi.h>
+#include <video/mcde_display-av8100.h>
+#include <video/mcde_display-ab8500.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+#include <plat/pincfg.h>
+#include "pins-db8500.h"
+#include "pins.h"
+#include "board-mop500.h"
+
+#define DSI_UNIT_INTERVAL_0 0x9
+#define DSI_UNIT_INTERVAL_1 0x9
+#define DSI_UNIT_INTERVAL_2 0x5
+
+#define DSI_PLL_FREQ_HZ 840320000
+/* Based on PLL DDR Freq at 798,72 MHz */
+#define HDMI_FREQ_HZ 33280000
+#define TV_FREQ_HZ 38400000
+
+#ifdef CONFIG_U8500_TV_OUTPUT_AV8100
+/* The initialization of hdmi disp driver must be delayed in order to
+ * ensure that inputclk will be available (needed by hdmi hw) */
+static struct delayed_work work_dispreg_hdmi;
+#define DISPREG_HDMI_DELAY 6000
+#endif
+
+enum {
+ PRIMARY_DISPLAY_ID,
+ SECONDARY_DISPLAY_ID,
+ FICTIVE_DISPLAY_ID,
+ AV8100_DISPLAY_ID,
+ AB8500_DISPLAY_ID,
+ MCDE_NR_OF_DISPLAYS
+};
+
+static int display_initialized_during_boot;
+
+static int __init startup_graphics_setup(char *str)
+{
+
+ if (get_option(&str, &display_initialized_during_boot) != 1)
+ display_initialized_during_boot = 0;
+
+ switch (display_initialized_during_boot) {
+ case 1:
+ pr_info("Startup graphics support\n");
+ break;
+ case 0:
+ default:
+ pr_info("No startup graphics supported\n");
+ break;
+ };
+
+ return 1;
+}
+__setup("startup_graphics=", startup_graphics_setup);
+
+#if defined(CONFIG_U8500_TV_OUTPUT_AV8100) || \
+ defined(CONFIG_U8500_TV_OUTPUT_AB8500)
+static struct mcde_col_transform rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x0042, 0x0081, 0x0019},
+ {0xffda, 0xffb6, 0x0070},
+ {0x0070, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+};
+#endif
+
+static struct mcde_port samsung_s6d16d0_port0 = {
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .frame_trig = MCDE_TRIG_SW,
+};
+
+static struct mcde_display_dsi_platform_data samsung_s6d16d0_pdata0 = {
+ .link = 0,
+};
+
+static struct mcde_display_device samsung_s6d16d0_display0 = {
+ .name = "samsung_s6d16d0",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &samsung_s6d16d0_port0,
+ .chnl_id = MCDE_CHNL_A,
+ .fifo = MCDE_FIFO_A,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+ .dev = {
+ .platform_data = &samsung_s6d16d0_pdata0,
+ },
+};
+
+static struct mcde_port sony_port0 = {
+ .link = 0,
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .frame_trig = MCDE_TRIG_HW,
+};
+
+static struct mcde_display_sony_acx424akp_platform_data
+ sony_acx424akp_display0_pdata = {
+ .reset_gpio = HREFV60_DISP1_RST_GPIO,
+};
+
+static struct mcde_display_device sony_acx424akp_display0 = {
+ .name = "mcde_disp_sony_acx424akp",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &sony_port0,
+ .chnl_id = MCDE_CHNL_A,
+ .fifo = MCDE_FIFO_A,
+ .orientation = MCDE_DISPLAY_ROT_0,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+ .dev = {
+ .platform_data = &sony_acx424akp_display0_pdata,
+ },
+};
+
+static struct mcde_port samsung_s6d16d0_port1 = {
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .frame_trig = MCDE_TRIG_SW,
+};
+
+static struct mcde_display_dsi_platform_data samsung_s6d16d0_pdata1 = {
+ .link = 1,
+};
+
+static struct mcde_display_device samsung_s6d16d0_display1 = {
+ .name = "samsung_s6d16d0",
+ .id = SECONDARY_DISPLAY_ID,
+ .port = &samsung_s6d16d0_port1,
+ .chnl_id = MCDE_CHNL_C1,
+ .fifo = MCDE_FIFO_C1,
+ .orientation = MCDE_DISPLAY_ROT_90_CCW,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .dev = {
+ .platform_data = &samsung_s6d16d0_pdata1,
+ },
+};
+
+#ifdef CONFIG_U8500_TV_OUTPUT_AB8500
+static struct mcde_port port_tvout1 = {
+ .type = MCDE_PORTTYPE_DPI,
+ .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP,
+ .link = 1, /* channel B */
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+ .phy = {
+ .dpi = {
+ .bus_width = 4, /* DDR mode */
+ .tv_mode = true,
+ .clock_div = MCDE_PORT_DPI_NO_CLOCK_DIV,
+ },
+ },
+};
+
+static struct ab8500_display_platform_data ab8500_display_pdata = {
+ .nr_regulators = 2,
+ .regulator_id = {"vtvout", "vcc-N2158"},
+ .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform,
+};
+
+static struct ux500_pins *tvout_pins;
+
+static int ab8500_platform_enable(struct mcde_display_device *ddev)
+{
+ int res = 0;
+
+ if (!tvout_pins) {
+ tvout_pins = ux500_pins_get("mcde-tvout");
+ if (!tvout_pins)
+ return -EINVAL;
+ }
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ res = ux500_pins_enable(tvout_pins);
+ if (res != 0)
+ goto failed;
+
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static int ab8500_platform_disable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+
+ res = ux500_pins_disable(tvout_pins);
+ if (res != 0)
+ goto failed;
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static struct mcde_display_device tvout_ab8500_display = {
+ .name = "mcde_tv_ab8500",
+ .id = AB8500_DISPLAY_ID,
+ .port = &port_tvout1,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 720,
+ .native_y_res = 576,
+ .dev = {
+ .platform_data = &ab8500_display_pdata,
+ },
+
+ /*
+ * We might need to describe the std here:
+ * - there are different PAL / NTSC formats (do they require MCDE
+ * settings?)
+ */
+ .platform_enable = ab8500_platform_enable,
+ .platform_disable = ab8500_platform_disable,
+};
+#endif
+
+#ifdef CONFIG_U8500_TV_OUTPUT_AV8100
+
+#if defined(CONFIG_AV8100_HWTRIG_INT)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE0
+#elif defined(CONFIG_AV8100_HWTRIG_I2SDAT3)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE1
+#elif defined(CONFIG_AV8100_HWTRIG_DSI_TE)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE_POLLING
+#else
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_OFF
+#endif
+static struct mcde_port av8100_port2 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 2,
+ .sync_src = AV8100_SYNC_SRC,
+ .update_auto_trig = true,
+ .phy = {
+ .dsi = {
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_2,
+ },
+ },
+ .hdmi_sdtv_switch = HDMI_SWITCH,
+};
+
+static struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = {
+ .cvbs_regulator_id = "vcc-N2158",
+ .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform,
+};
+
+static struct ux500_pins *av8100_pins;
+static int av8100_platform_enable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ if (!av8100_pins) {
+ av8100_pins = ux500_pins_get("av8100-hdmi");
+ if (!av8100_pins) {
+ res = -EINVAL;
+ goto failed;
+ }
+ }
+
+ res = ux500_pins_enable(av8100_pins);
+ if (res != 0)
+ goto failed;
+
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static int av8100_platform_disable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+
+ res = ux500_pins_disable(av8100_pins);
+ if (res != 0)
+ goto failed;
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static struct mcde_display_device av8100_hdmi = {
+ .name = "av8100_hdmi",
+ .id = AV8100_DISPLAY_ID,
+ .port = &av8100_port2,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 1280,
+ .native_y_res = 720,
+ .dev = {
+ .platform_data = &av8100_hdmi_pdata,
+ },
+ .platform_enable = av8100_platform_enable,
+ .platform_disable = av8100_platform_disable,
+};
+
+static void delayed_work_dispreg_hdmi(struct work_struct *ptr)
+{
+ if (mcde_display_device_register(&av8100_hdmi))
+ pr_warning("Failed to register av8100_hdmi\n");
+}
+#endif /* CONFIG_U8500_TV_OUTPUT_AV8100 */
+
+/*
+* This function will create the framebuffer for the display that is registered.
+*/
+static int display_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = dev;
+ u16 width, height;
+ u16 virtual_height;
+ struct fb_info *fbi;
+#if defined(CONFIG_DISPDEV) || defined(CONFIG_COMPDEV)
+ struct mcde_fb *mfb;
+#endif
+
+ if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
+ return 0;
+
+ if (ddev->id < 0 || ddev->id >= MCDE_NR_OF_DISPLAYS)
+ return 0;
+
+ mcde_dss_get_native_resolution(ddev, &width, &height);
+ virtual_height = height * 2;
+
+#ifndef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ if (ddev->id == AV8100_DISPLAY_ID)
+ goto out;
+#endif
+
+ /* Create frame buffer */
+ fbi = mcde_fb_create(ddev, width, height, width, virtual_height,
+ ddev->default_pixel_format, FB_ROTATE_UR);
+ if (IS_ERR(fbi)) {
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n", ddev->name);
+ goto display_postregistered_callback_err;
+ } else {
+ dev_info(&ddev->dev, "Framebuffer created (%s)\n", ddev->name);
+ }
+
+#ifdef CONFIG_DISPDEV
+ mfb = to_mcde_fb(fbi);
+
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true, mfb->ovlys[0]) < 0) {
+ dev_warn(&ddev->dev,
+ "Failed to create disp for display %s\n", ddev->name);
+ goto display_postregistered_callback_err;
+ } else {
+ dev_info(&ddev->dev, "Disp dev created for (%s)\n", ddev->name);
+ }
+#endif
+
+#ifdef CONFIG_COMPDEV
+ mfb = to_mcde_fb(fbi);
+ /* Create a compdev overlay for this display */
+ if (compdev_create(ddev, mfb->ovlys[0], true) < 0) {
+ dev_warn(&ddev->dev,
+ "Failed to create compdev for display %s\n",
+ ddev->name);
+ goto display_postregistered_callback_err;
+ } else {
+ dev_info(&ddev->dev, "compdev created for (%s)\n",
+ ddev->name);
+ }
+#endif
+
+out:
+ return 0;
+
+display_postregistered_callback_err:
+ return -1;
+}
+
+static struct notifier_block display_nb = {
+ .notifier_call = display_postregistered_callback,
+};
+
+/*
+* This function is used to refresh the display (lcd, hdmi, tvout) with black
+* when the framebuffer is registered.
+* The main display will not be updated if startup graphics is displayed
+* from u-boot.
+*/
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+ var = info->var;
+ fix = info->fix;
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+
+static struct notifier_block framebuffer_nb = {
+ .notifier_call = framebuffer_postregistered_callback,
+};
+
+static int __init init_display_devices(void)
+{
+ int ret;
+
+ if (!cpu_is_u8500())
+ return 0;
+
+ ret = fb_register_client(&framebuffer_nb);
+ if (ret)
+ pr_warning("Failed to register framebuffer notifier\n");
+
+ (void)mcde_dss_register_notifier(&display_nb);
+
+ /* Set powermode to STANDBY if startup graphics is executed */
+ if (display_initialized_during_boot) {
+ samsung_s6d16d0_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
+ sony_acx424akp_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* Display reset GPIO is different depending on reference boards */
+ if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) {
+ samsung_s6d16d0_pdata0.reset_gpio = HREFV60_DISP1_RST_GPIO;
+ samsung_s6d16d0_pdata1.reset_gpio = HREFV60_DISP2_RST_GPIO;
+ } else {
+ samsung_s6d16d0_pdata0.reset_gpio = MOP500_DISP1_RST_GPIO;
+ samsung_s6d16d0_pdata1.reset_gpio = MOP500_DISP2_RST_GPIO;
+ }
+
+ /* Initialize all needed clocks*/
+ if (!display_initialized_during_boot) {
+ struct clk *clk_dsi_pll;
+ struct clk *clk_hdmi;
+ struct clk *clk_tv;
+
+ /*
+ * The TV CLK is used as parent for the
+ * DSI LP clock.
+ */
+ clk_tv = clk_get(&u8500_mcde_device.dev, "tv");
+ if (TV_FREQ_HZ != clk_round_rate(clk_tv, TV_FREQ_HZ))
+ pr_warning("%s: TV_CLK freq differs %ld\n", __func__,
+ clk_round_rate(clk_tv, TV_FREQ_HZ));
+ clk_set_rate(clk_tv, TV_FREQ_HZ);
+ clk_put(clk_tv);
+
+ /*
+ * The HDMI CLK is used as parent for the
+ * DSI HS clock.
+ */
+ clk_hdmi = clk_get(&u8500_mcde_device.dev, "hdmi");
+ if (HDMI_FREQ_HZ != clk_round_rate(clk_hdmi, HDMI_FREQ_HZ))
+ pr_warning("%s: HDMI freq differs %ld\n", __func__,
+ clk_round_rate(clk_hdmi, HDMI_FREQ_HZ));
+ clk_set_rate(clk_hdmi, HDMI_FREQ_HZ);
+ clk_put(clk_hdmi);
+
+ /*
+ * The DSI PLL CLK is used as DSI PLL for direct freq for
+ * link 2. Link 0/1 is then divided with 1/2/4 from this freq.
+ */
+ clk_dsi_pll = clk_get(&u8500_mcde_device.dev, "dsihs2");
+ if (DSI_PLL_FREQ_HZ != clk_round_rate(clk_dsi_pll,
+ DSI_PLL_FREQ_HZ))
+ pr_warning("%s: DSI_PLL freq differs %ld\n", __func__,
+ clk_round_rate(clk_dsi_pll, DSI_PLL_FREQ_HZ));
+ clk_set_rate(clk_dsi_pll, DSI_PLL_FREQ_HZ);
+ clk_put(clk_dsi_pll);
+ }
+
+ /* Not all STUIBs supports VSYNC, disable vsync for STUIB */
+ if (uib_is_stuib()) {
+ /* Samsung display on STUIB */
+ samsung_s6d16d0_display0.port->sync_src = MCDE_SYNCSRC_OFF;
+ samsung_s6d16d0_display0.orientation = MCDE_DISPLAY_ROT_90_CCW;
+ (void)mcde_display_device_register(&samsung_s6d16d0_display0);
+ } else if (uib_is_u8500uib()) {
+ /* Samsung display on U8500UIB */
+ samsung_s6d16d0_display0.orientation = MCDE_DISPLAY_ROT_90_CW;
+ (void)mcde_display_device_register(&samsung_s6d16d0_display0);
+ } else if (uib_is_u8500uibr3()) {
+ /* Sony display on U8500UIBV3 */
+ (void)mcde_display_device_register(&sony_acx424akp_display0);
+ }
+ else
+ pr_warning("Unknown UI board\n");
+
+ /* Display reset GPIO is different depending on reference boards */
+ if (uib_is_stuib())
+ (void)mcde_display_device_register(&samsung_s6d16d0_display1);
+
+#if defined(CONFIG_U8500_TV_OUTPUT_AV8100)
+ INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
+ delayed_work_dispreg_hdmi);
+ schedule_delayed_work(&work_dispreg_hdmi,
+ msecs_to_jiffies(DISPREG_HDMI_DELAY));
+#elif defined(CONFIG_U8500_TV_OUTPUT_AB8500)
+ (void)mcde_display_device_register(&tvout_ab8500_display);
+#endif
+
+ return 0;
+}
+module_init(init_display_devices);
diff --git a/arch/arm/mach-ux500/board-u5500-mcde.c b/arch/arm/mach-ux500/board-u5500-mcde.c
new file mode 100644
index 00000000000..906b5572229
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-mcde.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/dispdev.h>
+#include <video/av8100.h>
+#include <asm/mach-types.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-generic_dsi.h>
+#include <video/mcde_display-sony_acx424akp_dsi.h>
+#include <video/mcde_display-av8100.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+
+#define DSI_UNIT_INTERVAL_0 0xA
+#define DSI_UNIT_INTERVAL_2 0x5
+
+/* The initialization of hdmi disp driver must be delayed in order to
+ * ensure that inputclk will be available (needed by hdmi hw) */
+static struct delayed_work work_dispreg_hdmi;
+#define DISPREG_HDMI_DELAY 6000
+
+enum {
+ PRIMARY_DISPLAY_ID,
+ AV8100_DISPLAY_ID,
+ MCDE_NR_OF_DISPLAYS
+};
+
+static int display_initialized_during_boot;
+
+static int __init startup_graphics_setup(char *str)
+{
+
+ if (get_option(&str, &display_initialized_during_boot) != 1)
+ display_initialized_during_boot = 0;
+
+ switch (display_initialized_during_boot) {
+ case 1:
+ pr_info("Startup graphics support\n");
+ break;
+ case 0:
+ default:
+ pr_info("No startup graphics supported\n");
+ break;
+ };
+
+ return 1;
+}
+__setup("startup_graphics=", startup_graphics_setup);
+
+static struct mcde_col_transform rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x0042, 0x0081, 0x0019},
+ {0xffda, 0xffb6, 0x0070},
+ {0x0070, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+};
+
+static struct mcde_port sony_port0 = {
+ .link = 0,
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .frame_trig = MCDE_TRIG_SW,
+};
+
+static struct mcde_display_sony_acx424akp_platform_data \
+ sony_acx424akp_display0_pdata = {
+ .reset_gpio = 226,
+};
+
+static struct mcde_display_device sony_acx424akp_display0 = {
+ .name = "mcde_disp_sony_acx424akp",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &sony_port0,
+ .chnl_id = MCDE_CHNL_A,
+ .fifo = MCDE_FIFO_A,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+ .dev = {
+ .platform_data = &sony_acx424akp_display0_pdata,
+ },
+};
+
+#if defined(CONFIG_AV8100_HWTRIG_INT)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE0
+#elif defined(CONFIG_AV8100_HWTRIG_I2SDAT3)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE1
+#elif defined(CONFIG_AV8100_HWTRIG_DSI_TE)
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_TE_POLLING
+#else
+ #define AV8100_SYNC_SRC MCDE_SYNCSRC_OFF
+#endif
+static struct mcde_port av8100_port2 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .link = 1,
+ .sync_src = AV8100_SYNC_SRC,
+ .update_auto_trig = true,
+ .phy = {
+ .dsi = {
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_2,
+ },
+ },
+ .hdmi_sdtv_switch = HDMI_SWITCH,
+};
+
+static struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = {
+ .rgb_2_yCbCr_transform = &rgb_2_yCbCr_transform,
+};
+
+static struct mcde_display_device av8100_hdmi = {
+ .name = "av8100_hdmi",
+ .id = AV8100_DISPLAY_ID,
+ .port = &av8100_port2,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB888,
+ .native_x_res = 1280,
+ .native_y_res = 720,
+ .dev = {
+ .platform_data = &av8100_hdmi_pdata,
+ },
+};
+
+static void delayed_work_dispreg_hdmi(struct work_struct *ptr)
+{
+ if (mcde_display_device_register(&av8100_hdmi))
+ pr_warning("Failed to register av8100_hdmi\n");
+}
+
+/*
+* This function will create the framebuffer for the display that is registered.
+*/
+static int display_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = dev;
+ u16 width, height;
+ u16 virtual_height;
+ u32 rotate = FB_ROTATE_UR;
+ struct fb_info *fbi;
+#ifdef CONFIG_DISPDEV
+ struct mcde_fb *mfb;
+#endif
+
+ if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
+ return 0;
+
+ if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= MCDE_NR_OF_DISPLAYS)
+ return 0;
+
+ mcde_dss_get_native_resolution(ddev, &width, &height);
+
+ virtual_height = height * 2;
+
+#ifndef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ if (ddev->id == AV8100_DISPLAY_ID)
+ goto out;
+#endif
+
+ /* Create frame buffer */
+ fbi = mcde_fb_create(ddev, width, height, width, virtual_height,
+ ddev->default_pixel_format, rotate);
+ if (IS_ERR(fbi)) {
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n", ddev->name);
+ goto display_postregistered_callback_err;
+ } else {
+ dev_info(&ddev->dev, "Framebuffer created (%s)\n", ddev->name);
+ }
+
+#ifdef CONFIG_DISPDEV
+ mfb = to_mcde_fb(fbi);
+
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true, mfb->ovlys[0]) < 0) {
+ dev_warn(&ddev->dev,
+ "Failed to create disp for display %s\n", ddev->name);
+ goto display_postregistered_callback_err;
+ } else {
+ dev_info(&ddev->dev, "Disp dev created for (%s)\n", ddev->name);
+ }
+#endif
+
+out:
+ return 0;
+
+display_postregistered_callback_err:
+ return -1;
+}
+
+static struct notifier_block display_nb = {
+ .notifier_call = display_postregistered_callback,
+};
+
+/*
+* This function is used to refresh the display (lcd, hdmi, tvout) with black
+* when the framebuffer is registered.
+* The main display will not be updated if startup graphics is displayed
+* from u-boot.
+*/
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+ var = info->var;
+ fix = info->fix;
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+
+static struct notifier_block framebuffer_nb = {
+ .notifier_call = framebuffer_postregistered_callback,
+};
+
+int __init init_u5500_display_devices(void)
+{
+ int ret;
+
+ if (!cpu_is_u5500())
+ return 0;
+
+ ret = fb_register_client(&framebuffer_nb);
+ if (ret)
+ pr_warning("Failed to register framebuffer notifier\n");
+
+ (void)mcde_dss_register_notifier(&display_nb);
+
+ if (display_initialized_during_boot)
+ sony_acx424akp_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
+
+ (void)mcde_display_device_register(&sony_acx424akp_display0);
+
+ INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
+ delayed_work_dispreg_hdmi);
+ schedule_delayed_work(&work_dispreg_hdmi,
+ msecs_to_jiffies(DISPREG_HDMI_DELAY));
+
+ return 0;
+}
+module_init(init_u5500_display_devices);
+
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1a9ae1647b0..f92560ef750 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -461,6 +461,40 @@ config BMP085
To compile this driver as a module, choose M here: the
module will be called bmp085.
+config DISPDEV
+ bool "Display overlay device"
+ depends on FB_MCDE
+ default n
+ help
+ This driver provides a way to use a second overlay for a display (in
+ addition to the framebuffer). The device allows for registration of
+ userspace buffers to be used with the overlay.
+
+config COMPDEV
+ bool "Display composition device"
+ depends on FB_MCDE && HWMEM
+ default n
+ help
+ This driver provides a way to use several overlays for a display.
+ This driver replaces the use of the framebuffer The device allows
+ for posting userspace buffers to be used with the overlays.
+
+config CLONEDEV
+ bool "Display cloning device"
+ depends on FB_MCDE && HWMEM && COMPDEV
+ default n
+ help
+ This driver provides a way to clone content between two compdev
+ devices.
+
+config CLONEDEV_DEBUG
+ bool "Display cloning device debug"
+ depends on CLONEDEV
+ default n
+ help
+ This driver provides a way to clone content between two compdev
+ devices.
+
config PCH_PHUB
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5317121efcd..2741a01610f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -48,6 +48,9 @@ obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_STM_TRACE) += stm.o
obj-$(CONFIG_HWMEM) += hwmem/
+obj-$(CONFIG_DISPDEV) += dispdev/
+obj-$(CONFIG_COMPDEV) += compdev/
+obj-$(CONFIG_CLONEDEV) += clonedev/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
diff --git a/drivers/misc/clonedev/Makefile b/drivers/misc/clonedev/Makefile
new file mode 100644
index 00000000000..f84859dd3ee
--- /dev/null
+++ b/drivers/misc/clonedev/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_CLONEDEV) += clonedev.o
+
+ifdef CONFIG_CLONEDEV_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/misc/clonedev/clonedev.c b/drivers/misc/clonedev/clonedev.c
new file mode 100644
index 00000000000..d3b770fd324
--- /dev/null
+++ b/drivers/misc/clonedev/clonedev.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Device for display cloning on external output.
+ *
+ * Author: Per-Daniel Olsson <per-daniel.olsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/ioctl.h>
+
+#include <linux/clonedev.h>
+
+#include <linux/compdev.h>
+#include <linux/mm.h>
+#include <video/mcde.h>
+
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(dev_list_lock);
+
+struct clonedev {
+ struct mutex lock;
+ struct miscdevice mdev;
+ struct list_head list;
+ bool open;
+ struct compdev *src_compdev;
+ struct compdev *dst_compdev;
+ bool overlay_case;
+ struct compdev_size dst_size;
+ struct compdev_scene_info s_info;
+};
+
+static void best_fit(struct compdev_rect *src_rect,
+ struct compdev_size *dst_size,
+ struct compdev_img *img)
+{
+ /* aspect ratio in 26.6 fixed point */
+ int aspect = 1;
+ int dst_w;
+ int dst_h;
+
+ if (img->rotation == COMPDEV_ROT_90_CCW ||
+ img->rotation == COMPDEV_ROT_270_CCW)
+ aspect = (src_rect->height << 6) / src_rect->width;
+ else
+ aspect = (src_rect->width << 6) / src_rect->height;
+
+ dst_w = aspect * dst_size->height >> 6;
+ dst_h = dst_size->height;
+ img->dst_rect.y = 0;
+
+ if (dst_w > dst_size->width) {
+ /*
+ * Destination rectangle too wide.
+ * Clamp to image width. Keep aspect ratio.
+ */
+ dst_h = (dst_size->width << 6) / aspect;
+ dst_w = dst_size->width;
+ }
+
+ /* center the image */
+ if (dst_w < dst_size->width) {
+ int offset = (dst_size->width - dst_w) / 2;
+ img->dst_rect.x = offset;
+ }
+
+ if (dst_h < dst_size->height) {
+ int offset = (dst_size->height - dst_h) / 2;
+ img->dst_rect.y = offset;
+ }
+
+ img->dst_rect.width = dst_w;
+ img->dst_rect.height = dst_h;
+}
+
+static int clonedev_open(struct inode *inode, struct file *file)
+{
+ struct clonedev *cd = NULL;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(cd, &dev_list, list)
+ if (cd->mdev.minor == iminor(inode))
+ break;
+
+ if (&cd->list == &dev_list) {
+ mutex_unlock(&dev_list_lock);
+ return -ENODEV;
+ }
+
+ if (cd->open) {
+ mutex_unlock(&dev_list_lock);
+ return -EBUSY;
+ }
+
+ cd->open = true;
+
+ mutex_unlock(&dev_list_lock);
+
+ file->private_data = cd;
+
+ return 0;
+}
+
+static int clonedev_release(struct inode *inode, struct file *file)
+{
+ struct clonedev *cd = NULL;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(cd, &dev_list, list)
+ if (cd->mdev.minor == iminor(inode))
+ break;
+ mutex_unlock(&dev_list_lock);
+
+ if (&cd->list == &dev_list)
+ return -ENODEV;
+
+ cd->open = false;
+ return 0;
+}
+
+static long clonedev_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct clonedev *cd = (struct clonedev *)file->private_data;
+
+ mutex_lock(&cd->lock);
+
+ switch (cmd) {
+ case CLONEDEV_SET_MODE_IOC:
+ /* TODO: Get the user data */
+
+ break;
+
+ default:
+ ret = -ENOSYS;
+ }
+
+ mutex_unlock(&cd->lock);
+
+ return ret;
+}
+
+static const struct file_operations clonedev_fops = {
+ .open = clonedev_open,
+ .release = clonedev_release,
+ .unlocked_ioctl = clonedev_ioctl,
+};
+
+static void init_clonedev(struct clonedev *cd, const char *name)
+{
+ mutex_init(&cd->lock);
+ INIT_LIST_HEAD(&cd->list);
+
+ cd->mdev.minor = MISC_DYNAMIC_MINOR;
+ cd->mdev.name = name;
+ cd->mdev.fops = &clonedev_fops;
+}
+
+static void clonedev_post_buffer_callback(void *data,
+ struct compdev_img *cb_img)
+{
+ struct clonedev *cd = (struct clonedev *)data;
+
+ mutex_lock(&cd->lock);
+
+ if (!cd->overlay_case || (cd->overlay_case &&
+ (cb_img->flags & COMPDEV_OVERLAY_FLAG))) {
+ struct compdev_img img;
+
+ img = *cb_img;
+
+ if (img.flags & COMPDEV_BYPASS_FLAG)
+ img.flags &= ~COMPDEV_BYPASS_FLAG;
+
+ if (cd->overlay_case)
+ img.rotation = cd->s_info.ovly_rotation;
+ else
+ img.rotation = cd->s_info.fb_rotation;
+
+ best_fit(&img.src_rect, &cd->dst_size, &img);
+
+ compdev_post_buffer(cd->dst_compdev, &img);
+ }
+ mutex_unlock(&cd->lock);
+}
+
+static void clonedev_post_scene_info_callback(void *data,
+ struct compdev_scene_info *s_info)
+{
+ struct clonedev *cd = (struct clonedev *)data;
+
+ mutex_lock(&cd->lock);
+ if (s_info->img_count > 1)
+ cd->overlay_case = true;
+ else
+ cd->overlay_case = false;
+
+ cd->s_info = *s_info;
+ cd->s_info.img_count = 1;
+ compdev_post_scene_info(cd->dst_compdev, &cd->s_info);
+ mutex_unlock(&cd->lock);
+}
+
+int clonedev_create(void)
+{
+ int ret;
+ struct clonedev *cd;
+
+ static int counter;
+ char name[10];
+
+ cd = kzalloc(sizeof(struct clonedev), GFP_KERNEL);
+ if (!cd)
+ return -ENOMEM;
+
+ snprintf(name, sizeof(name), "%s%d", CLONEDEV_DEFAULT_DEVICE_PREFIX,
+ counter++);
+ init_clonedev(cd, name);
+
+ ret = misc_register(&cd->mdev);
+ if (ret)
+ goto fail_register_misc;
+ mutex_lock(&dev_list_lock);
+ list_add_tail(&cd->list, &dev_list);
+ mutex_unlock(&dev_list_lock);
+
+ mutex_lock(&cd->lock);
+
+ compdev_get(0, &cd->src_compdev);
+ compdev_get(1, &cd->dst_compdev);
+ compdev_get_size(cd->dst_compdev, &cd->dst_size);
+
+ compdev_register_listener_callbacks(cd->src_compdev, (void *)cd,
+ &clonedev_post_buffer_callback,
+ &clonedev_post_scene_info_callback);
+
+ mutex_unlock(&cd->lock);
+ goto out;
+
+fail_register_misc:
+ kfree(cd);
+out:
+ return ret;
+}
+
+void clonedev_destroy(void)
+{
+ struct clonedev *cd;
+ struct clonedev *tmp;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(cd, tmp, &dev_list, list) {
+ compdev_put(cd->src_compdev);
+ compdev_put(cd->dst_compdev);
+ compdev_deregister_callbacks(cd->src_compdev);
+ list_del(&cd->list);
+ misc_deregister(&cd->mdev);
+ kfree(cd);
+ break;
+ }
+ mutex_unlock(&dev_list_lock);
+}
+
+static void clonedev_destroy_all(void)
+{
+ struct clonedev *cd;
+ struct clonedev *tmp;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(cd, tmp, &dev_list, list) {
+ list_del(&cd->list);
+ misc_deregister(&cd->mdev);
+ kfree(cd);
+ }
+ mutex_unlock(&dev_list_lock);
+
+ mutex_destroy(&dev_list_lock);
+}
+
+static int __init clonedev_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ mutex_init(&dev_list_lock);
+
+ return 0;
+}
+module_init(clonedev_init);
+
+static void __exit clonedev_exit(void)
+{
+ clonedev_destroy_all();
+ pr_info("%s\n", __func__);
+}
+module_exit(clonedev_exit);
+
+MODULE_AUTHOR("Per-Daniel Olsson <per-daniel.olsson@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Device for display cloning on external output");
+
diff --git a/drivers/misc/compdev/Makefile b/drivers/misc/compdev/Makefile
new file mode 100644
index 00000000000..b8385848712
--- /dev/null
+++ b/drivers/misc/compdev/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_COMPDEV) += compdev.o
+
+ifdef CONFIG_COMPDEV_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/misc/compdev/compdev.c b/drivers/misc/compdev/compdev.c
new file mode 100644
index 00000000000..d929a02c565
--- /dev/null
+++ b/drivers/misc/compdev/compdev.c
@@ -0,0 +1,1381 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Display overlay compositer device driver
+ *
+ * Author: Anders Bauer <anders.bauer@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * Modified: Per-Daniel Olsson <per-daniel.olsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/ioctl.h>
+#include <linux/sched.h>
+
+#include <linux/compdev.h>
+#include <linux/hwmem.h>
+#include <linux/mm.h>
+#include <video/mcde_dss.h>
+#include <video/b2r2_blt.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+
+#define BUFFER_CACHE_DEPTH 2
+#define NUM_COMPDEV_BUFS 2
+
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(dev_list_lock);
+static int dev_counter;
+
+struct compdev_buffer {
+ struct hwmem_alloc *alloc;
+ enum compdev_ptr_type type;
+ u32 size;
+ u32 paddr; /* if pinned */
+};
+
+struct compdev_img_internal {
+ struct compdev_img img;
+ u32 ref_count;
+};
+
+struct compdev_blt_work {
+ struct work_struct work;
+ struct compdev_img *src_img;
+ struct compdev_img_internal *dst_img;
+ int blt_handle;
+ bool mcde_rotation;
+ struct device *dev;
+};
+
+struct compdev_post_callback_work {
+ struct work_struct work;
+ struct compdev_img *img;
+ post_buffer_callback pb_cb;
+ void *cb_data;
+ struct device *dev;
+};
+
+struct buffer_cache_context {
+ struct compdev_img_internal
+ *img[BUFFER_CACHE_DEPTH];
+ u8 index;
+ u8 unused_counter;
+ struct device *dev;
+};
+
+struct dss_context {
+ struct device *dev;
+ struct mcde_display_device *ddev;
+ struct mcde_overlay *ovly[NUM_COMPDEV_BUFS];
+ struct compdev_buffer ovly_buffer[NUM_COMPDEV_BUFS];
+ struct compdev_size phy_size;
+ enum mcde_display_rotation display_rotation;
+ enum compdev_rotation current_buffer_rotation;
+ int blt_handle;
+ u8 temp_img_count;
+ struct compdev_img_internal *temp_img[NUM_COMPDEV_BUFS];
+ struct buffer_cache_context cache_ctx;
+};
+
+struct compdev {
+ struct mutex lock;
+ struct miscdevice mdev;
+ struct device *dev;
+ struct list_head list;
+ struct dss_context dss_ctx;
+ u16 ref_count;
+ struct workqueue_struct *worker_thread;
+ int dev_index;
+ post_buffer_callback pb_cb;
+ post_scene_info_callback si_cb;
+ struct compdev_scene_info s_info;
+ u8 sync_count;
+ u8 image_count;
+ struct compdev_img *images[NUM_COMPDEV_BUFS];
+ struct completion fence;
+ void *cb_data;
+ bool mcde_rotation;
+};
+
+static struct compdev *compdevs[MAX_NBR_OF_COMPDEVS];
+
+static int compdev_post_buffers_dss(struct dss_context *dss_ctx,
+ struct compdev_img *img1, struct compdev_img *img2);
+
+
+static int compdev_open(struct inode *inode, struct file *file)
+{
+ struct compdev *cd = NULL;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(cd, &dev_list, list)
+ if (cd->mdev.minor == iminor(inode))
+ break;
+
+ if (&cd->list == &dev_list) {
+ mutex_unlock(&dev_list_lock);
+ return -ENODEV;
+ }
+ mutex_unlock(&dev_list_lock);
+ file->private_data = cd;
+ return 0;
+}
+
+static int disable_overlay(struct mcde_overlay *ovly)
+{
+ struct mcde_overlay_info info;
+
+ mcde_dss_get_overlay_info(ovly, &info);
+ if (info.paddr != 0) {
+ /* Set the pointer to zero to disable the overlay */
+ info.paddr = 0;
+ mcde_dss_apply_overlay(ovly, &info);
+ }
+ return 0;
+}
+
+static int compdev_release(struct inode *inode, struct file *file)
+{
+ struct compdev *cd = NULL;
+ int i;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(cd, &dev_list, list)
+ if (cd->mdev.minor == iminor(inode))
+ break;
+ mutex_unlock(&dev_list_lock);
+
+ if (&cd->list == &dev_list)
+ return -ENODEV;
+
+ for (i = 0; i < NUM_COMPDEV_BUFS; i++) {
+ disable_overlay(cd->dss_ctx.ovly[i]);
+ if (cd->dss_ctx.ovly_buffer[i].paddr &&
+ cd->dss_ctx.ovly_buffer[i].type ==
+ COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET)
+ hwmem_unpin(cd->dss_ctx.ovly_buffer[i].alloc);
+
+ cd->dss_ctx.ovly_buffer[i].alloc = NULL;
+ cd->dss_ctx.ovly_buffer[i].size = 0;
+ cd->dss_ctx.ovly_buffer[i].paddr = 0;
+ }
+
+ return 0;
+}
+
+static enum mcde_ovly_pix_fmt get_ovly_fmt(enum compdev_fmt fmt)
+{
+ switch (fmt) {
+ default:
+ case COMPDEV_FMT_RGB565:
+ return MCDE_OVLYPIXFMT_RGB565;
+ case COMPDEV_FMT_RGB888:
+ return MCDE_OVLYPIXFMT_RGB888;
+ case COMPDEV_FMT_RGBA8888:
+ return MCDE_OVLYPIXFMT_RGBA8888;
+ case COMPDEV_FMT_RGBX8888:
+ return MCDE_OVLYPIXFMT_RGBX8888;
+ case COMPDEV_FMT_YUV422:
+ return MCDE_OVLYPIXFMT_YCbCr422;
+ }
+}
+
+static int compdev_setup_ovly(struct compdev_img *img,
+ struct compdev_buffer *buffer,
+ struct mcde_overlay *ovly,
+ int z_order,
+ struct dss_context *dss_ctx)
+{
+ int ret = 0;
+ enum hwmem_mem_type memtype;
+ enum hwmem_access access;
+ struct hwmem_mem_chunk mem_chunk;
+ size_t mem_chunk_length = 1;
+ struct hwmem_region rgn = { .offset = 0, .count = 1, .start = 0 };
+ struct mcde_overlay_info info;
+
+ if (img->buf.type == COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET) {
+ buffer->type = COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET;
+ buffer->alloc = hwmem_resolve_by_name(img->buf.hwmem_buf_name);
+ if (IS_ERR(buffer->alloc)) {
+ ret = PTR_ERR(buffer->alloc);
+ dev_warn(dss_ctx->dev,
+ "HWMEM resolve failed, %d\n", ret);
+ goto resolve_failed;
+ }
+
+ hwmem_get_info(buffer->alloc, &buffer->size, &memtype,
+ &access);
+
+ if (!(access & HWMEM_ACCESS_READ) ||
+ memtype != HWMEM_MEM_CONTIGUOUS_SYS) {
+ ret = -EACCES;
+ dev_warn(dss_ctx->dev,
+ "Invalid_mem overlay, %d\n", ret);
+ goto invalid_mem;
+ }
+ ret = hwmem_pin(buffer->alloc, &mem_chunk, &mem_chunk_length);
+ if (ret) {
+ dev_warn(dss_ctx->dev,
+ "Pin failed, %d\n", ret);
+ goto pin_failed;
+ }
+
+ rgn.size = rgn.end = buffer->size;
+ ret = hwmem_set_domain(buffer->alloc, HWMEM_ACCESS_READ,
+ HWMEM_DOMAIN_SYNC, &rgn);
+ if (ret)
+ dev_warn(dss_ctx->dev,
+ "Set domain failed, %d\n", ret);
+
+ buffer->paddr = mem_chunk.paddr;
+ } else if (img->buf.type == COMPDEV_PTR_PHYSICAL) {
+ buffer->type = COMPDEV_PTR_PHYSICAL;
+ buffer->alloc = NULL;
+ buffer->size = img->buf.len;
+ buffer->paddr = img->buf.offset;
+ }
+
+ info.stride = img->pitch;
+ info.fmt = get_ovly_fmt(img->fmt);
+ info.src_x = 0;
+ info.src_y = 0;
+ info.dst_x = img->dst_rect.x;
+ info.dst_y = img->dst_rect.y;
+ info.dst_z = z_order;
+ info.w = img->dst_rect.width;
+ info.h = img->dst_rect.height;
+ info.dirty.x = 0;
+ info.dirty.y = 0;
+ info.dirty.w = img->dst_rect.width;
+ info.dirty.h = img->dst_rect.height;
+ info.paddr = buffer->paddr;
+
+ mcde_dss_apply_overlay(ovly, &info);
+ return ret;
+
+pin_failed:
+invalid_mem:
+ buffer->alloc = NULL;
+ buffer->size = 0;
+ buffer->paddr = 0;
+
+resolve_failed:
+ return ret;
+}
+
+static int compdev_update_rotation(struct dss_context *dss_ctx,
+ enum compdev_rotation rotation)
+{
+ /* Set video mode */
+ struct mcde_video_mode vmode;
+ int ret = 0;
+
+ memset(&vmode, 0, sizeof(struct mcde_video_mode));
+ mcde_dss_get_video_mode(dss_ctx->ddev, &vmode);
+ if ((dss_ctx->display_rotation + rotation) % 180) {
+ vmode.xres = dss_ctx->phy_size.height;
+ vmode.yres = dss_ctx->phy_size.width;
+ } else {
+ vmode.xres = dss_ctx->phy_size.width;
+ vmode.yres = dss_ctx->phy_size.height;
+ }
+
+ /* Set rotation */
+ ret = mcde_dss_set_rotation(dss_ctx->ddev,
+ (dss_ctx->display_rotation + rotation) % 360);
+ if (ret != 0)
+ goto exit;
+
+ ret = mcde_dss_set_video_mode(dss_ctx->ddev, &vmode);
+ if (ret != 0)
+ goto exit;
+
+
+ /* Apply */
+ ret = mcde_dss_apply_channel(dss_ctx->ddev);
+exit:
+ return ret;
+}
+
+static int release_prev_frame(struct dss_context *dss_ctx)
+{
+ int ret = 0;
+ int i;
+
+ /* Handle unpin of previous buffers */
+ for (i = 0; i < NUM_COMPDEV_BUFS; i++) {
+ if (dss_ctx->ovly_buffer[i].type ==
+ COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET &&
+ dss_ctx->ovly_buffer[i].paddr != 0) {
+ hwmem_unpin(dss_ctx->ovly_buffer[i].alloc);
+ hwmem_release(dss_ctx->ovly_buffer[i].alloc);
+ }
+ dss_ctx->ovly_buffer[i].alloc = NULL;
+ dss_ctx->ovly_buffer[i].size = 0;
+ dss_ctx->ovly_buffer[i].paddr = 0;
+ }
+ return ret;
+
+}
+
+static enum b2r2_blt_fmt compdev_to_blt_format(enum compdev_fmt fmt)
+{
+ switch (fmt) {
+ case COMPDEV_FMT_RGBA8888:
+ return B2R2_BLT_FMT_32_BIT_ABGR8888;
+ case COMPDEV_FMT_RGB888:
+ return B2R2_BLT_FMT_24_BIT_RGB888;
+ case COMPDEV_FMT_RGB565:
+ return B2R2_BLT_FMT_16_BIT_RGB565;
+ case COMPDEV_FMT_YUV422:
+ return B2R2_BLT_FMT_CB_Y_CR_Y;
+ case COMPDEV_FMT_YCBCR42XMBN:
+ return B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE;
+ case COMPDEV_FMT_YUV420_SP:
+ return B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR;
+ case COMPDEV_FMT_YVU420_SP:
+ return B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR;
+ case COMPDEV_FMT_YUV420_P:
+ return B2R2_BLT_FMT_YUV420_PACKED_PLANAR;
+ default:
+ return B2R2_BLT_FMT_UNUSED;
+ }
+}
+
+static enum b2r2_blt_transform to_blt_transform
+ (enum compdev_rotation compdev_rot)
+{
+ switch (compdev_rot) {
+ case COMPDEV_ROT_0:
+ return B2R2_BLT_TRANSFORM_NONE;
+ case COMPDEV_ROT_90_CCW:
+ return B2R2_BLT_TRANSFORM_CCW_ROT_90;
+ case COMPDEV_ROT_180:
+ return B2R2_BLT_TRANSFORM_CCW_ROT_180;
+ case COMPDEV_ROT_270_CCW:
+ return B2R2_BLT_TRANSFORM_CCW_ROT_90;
+ default:
+ return B2R2_BLT_TRANSFORM_NONE;
+ }
+}
+
+static u32 get_stride(u32 width, enum compdev_fmt fmt)
+{
+ u32 stride = 0;
+ switch (fmt) {
+ case COMPDEV_FMT_RGB565:
+ stride = width * 2;
+ break;
+ case COMPDEV_FMT_RGB888:
+ stride = width * 3;
+ break;
+ case COMPDEV_FMT_RGBX8888:
+ stride = width * 4;
+ break;
+ case COMPDEV_FMT_RGBA8888:
+ stride = width * 4;
+ break;
+ case COMPDEV_FMT_YUV422:
+ stride = width * 2;
+ break;
+ case COMPDEV_FMT_YCBCR42XMBN:
+ case COMPDEV_FMT_YUV420_SP:
+ case COMPDEV_FMT_YVU420_SP:
+ case COMPDEV_FMT_YUV420_P:
+ stride = width;
+ break;
+ }
+
+ /* The display controller requires 8 byte aligned strides */
+ if (stride % 8)
+ stride += 8 - (stride % 8);
+
+ return stride;
+}
+
+static int alloc_comp_internal_img(enum compdev_fmt fmt,
+ u16 width, u16 height, struct compdev_img_internal **img_pp)
+{
+ struct hwmem_alloc *alloc;
+ int name;
+ u32 size;
+ u32 stride;
+ struct compdev_img_internal *img;
+
+ stride = get_stride(width, fmt);
+ size = stride * height;
+ size = PAGE_ALIGN(size);
+
+ img = kzalloc(sizeof(struct compdev_img_internal), GFP_KERNEL);
+
+ if (!img)
+ return -ENOMEM;
+
+ alloc = hwmem_alloc(size, HWMEM_ALLOC_HINT_WRITE_COMBINE |
+ HWMEM_ALLOC_HINT_UNCACHED,
+ (HWMEM_ACCESS_READ | HWMEM_ACCESS_WRITE |
+ HWMEM_ACCESS_IMPORT),
+ HWMEM_MEM_CONTIGUOUS_SYS);
+
+ if (IS_ERR(alloc)) {
+ kfree(img);
+ img = NULL;
+ return PTR_ERR(alloc);
+ }
+
+ name = hwmem_get_name(alloc);
+ if (name < 0) {
+ kfree(img);
+ img = NULL;
+ hwmem_release(alloc);
+ return name;
+ }
+
+ img->img.height = height;
+ img->img.width = width;
+ img->img.fmt = fmt;
+ img->img.pitch = stride;
+ img->img.buf.hwmem_buf_name = name;
+ img->img.buf.type = COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET;
+ img->img.buf.offset = 0;
+ img->img.buf.len = size;
+
+ img->ref_count = 1;
+
+ *img_pp = img;
+
+ return 0;
+}
+
+static void free_comp_img_buf(struct compdev_img_internal *img,
+ struct device *dev)
+{
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (img != NULL && img->ref_count) {
+ img->ref_count--;
+ if (img->ref_count == 0) {
+ struct hwmem_alloc *alloc;
+ if (img->img.buf.hwmem_buf_name > 0) {
+ alloc = hwmem_resolve_by_name(
+ img->img.buf.hwmem_buf_name);
+ if (IS_ERR(alloc)) {
+ dev_err(dev, "%s: Error getting Alloc "
+ "from HWMEM\n", __func__);
+ return;
+ }
+ /* Double release needed */
+ hwmem_release(alloc);
+ hwmem_release(alloc);
+ }
+ kfree(img);
+ }
+ }
+}
+
+struct compdev_img_internal *compdev_buffer_cache_get_image(
+ struct buffer_cache_context *cache_ctx, enum compdev_fmt fmt,
+ u16 width, u16 height)
+{
+ int i;
+ struct compdev_img_internal *img = NULL;
+
+ dev_dbg(cache_ctx->dev, "%s\n", __func__);
+
+ /* First check for a cache hit */
+ if (cache_ctx->unused_counter > 0) {
+ u8 active_index = cache_ctx->index;
+ struct compdev_img_internal *temp =
+ cache_ctx->img[active_index];
+ if (temp != NULL && temp->img.fmt == fmt &&
+ temp->img.width == width &&
+ temp->img.height == height) {
+ img = temp;
+ cache_ctx->unused_counter = 0;
+ }
+ }
+ /* Check if there was a cache hit */
+ if (img == NULL) {
+ /* Create new buffers and release old */
+ for (i = 0; i < BUFFER_CACHE_DEPTH; i++) {
+ if (cache_ctx->img[i]) {
+ free_comp_img_buf(cache_ctx->img[i],
+ cache_ctx->dev);
+ cache_ctx->img[i] = NULL;
+ }
+ cache_ctx->index = 0;
+ if (alloc_comp_internal_img(fmt, width, height,
+ &cache_ctx->img[i]))
+ dev_err(cache_ctx->dev,
+ "%s: Allocation error\n",
+ __func__);
+ }
+ img = cache_ctx->img[0];
+ }
+
+ if (img != NULL) {
+ img->ref_count++;
+ cache_ctx->unused_counter = 0;
+ cache_ctx->index++;
+ if (cache_ctx->index >= BUFFER_CACHE_DEPTH)
+ cache_ctx->index = 0;
+ }
+
+ return img;
+}
+
+static void compdev_buffer_cache_mark_frame
+ (struct buffer_cache_context *cache_ctx)
+{
+ if (cache_ctx->unused_counter < 2)
+ cache_ctx->unused_counter++;
+ if (cache_ctx->unused_counter == 2) {
+ int i;
+ for (i = 0; i < BUFFER_CACHE_DEPTH; i++) {
+ if (cache_ctx->img[i]) {
+ free_comp_img_buf(cache_ctx->img[i],
+ cache_ctx->dev);
+ cache_ctx->img[i] = NULL;
+ }
+ }
+ }
+}
+
+static bool check_hw_format(enum compdev_fmt fmt)
+{
+ if (fmt == COMPDEV_FMT_RGB565 ||
+ fmt == COMPDEV_FMT_RGB888 ||
+ fmt == COMPDEV_FMT_RGBA8888 ||
+ fmt == COMPDEV_FMT_RGBX8888 ||
+ fmt == COMPDEV_FMT_YUV422)
+ return true;
+ else
+ return false;
+}
+
+static enum compdev_fmt find_compatible_fmt(enum compdev_fmt fmt, bool rotation)
+{
+ if (!rotation) {
+ switch (fmt) {
+ case COMPDEV_FMT_RGB565:
+ case COMPDEV_FMT_RGB888:
+ case COMPDEV_FMT_RGBA8888:
+ case COMPDEV_FMT_RGBX8888:
+ return fmt;
+ case COMPDEV_FMT_YUV422:
+ case COMPDEV_FMT_YCBCR42XMBN:
+ case COMPDEV_FMT_YUV420_SP:
+ case COMPDEV_FMT_YVU420_SP:
+ case COMPDEV_FMT_YUV420_P:
+ return COMPDEV_FMT_YUV422;
+ default:
+ return COMPDEV_FMT_RGBA8888;
+ }
+ } else {
+ switch (fmt) {
+ case COMPDEV_FMT_RGB565:
+ case COMPDEV_FMT_RGB888:
+ case COMPDEV_FMT_RGBA8888:
+ case COMPDEV_FMT_RGBX8888:
+ return fmt;
+ case COMPDEV_FMT_YUV422:
+ case COMPDEV_FMT_YCBCR42XMBN:
+ case COMPDEV_FMT_YUV420_SP:
+ case COMPDEV_FMT_YVU420_SP:
+ case COMPDEV_FMT_YUV420_P:
+ return COMPDEV_FMT_RGB888;
+ default:
+ return COMPDEV_FMT_RGBA8888;
+ }
+ }
+}
+
+static void compdev_callback_worker_function(struct work_struct *work)
+{
+ struct compdev_post_callback_work *cb_work =
+ (struct compdev_post_callback_work *)work;
+
+ if (cb_work->pb_cb != NULL)
+ cb_work->pb_cb(cb_work->cb_data, cb_work->img);
+}
+static void compdev_blt_worker_function(struct work_struct *work)
+{
+ struct compdev_blt_work *blt_work = (struct compdev_blt_work *)work;
+ struct compdev_img *src_img;
+ struct compdev_img *dst_img;
+ struct b2r2_blt_req req;
+ int req_id;
+
+ dev_dbg(blt_work->dev, "%s\n", __func__);
+
+ src_img = blt_work->src_img;
+ dst_img = &blt_work->dst_img->img;
+
+ memset(&req, 0, sizeof(req));
+ req.size = sizeof(req);
+
+ if (src_img->buf.type == COMPDEV_PTR_PHYSICAL) {
+ req.src_img.buf.type = B2R2_BLT_PTR_PHYSICAL;
+ req.src_img.buf.fd = src_img->buf.fd;
+ } else {
+ struct hwmem_alloc *alloc;
+
+ req.src_img.buf.type = B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET;
+ req.src_img.buf.hwmem_buf_name = src_img->buf.hwmem_buf_name;
+
+ alloc = hwmem_resolve_by_name(src_img->buf.hwmem_buf_name);
+ if (IS_ERR(alloc)) {
+ dev_warn(blt_work->dev,
+ "HWMEM resolve failed\n");
+ }
+ hwmem_set_access(alloc,
+ HWMEM_ACCESS_READ | HWMEM_ACCESS_IMPORT,
+ task_tgid_nr(current));
+ hwmem_release(alloc);
+ }
+ req.src_img.pitch = src_img->pitch;
+ req.src_img.buf.offset = src_img->buf.offset;
+ req.src_img.buf.len = src_img->buf.len;
+ req.src_img.fmt = compdev_to_blt_format(src_img->fmt);
+ req.src_img.width = src_img->width;
+ req.src_img.height = src_img->height;
+
+ req.src_rect.x = src_img->src_rect.x;
+ req.src_rect.y = src_img->src_rect.y;
+ req.src_rect.width = src_img->src_rect.width;
+ req.src_rect.height = src_img->src_rect.height;
+
+ if (dst_img->buf.type == COMPDEV_PTR_PHYSICAL) {
+ req.dst_img.buf.type = B2R2_BLT_PTR_PHYSICAL;
+ req.dst_img.buf.fd = dst_img->buf.fd;
+ } else {
+ req.dst_img.buf.type = B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET;
+ req.dst_img.buf.hwmem_buf_name = dst_img->buf.hwmem_buf_name;
+ }
+ req.dst_img.pitch = dst_img->pitch;
+ req.dst_img.buf.offset = dst_img->buf.offset;
+ req.dst_img.buf.len = dst_img->buf.len;
+ req.dst_img.fmt = compdev_to_blt_format(dst_img->fmt);
+ req.dst_img.width = dst_img->width;
+ req.dst_img.height = dst_img->height;
+
+ if (blt_work->mcde_rotation)
+ req.transform = B2R2_BLT_TRANSFORM_NONE;
+ else
+ req.transform = to_blt_transform(src_img->rotation);
+ req.dst_rect.x = 0;
+ req.dst_rect.y = 0;
+ req.dst_rect.width = src_img->dst_rect.width;
+ req.dst_rect.height = src_img->dst_rect.height;
+
+ req.global_alpha = 0xff;
+ req.flags = B2R2_BLT_FLAG_DITHER;
+
+ req_id = b2r2_blt_request(blt_work->blt_handle, &req);
+
+ if (b2r2_blt_synch(blt_work->blt_handle, req_id) < 0) {
+ dev_err(blt_work->dev,
+ "%s: Could not perform b2r2_blt_synch",
+ __func__);
+ }
+
+ dst_img->src_rect.x = 0;
+ dst_img->src_rect.x = 0;
+ dst_img->src_rect.width = dst_img->width;
+ dst_img->src_rect.height = dst_img->height;
+
+ dst_img->dst_rect.x = src_img->dst_rect.x;
+ dst_img->dst_rect.y = src_img->dst_rect.y;
+ dst_img->dst_rect.width = src_img->dst_rect.width;
+ dst_img->dst_rect.height = src_img->dst_rect.height;
+
+ dst_img->rotation = src_img->rotation;
+}
+
+static int compdev_post_buffer_locked(struct compdev *cd,
+ struct compdev_img *src_img)
+{
+ int ret = 0;
+ int i;
+ bool transform_needed = false;
+ struct compdev_img *resulting_img;
+ struct compdev_blt_work blt_work;
+ struct compdev_post_callback_work cb_work;
+ bool callback_work = false;
+ bool bypass_case = false;
+
+ dev_dbg(cd->dev, "%s\n", __func__);
+
+ /* Free potential temp buffers */
+ for (i = 0; i < cd->dss_ctx.temp_img_count; i++)
+ free_comp_img_buf(cd->dss_ctx.temp_img[i], cd->dev);
+ cd->dss_ctx.temp_img_count = 0;
+
+ /* Check for bypass images */
+ if (src_img->flags & COMPDEV_BYPASS_FLAG)
+ bypass_case = true;
+
+ /* Handle callback */
+ if (cd->pb_cb != NULL) {
+ callback_work = true;
+ INIT_WORK((struct work_struct *)&cb_work,
+ compdev_callback_worker_function);
+ cb_work.img = src_img;
+ cb_work.pb_cb = cd->pb_cb;
+ cb_work.cb_data = cd->cb_data;
+ cb_work.dev = cd->dev;
+ queue_work(cd->worker_thread, (struct work_struct *)&cb_work);
+ }
+
+ if (!bypass_case) {
+ /* Determine if transform is needed */
+ /* First check scaling */
+ if ((src_img->rotation == COMPDEV_ROT_0 ||
+ src_img->rotation == COMPDEV_ROT_180) &&
+ (src_img->src_rect.width != src_img->dst_rect.width ||
+ src_img->src_rect.height != src_img->dst_rect.height))
+ transform_needed = true;
+ else if ((src_img->rotation == COMPDEV_ROT_90_CCW ||
+ src_img->rotation == COMPDEV_ROT_270_CCW) &&
+ (src_img->src_rect.width != src_img->dst_rect.height ||
+ src_img->src_rect.height != src_img->dst_rect.width))
+ transform_needed = true;
+
+ if (!transform_needed && check_hw_format(src_img->fmt) == false)
+ transform_needed = true;
+
+ if (transform_needed) {
+ u16 width = 0;
+ u16 height = 0;
+ enum compdev_fmt fmt;
+
+ INIT_WORK((struct work_struct *)&blt_work,
+ compdev_blt_worker_function);
+
+ if (cd->dss_ctx.blt_handle == 0) {
+ dev_dbg(cd->dev, "%s: B2R2 opened\n", __func__);
+ cd->dss_ctx.blt_handle = b2r2_blt_open();
+ if (cd->dss_ctx.blt_handle < 0) {
+ dev_warn(cd->dev,
+ "%s(%d): Failed to "
+ "open b2r2 device\n",
+ __func__, __LINE__);
+ }
+ }
+ blt_work.blt_handle = cd->dss_ctx.blt_handle;
+ blt_work.src_img = src_img;
+ blt_work.mcde_rotation = cd->mcde_rotation;
+
+ width = src_img->dst_rect.width;
+ height = src_img->dst_rect.height;
+
+ fmt = find_compatible_fmt(src_img->fmt,
+ (!cd->mcde_rotation) &&
+ (src_img->rotation != COMPDEV_ROT_0));
+
+ blt_work.dst_img = compdev_buffer_cache_get_image
+ (&cd->dss_ctx.cache_ctx,
+ fmt, width, height);
+
+ blt_work.dst_img->img.flags = src_img->flags;
+ blt_work.dev = cd->dev;
+
+ queue_work(cd->worker_thread,
+ (struct work_struct *)&blt_work);
+ flush_work_sync((struct work_struct *)&blt_work);
+
+ resulting_img = &blt_work.dst_img->img;
+
+ cd->dss_ctx.temp_img[cd->dss_ctx.temp_img_count] =
+ blt_work.dst_img;
+ cd->dss_ctx.temp_img_count++;
+
+ } else {
+ resulting_img = src_img;
+ }
+
+ if (!cd->mcde_rotation)
+ resulting_img->rotation = COMPDEV_ROT_0;
+
+ cd->images[cd->image_count] = resulting_img;
+ cd->image_count++;
+
+ /* make sure that a potential callback has returned */
+ if (callback_work)
+ flush_work_sync((struct work_struct *)&cb_work);
+
+ if (cd->sync_count > 1) {
+ cd->sync_count--;
+ mutex_unlock(&cd->lock);
+ /* Wait for fence */
+ wait_for_completion(&cd->fence);
+ mutex_lock(&cd->lock);
+ } else {
+ struct compdev_img *img1 = NULL;
+ struct compdev_img *img2 = NULL;
+
+ if (cd->sync_count)
+ cd->sync_count--;
+
+ img1 = cd->images[0];
+ if (cd->image_count)
+ img2 = cd->images[1];
+
+ /* Do the refresh */
+ compdev_post_buffers_dss(&cd->dss_ctx, img1, img2);
+ compdev_buffer_cache_mark_frame
+ (&cd->dss_ctx.cache_ctx);
+
+ if (cd->s_info.img_count > 1) {
+ /* Releasing fence */
+ complete(&cd->fence);
+ }
+
+ cd->sync_count = 0;
+ cd->image_count = 0;
+ cd->images[0] = NULL;
+ cd->images[1] = NULL;
+ }
+ } else {
+ /* make sure that a potential callback has returned */
+ if (callback_work)
+ flush_work_sync((struct work_struct *)&cb_work);
+ }
+
+ return ret;
+}
+
+static int compdev_post_buffers_dss(struct dss_context *dss_ctx,
+ struct compdev_img *img1, struct compdev_img *img2)
+{
+ int ret = 0;
+ int i = 0;
+
+ struct compdev_img *fb_img = NULL;
+ struct compdev_img *ovly_img = NULL;
+
+ /* Unpin the previous frame */
+ release_prev_frame(dss_ctx);
+
+ /* Set channel rotation */
+ if (img1 != NULL &&
+ (dss_ctx->current_buffer_rotation != img1->rotation)) {
+ if (compdev_update_rotation(dss_ctx, img1->rotation) != 0)
+ dev_warn(dss_ctx->dev,
+ "Failed to update MCDE rotation "
+ "(img1->rotation = %d), %d\n",
+ img1->rotation, ret);
+ else
+ dss_ctx->current_buffer_rotation = img1->rotation;
+ }
+
+ if ((img1 != NULL) && (img1->flags & COMPDEV_OVERLAY_FLAG))
+ ovly_img = img1;
+ else if (img1 != NULL)
+ fb_img = img1;
+
+
+ if ((img2 != NULL) && (img2->flags & COMPDEV_OVERLAY_FLAG))
+ ovly_img = img2;
+ else if (img2 != NULL)
+ fb_img = img2;
+
+ /* Handle buffers */
+ if (fb_img != NULL) {
+ ret = compdev_setup_ovly(fb_img,
+ &dss_ctx->ovly_buffer[i], dss_ctx->ovly[0], 1, dss_ctx);
+ if (ret)
+ dev_warn(dss_ctx->dev,
+ "Failed to setup overlay[%d], %d\n", 0, ret);
+ i++;
+ } else {
+ disable_overlay(dss_ctx->ovly[0]);
+ }
+
+
+ if (ovly_img != NULL) {
+ ret = compdev_setup_ovly(ovly_img,
+ &dss_ctx->ovly_buffer[i], dss_ctx->ovly[1], 0, dss_ctx);
+ if (ret)
+ dev_warn(dss_ctx->dev,
+ "Failed to setup overlay[%d], %d\n", 1, ret);
+ } else {
+ disable_overlay(dss_ctx->ovly[1]);
+ }
+
+ /* Do the display update */
+ mcde_dss_update_overlay(dss_ctx->ovly[0], true);
+
+ return ret;
+}
+
+static int compdev_post_scene_info_locked(struct compdev *cd,
+ struct compdev_scene_info *s_info)
+{
+ int ret = 0;
+
+ dev_dbg(cd->dev, "%s\n", __func__);
+
+ cd->s_info = *s_info;
+ cd->sync_count = cd->s_info.img_count;
+
+ /* always complete the fence in case someone is hanging incorrectly. */
+ complete(&cd->fence);
+ init_completion(&cd->fence);
+
+ /* Handle callback */
+ if (cd->si_cb != NULL) {
+ mutex_unlock(&cd->lock);
+ cd->si_cb(cd->cb_data, s_info);
+ mutex_lock(&cd->lock);
+ }
+ return ret;
+}
+
+
+static int compdev_get_size_locked(struct dss_context *dss_ctx,
+ struct compdev_size *size)
+{
+ int ret = 0;
+ if ((dss_ctx->display_rotation) % 180) {
+ size->height = dss_ctx->phy_size.width;
+ size->width = dss_ctx->phy_size.height;
+ } else {
+ size->height = dss_ctx->phy_size.height;
+ size->width = dss_ctx->phy_size.width;
+ }
+
+ return ret;
+}
+
+static int compdev_get_listener_state_locked(struct compdev *cd,
+ enum compdev_listener_state *state)
+{
+ int ret = 0;
+
+ *state = COMPDEV_LISTENER_OFF;
+ if (cd->pb_cb != NULL)
+ *state = COMPDEV_LISTENER_ON;
+ return ret;
+}
+
+static long compdev_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct compdev *cd = (struct compdev *)file->private_data;
+ struct compdev_img img;
+ struct compdev_scene_info s_info;
+
+ mutex_lock(&cd->lock);
+
+ switch (cmd) {
+ case COMPDEV_GET_SIZE_IOC:
+ {
+ struct compdev_size tmp;
+ compdev_get_size_locked(&cd->dss_ctx, &tmp);
+ ret = copy_to_user((void __user *)arg, &tmp,
+ sizeof(tmp));
+ if (ret)
+ ret = -EFAULT;
+ }
+ break;
+ case COMPDEV_GET_LISTENER_STATE_IOC:
+ {
+ enum compdev_listener_state state;
+ compdev_get_listener_state_locked(cd, &state);
+ ret = copy_to_user((void __user *)arg, &state,
+ sizeof(state));
+ if (ret)
+ ret = -EFAULT;
+ }
+ break;
+ case COMPDEV_POST_BUFFER_IOC:
+ memset(&img, 0, sizeof(img));
+ /* Get the user data */
+ if (copy_from_user(&img, (void *)arg, sizeof(img))) {
+ dev_warn(cd->dev,
+ "%s: copy_from_user failed\n",
+ __func__);
+ mutex_unlock(&cd->lock);
+ return -EFAULT;
+ }
+ ret = compdev_post_buffer_locked(cd, &img);
+
+ break;
+ case COMPDEV_POST_SCENE_INFO_IOC:
+ memset(&s_info, 0, sizeof(s_info));
+ /* Get the user data */
+ if (copy_from_user(&s_info, (void *)arg, sizeof(s_info))) {
+ dev_warn(cd->dev,
+ "%s: copy_from_user failed\n",
+ __func__);
+ mutex_unlock(&cd->lock);
+ return -EFAULT;
+ }
+ ret = compdev_post_scene_info_locked(cd, &s_info);
+
+ break;
+
+ default:
+ ret = -ENOSYS;
+ }
+
+ mutex_unlock(&cd->lock);
+
+ return ret;
+}
+
+static const struct file_operations compdev_fops = {
+ .open = compdev_open,
+ .release = compdev_release,
+ .unlocked_ioctl = compdev_ioctl,
+};
+
+static void init_compdev(struct compdev *cd, const char *name)
+{
+ mutex_init(&cd->lock);
+ INIT_LIST_HEAD(&cd->list);
+ init_completion(&cd->fence);
+
+ cd->mdev.minor = MISC_DYNAMIC_MINOR;
+ cd->mdev.name = name;
+ cd->mdev.fops = &compdev_fops;
+ cd->dev = cd->mdev.this_device;
+}
+
+static void init_dss_context(struct dss_context *dss_ctx,
+ struct mcde_display_device *ddev, struct compdev *cd)
+{
+ dss_ctx->ddev = ddev;
+ dss_ctx->dev = cd->dev;
+ memset(&dss_ctx->cache_ctx, 0, sizeof(struct buffer_cache_context));
+ dss_ctx->cache_ctx.dev = dss_ctx->dev;
+}
+
+int compdev_create(struct mcde_display_device *ddev,
+ struct mcde_overlay *parent_ovly, bool mcde_rotation)
+{
+ int ret = 0;
+ int i;
+ struct compdev *cd;
+ struct mcde_video_mode vmode;
+ struct mcde_overlay_info info;
+
+ char name[10];
+
+ if (dev_counter == 0) {
+ for (i = 0; i < MAX_NBR_OF_COMPDEVS; i++)
+ compdevs[i] = NULL;
+ }
+
+ if (dev_counter > MAX_NBR_OF_COMPDEVS)
+ return -ENOMEM;
+
+ cd = kzalloc(sizeof(struct compdev), GFP_KERNEL);
+ if (!cd)
+ return -ENOMEM;
+
+ compdevs[dev_counter] = cd;
+ cd->dev_index = dev_counter;
+
+ snprintf(name, sizeof(name), "%s%d", COMPDEV_DEFAULT_DEVICE_PREFIX,
+ dev_counter++);
+ init_compdev(cd, name);
+
+ init_dss_context(&cd->dss_ctx, ddev, cd);
+
+ mcde_dss_get_video_mode(ddev, &vmode);
+
+ cd->worker_thread = create_workqueue(name);
+ if (!cd->worker_thread) {
+ ret = -ENOMEM;
+ goto fail_workqueue;
+ }
+
+ cd->dss_ctx.ovly[0] = parent_ovly;
+ if (!cd->dss_ctx.ovly[0]) {
+ ret = -ENOMEM;
+ goto fail_create_ovly;
+ }
+
+ for (i = 1; i < NUM_COMPDEV_BUFS; i++) {
+ cd->dss_ctx.ovly[i] = mcde_dss_create_overlay(ddev, &info);
+ if (!cd->dss_ctx.ovly[i]) {
+ ret = -ENOMEM;
+ goto fail_create_ovly;
+ }
+ if (mcde_dss_enable_overlay(cd->dss_ctx.ovly[i]))
+ goto fail_create_ovly;
+ if (disable_overlay(cd->dss_ctx.ovly[i]))
+ goto fail_create_ovly;
+ }
+
+ mcde_dss_get_native_resolution(ddev, &cd->dss_ctx.phy_size.width,
+ &cd->dss_ctx.phy_size.height);
+ cd->dss_ctx.display_rotation = mcde_dss_get_rotation(ddev);
+ cd->dss_ctx.current_buffer_rotation = 0;
+
+ cd->mcde_rotation = mcde_rotation;
+
+ ret = misc_register(&cd->mdev);
+ if (ret)
+ goto fail_register_misc;
+ mutex_lock(&dev_list_lock);
+ list_add_tail(&cd->list, &dev_list);
+ mutex_unlock(&dev_list_lock);
+
+ goto out;
+
+fail_register_misc:
+fail_create_ovly:
+ for (i = 0; i < NUM_COMPDEV_BUFS; i++) {
+ if (cd->dss_ctx.ovly[i])
+ mcde_dss_destroy_overlay(cd->dss_ctx.ovly[i]);
+ }
+fail_workqueue:
+ kfree(cd);
+out:
+ return ret;
+}
+
+
+int compdev_get(int dev_idx, struct compdev **cd_pp)
+{
+ struct compdev *cd;
+ cd = NULL;
+
+ if (dev_idx >= MAX_NBR_OF_COMPDEVS)
+ return -ENOMEM;
+
+ cd = compdevs[dev_idx];
+ if (cd != NULL) {
+ mutex_lock(&cd->lock);
+ cd->ref_count++;
+ mutex_unlock(&cd->lock);
+ *cd_pp = cd;
+ return 0;
+ } else {
+ return -ENOMEM;
+ }
+}
+EXPORT_SYMBOL(compdev_get);
+
+int compdev_put(struct compdev *cd)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+
+ mutex_lock(&cd->lock);
+ cd->ref_count--;
+ if (cd->ref_count < 0)
+ dev_warn(cd->dev,
+ "%s: Incorrect ref count\n", __func__);
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_put);
+
+int compdev_get_size(struct compdev *cd, struct compdev_size *size)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+
+ mutex_lock(&cd->lock);
+
+ ret = compdev_get_size_locked(&cd->dss_ctx, size);
+
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_get_size);
+
+int compdev_get_listener_state(struct compdev *cd,
+ enum compdev_listener_state *listener_state)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+
+ mutex_lock(&cd->lock);
+
+ ret = compdev_get_listener_state_locked(cd, listener_state);
+
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_get_listener_state);
+
+
+int compdev_post_buffer(struct compdev *cd, struct compdev_img *img)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+
+ mutex_lock(&cd->lock);
+
+ ret = compdev_post_buffer_locked(cd, img);
+
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_post_buffer);
+
+int compdev_post_scene_info(struct compdev *cd,
+ struct compdev_scene_info *s_info)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+
+ mutex_lock(&cd->lock);
+
+ ret = compdev_post_scene_info_locked(cd, s_info);
+
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_post_scene_info);
+
+int compdev_register_listener_callbacks(struct compdev *cd, void *data,
+ post_buffer_callback pb_cb, post_scene_info_callback si_cb)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+ mutex_lock(&cd->lock);
+ cd->cb_data = data;
+ cd->pb_cb = pb_cb;
+ cd->si_cb = si_cb;
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_register_listener_callbacks);
+
+int compdev_deregister_callbacks(struct compdev *cd)
+{
+ int ret = 0;
+ if (cd == NULL)
+ return -ENOMEM;
+ mutex_lock(&cd->lock);
+ cd->cb_data = NULL;
+ cd->pb_cb = NULL;
+ cd->si_cb = NULL;
+ mutex_unlock(&cd->lock);
+ return ret;
+}
+EXPORT_SYMBOL(compdev_deregister_callbacks);
+
+void compdev_destroy(struct mcde_display_device *ddev)
+{
+ struct compdev *cd;
+ struct compdev *tmp;
+ int i;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(cd, tmp, &dev_list, list) {
+ if (cd->dss_ctx.ddev == ddev) {
+ list_del(&cd->list);
+ misc_deregister(&cd->mdev);
+ for (i = 1; i < NUM_COMPDEV_BUFS; i++)
+ mcde_dss_destroy_overlay(cd->dss_ctx.ovly[i]);
+ b2r2_blt_close(cd->dss_ctx.blt_handle);
+
+ release_prev_frame(&cd->dss_ctx);
+
+ /* Free potential temp buffers */
+ for (i = 0; i < cd->dss_ctx.temp_img_count; i++)
+ free_comp_img_buf(cd->dss_ctx.temp_img[i],
+ cd->dev);
+
+ for (i = 0; i < BUFFER_CACHE_DEPTH; i++) {
+ if (cd->dss_ctx.cache_ctx.img[i]) {
+ free_comp_img_buf
+ (cd->dss_ctx.cache_ctx.img[i],
+ cd->dev);
+ cd->dss_ctx.cache_ctx.img[i] = NULL;
+ }
+ }
+
+ destroy_workqueue(cd->worker_thread);
+ kfree(cd);
+ break;
+ }
+ }
+ dev_counter--;
+ mutex_unlock(&dev_list_lock);
+}
+
+static void compdev_destroy_all(void)
+{
+ struct compdev *cd;
+ struct compdev *tmp;
+ int i;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(cd, tmp, &dev_list, list) {
+ list_del(&cd->list);
+ misc_deregister(&cd->mdev);
+ for (i = 0; i < NUM_COMPDEV_BUFS; i++)
+ mcde_dss_destroy_overlay(cd->dss_ctx.ovly[i]);
+
+ release_prev_frame(&cd->dss_ctx);
+ /* Free potential temp buffers */
+ for (i = 0; i < cd->dss_ctx.temp_img_count; i++)
+ free_comp_img_buf(cd->dss_ctx.temp_img[i], cd->dev);
+
+ for (i = 0; i < BUFFER_CACHE_DEPTH; i++) {
+ if (cd->dss_ctx.cache_ctx.img[i]) {
+ free_comp_img_buf
+ (cd->dss_ctx.cache_ctx.img[i],
+ cd->dev);
+ cd->dss_ctx.cache_ctx.img[i] = NULL;
+ }
+ }
+
+ kfree(cd);
+ }
+ mutex_unlock(&dev_list_lock);
+
+ mutex_destroy(&dev_list_lock);
+}
+
+static int __init compdev_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ mutex_init(&dev_list_lock);
+
+ return 0;
+}
+module_init(compdev_init);
+
+static void __exit compdev_exit(void)
+{
+ compdev_destroy_all();
+ pr_info("%s\n", __func__);
+}
+module_exit(compdev_exit);
+
+MODULE_AUTHOR("Anders Bauer <anders.bauer@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Display overlay device driver");
+
diff --git a/drivers/misc/dispdev/Makefile b/drivers/misc/dispdev/Makefile
new file mode 100644
index 00000000000..11dc7611d26
--- /dev/null
+++ b/drivers/misc/dispdev/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DISPDEV) += dispdev.o
diff --git a/drivers/misc/dispdev/dispdev.c b/drivers/misc/dispdev/dispdev.c
new file mode 100644
index 00000000000..5413a252d35
--- /dev/null
+++ b/drivers/misc/dispdev/dispdev.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Display output device driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+
+#include <linux/dispdev.h>
+#include <linux/hwmem.h>
+#include <video/mcde_dss.h>
+
+#define DENSITY_CHECK (16)
+#define MAX_BUFFERS 4
+
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(dev_list_lock);
+
+enum buffer_state {
+ BUF_UNUSED = 0,
+ BUF_QUEUED,
+ BUF_ACTIVATED,
+/*TODO:waitfordone BUF_DEACTIVATED,*/
+ BUF_FREE,
+ BUF_DEQUEUED,
+};
+
+struct dispdev_buffer {
+ struct hwmem_alloc *alloc;
+ u32 size;
+ enum buffer_state state;
+ u32 paddr; /* if pinned */
+};
+
+struct dispdev {
+ bool open;
+ struct mutex lock;
+ struct miscdevice mdev;
+ struct list_head list;
+ struct mcde_display_device *ddev;
+ struct mcde_overlay *ovly;
+ struct mcde_overlay *parent_ovly;
+ struct dispdev_config config;
+ bool overlay;
+ struct dispdev_buffer buffers[MAX_BUFFERS];
+ wait_queue_head_t waitq_dq;
+ /*
+ * For the rotation use case
+ * buffers_need_update is used to ensure that a set_config that
+ * changes width or height is followed by a unregister_buffer.
+ */
+ bool buffers_need_update;
+ /*
+ * For the overlay startup use case.
+ * first_update is used to handle the first update after a set_config.
+ * In this case a queue_buffer will arrive after set_config and not a
+ * unregister_buffer as in the rotation use case.
+ */
+ bool first_update;
+ char name[sizeof(DISPDEV_DEFAULT_DEVICE_PREFIX) + 3];
+};
+
+static int find_buf(struct dispdev *dd, enum buffer_state state)
+{
+ int i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ if (dd->buffers[i].state == state)
+ return i;
+ return -1;
+}
+
+int dispdev_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ struct dispdev *dd = NULL;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(dd, &dev_list, list)
+ if (dd->mdev.minor == iminor(inode))
+ break;
+
+ if (&dd->list == &dev_list) {
+ mutex_unlock(&dev_list_lock);
+ return -ENODEV;
+ }
+
+ if (dd->open) {
+ mutex_unlock(&dev_list_lock);
+ return -EBUSY;
+ }
+
+ dd->open = true;
+
+ mutex_unlock(&dev_list_lock);
+
+ ret = mcde_dss_enable_overlay(dd->ovly);
+ if (ret)
+ return ret;
+
+ file->private_data = dd;
+
+ return 0;
+}
+
+int dispdev_release(struct inode *inode, struct file *file)
+{
+ int i;
+ struct dispdev *dd = NULL;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry(dd, &dev_list, list)
+ if (dd->mdev.minor == iminor(inode))
+ break;
+ mutex_unlock(&dev_list_lock);
+
+ if (&dd->list == &dev_list)
+ return -ENODEV;
+
+ /* TODO: Make sure it waits for completion */
+ mcde_dss_disable_overlay(dd->ovly);
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ if (dd->buffers[i].paddr)
+ hwmem_unpin(dd->buffers[i].alloc);
+ if (dd->buffers[i].alloc)
+ hwmem_release(dd->buffers[i].alloc);
+ dd->buffers[i].alloc = NULL;
+ dd->buffers[i].state = BUF_UNUSED;
+ dd->buffers[i].size = 0;
+ dd->buffers[i].paddr = 0;
+ }
+ dd->open = false;
+ wake_up(&dd->waitq_dq);
+ return 0;
+}
+
+static enum mcde_ovly_pix_fmt get_ovly_fmt(enum dispdev_fmt fmt)
+{
+ switch (fmt) {
+ default:
+ case DISPDEV_FMT_RGB565:
+ return MCDE_OVLYPIXFMT_RGB565;
+ case DISPDEV_FMT_RGB888:
+ return MCDE_OVLYPIXFMT_RGB888;
+ case DISPDEV_FMT_RGBA8888:
+ return MCDE_OVLYPIXFMT_RGBA8888;
+ case DISPDEV_FMT_RGBX8888:
+ return MCDE_OVLYPIXFMT_RGBX8888;
+ case DISPDEV_FMT_YUV422:
+ return MCDE_OVLYPIXFMT_YCbCr422;
+ }
+}
+
+static void get_ovly_info(struct dispdev_config *cfg,
+ struct mcde_video_mode *vmode,
+ struct mcde_overlay_info *info, bool overlay)
+{
+ info->paddr = 0;
+ info->stride = cfg->stride;
+ info->fmt = get_ovly_fmt(cfg->format);
+ info->src_x = 0;
+ info->src_y = 0;
+ info->dst_x = cfg->x;
+ info->dst_y = cfg->y;
+ info->dst_z = cfg->z;
+ info->w = cfg->width;
+ info->h = cfg->height;
+ info->dirty.x = 0;
+ info->dirty.y = 0;
+ info->dirty.w = vmode->xres;
+ info->dirty.h = vmode->yres;
+}
+
+static int dispdev_set_config(struct dispdev *dd, struct dispdev_config *cfg)
+{
+ int ret = 0;
+ if (memcmp(&dd->config, cfg, sizeof(struct dispdev_config)) == 0)
+ return 0;
+
+ /*
+ * Only update MCDE if format, stride, width and height
+ * is the same. Otherwise just store the new config and update
+ * MCDE in the next queue buffer. This because the buffer that is
+ * active can be have the wrong format, width ...
+ */
+ if (cfg->format == dd->config.format &&
+ cfg->stride == dd->config.stride &&
+ cfg->width == dd->config.width &&
+ cfg->height == dd->config.height) {
+
+ int buf_index;
+ if (!dd->buffers_need_update) {
+ buf_index = find_buf(dd, BUF_ACTIVATED);
+ if (buf_index >= 0) {
+ struct mcde_overlay_info info;
+ struct dispdev_buffer *buf;
+ struct mcde_video_mode vmode;
+
+ buf = &dd->buffers[buf_index];
+ mcde_dss_get_video_mode(dd->ddev, &vmode);
+ get_ovly_info(cfg, &vmode, &info, dd->overlay);
+ info.paddr = buf->paddr;
+ ret = mcde_dss_apply_overlay(dd->ovly, &info);
+ if (!ret)
+ mcde_dss_update_overlay(dd->ovly,
+ false);
+ }
+ }
+ } else {
+ dd->buffers_need_update = true;
+ }
+
+ dd->config = *cfg;
+
+ return ret;
+}
+
+static int dispdev_register_buffer(struct dispdev *dd, s32 hwmem_name)
+{
+ int ret;
+ struct dispdev_buffer *buf;
+ enum hwmem_mem_type memtype;
+ enum hwmem_access access;
+
+ ret = find_buf(dd, BUF_UNUSED);
+ if (ret < 0)
+ return -ENOMEM;
+ buf = &dd->buffers[ret];
+ buf->alloc = hwmem_resolve_by_name(hwmem_name);
+ if (IS_ERR(buf->alloc)) {
+ ret = PTR_ERR(buf->alloc);
+ goto resolve_failed;
+ }
+
+ hwmem_get_info(buf->alloc, &buf->size, &memtype, &access);
+
+ if (!(access & HWMEM_ACCESS_READ) ||
+ memtype != HWMEM_MEM_CONTIGUOUS_SYS) {
+ ret = -EACCES;
+ goto invalid_mem;
+ }
+
+ buf->state = BUF_FREE;
+ goto out;
+invalid_mem:
+ hwmem_release(buf->alloc);
+resolve_failed:
+out:
+ return ret;
+}
+
+static int dispdev_unregister_buffer(struct dispdev *dd, u32 buf_idx)
+{
+ struct dispdev_buffer *buf = &dd->buffers[buf_idx];
+
+ if (buf_idx >= ARRAY_SIZE(dd->buffers))
+ return -EINVAL;
+
+ if (buf->state == BUF_UNUSED)
+ return -EINVAL;
+
+ if (dd->buffers_need_update)
+ dd->buffers_need_update = false;
+
+ if (buf->state == BUF_ACTIVATED) {
+ /* Disable the overlay */
+ struct mcde_overlay_info info;
+ struct mcde_video_mode vmode;
+ /* TODO Wait for frame done */
+ mcde_dss_get_video_mode(dd->ddev, &vmode);
+ get_ovly_info(&dd->config, &vmode, &info, dd->overlay);
+ mcde_dss_apply_overlay(dd->ovly, &info);
+ mcde_dss_update_overlay(dd->ovly, false);
+ hwmem_unpin(dd->buffers[buf_idx].alloc);
+ }
+
+ hwmem_release(buf->alloc);
+ buf->state = BUF_UNUSED;
+ buf->alloc = NULL;
+ buf->size = 0;
+ buf->paddr = 0;
+ dd->first_update = false;
+
+ return 0;
+}
+
+
+/**
+ * @brief Check if the buffer is transparent or black (ARGB = X000)
+ * Note: Only for ARGB32.
+ * Worst case: a ~full transparent buffer
+ * Results: ~2200us @800Mhz for a WVGA screen, with DENSITY_CHECK=8
+ * ~520us @800Mhz for a WVGA screen, with DENSITY_CHECK=16
+ *
+ * @param w witdh
+ * @param h height
+ * @param addr buffer addr
+ *
+ * @return 1 if the buffer is transparent, else 0
+ */
+static int is_transparent(int w, int h, u32 *addr)
+{
+ int i, j;
+ u32 *c, *next_line;
+ u32 sum;
+
+ next_line = addr;
+ sum = 0;
+
+ /* TODO Optimize me */
+ for (j = 0; j < h; j += DENSITY_CHECK) {
+ c = next_line;
+ for (i = 0; i < w; i += DENSITY_CHECK) {
+ sum += ((*c) & 0x00FFFFFF);
+ c += DENSITY_CHECK;
+ }
+ if (sum)
+ return 0; /* Not "transparent" */
+ next_line += (w * DENSITY_CHECK);
+ }
+
+ return 1; /* "Transparent" */
+}
+
+static int dispdev_queue_buffer(struct dispdev *dd,
+ struct dispdev_buffer_info *buffer)
+{
+ int ret, i;
+ struct mcde_overlay_info info;
+ struct hwmem_mem_chunk mem_chunk;
+ size_t mem_chunk_length = 1;
+ struct hwmem_region rgn = { .offset = 0, .count = 1, .start = 0 };
+ struct hwmem_alloc *alloc;
+ struct mcde_video_mode vmode;
+ u32 buf_idx = buffer->buf_idx;
+
+ if (buf_idx >= ARRAY_SIZE(dd->buffers) ||
+ dd->buffers[buf_idx].state != BUF_DEQUEUED)
+ return -EINVAL;
+
+ alloc = dd->buffers[buf_idx].alloc;
+ mcde_dss_get_video_mode(dd->ddev, &vmode);
+ get_ovly_info(&dd->config, &vmode, &info, dd->overlay);
+ ret = hwmem_pin(alloc, &mem_chunk, &mem_chunk_length);
+ if (ret) {
+ dev_warn(dd->mdev.this_device, "Pin failed, %d\n", ret);
+ return -EINVAL;
+ }
+
+ rgn.size = rgn.end = dd->buffers[buf_idx].size;
+ ret = hwmem_set_domain(alloc, HWMEM_ACCESS_READ,
+ HWMEM_DOMAIN_SYNC, &rgn);
+ if (ret)
+ dev_warn(dd->mdev.this_device, "Set domain failed, %d\n", ret);
+
+ i = find_buf(dd, BUF_ACTIVATED);
+ if (i >= 0) {
+ dd->buffers[i].state = BUF_FREE;
+ wake_up(&dd->waitq_dq);
+ }
+
+ if (!dd->first_update) {
+ dd->first_update = true;
+ dd->buffers_need_update = false;
+ }
+
+ dd->buffers[buf_idx].paddr = mem_chunk.paddr;
+
+ if (buffer->display_update && !dd->buffers_need_update &&
+ dd->config.width == buffer->buf_cfg.width &&
+ dd->config.height == buffer->buf_cfg.height &&
+ dd->config.format == buffer->buf_cfg.format &&
+ dd->config.stride == buffer->buf_cfg.stride) {
+ info.paddr = mem_chunk.paddr;
+ mcde_dss_apply_overlay(dd->ovly, &info);
+ mcde_dss_update_overlay(dd->ovly, false);
+ } else if (buffer->display_update) {
+ dd->buffers_need_update = true;
+ }
+
+ /* Disable the MCDE FB overlay */
+ if ((dd->parent_ovly->state != NULL) &&
+ (dd->ddev->check_transparency)) {
+ dd->ddev->check_transparency--;
+ mcde_dss_get_overlay_info(dd->parent_ovly, &info);
+ if (dd->ddev->check_transparency == 0) {
+ if (is_transparent(info.w, info.h, info.vaddr)) {
+ mcde_dss_disable_overlay(dd->parent_ovly);
+ printk(KERN_INFO "%s Disable overlay\n",
+ __func__);
+ }
+ }
+ }
+
+ dd->buffers[buf_idx].state = BUF_ACTIVATED;
+
+ return 0;
+}
+
+static int dispdev_dequeue_buffer(struct dispdev *dd)
+{
+ int i;
+
+ i = find_buf(dd, BUF_FREE);
+ if (i < 0) {
+ if (find_buf(dd, BUF_ACTIVATED) < 0)
+ return -EINVAL;
+ mutex_unlock(&dd->lock);
+ wait_event(dd->waitq_dq, (i = find_buf(dd, BUF_FREE)) >= 0);
+ mutex_lock(&dd->lock);
+ }
+ hwmem_unpin(dd->buffers[i].alloc);
+ dd->buffers[i].state = BUF_DEQUEUED;
+ dd->buffers[i].paddr = 0;
+
+ return i;
+}
+
+long dispdev_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct dispdev *dd = (struct dispdev *)file->private_data;
+
+ mutex_lock(&dd->lock);
+
+ switch (cmd) {
+ case DISPDEV_SET_CONFIG_IOC:
+ {
+ struct dispdev_config cfg;
+ if (copy_from_user(&cfg, (void __user *)arg,
+ sizeof(cfg)))
+ ret = -EFAULT;
+ else
+ ret = dispdev_set_config(dd, &cfg);
+ }
+ break;
+ case DISPDEV_GET_CONFIG_IOC:
+ ret = copy_to_user((void __user *)arg, &dd->config,
+ sizeof(dd->config));
+ if (ret)
+ ret = -EFAULT;
+ break;
+ case DISPDEV_REGISTER_BUFFER_IOC:
+ ret = dispdev_register_buffer(dd, (s32)arg);
+ break;
+ case DISPDEV_UNREGISTER_BUFFER_IOC:
+ ret = dispdev_unregister_buffer(dd, (u32)arg);
+ break;
+ case DISPDEV_QUEUE_BUFFER_IOC:
+ {
+ struct dispdev_buffer_info buffer;
+ if (copy_from_user(&buffer, (void __user *)arg,
+ sizeof(buffer)))
+ ret = -EFAULT;
+ else
+ ret = dispdev_queue_buffer(dd, &buffer);
+ break;
+ }
+ case DISPDEV_DEQUEUE_BUFFER_IOC:
+ ret = dispdev_dequeue_buffer(dd);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ mutex_unlock(&dd->lock);
+
+ return ret;
+}
+
+static const struct file_operations dispdev_fops = {
+ .open = dispdev_open,
+ .release = dispdev_release,
+ .unlocked_ioctl = dispdev_ioctl,
+};
+
+static void init_dispdev(struct dispdev *dd, struct mcde_display_device *ddev,
+ const char *name, bool overlay)
+{
+ u16 w, h;
+ int rotation;
+
+ mutex_init(&dd->lock);
+ INIT_LIST_HEAD(&dd->list);
+ dd->ddev = ddev;
+ dd->overlay = overlay;
+ mcde_dss_get_native_resolution(ddev, &w, &h);
+ rotation = mcde_dss_get_rotation(ddev);
+
+ if ((rotation == MCDE_DISPLAY_ROT_90_CCW) ||
+ (rotation == MCDE_DISPLAY_ROT_90_CW)) {
+ dd->config.width = h;
+ dd->config.height = w;
+ } else {
+ dd->config.width = w;
+ dd->config.height = h;
+ }
+ dd->config.format = DISPDEV_FMT_RGB565;
+ dd->config.stride = sizeof(u16) * w;
+ dd->config.x = 0;
+ dd->config.y = 0;
+ dd->config.z = 0;
+ dd->buffers_need_update = false;
+ dd->first_update = false;
+ init_waitqueue_head(&dd->waitq_dq);
+ dd->mdev.minor = MISC_DYNAMIC_MINOR;
+ dd->mdev.name = name;
+ dd->mdev.fops = &dispdev_fops;
+ pr_info("%s: name=%s w=%d, h=%d, fmt=%d, stride=%d\n", __func__, name,
+ dd->config.width, dd->config.height, dd->config.format,
+ dd->config.stride);
+}
+
+int dispdev_create(struct mcde_display_device *ddev, bool overlay,
+ struct mcde_overlay *parent_ovly)
+{
+ int ret = 0;
+ struct dispdev *dd;
+ struct mcde_video_mode vmode;
+ struct mcde_overlay_info info = {0};
+
+ static int counter;
+
+ dd = kzalloc(sizeof(struct dispdev), GFP_KERNEL);
+ if (!dd)
+ return -ENOMEM;
+
+ snprintf(dd->name, sizeof(dd->name), "%s%d",
+ DISPDEV_DEFAULT_DEVICE_PREFIX, counter++);
+ init_dispdev(dd, ddev, dd->name, overlay);
+
+ if (!overlay) {
+ ret = mcde_dss_enable_display(ddev);
+ if (ret)
+ goto fail_enable_display;
+ mcde_dss_get_video_mode(ddev, &vmode);
+ mcde_dss_try_video_mode(ddev, &vmode);
+ ret = mcde_dss_set_video_mode(ddev, &vmode);
+ if (ret)
+ goto fail_set_video_mode;
+ mcde_dss_set_pixel_format(ddev, info.fmt);
+ mcde_dss_apply_channel(ddev);
+ } else
+ mcde_dss_get_video_mode(ddev, &vmode);
+ get_ovly_info(&dd->config, &vmode, &info, overlay);
+
+ /* Save the MCDE FB overlay */
+ dd->parent_ovly = parent_ovly;
+
+ dd->ovly = mcde_dss_create_overlay(ddev, &info);
+ if (!dd->ovly) {
+ ret = -ENOMEM;
+ goto fail_create_ovly;
+ }
+
+ ret = misc_register(&dd->mdev);
+ if (ret)
+ goto fail_register_misc;
+ mutex_lock(&dev_list_lock);
+ list_add_tail(&dd->list, &dev_list);
+ mutex_unlock(&dev_list_lock);
+
+ goto out;
+
+fail_register_misc:
+ mcde_dss_destroy_overlay(dd->ovly);
+fail_create_ovly:
+ if (!overlay)
+ mcde_dss_disable_display(ddev);
+fail_set_video_mode:
+fail_enable_display:
+ kfree(dd);
+out:
+ return ret;
+}
+
+void dispdev_destroy(struct mcde_display_device *ddev)
+{
+ struct dispdev *dd;
+ struct dispdev *tmp;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(dd, tmp, &dev_list, list) {
+ if (dd->ddev == ddev) {
+ list_del(&dd->list);
+ misc_deregister(&dd->mdev);
+ mcde_dss_destroy_overlay(dd->ovly);
+ /*
+ * TODO: Uncomment when DSS has reference
+ * counting of enable/disable
+ */
+ /* mcde_dss_disable_display(dd->ddev); */
+ kfree(dd);
+ break;
+ }
+ }
+ mutex_unlock(&dev_list_lock);
+}
+
+static void dispdev_destroy_all(void)
+{
+ struct dispdev *dd;
+ struct dispdev *tmp;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(dd, tmp, &dev_list, list) {
+ list_del(&dd->list);
+ misc_deregister(&dd->mdev);
+ mcde_dss_destroy_overlay(dd->ovly);
+ /*
+ * TODO: Uncomment when DSS has reference
+ * counting of enable/disable
+ */
+ /* mcde_dss_disable_display(dd->ddev); */
+ kfree(dd);
+ }
+ mutex_unlock(&dev_list_lock);
+
+ mutex_destroy(&dev_list_lock);
+}
+
+static int __init dispdev_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ mutex_init(&dev_list_lock);
+
+ return 0;
+}
+module_init(dispdev_init);
+
+static void __exit dispdev_exit(void)
+{
+ dispdev_destroy_all();
+ pr_info("%s\n", __func__);
+}
+module_exit(dispdev_exit);
+
+MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Display output device driver");
+
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a290be51a1f..93a7c86171e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -286,6 +286,8 @@ config FB_CIRRUS
Say N unless you have such a graphics board or plan to get one
before you next recompile the kernel.
+source "drivers/video/mcde/Kconfig"
+
config FB_PM2
tristate "Permedia2 support"
depends on FB && ((AMIGA && BROKEN) || PCI)
@@ -2415,6 +2417,8 @@ source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
source "drivers/video/exynos/Kconfig"
source "drivers/video/backlight/Kconfig"
+source "drivers/video/av8100/Kconfig"
+source "drivers/video/b2r2/Kconfig"
if VT
source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9356add945b..3a4ad2ebe33 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -139,6 +139,9 @@ obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-y += omap2/
+obj-$(CONFIG_FB_MCDE) += mcde/
+obj-$(CONFIG_AV8100) += av8100/
+obj-y += b2r2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
diff --git a/drivers/video/av8100/Kconfig b/drivers/video/av8100/Kconfig
new file mode 100644
index 00000000000..40b9943aaa9
--- /dev/null
+++ b/drivers/video/av8100/Kconfig
@@ -0,0 +1,48 @@
+config AV8100
+ tristate "AV8100 driver support(HDMI/CVBS)"
+ default n
+ help
+ Please enable this feature if hdmi/tvout driver support is required.
+
+config HDMI_AV8100_DEBUG
+ bool "HDMI and AV8100 debug messages"
+ default n
+ depends on AV8100
+ ---help---
+ Say Y here if you want the HDMI and AV8100 driver to
+ output debug messages.
+
+choice
+ prompt "AV8100 HW trig method"
+ default AV8100_HWTRIG_DSI_TE
+
+config AV8100_HWTRIG_INT
+ bool "AV8100 HW trig on INT"
+ depends on AV8100
+ ---help---
+ If you say Y here AV8100 will use HW triggering
+ from AV8100 INT to MCDE sync0.
+
+config AV8100_HWTRIG_I2SDAT3
+ bool "AV8100 HW trig on I2SDAT3"
+ depends on AV8100
+ ---help---
+ If you say Y here AV8100 will use HW triggering
+ from AV8100 I2SDAT3 to MCDE sync1.
+
+config AV8100_HWTRIG_DSI_TE
+ bool "AV8100 HW trig on DSI"
+ depends on AV8100
+ ---help---
+ If you say Y here AV8100 will use HW triggering
+ using DSI TE polling between AV8100 and MCDE.
+
+config AV8100_HWTRIG_NONE
+ bool "AV8100 SW trig"
+ depends on AV8100
+ ---help---
+ If you say Y here AV8100 will use SW triggering
+ between AV8100 and MCDE.
+
+endchoice
+
diff --git a/drivers/video/av8100/Makefile b/drivers/video/av8100/Makefile
new file mode 100644
index 00000000000..2d3028b18ca
--- /dev/null
+++ b/drivers/video/av8100/Makefile
@@ -0,0 +1,10 @@
+# Make file for compiling and loadable module HDMI
+
+obj-$(CONFIG_AV8100) += av8100.o hdmi.o
+
+ifdef CONFIG_HDMI_AV8100_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+clean-files := av8100.o hdmi.o built-in.o modules.order
+
diff --git a/drivers/video/av8100/av8100.c b/drivers/video/av8100/av8100.c
new file mode 100644
index 00000000000..d5d159079c3
--- /dev/null
+++ b/drivers/video/av8100/av8100.c
@@ -0,0 +1,4166 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * AV8100 driver
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/timer.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/dbx500-prcmu.h>
+
+#include "av8100_regs.h"
+#include <video/av8100.h>
+#include <video/hdmi.h>
+#include <linux/firmware.h>
+
+#define AV8100_FW_FILENAME "av8100.fw"
+#define CUT_STR_0 "2.1"
+#define CUT_STR_1 "2.2"
+#define CUT_STR_3 "2.3"
+#define CUT_STR_30 "3.0"
+#define CUT_STR_UNKNOWN ""
+#define AV8100_DEVNR_DEFAULT 0
+
+/* Interrupts */
+#define AV8100_INT_EVENT 0x1
+#define AV8100_PLUGSTARTUP_EVENT 0x4
+
+#define AV8100_PLUGSTARTUP_TIME 100
+
+/* Standby search time */
+#define AV8100_ON_TIME 1 /* 9 ms step */
+#define AV8100_DENC_OFF_TIME 3 /* 275 ms step if > V1. Not used if V1 */
+#define AV8100_HDMI_OFF_TIME 2 /* 140 ms step if V2. 80 ms step if V1 */
+
+/* Command offsets */
+#define AV8100_COMMAND_OFFSET 0x10
+#define AV8100_CUTVER_OFFSET 0x11
+#define AV8100_COMMAND_MAX_LENGTH 0x81
+#define AV8100_CMD_BUF_OFFSET (AV8100_COMMAND_OFFSET + 1)
+#define AV8100_2ND_RET_BYTE_OFFSET (AV8100_COMMAND_OFFSET + 1)
+#define AV8100_CEC_RET_BUF_OFFSET (AV8100_COMMAND_OFFSET + 4)
+#define AV8100_HDCP_RET_BUF_OFFSET (AV8100_COMMAND_OFFSET + 2)
+#define AV8100_EDID_RET_BUF_OFFSET (AV8100_COMMAND_OFFSET + 1)
+#define AV8100_FUSE_CRC_OFFSET (AV8100_COMMAND_OFFSET + 2)
+#define AV8100_FUSE_PRGD_OFFSET (AV8100_COMMAND_OFFSET + 3)
+#define AV8100_CRC32_OFFSET (AV8100_COMMAND_OFFSET + 2)
+#define AV8100_CEC_ADDR_OFFSET (AV8100_COMMAND_OFFSET + 3)
+
+/* Tearing effect line numbers */
+#define AV8100_TE_LINE_NB_14 14
+#define AV8100_TE_LINE_NB_17 17
+#define AV8100_TE_LINE_NB_18 18
+#define AV8100_TE_LINE_NB_21 21
+#define AV8100_TE_LINE_NB_22 22
+#define AV8100_TE_LINE_NB_24 24
+#define AV8100_TE_LINE_NB_25 25
+#define AV8100_TE_LINE_NB_26 26
+#define AV8100_TE_LINE_NB_29 29
+#define AV8100_TE_LINE_NB_30 30
+#define AV8100_TE_LINE_NB_32 32
+#define AV8100_TE_LINE_NB_38 38
+#define AV8100_TE_LINE_NB_40 40
+#define AV8100_UI_X4_DEFAULT 6
+
+#define HDMI_REQUEST_FOR_REVOCATION_LIST_INPUT 2
+#define HDMI_CEC_MESSAGE_WRITE_BUFFER_SIZE 16
+#define HDMI_HDCP_SEND_KEY_SIZE 7
+#define HDMI_INFOFRAME_DATA_SIZE 28
+#define HDMI_FUSE_AES_KEY_SIZE 16
+#define HDMI_FUSE_AES_KEY_RET_SIZE 2
+#define HDMI_LOADAES_END_BLK_NR 145
+#define HDMI_CRC32_SIZE 4
+#define HDMI_HDCP_MGMT_BKSV_SIZE 5
+#define HDMI_HDCP_MGMT_SHA_SIZE 20
+#define HDMI_HDCP_MGMT_MAX_DEVICES_SIZE 20
+#define HDMI_HDCP_MGMT_DEVICE_MASK 0x7F
+#define HDMI_EDIDREAD_SIZE 0x7F
+
+#define HPDS_INVALID 0xF
+#define CPDS_INVALID 0xF
+#define CECRX_INVALID 0xF
+
+#define REG_16_8_LSB(p) ((u8)(p & 0xFF))
+#define REG_16_8_MSB(p) ((u8)((p & 0xFF00)>>8))
+#define REG_32_8_MSB(p) ((u8)((p & 0xFF000000)>>24))
+#define REG_32_8_MMSB(p) ((u8)((p & 0x00FF0000)>>16))
+#define REG_32_8_MLSB(p) ((u8)((p & 0x0000FF00)>>8))
+#define REG_32_8_LSB(p) ((u8)(p & 0x000000FF))
+#define REG_10_8_MSB(p) ((u8)((p & 0x300)>>8))
+#define REG_12_8_MSB(p) ((u8)((p & 0xf00)>>8))
+
+#define AV8100_WAITTIME_1MS 1
+#define AV8100_WAITTIME_5MS 5
+#define AV8100_WAITTIME_10MS 10
+#define AV8100_WAITTIME_50MS 50
+#define AV8100_WATTIME_100US 100
+
+static DEFINE_MUTEX(av8100_hw_mutex);
+#define LOCK_AV8100_HW mutex_lock(&av8100_hw_mutex)
+#define UNLOCK_AV8100_HW mutex_unlock(&av8100_hw_mutex)
+static DEFINE_MUTEX(av8100_fwdl_mutex);
+#define LOCK_AV8100_FWDL mutex_lock(&av8100_fwdl_mutex)
+#define UNLOCK_AV8100_FWDL mutex_unlock(&av8100_fwdl_mutex)
+
+struct color_conversion_cmd {
+ unsigned short c0;
+ unsigned short c1;
+ unsigned short c2;
+ unsigned short c3;
+ unsigned short c4;
+ unsigned short c5;
+ unsigned short c6;
+ unsigned short c7;
+ unsigned short c8;
+ unsigned short aoffset;
+ unsigned short boffset;
+ unsigned short coffset;
+ unsigned char lmax;
+ unsigned char lmin;
+ unsigned char cmax;
+ unsigned char cmin;
+};
+
+struct av8100_config {
+ struct i2c_client *client;
+ struct i2c_device_id *id;
+ struct av8100_video_input_format_cmd hdmi_video_input_cmd;
+ struct av8100_audio_input_format_cmd hdmi_audio_input_cmd;
+ struct av8100_video_output_format_cmd hdmi_video_output_cmd;
+ struct av8100_video_scaling_format_cmd hdmi_video_scaling_cmd;
+ enum av8100_color_transform color_transform;
+ struct av8100_cec_message_write_format_cmd
+ hdmi_cec_message_write_cmd;
+ struct av8100_cec_message_read_back_format_cmd
+ hdmi_cec_message_read_back_cmd;
+ struct av8100_denc_format_cmd hdmi_denc_cmd;
+ struct av8100_hdmi_cmd hdmi_cmd;
+ struct av8100_hdcp_send_key_format_cmd hdmi_hdcp_send_key_cmd;
+ struct av8100_hdcp_management_format_cmd
+ hdmi_hdcp_management_format_cmd;
+ struct av8100_infoframes_format_cmd hdmi_infoframes_cmd;
+ struct av8100_edid_section_readback_format_cmd
+ hdmi_edid_section_readback_cmd;
+ struct av8100_pattern_generator_format_cmd hdmi_pattern_generator_cmd;
+ struct av8100_fuse_aes_key_format_cmd hdmi_fuse_aes_key_cmd;
+};
+
+enum av8100_plug_state {
+ AV8100_UNPLUGGED,
+ AV8100_PLUGGED_STARTUP,
+ AV8100_PLUGGED
+};
+
+struct av8100_params {
+ int denc_off_time;/* 5 volt time */
+ int hdmi_off_time;/* 5 volt time */
+ int on_time;/* 5 volt time */
+ u8 hpdm;/*stby_int_mask*/
+ u8 cpdm;/*stby_int_mask*/
+ u8 cecm;/*gen_int_mask*/
+ u8 hdcpm;/*gen_int_mask*/
+ u8 uovbm;/*gen_int_mask*/
+ void (*hdmi_ev_cb)(enum av8100_hdmi_event);
+ enum av8100_plug_state plug_state;
+ struct clk *inputclk;
+ bool inputclk_requested;
+ bool opp_requested;
+ struct regulator *regulator_pwr;
+ bool regulator_requested;
+ bool pre_suspend_power;
+ bool ints_enabled;
+ bool irq_requested;
+};
+
+/**
+ * struct av8100_cea - CEA(consumer electronic access) standard structure
+ * @cea_id:
+ * @cea_nb:
+ * @vtotale:
+ **/
+
+struct av8100_cea {
+ char cea_id[40];
+ int cea_nb;
+ int vtotale;
+ int vactive;
+ int vsbp;
+ int vslen;
+ int vsfp;
+ char vpol[5];
+ int htotale;
+ int hactive;
+ int hbp;
+ int hslen;
+ int hfp;
+ int frequence;
+ char hpol[5];
+ int reg_line_duration;
+ int blkoel_duration;
+ int uix4;
+ int pll_mult;
+ int pll_div;
+};
+
+enum av8100_command_size {
+ AV8100_COMMAND_VIDEO_INPUT_FORMAT_SIZE = 0x17,
+ AV8100_COMMAND_AUDIO_INPUT_FORMAT_SIZE = 0x8,
+ AV8100_COMMAND_VIDEO_OUTPUT_FORMAT_SIZE = 0x1E,
+ AV8100_COMMAND_VIDEO_SCALING_FORMAT_SIZE = 0x11,
+ AV8100_COMMAND_COLORSPACECONVERSION_SIZE = 0x1D,
+ AV8100_COMMAND_CEC_MESSAGE_WRITE_SIZE = 0x12,
+ AV8100_COMMAND_CEC_MESSAGE_READ_BACK_SIZE = 0x1,
+ AV8100_COMMAND_DENC_SIZE = 0x6,
+ AV8100_COMMAND_HDMI_SIZE = 0x4,
+ AV8100_COMMAND_HDCP_SENDKEY_SIZE = 0xA,
+ AV8100_COMMAND_HDCP_MANAGEMENT_SIZE = 0x3,
+ AV8100_COMMAND_INFOFRAMES_SIZE = 0x21,
+ AV8100_COMMAND_EDID_SECTION_READBACK_SIZE = 0x3,
+ AV8100_COMMAND_PATTERNGENERATOR_SIZE = 0x4,
+ AV8100_COMMAND_FUSE_AES_KEY_SIZE = 0x12,
+ AV8100_COMMAND_FUSE_AES_CHK_SIZE = 0x2,
+};
+
+struct av8100_device {
+ struct list_head list;
+ struct miscdevice miscdev;
+ struct device *dev;
+ struct av8100_config config;
+ struct av8100_status status;
+ struct timer_list timer;
+ wait_queue_head_t event;
+ int flag;
+ struct av8100_params params;
+ u8 chip_version;
+};
+
+static const unsigned int waittime_retry[10] = {
+ 1, 2, 4, 6, 8, 10, 10, 10, 10, 10};
+
+static int av8100_5V_w(u8 denc_off, u8 hdmi_off, u8 on);
+static void clr_plug_status(struct av8100_device *adev,
+ enum av8100_plugin_status status);
+static void set_plug_status(struct av8100_device *adev,
+ enum av8100_plugin_status status);
+static void cec_rx(struct av8100_device *adev);
+static void cec_tx(struct av8100_device *adev);
+static void cec_txerr(struct av8100_device *adev);
+static void hdcp_changed(struct av8100_device *adev);
+static const struct color_conversion_cmd *get_color_transform_cmd(
+ struct av8100_device *adev,
+ enum av8100_color_transform transform);
+static int av8100_open(struct inode *inode, struct file *filp);
+static int av8100_release(struct inode *inode, struct file *filp);
+static long av8100_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg);
+static int __devinit av8100_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id);
+static int __devexit av8100_remove(struct i2c_client *i2c_client);
+
+static const struct file_operations av8100_fops = {
+ .owner = THIS_MODULE,
+ .open = av8100_open,
+ .release = av8100_release,
+ .unlocked_ioctl = av8100_ioctl
+};
+
+/* List of devices */
+static LIST_HEAD(av8100_device_list);
+
+static const struct av8100_cea av8100_all_cea[29] = {
+/* cea id
+ * cea_nr vtot vact vsbpp vslen
+ * vsfp vpol htot hact hbp hslen hfp freq
+ * hpol rld bd uix4 pm pd */
+{ "0 CUSTOM ",
+ 0, 0, 0, 0, 0,
+ 0, "-", 800, 640, 16, 96, 10, 25200000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be defined*/
+{ "1 CEA 1 VESA 4 640x480p @ 60 Hz ",
+ 1, 525, 480, 33, 2,
+ 10, "-", 800, 640, 49, 290, 146, 25200000,
+ "-", 2438, 1270, 6, 32, 1},/*RGB888*/
+{ "2 CEA 2 - 3 720x480p @ 60 Hz 4:3 ",
+ 2, 525, 480, 30, 6,
+ 9, "-", 858, 720, 34, 130, 128, 27027000,
+ "-", 1828, 0x3C0, 8, 24, 1},/*RGB565*/
+{ "3 CEA 4 1280x720p @ 60 Hz ",
+ 4, 750, 720, 20, 5,
+ 5, "+", 1650, 1280, 114, 39, 228, 74250000,
+ "+", 1706, 164, 6, 32, 1},/*RGB565*/
+{ "4 CEA 5 1920x1080i @ 60 Hz ",
+ 5, 1125, 540, 20, 5,
+ 0, "+", 2200, 1920, 88, 44, 10, 74250000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "5 CEA 6-7 480i (NTSC) ",
+ 6, 525, 240, 44, 5,
+ 0, "-", 858, 720, 12, 64, 10, 13513513,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "6 CEA 14-15 480p @ 60 Hz ",
+ 14, 525, 480, 44, 5,
+ 0, "-", 858, 720, 12, 64, 10, 27027000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "7 CEA 16 1920x1080p @ 60 Hz ",
+ 16, 1125, 1080, 36, 5,
+ 0, "+", 1980, 1280, 440, 40, 10, 133650000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "8 CEA 17-18 720x576p @ 50 Hz ",
+ 17, 625, 576, 44, 5,
+ 0, "-", 864, 720, 12, 64, 10, 27000000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "9 CEA 19 1280x720p @ 50 Hz ",
+ 19, 750, 720, 25, 5,
+ 0, "+", 1980, 1280, 440, 40, 10, 74250000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "10 CEA 20 1920 x 1080i @ 50 Hz ",
+ 20, 1125, 540, 20, 5,
+ 0, "+", 2640, 1920, 528, 44, 10, 74250000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "11 CEA 21-22 576i (PAL) ",
+ 21, 625, 288, 44, 5,
+ 0, "-", 1728, 1440, 12, 64, 10, 27000000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "12 CEA 29/30 576p ",
+ 29, 625, 576, 44, 5,
+ 0, "-", 864, 720, 12, 64, 10, 27000000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "13 CEA 31 1080p 50Hz ",
+ 31, 1125, 1080, 44, 5,
+ 0, "-", 2640, 1920, 12, 64, 10, 148500000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "14 CEA 32 1920x1080p @ 24 Hz ",
+ 32, 1125, 1080, 36, 5,
+ 4, "+", 2750, 1920, 660, 44, 153, 74250000,
+ "+", 2844, 0x530, 6, 32, 1},/*RGB565*/
+{ "15 CEA 33 1920x1080p @ 25 Hz ",
+ 33, 1125, 1080, 36, 5,
+ 4, "+", 2640, 1920, 528, 44, 10, 74250000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "16 CEA 34 1920x1080p @ 30Hz ",
+ 34, 1125, 1080, 36, 5,
+ 4, "+", 2200, 1920, 91, 44, 153, 74250000,
+ "+", 2275, 0xAB, 6, 32, 1},/*RGB565*/
+{ "17 CEA 60 1280x720p @ 24 Hz ",
+ 60, 750, 720, 20, 5,
+ 5, "+", 3300, 1280, 284, 50, 2276, 59400000,
+ "+", 4266, 0xAD0, 5, 32, 1},/*RGB565*/
+{ "18 CEA 61 1280x720p @ 25 Hz ",
+ 61, 750, 720, 20, 5,
+ 5, "+", 3960, 1280, 228, 39, 2503, 74250000,
+ "+", 4096, 0x500, 5, 32, 1},/*RGB565*/
+{ "19 CEA 62 1280x720p @ 30 Hz ",
+ 62, 750, 720, 20, 5,
+ 5, "+", 3300, 1280, 228, 39, 1820, 74250000,
+ "+", 3413, 0x770, 5, 32, 1},/*RGB565*/
+{ "20 VESA 9 800x600 @ 60 Hz ",
+ 109, 628, 600, 28, 4,
+ 0, "+", 1056, 800, 40, 128, 10, 40000000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "21 VESA 14 848x480 @ 60 Hz ",
+ 114, 517, 480, 20, 5,
+ 0, "+", 1088, 848, 24, 80, 10, 33750000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "22 VESA 16 1024x768 @ 60 Hz ",
+ 116, 806, 768, 38, 6,
+ 0, "-", 1344, 1024, 24, 135, 10, 65000000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "23 VESA 22 1280x768 @ 60 Hz ",
+ 122, 790, 768, 34, 4,
+ 0, "+", 1440, 1280, 48, 160, 10, 68250000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "24 VESA 23 1280x768 @ 60 Hz ",
+ 123, 798, 768, 30, 7,
+ 0, "+", 1664, 1280, 64, 128, 10, 79500000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "25 VESA 27 1280x800 @ 60 Hz ",
+ 127, 823, 800, 23, 6,
+ 0, "+", 1440, 1280, 48, 32, 10, 71000000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "26 VESA 28 1280x800 @ 60 Hz ",
+ 128, 831, 800, 31, 6,
+ 0, "+", 1680, 1280, 72, 128, 10, 83500000,
+ "-", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "27 VESA 39 1360x768 @ 60 Hz ",
+ 139, 795, 768, 22, 5,
+ 0, "-", 1792, 1360, 48, 32, 10, 85500000,
+ "+", 0, 0, 0, 0, 0},/*Settings to be define*/
+{ "28 VESA 81 1366x768 @ 60 Hz ",
+ 181, 798, 768, 30, 5,
+ 0, "+", 1792, 1366, 72, 136, 10, 85750000,
+ "-", 0, 0, 0, 0, 0} /*Settings to be define*/
+};
+
+const struct color_conversion_cmd col_trans_identity = {
+ .c0 = 0x0100, .c1 = 0x0000, .c2 = 0x0000,
+ .c3 = 0x0000, .c4 = 0x0100, .c5 = 0x0000,
+ .c6 = 0x0000, .c7 = 0x0000, .c8 = 0x0100,
+ .aoffset = 0x0000, .boffset = 0x0000, .coffset = 0x0000,
+ .lmax = 0xff,
+ .lmin = 0x00,
+ .cmax = 0xff,
+ .cmin = 0x00,
+};
+
+const struct color_conversion_cmd col_trans_identity_clamp_yuv = {
+ .c0 = 0x0100, .c1 = 0x0000, .c2 = 0x0000,
+ .c3 = 0x0000, .c4 = 0x0100, .c5 = 0x0000,
+ .c6 = 0x0000, .c7 = 0x0000, .c8 = 0x0100,
+ .aoffset = 0x0000, .boffset = 0x0000, .coffset = 0x0000,
+ .lmax = 0xeb,
+ .lmin = 0x10,
+ .cmax = 0xf0,
+ .cmin = 0x10,
+};
+
+const struct color_conversion_cmd col_trans_yuv_to_rgb_v1 = {
+ .c0 = 0x0087, .c1 = 0x0000, .c2 = 0x00ba,
+ .c3 = 0x0087, .c4 = 0xffd3, .c5 = 0xffa1,
+ .c6 = 0x0087, .c7 = 0x00eb, .c8 = 0x0000,
+ .aoffset = 0xffab, .boffset = 0x004e, .coffset = 0xff92,
+ .lmax = 0xff,
+ .lmin = 0x00,
+ .cmax = 0xff,
+ .cmin = 0x00,
+};
+
+const struct color_conversion_cmd col_trans_yuv_to_rgb_v2 = {
+ .c0 = 0x0198, .c1 = 0x012a, .c2 = 0x0000,
+ .c3 = 0xff30, .c4 = 0x012a, .c5 = 0xff9c,
+ .c6 = 0x0000, .c7 = 0x012a, .c8 = 0x0204,
+ .aoffset = 0xff21, .boffset = 0x0088, .coffset = 0xfeeb,
+ .lmax = 0xff,
+ .lmin = 0x00,
+ .cmax = 0xff,
+ .cmin = 0x00,
+};
+
+const struct color_conversion_cmd col_trans_yuv_to_denc = {
+ .c0 = 0x0100, .c1 = 0x0000, .c2 = 0x0000,
+ .c3 = 0x0000, .c4 = 0x0100, .c5 = 0x0000,
+ .c6 = 0x0000, .c7 = 0x0000, .c8 = 0x0100,
+ .aoffset = 0x0000, .boffset = 0x0000, .coffset = 0x0000,
+ .lmax = 0xeb,
+ .lmin = 0x10,
+ .cmax = 0xf0,
+ .cmin = 0x10,
+};
+
+const struct color_conversion_cmd col_trans_rgb_to_denc = {
+ .c0 = 0x0070, .c1 = 0xffb6, .c2 = 0xffda,
+ .c3 = 0x0042, .c4 = 0x0081, .c5 = 0x0019,
+ .c6 = 0xffee, .c7 = 0xffa2, .c8 = 0x0070,
+ .aoffset = 0x007f, .boffset = 0x0010, .coffset = 0x007f,
+ .lmax = 0xff,
+ .lmin = 0x00,
+ .cmax = 0xff,
+ .cmin = 0x00,
+};
+
+static const struct i2c_device_id av8100_id[] = {
+ { "av8100", 0 },
+ { }
+};
+
+static struct av8100_device *devnr_to_adev(int devnr)
+{
+ /* Get device from list of devices */
+ struct list_head *element;
+ struct av8100_device *av8100_dev;
+ int cnt = 0;
+
+ list_for_each(element, &av8100_device_list) {
+ av8100_dev = list_entry(element, struct av8100_device, list);
+ if (cnt == devnr)
+ return av8100_dev;
+ cnt++;
+ }
+
+ return NULL;
+}
+
+static struct av8100_device *dev_to_adev(struct device *dev)
+{
+ /* Get device from list of devices */
+ struct list_head *element;
+ struct av8100_device *av8100_dev;
+ int cnt = 0;
+
+ list_for_each(element, &av8100_device_list) {
+ av8100_dev = list_entry(element, struct av8100_device, list);
+ if (av8100_dev->dev == dev)
+ return av8100_dev;
+ cnt++;
+ }
+
+ return NULL;
+}
+
+static int adev_to_devnr(struct av8100_device *adev)
+{
+ /* Get devnr from list of devices */
+ struct list_head *element;
+ struct av8100_device *av8100_dev;
+ int cnt = 0;
+
+ list_for_each(element, &av8100_device_list) {
+ av8100_dev = list_entry(element, struct av8100_device, list);
+ if (av8100_dev == adev)
+ return cnt;
+ cnt++;
+ }
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_PM
+static int av8100_suspend(struct device *dev)
+{
+ int ret = 0;
+ struct av8100_device *adev;
+
+ adev = dev_to_adev(dev);
+ if (!adev)
+ return -EFAULT;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ adev->params.pre_suspend_power =
+ (av8100_status_get().av8100_state > AV8100_OPMODE_SHUTDOWN);
+
+ if (adev->params.pre_suspend_power) {
+ ret = av8100_powerdown();
+ if (ret)
+ dev_err(dev, "av8100_powerdown failed\n");
+ }
+
+ return ret;
+}
+
+static int av8100_resume(struct device *dev)
+{
+ int ret;
+ u8 hpds = 0;
+ struct av8100_device *adev;
+
+ adev = dev_to_adev(dev);
+ if (!adev)
+ return -EFAULT;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (adev->params.pre_suspend_power) {
+ ret = av8100_powerup();
+ if (ret) {
+ dev_err(dev, "av8100_powerup failed\n");
+ return ret;
+ }
+
+ /* Check HDMI plug status */
+ if (av8100_reg_stby_r(NULL, NULL, &hpds, NULL, NULL)) {
+ dev_warn(dev, "av8100_reg_stby_r failed\n");
+ goto av8100_resume_end;
+ }
+
+ if (hpds)
+ set_plug_status(adev, AV8100_HDMI_PLUGIN); /* Plugged*/
+ else
+ clr_plug_status(adev,
+ AV8100_HDMI_PLUGIN); /* Unplugged*/
+
+ adev->params.hpdm = AV8100_STANDBY_INTERRUPT_MASK_HPDM_HIGH;
+ av8100_enable_interrupt();
+ }
+
+av8100_resume_end:
+ return 0;
+}
+
+static const struct dev_pm_ops av8100_dev_pm_ops = {
+ .suspend = av8100_suspend,
+ .resume = av8100_resume,
+};
+#endif
+
+static struct i2c_driver av8100_driver = {
+ .probe = av8100_probe,
+ .remove = av8100_remove,
+ .driver = {
+ .name = "av8100",
+#ifdef CONFIG_PM
+ .pm = &av8100_dev_pm_ops,
+#endif
+ },
+ .id_table = av8100_id,
+};
+
+static void av8100_plugtimer_int(unsigned long value)
+{
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev((int)value);
+ adev->flag |= AV8100_PLUGSTARTUP_EVENT;
+ wake_up_interruptible(&adev->event);
+ del_timer(&adev->timer);
+}
+
+static int av8100_int_event_handle(struct av8100_device *adev)
+{
+ u8 hpdi = 0;
+ u8 cpdi = 0;
+ u8 uovbi = 0;
+ u8 hdcpi = 0;
+ u8 ceci = 0;
+ u8 hpds = 0;
+ u8 cpds = 0;
+ u8 hdcps = 0;
+ u8 onuvb = 0;
+ u8 cectxerr = 0;
+ u8 cecrx = 0;
+ u8 cectx = 0;
+
+ /* STANDBY_PENDING_INTERRUPT reg */
+ if (av8100_reg_stby_pend_int_r(&hpdi, &cpdi, NULL, NULL)) {
+ dev_dbg(adev->dev, "av8100_reg_stby_pend_int_r failed\n");
+ goto av8100_int_event_handle_1;
+ }
+
+ /* Plug event */
+ if (hpdi | cpdi) {
+ /* Clear pending interrupts */
+ (void)av8100_reg_stby_pend_int_w(1, 1, 1, 0);
+
+ /* STANDBY reg */
+ if (av8100_reg_stby_r(NULL, NULL, &hpds, &cpds, NULL)) {
+ dev_dbg(adev->dev, "av8100_reg_stby_r failed\n");
+ goto av8100_int_event_handle_1;
+ }
+ }
+
+ if (cpdi & adev->params.cpdm) {
+ /* TVout plugin change */
+ if (cpds) {
+ dev_dbg(adev->dev, "cpds 1\n");
+ set_plug_status(adev, AV8100_CVBS_PLUGIN);
+ } else {
+ dev_dbg(adev->dev, "cpds 0\n");
+ clr_plug_status(adev, AV8100_CVBS_PLUGIN);
+ }
+ }
+
+ if (hpdi & adev->params.hpdm) {
+ /* HDMI plugin change */
+ if (hpds) {
+ /* Plugged */
+ /* Set 5V always on */
+ av8100_5V_w(adev->params.denc_off_time,
+ 0,
+ adev->params.on_time);
+ dev_dbg(adev->dev, "hpds 1\n");
+ set_plug_status(adev, AV8100_HDMI_PLUGIN);
+ } else {
+ /* Unplugged */
+ av8100_5V_w(adev->params.denc_off_time,
+ adev->params.hdmi_off_time,
+ adev->params.on_time);
+ dev_dbg(adev->dev, "hpds 0\n");
+ clr_plug_status(adev, AV8100_HDMI_PLUGIN);
+ }
+ }
+
+av8100_int_event_handle_1:
+ /* GENERAL_INTERRUPT reg */
+ if (av8100_reg_gen_int_r(NULL, NULL, NULL, &ceci,
+ &hdcpi, &uovbi, NULL)) {
+ dev_dbg(adev->dev, "av8100_reg_gen_int_r failed\n");
+ return -EINVAL;
+ }
+
+ /* CEC or HDCP event */
+ if (ceci | hdcpi | uovbi) {
+ /* Clear pending interrupts */
+ av8100_reg_gen_int_w(1, 1, 1, 1, 1, 1);
+
+ /* GENERAL_STATUS reg */
+ if (av8100_reg_gen_status_r(&cectxerr, &cecrx, &cectx, NULL,
+ &onuvb, &hdcps) != 0) {
+ dev_dbg(adev->dev, "av8100_reg_gen_status_r fail\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Underflow or overflow */
+ if (uovbi)
+ dev_dbg(adev->dev, "uovbi %d\n", onuvb);
+
+ /* CEC received */
+ if (ceci && cecrx) {
+ u8 val;
+
+ dev_dbg(adev->dev, "cecrx\n");
+
+ /* Clear cecrx in status reg*/
+ if (av8100_reg_r(AV8100_GENERAL_STATUS, &val) == 0) {
+ if (av8100_reg_w(AV8100_GENERAL_STATUS,
+ val & ~AV8100_GENERAL_STATUS_CECREC_MASK))
+ dev_info(adev->dev, "gen_stat write error\n");
+ } else {
+ dev_info(adev->dev, "gen_stat read error\n");
+ }
+
+ /* Report CEC event */
+ cec_rx(adev);
+ }
+
+ /* CEC tx error */
+ if (ceci && cectx && cectxerr) {
+ dev_dbg(adev->dev, "cectxerr\n");
+ /* Report CEC tx error event */
+ cec_txerr(adev);
+ } else if (ceci && cectx) {
+ dev_dbg(adev->dev, "cectx\n");
+ /* Report CEC tx event */
+ cec_tx(adev);
+ }
+
+ /* HDCP event */
+ if (hdcpi) {
+ dev_dbg(adev->dev, "hdcpch:%0x\n", hdcps);
+ /* Report HDCP status change event */
+ hdcp_changed(adev);
+ }
+
+ return 0;
+}
+
+static int av8100_plugstartup_event_handle(struct av8100_device *adev)
+{
+ u8 hpds = 0;
+ u8 cpds = 0;
+
+ switch (adev->params.plug_state) {
+ case AV8100_UNPLUGGED:
+ case AV8100_PLUGGED:
+ default:
+ break;
+
+ case AV8100_PLUGGED_STARTUP:
+ /* Unmask interrupt */
+ adev->params.hpdm = AV8100_STANDBY_INTERRUPT_MASK_HPDM_HIGH;
+ if (av8100_reg_stby_int_mask_w(adev->params.hpdm,
+ adev->params.cpdm,
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_INPUT,
+ AV8100_STANDBY_INTERRUPT_MASK_IPOL_LOW)) {
+ dev_dbg(adev->dev,
+ "av8100_reg_stby_int_mask_w fail\n");
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ /* Get actual plug status */
+ if (av8100_reg_stby_r(NULL, NULL, &hpds, &cpds, NULL))
+ dev_dbg(adev->dev, "av8100_reg_stby_r fail\n");
+
+ /* Set plugstate */
+ if (hpds) {
+ adev->params.plug_state = AV8100_PLUGGED;
+ dev_dbg(adev->dev, "plug_state:2\n");
+ } else {
+ adev->params.plug_state = AV8100_UNPLUGGED;
+ dev_dbg(adev->dev, "plug_state:0\n");
+
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(
+ AV8100_HDMI_EVENT_HDMI_PLUGOUT);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int av8100_thread(void *p)
+{
+ u8 flags;
+ struct av8100_device *adev = p;
+
+ while (1) {
+ wait_event_interruptible(adev->event, (adev->flag != 0));
+ flags = adev->flag;
+ adev->flag = 0;
+
+ if (adev->status.av8100_state < AV8100_OPMODE_STANDBY)
+ continue;
+
+ if (flags & AV8100_INT_EVENT)
+ (void)av8100_int_event_handle(adev);
+
+ if (flags & AV8100_PLUGSTARTUP_EVENT)
+ (void)av8100_plugstartup_event_handle(adev);
+ }
+
+ return 0;
+}
+
+static irqreturn_t av8100_intr_handler(int irq, void *p)
+{
+ struct av8100_device *adev;
+
+ adev = (struct av8100_device *) p;
+ adev->flag |= AV8100_INT_EVENT;
+ wake_up_interruptible(&adev->event);
+
+ return IRQ_HANDLED;
+}
+
+static u16 av8100_get_te_line_nb(
+ enum av8100_output_CEA_VESA output_video_format)
+{
+ u16 retval;
+
+ switch (output_video_format) {
+ case AV8100_CEA1_640X480P_59_94HZ:
+ case AV8100_CEA2_3_720X480P_59_94HZ:
+ case AV8100_VESA16_1024X768P_60HZ:
+ retval = AV8100_TE_LINE_NB_30;
+ break;
+
+ case AV8100_CEA4_1280X720P_60HZ:
+ case AV8100_CEA60_1280X720P_24HZ:
+ case AV8100_CEA61_1280X720P_25HZ:
+ case AV8100_CEA62_1280X720P_30HZ:
+ retval = AV8100_TE_LINE_NB_21;
+ break;
+
+ case AV8100_CEA5_1920X1080I_60HZ:
+ case AV8100_CEA6_7_NTSC_60HZ:
+ case AV8100_CEA20_1920X1080I_50HZ:
+ case AV8100_CEA21_22_576I_PAL_50HZ:
+ case AV8100_VESA27_1280X800P_59_91HZ:
+ retval = AV8100_TE_LINE_NB_18;
+ break;
+
+ case AV8100_CEA14_15_480p_60HZ:
+ retval = AV8100_TE_LINE_NB_32;
+ break;
+
+ case AV8100_CEA17_18_720X576P_50HZ:
+ case AV8100_CEA29_30_576P_50HZ:
+ retval = AV8100_TE_LINE_NB_40;
+ break;
+
+ case AV8100_CEA19_1280X720P_50HZ:
+ case AV8100_VESA39_1360X768P_60_02HZ:
+ retval = AV8100_TE_LINE_NB_22;
+ break;
+
+ case AV8100_CEA32_1920X1080P_24HZ:
+ case AV8100_CEA33_1920X1080P_25HZ:
+ case AV8100_CEA34_1920X1080P_30HZ:
+ retval = AV8100_TE_LINE_NB_38;
+ break;
+
+ case AV8100_VESA9_800X600P_60_32HZ:
+ retval = AV8100_TE_LINE_NB_24;
+ break;
+
+ case AV8100_VESA14_848X480P_60HZ:
+ retval = AV8100_TE_LINE_NB_29;
+ break;
+
+ case AV8100_VESA22_1280X768P_59_99HZ:
+ retval = AV8100_TE_LINE_NB_17;
+ break;
+
+ case AV8100_VESA23_1280X768P_59_87HZ:
+ case AV8100_VESA81_1366X768P_59_79HZ:
+ retval = AV8100_TE_LINE_NB_25;
+ break;
+
+ case AV8100_VESA28_1280X800P_59_81HZ:
+ retval = AV8100_TE_LINE_NB_26;
+ break;
+
+ case AV8100_CEA16_1920X1080P_60HZ:
+ case AV8100_CEA31_1920x1080P_50Hz:
+ default:
+ /* TODO */
+ retval = AV8100_TE_LINE_NB_38;
+ break;
+ }
+
+ return retval;
+}
+
+static u16 av8100_get_ui_x4(
+ enum av8100_output_CEA_VESA output_video_format)
+{
+ return AV8100_UI_X4_DEFAULT;
+}
+
+static int av8100_config_video_output_dep(
+ enum av8100_output_CEA_VESA output_format)
+{
+ int retval;
+ union av8100_configuration config;
+
+ /* video input */
+ config.video_input_format.dsi_input_mode =
+ AV8100_HDMI_DSI_COMMAND_MODE;
+ config.video_input_format.input_pixel_format = AV8100_INPUT_PIX_RGB565;
+ config.video_input_format.total_horizontal_pixel =
+ av8100_all_cea[output_format].htotale;
+ config.video_input_format.total_horizontal_active_pixel =
+ av8100_all_cea[output_format].hactive;
+ config.video_input_format.total_vertical_lines =
+ av8100_all_cea[output_format].vtotale;
+ config.video_input_format.total_vertical_active_lines =
+ av8100_all_cea[output_format].vactive;
+
+ switch (output_format) {
+ case AV8100_CEA5_1920X1080I_60HZ:
+ case AV8100_CEA20_1920X1080I_50HZ:
+ case AV8100_CEA21_22_576I_PAL_50HZ:
+ case AV8100_CEA6_7_NTSC_60HZ:
+ config.video_input_format.video_mode =
+ AV8100_VIDEO_INTERLACE;
+ break;
+
+ default:
+ config.video_input_format.video_mode =
+ AV8100_VIDEO_PROGRESSIVE;
+ break;
+ }
+
+ config.video_input_format.nb_data_lane =
+ AV8100_DATA_LANES_USED_2;
+ config.video_input_format.nb_virtual_ch_command_mode = 0;
+ config.video_input_format.nb_virtual_ch_video_mode = 0;
+ config.video_input_format.ui_x4 = av8100_get_ui_x4(output_format);
+ config.video_input_format.TE_line_nb = av8100_get_te_line_nb(
+ output_format);
+ config.video_input_format.TE_config = AV8100_TE_OFF;
+ config.video_input_format.master_clock_freq = 0;
+
+ retval = av8100_conf_prep(
+ AV8100_COMMAND_VIDEO_INPUT_FORMAT, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* DENC */
+ switch (output_format) {
+ case AV8100_CEA21_22_576I_PAL_50HZ:
+ config.denc_format.cvbs_video_format = AV8100_CVBS_625;
+ config.denc_format.standard_selection = AV8100_PAL_BDGHI;
+ break;
+
+ case AV8100_CEA6_7_NTSC_60HZ:
+ config.denc_format.cvbs_video_format = AV8100_CVBS_525;
+ config.denc_format.standard_selection = AV8100_NTSC_M;
+ break;
+
+ default:
+ /* Not supported */
+ break;
+ }
+
+ return 0;
+}
+
+static int av8100_config_init(struct av8100_device *adev)
+{
+ int retval;
+ union av8100_configuration config;
+
+ dev_dbg(adev->dev, "%s\n", __func__);
+
+ memset(&config, 0, sizeof(union av8100_configuration));
+ memset(&adev->config, 0, sizeof(struct av8100_config));
+
+ /* Color conversion */
+ config.color_transform = AV8100_COLOR_TRANSFORM_INDENTITY;
+ retval = av8100_conf_prep(
+ AV8100_COMMAND_COLORSPACECONVERSION, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* DENC */
+ config.denc_format.cvbs_video_format = AV8100_CVBS_625;
+ config.denc_format.standard_selection = AV8100_PAL_BDGHI;
+ config.denc_format.enable = 0;
+ config.denc_format.macrovision_enable = 0;
+ config.denc_format.internal_generator = 0;
+ retval = av8100_conf_prep(AV8100_COMMAND_DENC, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* Video output */
+ config.video_output_format.video_output_cea_vesa =
+ AV8100_CEA4_1280X720P_60HZ;
+
+ retval = av8100_conf_prep(
+ AV8100_COMMAND_VIDEO_OUTPUT_FORMAT, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* Video input */
+ av8100_config_video_output_dep(
+ config.video_output_format.video_output_cea_vesa);
+
+ /* Pattern generator */
+ config.pattern_generator_format.pattern_audio_mode =
+ AV8100_PATTERN_AUDIO_OFF;
+ config.pattern_generator_format.pattern_type =
+ AV8100_PATTERN_GENERATOR;
+ config.pattern_generator_format.pattern_video_format =
+ AV8100_PATTERN_720P;
+ retval = av8100_conf_prep(AV8100_COMMAND_PATTERNGENERATOR,
+ &config);
+ if (retval)
+ return -EFAULT;
+
+ /* Audio input */
+ config.audio_input_format.audio_input_if_format =
+ AV8100_AUDIO_I2SDELAYED_MODE;
+ config.audio_input_format.i2s_input_nb = 1;
+ config.audio_input_format.sample_audio_freq = AV8100_AUDIO_FREQ_48KHZ;
+ config.audio_input_format.audio_word_lg = AV8100_AUDIO_16BITS;
+ config.audio_input_format.audio_format = AV8100_AUDIO_LPCM_MODE;
+ config.audio_input_format.audio_if_mode = AV8100_AUDIO_MASTER;
+ config.audio_input_format.audio_mute = AV8100_AUDIO_MUTE_DISABLE;
+ retval = av8100_conf_prep(
+ AV8100_COMMAND_AUDIO_INPUT_FORMAT, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* HDMI mode */
+ config.hdmi_format.hdmi_mode = AV8100_HDMI_ON;
+ config.hdmi_format.hdmi_format = AV8100_HDMI;
+ config.hdmi_format.dvi_format = AV8100_DVI_CTRL_CTL0;
+ retval = av8100_conf_prep(AV8100_COMMAND_HDMI, &config);
+ if (retval)
+ return -EFAULT;
+
+ /* EDID section readback */
+ config.edid_section_readback_format.address = 0xA0;
+ config.edid_section_readback_format.block_number = 0;
+ retval = av8100_conf_prep(
+ AV8100_COMMAND_EDID_SECTION_READBACK, &config);
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int av8100_params_init(struct av8100_device *adev)
+{
+ dev_dbg(adev->dev, "%s\n", __func__);
+
+ memset(&adev->params, 0, sizeof(struct av8100_params));
+
+ adev->params.denc_off_time = AV8100_DENC_OFF_TIME;
+ adev->params.hdmi_off_time = AV8100_HDMI_OFF_TIME;
+ adev->params.on_time = AV8100_ON_TIME;
+
+ adev->params.hpdm = AV8100_STANDBY_INTERRUPT_MASK_HPDM_HIGH;
+ adev->params.cpdm = AV8100_STANDBY_INTERRUPT_MASK_CPDM_HIGH;
+ adev->params.hdcpm = AV8100_GENERAL_INTERRUPT_MASK_HDCPM_HIGH;
+ adev->params.cecm = AV8100_GENERAL_INTERRUPT_MASK_CECM_HIGH;
+ adev->params.uovbm = AV8100_GENERAL_INTERRUPT_MASK_UOVBM_HIGH;
+
+ return 0;
+}
+
+static void clr_plug_status(struct av8100_device *adev,
+ enum av8100_plugin_status status)
+{
+ adev->status.av8100_plugin_status &= ~status;
+
+ switch (status) {
+ case AV8100_HDMI_PLUGIN:
+ switch (adev->params.plug_state) {
+ case AV8100_UNPLUGGED:
+ case AV8100_PLUGGED_STARTUP:
+ default:
+ break;
+
+ case AV8100_PLUGGED:
+ adev->params.plug_state =
+ AV8100_UNPLUGGED;
+ dev_dbg(adev->dev, "plug_state:0\n");
+
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(
+ AV8100_HDMI_EVENT_HDMI_PLUGOUT);
+ break;
+ }
+ break;
+
+ case AV8100_CVBS_PLUGIN:
+ /* TODO */
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void set_plug_status(struct av8100_device *adev,
+ enum av8100_plugin_status status)
+{
+ adev->status.av8100_plugin_status |= status;
+
+ switch (status) {
+ case AV8100_HDMI_PLUGIN:
+ switch (adev->params.plug_state) {
+ case AV8100_UNPLUGGED:
+ adev->params.plug_state =
+ AV8100_PLUGGED_STARTUP;
+
+ dev_dbg(adev->dev, "plug_state:1\n");
+
+ /*
+ * Mask interrupts to avoid plug detect during
+ * startup
+ * */
+ adev->params.hpdm =
+ AV8100_STANDBY_INTERRUPT_MASK_HPDM_LOW;
+ if (av8100_reg_stby_int_mask_w(
+ adev->params.hpdm,
+ adev->params.cpdm,
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_INPUT,
+ AV8100_STANDBY_INTERRUPT_MASK_IPOL_LOW)) {
+ dev_dbg(adev->dev,
+ "av8100_reg_stby_int_mask_w fail\n");
+ }
+
+ /* Set plug startup timer */
+ init_timer(&adev->timer);
+ adev->timer.expires = jiffies +
+ AV8100_PLUGSTARTUP_TIME;
+ adev->timer.function =
+ av8100_plugtimer_int;
+ adev->timer.data = 0;
+ adev->timer.data = adev_to_devnr(adev);
+ mod_timer(&adev->timer, adev->timer.expires);
+
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(
+ AV8100_HDMI_EVENT_HDMI_PLUGIN);
+ break;
+
+ case AV8100_PLUGGED_STARTUP:
+ case AV8100_PLUGGED:
+ default:
+ break;
+ }
+ break;
+
+ case AV8100_CVBS_PLUGIN:
+ /* TODO */
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void cec_rx(struct av8100_device *adev)
+{
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(AV8100_HDMI_EVENT_CEC);
+}
+
+static void cec_tx(struct av8100_device *adev)
+{
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(AV8100_HDMI_EVENT_CECTX);
+}
+
+static void cec_txerr(struct av8100_device *adev)
+{
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(AV8100_HDMI_EVENT_CECTXERR);
+}
+
+static void hdcp_changed(struct av8100_device *adev)
+{
+ if (adev->params.hdmi_ev_cb)
+ adev->params.hdmi_ev_cb(AV8100_HDMI_EVENT_HDCP);
+}
+
+static void av8100_set_state(struct av8100_device *adev,
+ enum av8100_operating_mode state)
+{
+ adev->status.av8100_state = state;
+
+ if (state <= AV8100_OPMODE_STANDBY) {
+ clr_plug_status(adev, AV8100_HDMI_PLUGIN);
+ clr_plug_status(adev, AV8100_CVBS_PLUGIN);
+ adev->status.hdmi_on = false;
+ }
+}
+
+/**
+ * write_single_byte() - Write a single byte to av8100
+ * through i2c interface.
+ * @client: i2c client structure
+ * @reg: register offset
+ * @data: data byte to be written
+ *
+ * This funtion uses smbus byte write API to write a single byte to av8100
+ **/
+static int write_single_byte(struct i2c_client *client, u8 reg,
+ u8 data)
+{
+ int ret;
+ struct device *dev = &client->dev;
+
+ ret = i2c_smbus_write_byte_data(client, reg, data);
+ if (ret < 0)
+ dev_dbg(dev, "i2c smbus write byte failed\n");
+
+ return ret;
+}
+
+/**
+ * read_single_byte() - read single byte from av8100
+ * through i2c interface
+ * @client: i2c client structure
+ * @reg: register offset
+ * @val: register value
+ *
+ * This funtion uses smbus read block API to read single byte from the reg
+ * offset.
+ **/
+static int read_single_byte(struct i2c_client *client, u8 reg, u8 *val)
+{
+ int value;
+ struct device *dev = &client->dev;
+
+ value = i2c_smbus_read_byte_data(client, reg);
+ if (value < 0) {
+ dev_dbg(dev, "i2c smbus read byte failed,read data = %x "
+ "from offset:%x\n" , value, reg);
+ return -EFAULT;
+ }
+
+ *val = (u8) value;
+ return 0;
+}
+
+/**
+ * write_multi_byte() - Write a multiple bytes to av8100 through
+ * i2c interface.
+ * @client: i2c client structure
+ * @buf: buffer to be written
+ * @nbytes: nunmber of bytes to be written
+ *
+ * This funtion uses smbus block write API's to write n number of bytes to the
+ * av8100
+ **/
+static int write_multi_byte(struct i2c_client *client, u8 reg,
+ u8 *buf, u8 nbytes)
+{
+ int ret;
+ struct device *dev = &client->dev;
+
+ ret = i2c_smbus_write_i2c_block_data(client, reg, nbytes, buf);
+ if (ret < 0)
+ dev_dbg(dev, "i2c smbus write multi byte error\n");
+
+ return ret;
+}
+
+static int configuration_video_input_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_video_input_cmd.dsi_input_mode;
+ buffer[1] = adev->config.hdmi_video_input_cmd.input_pixel_format;
+ buffer[2] = REG_16_8_MSB(adev->config.hdmi_video_input_cmd.
+ total_horizontal_pixel);
+ buffer[3] = REG_16_8_LSB(adev->config.hdmi_video_input_cmd.
+ total_horizontal_pixel);
+ buffer[4] = REG_16_8_MSB(adev->config.hdmi_video_input_cmd.
+ total_horizontal_active_pixel);
+ buffer[5] = REG_16_8_LSB(adev->config.hdmi_video_input_cmd.
+ total_horizontal_active_pixel);
+ buffer[6] = REG_16_8_MSB(adev->config.hdmi_video_input_cmd.
+ total_vertical_lines);
+ buffer[7] = REG_16_8_LSB(adev->config.hdmi_video_input_cmd.
+ total_vertical_lines);
+ buffer[8] = REG_16_8_MSB(adev->config.hdmi_video_input_cmd.
+ total_vertical_active_lines);
+ buffer[9] = REG_16_8_LSB(adev->config.hdmi_video_input_cmd.
+ total_vertical_active_lines);
+ buffer[10] = adev->config.hdmi_video_input_cmd.video_mode;
+ buffer[11] = adev->config.hdmi_video_input_cmd.nb_data_lane;
+ buffer[12] = adev->config.hdmi_video_input_cmd.
+ nb_virtual_ch_command_mode;
+ buffer[13] = adev->config.hdmi_video_input_cmd.
+ nb_virtual_ch_video_mode;
+ buffer[14] = REG_16_8_MSB(adev->config.hdmi_video_input_cmd.
+ TE_line_nb);
+ buffer[15] = REG_16_8_LSB(adev->config.hdmi_video_input_cmd.
+ TE_line_nb);
+ buffer[16] = adev->config.hdmi_video_input_cmd.TE_config;
+ buffer[17] = REG_32_8_MSB(adev->config.hdmi_video_input_cmd.
+ master_clock_freq);
+ buffer[18] = REG_32_8_MMSB(adev->config.hdmi_video_input_cmd.
+ master_clock_freq);
+ buffer[19] = REG_32_8_MLSB(adev->config.hdmi_video_input_cmd.
+ master_clock_freq);
+ buffer[20] = REG_32_8_LSB(adev->config.hdmi_video_input_cmd.
+ master_clock_freq);
+ buffer[21] = adev->config.hdmi_video_input_cmd.ui_x4;
+
+ *length = AV8100_COMMAND_VIDEO_INPUT_FORMAT_SIZE - 1;
+ return 0;
+
+}
+
+static int configuration_audio_input_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_audio_input_cmd.audio_input_if_format;
+ buffer[1] = adev->config.hdmi_audio_input_cmd.i2s_input_nb;
+ buffer[2] = adev->config.hdmi_audio_input_cmd.sample_audio_freq;
+ buffer[3] = adev->config.hdmi_audio_input_cmd.audio_word_lg;
+ buffer[4] = adev->config.hdmi_audio_input_cmd.audio_format;
+ buffer[5] = adev->config.hdmi_audio_input_cmd.audio_if_mode;
+ buffer[6] = adev->config.hdmi_audio_input_cmd.audio_mute;
+
+ *length = AV8100_COMMAND_AUDIO_INPUT_FORMAT_SIZE - 1;
+ return 0;
+}
+
+static int configuration_video_output_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_video_output_cmd.
+ video_output_cea_vesa;
+
+ if (buffer[0] == AV8100_CUSTOM) {
+ buffer[1] = adev->config.hdmi_video_output_cmd.
+ vsync_polarity;
+ buffer[2] = adev->config.hdmi_video_output_cmd.
+ hsync_polarity;
+ buffer[3] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.total_horizontal_pixel);
+ buffer[4] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.total_horizontal_pixel);
+ buffer[5] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.total_horizontal_active_pixel);
+ buffer[6] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.total_horizontal_active_pixel);
+ buffer[7] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.total_vertical_in_half_lines);
+ buffer[8] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.total_vertical_in_half_lines);
+ buffer[9] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.
+ total_vertical_active_in_half_lines);
+ buffer[10] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.
+ total_vertical_active_in_half_lines);
+ buffer[11] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.hsync_start_in_pixel);
+ buffer[12] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.hsync_start_in_pixel);
+ buffer[13] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.hsync_length_in_pixel);
+ buffer[14] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.hsync_length_in_pixel);
+ buffer[15] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.vsync_start_in_half_line);
+ buffer[16] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.vsync_start_in_half_line);
+ buffer[17] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.vsync_length_in_half_line);
+ buffer[18] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.vsync_length_in_half_line);
+ buffer[19] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.hor_video_start_pixel);
+ buffer[20] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.hor_video_start_pixel);
+ buffer[21] = REG_16_8_MSB(adev->config.
+ hdmi_video_output_cmd.vert_video_start_pixel);
+ buffer[22] = REG_16_8_LSB(adev->config.
+ hdmi_video_output_cmd.vert_video_start_pixel);
+ buffer[23] = adev->config.hdmi_video_output_cmd.video_type;
+ buffer[24] = adev->config.hdmi_video_output_cmd.pixel_repeat;
+ buffer[25] = REG_32_8_MSB(adev->config.
+ hdmi_video_output_cmd.pixel_clock_freq_Hz);
+ buffer[26] = REG_32_8_MMSB(adev->config.
+ hdmi_video_output_cmd.pixel_clock_freq_Hz);
+ buffer[27] = REG_32_8_MLSB(adev->config.
+ hdmi_video_output_cmd.pixel_clock_freq_Hz);
+ buffer[28] = REG_32_8_LSB(adev->config.
+ hdmi_video_output_cmd.pixel_clock_freq_Hz);
+
+ *length = AV8100_COMMAND_VIDEO_OUTPUT_FORMAT_SIZE - 1;
+ } else {
+ *length = 1;
+ }
+
+ return 0;
+}
+
+static int configuration_video_scaling_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ h_start_in_pixel);
+ buffer[1] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ h_start_in_pixel);
+ buffer[2] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ h_stop_in_pixel);
+ buffer[3] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ h_stop_in_pixel);
+ buffer[4] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ v_start_in_line);
+ buffer[5] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ v_start_in_line);
+ buffer[6] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ v_stop_in_line);
+ buffer[7] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ v_stop_in_line);
+ buffer[8] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ h_start_out_pixel);
+ buffer[9] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd
+ .h_start_out_pixel);
+ buffer[10] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ h_stop_out_pixel);
+ buffer[11] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ h_stop_out_pixel);
+ buffer[12] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ v_start_out_line);
+ buffer[13] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ v_start_out_line);
+ buffer[14] = REG_16_8_MSB(adev->config.hdmi_video_scaling_cmd.
+ v_stop_out_line);
+ buffer[15] = REG_16_8_LSB(adev->config.hdmi_video_scaling_cmd.
+ v_stop_out_line);
+
+ *length = AV8100_COMMAND_VIDEO_SCALING_FORMAT_SIZE - 1;
+ return 0;
+}
+
+static int configuration_colorspace_conversion_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ const struct color_conversion_cmd *hdmi_color_space_conversion_cmd;
+
+ hdmi_color_space_conversion_cmd =
+ get_color_transform_cmd(adev, adev->config.color_transform);
+
+ buffer[0] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c0);
+ buffer[1] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c0);
+ buffer[2] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c1);
+ buffer[3] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c1);
+ buffer[4] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c2);
+ buffer[5] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c2);
+ buffer[6] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c3);
+ buffer[7] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c3);
+ buffer[8] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c4);
+ buffer[9] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c4);
+ buffer[10] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c5);
+ buffer[11] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c5);
+ buffer[12] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c6);
+ buffer[13] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c6);
+ buffer[14] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c7);
+ buffer[15] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c7);
+ buffer[16] = REG_12_8_MSB(hdmi_color_space_conversion_cmd->c8);
+ buffer[17] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->c8);
+ buffer[18] = REG_10_8_MSB(hdmi_color_space_conversion_cmd->aoffset);
+ buffer[19] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->aoffset);
+ buffer[20] = REG_10_8_MSB(hdmi_color_space_conversion_cmd->boffset);
+ buffer[21] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->boffset);
+ buffer[22] = REG_10_8_MSB(hdmi_color_space_conversion_cmd->coffset);
+ buffer[23] = REG_16_8_LSB(hdmi_color_space_conversion_cmd->coffset);
+ buffer[24] = hdmi_color_space_conversion_cmd->lmax;
+ buffer[25] = hdmi_color_space_conversion_cmd->lmin;
+ buffer[26] = hdmi_color_space_conversion_cmd->cmax;
+ buffer[27] = hdmi_color_space_conversion_cmd->cmin;
+
+ *length = AV8100_COMMAND_COLORSPACECONVERSION_SIZE - 1;
+ return 0;
+}
+
+static int configuration_cec_message_write_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_cec_message_write_cmd.buffer_length;
+ memcpy(&buffer[1], adev->config.hdmi_cec_message_write_cmd.buffer,
+ adev->config.hdmi_cec_message_write_cmd.buffer_length);
+
+ *length = adev->config.hdmi_cec_message_write_cmd.buffer_length + 1;
+
+ return 0;
+}
+
+static int configuration_cec_message_read_get(char *buffer,
+ unsigned int *length)
+{
+ /* No buffer data */
+ *length = AV8100_COMMAND_CEC_MESSAGE_READ_BACK_SIZE - 1;
+ return 0;
+}
+
+static int configuration_denc_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_denc_cmd.cvbs_video_format;
+ buffer[1] = adev->config.hdmi_denc_cmd.standard_selection;
+ buffer[2] = adev->config.hdmi_denc_cmd.enable;
+ buffer[3] = adev->config.hdmi_denc_cmd.macrovision_enable;
+ buffer[4] = adev->config.hdmi_denc_cmd.internal_generator;
+
+ *length = AV8100_COMMAND_DENC_SIZE - 1;
+ return 0;
+}
+
+static int configuration_hdmi_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_cmd.hdmi_mode;
+ buffer[1] = adev->config.hdmi_cmd.hdmi_format;
+ buffer[2] = adev->config.hdmi_cmd.dvi_format;
+
+ *length = AV8100_COMMAND_HDMI_SIZE - 1;
+ return 0;
+}
+
+static int configuration_hdcp_sendkey_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_hdcp_send_key_cmd.key_number;
+ memcpy(&buffer[1], adev->config.hdmi_hdcp_send_key_cmd.data,
+ adev->config.hdmi_hdcp_send_key_cmd.data_len);
+
+ *length = adev->config.hdmi_hdcp_send_key_cmd.data_len + 1;
+ return 0;
+}
+
+static int configuration_hdcp_management_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_hdcp_management_format_cmd.req_type;
+ buffer[1] = adev->config.hdmi_hdcp_management_format_cmd.encr_use;
+
+ *length = AV8100_COMMAND_HDCP_MANAGEMENT_SIZE - 1;
+ return 0;
+}
+
+static int configuration_infoframe_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_infoframes_cmd.type;
+ buffer[1] = adev->config.hdmi_infoframes_cmd.version;
+ buffer[2] = adev->config.hdmi_infoframes_cmd.length;
+ buffer[3] = adev->config.hdmi_infoframes_cmd.crc;
+ memcpy(&buffer[4], adev->config.hdmi_infoframes_cmd.data,
+ HDMI_INFOFRAME_DATA_SIZE);
+
+ *length = adev->config.hdmi_infoframes_cmd.length + 4;
+ return 0;
+}
+
+static int av8100_edid_section_readback_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_edid_section_readback_cmd.address;
+ buffer[1] = adev->config.hdmi_edid_section_readback_cmd.
+ block_number;
+
+ *length = AV8100_COMMAND_EDID_SECTION_READBACK_SIZE - 1;
+ return 0;
+}
+
+static int configuration_pattern_generator_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_pattern_generator_cmd.pattern_type;
+ buffer[1] = adev->config.hdmi_pattern_generator_cmd.
+ pattern_video_format;
+ buffer[2] = adev->config.hdmi_pattern_generator_cmd.
+ pattern_audio_mode;
+
+ *length = AV8100_COMMAND_PATTERNGENERATOR_SIZE - 1;
+ return 0;
+}
+
+static int configuration_fuse_aes_key_get(struct av8100_device *adev,
+ char *buffer, unsigned int *length)
+{
+ buffer[0] = adev->config.hdmi_fuse_aes_key_cmd.fuse_operation;
+ if (adev->config.hdmi_fuse_aes_key_cmd.fuse_operation) {
+ /* Write key command */
+ memcpy(&buffer[1], adev->config.hdmi_fuse_aes_key_cmd.key,
+ HDMI_FUSE_AES_KEY_SIZE);
+
+ *length = AV8100_COMMAND_FUSE_AES_KEY_SIZE - 1;
+ } else {
+ /* Check key command */
+ *length = AV8100_COMMAND_FUSE_AES_CHK_SIZE - 1;
+ }
+ return 0;
+}
+
+static int get_command_return_first(struct i2c_client *i2c,
+ enum av8100_command_type command_type) {
+ int retval = 0;
+ char val;
+ struct device *dev = &i2c->dev;
+
+ retval = read_single_byte(i2c, AV8100_COMMAND_OFFSET, &val);
+ if (retval) {
+ dev_dbg(dev, "%s 1st ret failed\n", __func__);
+ return retval;
+ }
+
+ if (val != (0x80 | command_type)) {
+ dev_dbg(dev, "%s 1st ret wrong:%x\n", __func__, val);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int get_command_return_data(struct i2c_client *i2c,
+ enum av8100_command_type command_type,
+ u8 *command_buffer,
+ u8 *buffer_length,
+ u8 *buffer)
+{
+ int retval = 0;
+ char val;
+ int index = 0;
+ struct device *dev = &i2c->dev;
+
+ if (buffer_length)
+ *buffer_length = 0;
+
+ switch (command_type) {
+ case AV8100_COMMAND_VIDEO_INPUT_FORMAT:
+ case AV8100_COMMAND_AUDIO_INPUT_FORMAT:
+ case AV8100_COMMAND_VIDEO_OUTPUT_FORMAT:
+ case AV8100_COMMAND_VIDEO_SCALING_FORMAT:
+ case AV8100_COMMAND_COLORSPACECONVERSION:
+ case AV8100_COMMAND_CEC_MESSAGE_WRITE:
+ case AV8100_COMMAND_DENC:
+ case AV8100_COMMAND_HDMI:
+ case AV8100_COMMAND_INFOFRAMES:
+ case AV8100_COMMAND_PATTERNGENERATOR:
+ /* Get the second return byte */
+ retval = read_single_byte(i2c,
+ AV8100_2ND_RET_BYTE_OFFSET, &val);
+ if (retval)
+ goto get_command_return_data_fail2r;
+
+ if (val) {
+ retval = -EFAULT;
+ goto get_command_return_data_fail2v;
+ }
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_READ_BACK:
+ if ((buffer == NULL) || (buffer_length == NULL)) {
+ retval = -EINVAL;
+ goto get_command_return_data_fail;
+ }
+
+ /* Get the return buffer length */
+ retval = read_single_byte(i2c, AV8100_CEC_ADDR_OFFSET, &val);
+ if (retval)
+ goto get_command_return_data_fail;
+
+ dev_dbg(dev, "cec buflen:%d\n", val);
+ *buffer_length = val;
+
+ if (*buffer_length >
+ HDMI_CEC_READ_MAXSIZE) {
+ dev_dbg(dev, "CEC size too large %d\n",
+ *buffer_length);
+ *buffer_length = HDMI_CEC_READ_MAXSIZE;
+ }
+
+ dev_dbg(dev, "return data: ");
+
+ /* Get the return buffer */
+ for (index = 0; index < *buffer_length; ++index) {
+ retval = read_single_byte(i2c,
+ AV8100_CEC_RET_BUF_OFFSET + index, &val);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = val;
+ dev_dbg(dev, "%02x ", *(buffer + index));
+ }
+ }
+
+ dev_dbg(dev, "\n");
+ break;
+
+ case AV8100_COMMAND_HDCP_MANAGEMENT:
+ {
+ u8 nrdev;
+ u8 devcnt;
+ int cnt;
+
+ /* Get the second return byte */
+ retval = read_single_byte(i2c,
+ AV8100_2ND_RET_BYTE_OFFSET, &val);
+ if (retval) {
+ goto get_command_return_data_fail2r;
+ } else {
+ /* Check the second return byte */
+ if (val)
+ goto get_command_return_data_fail2v;
+ }
+
+ if ((buffer == NULL) || (buffer_length == NULL))
+ /* Ignore return data */
+ break;
+
+ dev_dbg(dev, "req_type:%02x ", command_buffer[0]);
+
+ /* Check if revoc list data is requested */
+ if (command_buffer[0] !=
+ HDMI_REQUEST_FOR_REVOCATION_LIST_INPUT) {
+ *buffer_length = 0;
+ break;
+ }
+
+ dev_dbg(dev, "return data: ");
+
+ /* Get the return buffer */
+ for (cnt = 0; cnt < HDMI_HDCP_MGMT_BKSV_SIZE; cnt++) {
+ retval = read_single_byte(i2c,
+ AV8100_HDCP_RET_BUF_OFFSET + index, &val);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = val;
+ dev_dbg(dev, "%02x ", *(buffer + index));
+ }
+ index++;
+ }
+
+ /* Get Device count */
+ retval = read_single_byte(i2c,
+ AV8100_HDCP_RET_BUF_OFFSET + index, &nrdev);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = nrdev;
+ dev_dbg(dev, "%02x ", *(buffer + index));
+ }
+ index++;
+
+ /* Determine number of devices */
+ nrdev &= HDMI_HDCP_MGMT_DEVICE_MASK;
+ if (nrdev > HDMI_HDCP_MGMT_MAX_DEVICES_SIZE)
+ nrdev = HDMI_HDCP_MGMT_MAX_DEVICES_SIZE;
+
+ /* Get Bksv for each connected equipment */
+ for (devcnt = 0; devcnt < nrdev; devcnt++)
+ for (cnt = 0; cnt < HDMI_HDCP_MGMT_BKSV_SIZE; cnt++) {
+ retval = read_single_byte(i2c,
+ AV8100_HDCP_RET_BUF_OFFSET + index,
+ &val);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = val;
+ dev_dbg(dev, "%02x ",
+ *(buffer + index));
+ }
+ index++;
+ }
+
+ if (nrdev == 0)
+ goto hdcp_management_end;
+
+ /* Get SHA signature */
+ for (cnt = 0; cnt < HDMI_HDCP_MGMT_SHA_SIZE - 1; cnt++) {
+ retval = read_single_byte(i2c,
+ AV8100_HDCP_RET_BUF_OFFSET + index, &val);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = val;
+ dev_dbg(dev, "%02x ", *(buffer + index));
+ }
+ index++;
+ }
+
+hdcp_management_end:
+ *buffer_length = index;
+
+ dev_dbg(dev, "\n");
+ }
+ break;
+
+ case AV8100_COMMAND_EDID_SECTION_READBACK:
+ if ((buffer == NULL) || (buffer_length == NULL)) {
+ retval = -EINVAL;
+ goto get_command_return_data_fail;
+ }
+
+ /* Return buffer length is fixed */
+ *buffer_length = HDMI_EDIDREAD_SIZE;
+
+ dev_dbg(dev, "return data: ");
+
+ /* Get the return buffer */
+ for (index = 0; index < *buffer_length; ++index) {
+ retval = read_single_byte(i2c,
+ AV8100_EDID_RET_BUF_OFFSET + index, &val);
+ if (retval) {
+ *buffer_length = 0;
+ goto get_command_return_data_fail;
+ } else {
+ *(buffer + index) = val;
+ dev_dbg(dev, "%02x ", *(buffer + index));
+ }
+ }
+
+ dev_dbg(dev, "\n");
+ break;
+
+ case AV8100_COMMAND_FUSE_AES_KEY:
+ if ((buffer == NULL) || (buffer_length == NULL)) {
+ retval = -EINVAL;
+ goto get_command_return_data_fail;
+ }
+
+ /* Get the second return byte */
+ retval = read_single_byte(i2c,
+ AV8100_2ND_RET_BYTE_OFFSET, &val);
+
+ if (retval)
+ goto get_command_return_data_fail2r;
+
+ /* Check the second return byte */
+ if (val) {
+ retval = -EFAULT;
+ goto get_command_return_data_fail2v;
+ }
+
+ /* Return buffer length is fixed */
+ *buffer_length = HDMI_FUSE_AES_KEY_RET_SIZE;
+
+ /* Get CRC */
+ retval = read_single_byte(i2c,
+ AV8100_FUSE_CRC_OFFSET, &val);
+ if (retval)
+ goto get_command_return_data_fail;
+
+ *buffer = val;
+ dev_dbg(dev, "CRC:%02x ", val);
+
+ /* Get programmed status */
+ retval = read_single_byte(i2c,
+ AV8100_FUSE_PRGD_OFFSET, &val);
+ if (retval)
+ goto get_command_return_data_fail;
+
+ *(buffer + 1) = val;
+
+ dev_dbg(dev, "programmed:%02x ", val);
+ break;
+
+ case AV8100_COMMAND_HDCP_SENDKEY:
+ if ((command_buffer[0] == HDMI_LOADAES_END_BLK_NR) &&
+ ((buffer == NULL) || (buffer_length == NULL))) {
+ retval = -EINVAL;
+ goto get_command_return_data_fail;
+ }
+
+ /* Get the second return byte */
+ retval = read_single_byte(i2c,
+ AV8100_2ND_RET_BYTE_OFFSET, &val);
+ if (retval)
+ goto get_command_return_data_fail2r;
+
+ if (val) {
+ retval = -EFAULT;
+ goto get_command_return_data_fail2v;
+ }
+
+ if (command_buffer[0] == HDMI_LOADAES_END_BLK_NR) {
+ /* Return CRC32 if last AES block */
+ int cnt;
+
+ dev_dbg(dev, "CRC32:");
+ for (cnt = 0; cnt < HDMI_CRC32_SIZE; cnt++) {
+ if (read_single_byte(i2c,
+ AV8100_CRC32_OFFSET + cnt, &val))
+ goto get_command_return_data_fail;
+ *(buffer + cnt) = val;
+ dev_dbg(dev, "%02x", val);
+ }
+
+ *buffer_length = HDMI_CRC32_SIZE;
+ }
+ break;
+
+ default:
+ retval = -EFAULT;
+ break;
+ }
+
+ return retval;
+get_command_return_data_fail2r:
+ dev_dbg(dev, "%s Reading 2nd return byte failed\n", __func__);
+ return retval;
+get_command_return_data_fail2v:
+ dev_dbg(dev, "%s 2nd return byte is wrong:%x\n", __func__, val);
+ return retval;
+get_command_return_data_fail:
+ dev_dbg(dev, "%s FAIL\n", __func__);
+ return retval;
+}
+
+static int av8100_powerup1(struct av8100_device *adev)
+{
+ int retval;
+ struct av8100_platform_data *pdata = adev->dev->platform_data;
+
+ /* Regulator enable */
+ if ((adev->params.regulator_pwr) &&
+ (adev->params.regulator_requested == false)) {
+ retval = regulator_enable(adev->params.regulator_pwr);
+ if (retval < 0) {
+ dev_warn(adev->dev, "%s: regulator_enable failed\n",
+ __func__);
+ return retval;
+ }
+ dev_dbg(adev->dev, "regulator_enable ok\n");
+ adev->params.regulator_requested = true;
+ }
+
+ /* Reset av8100 */
+ gpio_set_value_cansleep(pdata->reset, 1);
+
+ /* Need to wait before proceeding */
+ mdelay(AV8100_WAITTIME_1MS);
+
+ av8100_set_state(adev, AV8100_OPMODE_STANDBY);
+
+ if (pdata->alt_powerupseq) {
+ dev_dbg(adev->dev, "powerup seq alt\n");
+ retval = av8100_5V_w(0, 0, AV8100_ON_TIME);
+ if (retval) {
+ dev_err(adev->dev, "%s reg_wr err 1\n", __func__);
+ goto av8100_powerup1_err;
+ }
+
+ udelay(AV8100_WATTIME_100US);
+
+ retval = av8100_reg_stby_pend_int_w(
+ AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_HIGH);
+ if (retval) {
+ dev_err(adev->dev, "%s reg_wr err 2\n", __func__);
+ goto av8100_powerup1_err;
+ }
+
+ udelay(AV8100_WATTIME_100US);
+
+ retval = av8100_reg_stby_w(AV8100_STANDBY_CPD_LOW,
+ AV8100_STANDBY_STBY_HIGH, pdata->mclk_freq);
+ if (retval) {
+ dev_err(adev->dev, "%s reg_wr err 3\n", __func__);
+ goto av8100_powerup1_err;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ retval = av8100_reg_stby_w(AV8100_STANDBY_CPD_LOW,
+ AV8100_STANDBY_STBY_LOW, pdata->mclk_freq);
+ if (retval) {
+ dev_err(adev->dev, "%s reg_wr err 4\n", __func__);
+ goto av8100_powerup1_err;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ retval = av8100_reg_stby_pend_int_w(
+ AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_LOW);
+ if (retval) {
+ dev_err(adev->dev, "%s reg_wr err 5\n", __func__);
+ goto av8100_powerup1_err;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+ }
+
+ retval = request_irq(pdata->irq, av8100_intr_handler,
+ IRQF_TRIGGER_RISING, "av8100", adev);
+ if (retval == 0)
+ adev->params.irq_requested = true;
+ else
+ dev_err(adev->dev, "request_irq %d failed %d\n",
+ pdata->irq, retval);
+
+ return retval;
+
+av8100_powerup1_err:
+ av8100_powerdown();
+ return -EFAULT;
+}
+
+static int av8100_powerup2(struct av8100_device *adev)
+{
+ int retval;
+
+ /* ON time & OFF time on 5v HDMI plug detect */
+ retval = av8100_5V_w(adev->params.denc_off_time,
+ adev->params.hdmi_off_time,
+ adev->params.on_time);
+ if (retval) {
+ dev_err(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return retval;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ av8100_set_state(adev, AV8100_OPMODE_SCAN);
+
+ return 0;
+}
+
+static int register_read_internal(u8 offset, u8 *value)
+{
+ int retval = 0;
+ struct i2c_client *i2c;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EFAULT;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ i2c = adev->config.client;
+
+ /* Read from register */
+ retval = read_single_byte(i2c, offset, value);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to read the value from av8100 register\n");
+ return -EFAULT;
+ }
+
+ return retval;
+}
+
+static int register_write_internal(u8 offset, u8 value)
+{
+ int retval;
+ struct i2c_client *i2c;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EFAULT;
+
+ i2c = adev->config.client;
+
+ /* Write to register */
+ retval = write_single_byte(i2c, offset, value);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int av8100_powerscan(void)
+{
+ int retval;
+ struct av8100_device *adev;
+ struct av8100_platform_data *pdata;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EFAULT;
+
+ pdata = adev->dev->platform_data;
+
+ dev_dbg(adev->dev, "%s\n", __func__);
+
+ if (av8100_status_get().av8100_state > AV8100_OPMODE_SCAN) {
+ dev_dbg(adev->dev, "set to scan mode\n");
+
+ av8100_disable_interrupt();
+
+ /* Stby mode */
+ retval = av8100_reg_stby_w(AV8100_STANDBY_CPD_LOW,
+ AV8100_STANDBY_STBY_LOW, pdata->mclk_freq);
+ if (retval) {
+ dev_err(adev->dev,
+ "Failed to write to av8100 register\n");
+ return retval;
+ }
+
+ /* Remove APE OPP requirement */
+ if (adev->params.opp_requested) {
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+ (char *)adev->miscdev.name);
+ prcmu_qos_remove_requirement(PRCMU_QOS_DDR_OPP,
+ (char *)adev->miscdev.name);
+ adev->params.opp_requested = false;
+ }
+
+ /* Clock disable */
+ if (adev->params.inputclk &&
+ adev->params.inputclk_requested) {
+ clk_disable(adev->params.inputclk);
+ adev->params.inputclk_requested = false;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ av8100_enable_interrupt();
+
+ av8100_set_state(adev, AV8100_OPMODE_SCAN);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(av8100_powerscan);
+
+int av8100_powerup(void)
+{
+ int ret = 0;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EFAULT;
+
+ if (av8100_status_get().av8100_state == AV8100_OPMODE_UNDEFINED)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state < AV8100_OPMODE_STANDBY) {
+ ret = av8100_powerup1(adev);
+ if (ret) {
+ dev_err(adev->dev, "av8100_powerup1 fail\n");
+ return -EFAULT;
+ }
+ }
+
+ if (av8100_status_get().av8100_state < AV8100_OPMODE_SCAN)
+ ret = av8100_powerup2(adev);
+
+ av8100_enable_interrupt();
+
+ return ret;
+}
+EXPORT_SYMBOL(av8100_powerup);
+
+int av8100_powerdown(void)
+{
+ int retval = 0;
+ struct av8100_device *adev;
+ struct av8100_platform_data *pdata;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EFAULT;
+
+ pdata = adev->dev->platform_data;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ goto av8100_powerdown_end;
+
+ av8100_disable_interrupt();
+
+ if (adev->params.irq_requested)
+ free_irq(pdata->irq, adev);
+ adev->params.irq_requested = false;
+
+ if (pdata->alt_powerupseq) {
+ retval = av8100_reg_stby_pend_int_w(
+ AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_HIGH);
+
+ if (retval)
+ dev_err(adev->dev, "%s reg_wr err\n", __func__);
+ msleep(AV8100_WAITTIME_50MS);
+ }
+
+ /* Remove APE OPP requirement */
+ if (adev->params.opp_requested) {
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+ (char *)adev->miscdev.name);
+ prcmu_qos_remove_requirement(PRCMU_QOS_DDR_OPP,
+ (char *)adev->miscdev.name);
+ adev->params.opp_requested = false;
+ }
+
+ /* Clock disable */
+ if (adev->params.inputclk && adev->params.inputclk_requested) {
+ clk_disable(adev->params.inputclk);
+ adev->params.inputclk_requested = false;
+ }
+
+ av8100_set_state(adev, AV8100_OPMODE_SHUTDOWN);
+
+ gpio_set_value_cansleep(pdata->reset, 0);
+
+ /* Regulator disable */
+ if ((adev->params.regulator_pwr) &&
+ (adev->params.regulator_requested)) {
+ dev_dbg(adev->dev, "regulator_disable\n");
+ regulator_disable(adev->params.regulator_pwr);
+ adev->params.regulator_requested = false;
+ }
+
+ if (pdata->alt_powerupseq)
+ mdelay(AV8100_WAITTIME_5MS);
+
+av8100_powerdown_end:
+ return retval;
+}
+EXPORT_SYMBOL(av8100_powerdown);
+
+int av8100_download_firmware(enum interface_type if_type)
+{
+ int retval;
+ int temp = 0x0;
+ int increment = 15;
+ int index = 0;
+ int size = 0x0;
+ char val = 0x0;
+ char checksum = 0;
+ int cnt;
+ int cnt_max;
+ struct i2c_client *i2c;
+ u8 uc;
+ u8 fdl;
+ u8 hld;
+ u8 wa;
+ u8 ra;
+ struct av8100_platform_data *pdata;
+ const struct firmware *fw_file;
+ u8 *fw_buff;
+ int fw_bytes;
+ struct av8100_device *adev;
+ struct av8100_status status;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ LOCK_AV8100_FWDL;
+
+ status = av8100_status_get();
+ if (status.av8100_state <= AV8100_OPMODE_SHUTDOWN) {
+ retval = -EINVAL;
+ goto av8100_download_firmware_err2;
+ }
+
+ if (status.av8100_state >= AV8100_OPMODE_INIT) {
+ dev_dbg(adev->dev, "FW already ok\n");
+ retval = 0;
+ goto av8100_download_firmware_err2;
+ }
+
+ av8100_set_state(adev, AV8100_OPMODE_INIT);
+
+ pdata = adev->dev->platform_data;
+
+ /* Request firmware */
+ if (request_firmware(&fw_file,
+ AV8100_FW_FILENAME,
+ adev->dev)) {
+ dev_err(adev->dev, "fw request failed\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err2;
+ }
+
+ /* Master clock timing, running */
+ retval = av8100_reg_stby_w(AV8100_STANDBY_CPD_LOW,
+ AV8100_STANDBY_STBY_HIGH, pdata->mclk_freq);
+ if (retval) {
+ dev_err(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ goto av8100_download_firmware_err;
+ }
+
+ mdelay(AV8100_WAITTIME_1MS);
+
+ /* Clock enable */
+ if (adev->params.inputclk &&
+ adev->params.inputclk_requested == false) {
+ if (clk_enable(adev->params.inputclk)) {
+ dev_err(adev->dev, "inputclk en failed\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ adev->params.inputclk_requested = true;
+ }
+
+ /* Request 100% APE OPP */
+ if (adev->params.opp_requested == false) {
+ if (prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+ (char *)adev->miscdev.name, 100)) {
+ dev_err(adev->dev, "APE OPP 100 failed\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+ if (prcmu_qos_add_requirement(PRCMU_QOS_DDR_OPP,
+ (char *)adev->miscdev.name, 100)) {
+ dev_err(adev->dev, "DDR OPP 100 failed\n");
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+ (char *)adev->miscdev.name);
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ adev->params.opp_requested = true;
+ }
+
+ msleep(AV8100_WAITTIME_10MS);
+
+ /* Prepare firmware data */
+ fw_bytes = fw_file->size;
+ fw_buff = (u8 *)fw_file->data;
+ dev_dbg(adev->dev, "fw size:%d\n", fw_bytes);
+
+ i2c = adev->config.client;
+
+ /* Enable firmware download */
+ retval = av8100_reg_gen_ctrl_w(
+ AV8100_GENERAL_CONTROL_FDL_HIGH,
+ AV8100_GENERAL_CONTROL_HLD_HIGH,
+ AV8100_GENERAL_CONTROL_WA_LOW,
+ AV8100_GENERAL_CONTROL_RA_LOW);
+ if (retval) {
+ dev_err(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ retval = av8100_reg_gen_ctrl_r(&fdl, &hld, &wa, &ra);
+ if (retval) {
+ dev_err(adev->dev,
+ "Failed to read the value from av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ } else {
+ dev_dbg(adev->dev, "GENERAL_CONTROL_REG register fdl:%d "
+ "hld:%d wa:%d ra:%d\n", fdl, hld, wa, ra);
+ }
+
+ LOCK_AV8100_HW;
+
+ temp = fw_bytes % increment;
+ for (size = 0; size < (fw_bytes-temp); size = size + increment,
+ index += increment) {
+ if (if_type == I2C_INTERFACE) {
+ retval = write_multi_byte(i2c,
+ AV8100_FIRMWARE_DOWNLOAD_ENTRY, fw_buff + size,
+ increment);
+ if (retval) {
+ dev_dbg(adev->dev, "Failed to download the "
+ "av8100 firmware\n");
+ UNLOCK_AV8100_HW;
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+ } else if (if_type == DSI_INTERFACE) {
+ dev_dbg(adev->dev,
+ "DSI_INTERFACE is currently not supported\n");
+ UNLOCK_AV8100_HW;
+ retval = -EINVAL;
+ goto av8100_download_firmware_err;
+ } else {
+ UNLOCK_AV8100_HW;
+ retval = -EINVAL;
+ goto av8100_download_firmware_err;
+ }
+ }
+
+ /* Transfer last firmware bytes */
+ if (if_type == I2C_INTERFACE) {
+ retval = write_multi_byte(i2c,
+ AV8100_FIRMWARE_DOWNLOAD_ENTRY, fw_buff + size, temp);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to download the av8100 firmware\n");
+ UNLOCK_AV8100_HW;
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+ } else if (if_type == DSI_INTERFACE) {
+ /* TODO: Add support for DSI firmware download */
+ UNLOCK_AV8100_HW;
+ retval = -EINVAL;
+ goto av8100_download_firmware_err;
+ } else {
+ UNLOCK_AV8100_HW;
+ retval = -EINVAL;
+ goto av8100_download_firmware_err;
+ }
+
+ /* check transfer*/
+ for (size = 0; size < fw_bytes; size++)
+ checksum = checksum ^ fw_buff[size];
+
+ UNLOCK_AV8100_HW;
+
+ retval = av8100_reg_fw_dl_entry_r(&val);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to read the value from the av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ dev_dbg(adev->dev, "checksum:%x,val:%x\n", checksum, val);
+
+ if (checksum != val) {
+ dev_dbg(adev->dev,
+ ">Fw downloading.... FAIL checksum issue\n");
+ dev_dbg(adev->dev, "checksum = %d\n", checksum);
+ dev_dbg(adev->dev, "checksum read: %d\n", val);
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ } else {
+ dev_dbg(adev->dev, ">Fw downloading.... success\n");
+ }
+
+ /* Set to idle mode */
+ av8100_reg_gen_ctrl_w(AV8100_GENERAL_CONTROL_FDL_LOW,
+ AV8100_GENERAL_CONTROL_HLD_LOW, AV8100_GENERAL_CONTROL_WA_LOW,
+ AV8100_GENERAL_CONTROL_RA_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to the av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ /* Wait Internal Micro controler ready */
+ cnt = 0;
+ cnt_max = sizeof(waittime_retry) / sizeof(waittime_retry[0]);
+ retval = av8100_reg_gen_status_r(NULL, NULL, NULL, &uc,
+ NULL, NULL);
+ while ((retval == 0) && (uc != 0x1) && (cnt < cnt_max)) {
+ mdelay(waittime_retry[cnt]);
+ retval = av8100_reg_gen_status_r(NULL, NULL, NULL,
+ &uc, NULL, NULL);
+ cnt++;
+ }
+ dev_dbg(adev->dev, "av8100 fwdl cnt:%d\n", cnt);
+
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to read the value from the av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_download_firmware_err;
+ }
+
+ if (uc != 0x1)
+ dev_dbg(adev->dev, "UC is not ready\n");
+
+ release_firmware(fw_file);
+
+ if (adev->chip_version != 1) {
+ char *cut_str;
+
+ /* Get cut version */
+ retval = read_single_byte(i2c, AV8100_CUTVER_OFFSET, &val);
+ if (retval) {
+ dev_err(adev->dev, "Read cut ver failed\n");
+ return retval;
+ }
+
+ switch (val) {
+ case 0x00:
+ cut_str = CUT_STR_0;
+ break;
+ case 0x01:
+ cut_str = CUT_STR_1;
+ break;
+ case 0x03:
+ cut_str = CUT_STR_3;
+ break;
+ case 0x30:
+ cut_str = CUT_STR_30;
+ break;
+ default:
+ cut_str = CUT_STR_UNKNOWN;
+ break;
+ }
+ dev_dbg(adev->dev, "Cut ver %d %s\n", val, cut_str);
+ }
+
+ av8100_set_state(adev, AV8100_OPMODE_IDLE);
+
+ UNLOCK_AV8100_FWDL;
+ return 0;
+
+av8100_download_firmware_err:
+ release_firmware(fw_file);
+
+ /* Remove APE OPP requirement */
+ if (adev->params.opp_requested) {
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+ (char *)adev->miscdev.name);
+ prcmu_qos_remove_requirement(PRCMU_QOS_DDR_OPP,
+ (char *)adev->miscdev.name);
+ adev->params.opp_requested = false;
+ }
+
+ /* Clock disable */
+ if (adev->params.inputclk && adev->params.inputclk_requested) {
+ clk_disable(adev->params.inputclk);
+ adev->params.inputclk_requested = false;
+ }
+
+av8100_download_firmware_err2:
+ UNLOCK_AV8100_FWDL;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_download_firmware);
+
+int av8100_disable_interrupt(void)
+{
+ int retval;
+ u8 hpdm = 0;
+ u8 cpdm = 0;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ if (!adev->params.ints_enabled)
+ return 0;
+
+ retval = av8100_reg_stby_pend_int_w(
+ AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ retval = av8100_reg_gen_int_mask_w(
+ AV8100_GENERAL_INTERRUPT_MASK_EOCM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_VSIM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_VSOM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_CECM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_HDCPM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_UOVBM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_TEM_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ hpdm = adev->params.hpdm;
+ cpdm = adev->params.cpdm;
+
+ retval = av8100_reg_stby_int_mask_w(
+ AV8100_STANDBY_INTERRUPT_MASK_HPDM_LOW,
+ AV8100_STANDBY_INTERRUPT_MASK_CPDM_LOW,
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_INPUT,
+ AV8100_STANDBY_INTERRUPT_MASK_IPOL_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ adev->params.hpdm = hpdm;
+ adev->params.cpdm = cpdm;
+ adev->params.ints_enabled = false;
+
+ return 0;
+}
+EXPORT_SYMBOL(av8100_disable_interrupt);
+
+int av8100_enable_interrupt(void)
+{
+ int retval;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ if (adev->params.ints_enabled)
+ return 0;
+
+ retval = av8100_reg_stby_pend_int_w(
+ AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW,
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ retval = av8100_reg_gen_int_mask_w(
+ AV8100_GENERAL_INTERRUPT_MASK_EOCM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_VSIM_LOW,
+ AV8100_GENERAL_INTERRUPT_MASK_VSOM_LOW,
+ adev->params.cecm,
+ adev->params.hdcpm,
+ adev->params.uovbm,
+ AV8100_GENERAL_INTERRUPT_MASK_TEM_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ retval = av8100_reg_stby_int_mask_w(
+ adev->params.hpdm,
+ adev->params.cpdm,
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_INPUT,
+ AV8100_STANDBY_INTERRUPT_MASK_IPOL_LOW);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ return -EFAULT;
+ }
+
+ adev->params.ints_enabled = true;
+
+ return 0;
+}
+EXPORT_SYMBOL(av8100_enable_interrupt);
+
+int av8100_reg_stby_w(
+ u8 cpd, u8 stby, u8 mclkrng)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_STANDBY_CPD(cpd) | AV8100_STANDBY_STBY(stby) |
+ AV8100_STANDBY_MCLKRNG(mclkrng);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_STANDBY, val);
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_w);
+
+static int av8100_5V_w(u8 denc_off, u8 hdmi_off, u8 on)
+{
+ u8 val;
+ int retval;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value.
+ * chip_version == 1 have one common off time
+ * chip_version > 1 support different off time for hdmi and tvout. */
+ if (adev->chip_version == 1)
+ val = AV8100_HDMI_5_VOLT_TIME_OFF_TIME(hdmi_off) |
+ AV8100_HDMI_5_VOLT_TIME_ON_TIME(on);
+ else
+ val = AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME(denc_off) |
+ AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME(hdmi_off) |
+ AV8100_HDMI_5_VOLT_TIME_ON_TIME(on);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_HDMI_5_VOLT_TIME, val);
+
+ UNLOCK_AV8100_HW;
+
+ return retval;
+}
+
+int av8100_reg_hdmi_5_volt_time_w(u8 denc_off, u8 hdmi_off, u8 on)
+{
+ int retval;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ retval = av8100_5V_w(denc_off, hdmi_off, on);
+
+ /* Set vars */
+ if (adev->chip_version > 1)
+ adev->params.denc_off_time = denc_off;
+
+ adev->params.hdmi_off_time = hdmi_off;
+ if (on)
+ adev->params.on_time = on;
+
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_hdmi_5_volt_time_w);
+
+int av8100_reg_stby_int_mask_w(
+ u8 hpdm, u8 cpdm, u8 stbygpiocfg, u8 ipol)
+{
+ int retval;
+ u8 val;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_STANDBY_INTERRUPT_MASK_HPDM(hpdm) |
+ AV8100_STANDBY_INTERRUPT_MASK_CPDM(cpdm) |
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG(stbygpiocfg) |
+ AV8100_STANDBY_INTERRUPT_MASK_IPOL(ipol);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_STANDBY_INTERRUPT_MASK, val);
+
+ adev->params.hpdm = hpdm;
+ adev->params.cpdm = cpdm;
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_int_mask_w);
+
+int av8100_reg_stby_pend_int_w(
+ u8 hpdi, u8 cpdi, u8 oni, u8 bpdig)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_STANDBY_PENDING_INTERRUPT_HPDI(hpdi) |
+ AV8100_STANDBY_PENDING_INTERRUPT_CPDI(cpdi) |
+ AV8100_STANDBY_PENDING_INTERRUPT_ONI(oni) |
+ AV8100_STANDBY_PENDING_INTERRUPT_BPDIG(bpdig);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_STANDBY_PENDING_INTERRUPT, val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_pend_int_w);
+
+int av8100_reg_gen_int_mask_w(
+ u8 eocm, u8 vsim, u8 vsom, u8 cecm, u8 hdcpm, u8 uovbm, u8 tem)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_GENERAL_INTERRUPT_MASK_EOCM(eocm) |
+ AV8100_GENERAL_INTERRUPT_MASK_VSIM(vsim) |
+ AV8100_GENERAL_INTERRUPT_MASK_VSOM(vsom) |
+ AV8100_GENERAL_INTERRUPT_MASK_CECM(cecm) |
+ AV8100_GENERAL_INTERRUPT_MASK_HDCPM(hdcpm) |
+ AV8100_GENERAL_INTERRUPT_MASK_UOVBM(uovbm) |
+ AV8100_GENERAL_INTERRUPT_MASK_TEM(tem);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_GENERAL_INTERRUPT_MASK, val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_int_mask_w);
+
+int av8100_reg_gen_int_w(
+ u8 eoci, u8 vsii, u8 vsoi, u8 ceci, u8 hdcpi, u8 uovbi)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_GENERAL_INTERRUPT_EOCI(eoci) |
+ AV8100_GENERAL_INTERRUPT_VSII(vsii) |
+ AV8100_GENERAL_INTERRUPT_VSOI(vsoi) |
+ AV8100_GENERAL_INTERRUPT_CECI(ceci) |
+ AV8100_GENERAL_INTERRUPT_HDCPI(hdcpi) |
+ AV8100_GENERAL_INTERRUPT_UOVBI(uovbi);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_GENERAL_INTERRUPT, val);
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_int_w);
+
+int av8100_reg_gpio_conf_w(
+ u8 dat3dir, u8 dat3val, u8 dat2dir, u8 dat2val, u8 dat1dir,
+ u8 dat1val, u8 ucdbg)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_GPIO_CONFIGURATION_DAT3DIR(dat3dir) |
+ AV8100_GPIO_CONFIGURATION_DAT3VAL(dat3val) |
+ AV8100_GPIO_CONFIGURATION_DAT2DIR(dat2dir) |
+ AV8100_GPIO_CONFIGURATION_DAT2VAL(dat2val) |
+ AV8100_GPIO_CONFIGURATION_DAT1DIR(dat1dir) |
+ AV8100_GPIO_CONFIGURATION_DAT1VAL(dat1val) |
+ AV8100_GPIO_CONFIGURATION_UCDBG(ucdbg);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_GPIO_CONFIGURATION, val);
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gpio_conf_w);
+
+int av8100_reg_gen_ctrl_w(
+ u8 fdl, u8 hld, u8 wa, u8 ra)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_GENERAL_CONTROL_FDL(fdl) |
+ AV8100_GENERAL_CONTROL_HLD(hld) |
+ AV8100_GENERAL_CONTROL_WA(wa) |
+ AV8100_GENERAL_CONTROL_RA(ra);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_GENERAL_CONTROL, val);
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_ctrl_w);
+
+int av8100_reg_fw_dl_entry_w(
+ u8 mbyte_code_entry)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Set register value */
+ val = AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY(
+ mbyte_code_entry);
+
+ /* Write to register */
+ retval = register_write_internal(AV8100_FIRMWARE_DOWNLOAD_ENTRY, val);
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_fw_dl_entry_w);
+
+int av8100_reg_w(
+ u8 offset, u8 value)
+{
+ int retval = 0;
+ struct i2c_client *i2c;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ i2c = adev->config.client;
+
+ /* Write to register */
+ retval = write_single_byte(i2c, offset, value);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to write the value to av8100 register\n");
+ UNLOCK_AV8100_HW;
+ return -EFAULT;
+ }
+
+ UNLOCK_AV8100_HW;
+ return 0;
+}
+EXPORT_SYMBOL(av8100_reg_w);
+
+int av8100_reg_stby_r(
+ u8 *cpd, u8 *stby, u8 *hpds, u8 *cpds, u8 *mclkrng)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_STANDBY, &val);
+
+ /* Set return params */
+ if (cpd)
+ *cpd = AV8100_STANDBY_CPD_GET(val);
+ if (stby)
+ *stby = AV8100_STANDBY_STBY_GET(val);
+ if (hpds)
+ *hpds = AV8100_STANDBY_HPDS_GET(val);
+ if (cpds)
+ *cpds = AV8100_STANDBY_CPDS_GET(val);
+ if (mclkrng)
+ *mclkrng = AV8100_STANDBY_MCLKRNG_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_r);
+
+int av8100_reg_hdmi_5_volt_time_r(
+ u8 *denc_off_time, u8 *hdmi_off_time, u8 *on_time)
+{
+ int retval;
+ u8 val;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_HDMI_5_VOLT_TIME, &val);
+
+ /* Set return params */
+ if (adev->chip_version == 1) {
+ if (denc_off_time)
+ *denc_off_time = 0;
+ if (hdmi_off_time)
+ *hdmi_off_time =
+ AV8100_HDMI_5_VOLT_TIME_OFF_TIME_GET(val);
+ } else {
+ if (denc_off_time)
+ *denc_off_time =
+ AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME_GET(val);
+ if (hdmi_off_time)
+ *hdmi_off_time =
+ AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME_GET(val);
+ }
+
+ if (on_time)
+ *on_time = AV8100_HDMI_5_VOLT_TIME_ON_TIME_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_hdmi_5_volt_time_r);
+
+int av8100_reg_stby_int_mask_r(
+ u8 *hpdm, u8 *cpdm, u8 *stbygpiocfg, u8 *ipol)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_STANDBY_INTERRUPT_MASK, &val);
+
+ /* Set return params */
+ if (hpdm)
+ *hpdm = AV8100_STANDBY_INTERRUPT_MASK_HPDM_GET(val);
+ if (cpdm)
+ *cpdm = AV8100_STANDBY_INTERRUPT_MASK_CPDM_GET(val);
+ if (stbygpiocfg)
+ *stbygpiocfg =
+ AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_GET(val);
+ if (ipol)
+ *ipol = AV8100_STANDBY_INTERRUPT_MASK_IPOL_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_int_mask_r);
+
+int av8100_reg_stby_pend_int_r(
+ u8 *hpdi, u8 *cpdi, u8 *oni, u8 *sid)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_STANDBY_PENDING_INTERRUPT,
+ &val);
+
+ /* Set return params */
+ if (hpdi)
+ *hpdi = AV8100_STANDBY_PENDING_INTERRUPT_HPDI_GET(val);
+ if (cpdi)
+ *cpdi = AV8100_STANDBY_PENDING_INTERRUPT_CPDI_GET(val);
+ if (oni)
+ *oni = AV8100_STANDBY_PENDING_INTERRUPT_ONI_GET(val);
+ if (sid)
+ *sid = AV8100_STANDBY_PENDING_INTERRUPT_SID_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_stby_pend_int_r);
+
+int av8100_reg_gen_int_mask_r(
+ u8 *eocm,
+ u8 *vsim,
+ u8 *vsom,
+ u8 *cecm,
+ u8 *hdcpm,
+ u8 *uovbm,
+ u8 *tem)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_GENERAL_INTERRUPT_MASK, &val);
+
+ /* Set return params */
+ if (eocm)
+ *eocm = AV8100_GENERAL_INTERRUPT_MASK_EOCM_GET(val);
+ if (vsim)
+ *vsim = AV8100_GENERAL_INTERRUPT_MASK_VSIM_GET(val);
+ if (vsom)
+ *vsom = AV8100_GENERAL_INTERRUPT_MASK_VSOM_GET(val);
+ if (cecm)
+ *cecm = AV8100_GENERAL_INTERRUPT_MASK_CECM_GET(val);
+ if (hdcpm)
+ *hdcpm = AV8100_GENERAL_INTERRUPT_MASK_HDCPM_GET(val);
+ if (uovbm)
+ *uovbm = AV8100_GENERAL_INTERRUPT_MASK_UOVBM_GET(val);
+ if (tem)
+ *tem = AV8100_GENERAL_INTERRUPT_MASK_TEM_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_int_mask_r);
+
+int av8100_reg_gen_int_r(
+ u8 *eoci,
+ u8 *vsii,
+ u8 *vsoi,
+ u8 *ceci,
+ u8 *hdcpi,
+ u8 *uovbi,
+ u8 *tei)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_GENERAL_INTERRUPT, &val);
+
+ /* Set return params */
+ if (eoci)
+ *eoci = AV8100_GENERAL_INTERRUPT_EOCI_GET(val);
+ if (vsii)
+ *vsii = AV8100_GENERAL_INTERRUPT_VSII_GET(val);
+ if (vsoi)
+ *vsoi = AV8100_GENERAL_INTERRUPT_VSOI_GET(val);
+ if (ceci)
+ *ceci = AV8100_GENERAL_INTERRUPT_CECI_GET(val);
+ if (hdcpi)
+ *hdcpi = AV8100_GENERAL_INTERRUPT_HDCPI_GET(val);
+ if (uovbi)
+ *uovbi = AV8100_GENERAL_INTERRUPT_UOVBI_GET(val);
+ if (tei)
+ *tei = AV8100_GENERAL_INTERRUPT_TEI_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_int_r);
+
+int av8100_reg_gen_status_r(
+ u8 *cectxerr,
+ u8 *cecrec,
+ u8 *cectrx,
+ u8 *uc,
+ u8 *onuvb,
+ u8 *hdcps)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_GENERAL_STATUS, &val);
+
+ /* Set return params */
+ if (cectxerr)
+ *cectxerr = AV8100_GENERAL_STATUS_CECTXERR_GET(val);
+ if (cecrec)
+ *cecrec = AV8100_GENERAL_STATUS_CECREC_GET(val);
+ if (cectrx)
+ *cectrx = AV8100_GENERAL_STATUS_CECTRX_GET(val);
+ if (uc)
+ *uc = AV8100_GENERAL_STATUS_UC_GET(val);
+ if (onuvb)
+ *onuvb = AV8100_GENERAL_STATUS_ONUVB_GET(val);
+ if (hdcps)
+ *hdcps = AV8100_GENERAL_STATUS_HDCPS_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_status_r);
+
+int av8100_reg_gpio_conf_r(
+ u8 *dat3dir,
+ u8 *dat3val,
+ u8 *dat2dir,
+ u8 *dat2val,
+ u8 *dat1dir,
+ u8 *dat1val,
+ u8 *ucdbg)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_GPIO_CONFIGURATION, &val);
+
+ /* Set return params */
+ if (dat3dir)
+ *dat3dir = AV8100_GPIO_CONFIGURATION_DAT3DIR_GET(val);
+ if (dat3val)
+ *dat3val = AV8100_GPIO_CONFIGURATION_DAT3VAL_GET(val);
+ if (dat2dir)
+ *dat2dir = AV8100_GPIO_CONFIGURATION_DAT2DIR_GET(val);
+ if (dat2val)
+ *dat2val = AV8100_GPIO_CONFIGURATION_DAT2VAL_GET(val);
+ if (dat1dir)
+ *dat1dir = AV8100_GPIO_CONFIGURATION_DAT1DIR_GET(val);
+ if (dat1val)
+ *dat1val = AV8100_GPIO_CONFIGURATION_DAT1VAL_GET(val);
+ if (ucdbg)
+ *ucdbg = AV8100_GPIO_CONFIGURATION_UCDBG_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gpio_conf_r);
+
+int av8100_reg_gen_ctrl_r(
+ u8 *fdl,
+ u8 *hld,
+ u8 *wa,
+ u8 *ra)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_GENERAL_CONTROL, &val);
+ /* Set return params */
+ if (fdl)
+ *fdl = AV8100_GENERAL_CONTROL_FDL_GET(val);
+ if (hld)
+ *hld = AV8100_GENERAL_CONTROL_HLD_GET(val);
+ if (wa)
+ *wa = AV8100_GENERAL_CONTROL_WA_GET(val);
+ if (ra)
+ *ra = AV8100_GENERAL_CONTROL_RA_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_gen_ctrl_r);
+
+int av8100_reg_fw_dl_entry_r(
+ u8 *mbyte_code_entry)
+{
+ int retval;
+ u8 val;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ /* Read from register */
+ retval = register_read_internal(AV8100_FIRMWARE_DOWNLOAD_ENTRY, &val);
+
+ /* Set return params */
+ if (mbyte_code_entry)
+ *mbyte_code_entry =
+ AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY_GET(val);
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_fw_dl_entry_r);
+
+int av8100_reg_r(
+ u8 offset,
+ u8 *value)
+{
+ int retval = 0;
+ struct i2c_client *i2c;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ i2c = adev->config.client;
+
+ /* Read from register */
+ retval = read_single_byte(i2c, offset, value);
+ if (retval) {
+ dev_dbg(adev->dev,
+ "Failed to read the value from av8100 register\n");
+ retval = -EFAULT;
+ goto av8100_register_read_out;
+ }
+
+av8100_register_read_out:
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_reg_r);
+
+int av8100_conf_get(enum av8100_command_type command_type,
+ union av8100_configuration *config)
+{
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state == AV8100_OPMODE_UNDEFINED)
+ return -EINVAL;
+
+ /* Put configuration data to the corresponding data struct depending
+ * on command type */
+ switch (command_type) {
+ case AV8100_COMMAND_VIDEO_INPUT_FORMAT:
+ memcpy(&config->video_input_format,
+ &adev->config.hdmi_video_input_cmd,
+ sizeof(struct av8100_video_input_format_cmd));
+ break;
+
+ case AV8100_COMMAND_AUDIO_INPUT_FORMAT:
+ memcpy(&config->audio_input_format,
+ &adev->config.hdmi_audio_input_cmd,
+ sizeof(struct av8100_audio_input_format_cmd));
+ break;
+
+ case AV8100_COMMAND_VIDEO_OUTPUT_FORMAT:
+ memcpy(&config->video_output_format,
+ &adev->config.hdmi_video_output_cmd,
+ sizeof(struct av8100_video_output_format_cmd));
+ break;
+
+ case AV8100_COMMAND_VIDEO_SCALING_FORMAT:
+ memcpy(&config->video_scaling_format,
+ &adev->config.hdmi_video_scaling_cmd,
+ sizeof(struct av8100_video_scaling_format_cmd));
+ break;
+
+ case AV8100_COMMAND_COLORSPACECONVERSION:
+ config->color_transform = adev->config.color_transform;
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_WRITE:
+ memcpy(&config->cec_message_write_format,
+ &adev->config.hdmi_cec_message_write_cmd,
+ sizeof(struct av8100_cec_message_write_format_cmd));
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_READ_BACK:
+ memcpy(&config->cec_message_read_back_format,
+ &adev->config.hdmi_cec_message_read_back_cmd,
+ sizeof(struct av8100_cec_message_read_back_format_cmd));
+ break;
+
+ case AV8100_COMMAND_DENC:
+ memcpy(&config->denc_format, &adev->config.hdmi_denc_cmd,
+ sizeof(struct av8100_denc_format_cmd));
+ break;
+
+ case AV8100_COMMAND_HDMI:
+ memcpy(&config->hdmi_format, &adev->config.hdmi_cmd,
+ sizeof(struct av8100_hdmi_cmd));
+ break;
+
+ case AV8100_COMMAND_HDCP_SENDKEY:
+ memcpy(&config->hdcp_send_key_format,
+ &adev->config.hdmi_hdcp_send_key_cmd,
+ sizeof(struct av8100_hdcp_send_key_format_cmd));
+ break;
+
+ case AV8100_COMMAND_HDCP_MANAGEMENT:
+ memcpy(&config->hdcp_management_format,
+ &adev->config.hdmi_hdcp_management_format_cmd,
+ sizeof(struct av8100_hdcp_management_format_cmd));
+ break;
+
+ case AV8100_COMMAND_INFOFRAMES:
+ memcpy(&config->infoframes_format,
+ &adev->config.hdmi_infoframes_cmd,
+ sizeof(struct av8100_infoframes_format_cmd));
+ break;
+
+ case AV8100_COMMAND_EDID_SECTION_READBACK:
+ memcpy(&config->edid_section_readback_format,
+ &adev->config.hdmi_edid_section_readback_cmd,
+ sizeof(struct
+ av8100_edid_section_readback_format_cmd));
+ break;
+
+ case AV8100_COMMAND_PATTERNGENERATOR:
+ memcpy(&config->pattern_generator_format,
+ &adev->config.hdmi_pattern_generator_cmd,
+ sizeof(struct av8100_pattern_generator_format_cmd));
+ break;
+
+ case AV8100_COMMAND_FUSE_AES_KEY:
+ memcpy(&config->fuse_aes_key_format,
+ &adev->config.hdmi_fuse_aes_key_cmd,
+ sizeof(struct av8100_fuse_aes_key_format_cmd));
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(av8100_conf_get);
+
+int av8100_conf_prep(enum av8100_command_type command_type,
+ union av8100_configuration *config)
+{
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!config || !adev)
+ return -EINVAL;
+
+ /* Put configuration data to the corresponding data struct depending
+ * on command type */
+ switch (command_type) {
+ case AV8100_COMMAND_VIDEO_INPUT_FORMAT:
+ memcpy(&adev->config.hdmi_video_input_cmd,
+ &config->video_input_format,
+ sizeof(struct av8100_video_input_format_cmd));
+ break;
+
+ case AV8100_COMMAND_AUDIO_INPUT_FORMAT:
+ memcpy(&adev->config.hdmi_audio_input_cmd,
+ &config->audio_input_format,
+ sizeof(struct av8100_audio_input_format_cmd));
+ break;
+
+ case AV8100_COMMAND_VIDEO_OUTPUT_FORMAT:
+ memcpy(&adev->config.hdmi_video_output_cmd,
+ &config->video_output_format,
+ sizeof(struct av8100_video_output_format_cmd));
+
+ /* Set params that depend on video output */
+ av8100_config_video_output_dep(adev->config.
+ hdmi_video_output_cmd.video_output_cea_vesa);
+ break;
+
+ case AV8100_COMMAND_VIDEO_SCALING_FORMAT:
+ memcpy(&adev->config.hdmi_video_scaling_cmd,
+ &config->video_scaling_format,
+ sizeof(struct av8100_video_scaling_format_cmd));
+ break;
+
+ case AV8100_COMMAND_COLORSPACECONVERSION:
+ adev->config.color_transform = config->color_transform;
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_WRITE:
+ memcpy(&adev->config.hdmi_cec_message_write_cmd,
+ &config->cec_message_write_format,
+ sizeof(struct av8100_cec_message_write_format_cmd));
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_READ_BACK:
+ memcpy(&adev->config.hdmi_cec_message_read_back_cmd,
+ &config->cec_message_read_back_format,
+ sizeof(struct av8100_cec_message_read_back_format_cmd));
+ break;
+
+ case AV8100_COMMAND_DENC:
+ memcpy(&adev->config.hdmi_denc_cmd, &config->denc_format,
+ sizeof(struct av8100_denc_format_cmd));
+ break;
+
+ case AV8100_COMMAND_HDMI:
+ memcpy(&adev->config.hdmi_cmd, &config->hdmi_format,
+ sizeof(struct av8100_hdmi_cmd));
+ break;
+
+ case AV8100_COMMAND_HDCP_SENDKEY:
+ memcpy(&adev->config.hdmi_hdcp_send_key_cmd,
+ &config->hdcp_send_key_format,
+ sizeof(struct av8100_hdcp_send_key_format_cmd));
+ break;
+
+ case AV8100_COMMAND_HDCP_MANAGEMENT:
+ memcpy(&adev->config.hdmi_hdcp_management_format_cmd,
+ &config->hdcp_management_format,
+ sizeof(struct av8100_hdcp_management_format_cmd));
+ break;
+
+ case AV8100_COMMAND_INFOFRAMES:
+ memcpy(&adev->config.hdmi_infoframes_cmd,
+ &config->infoframes_format,
+ sizeof(struct av8100_infoframes_format_cmd));
+ break;
+
+ case AV8100_COMMAND_EDID_SECTION_READBACK:
+ memcpy(&adev->config.hdmi_edid_section_readback_cmd,
+ &config->edid_section_readback_format,
+ sizeof(struct
+ av8100_edid_section_readback_format_cmd));
+ break;
+
+ case AV8100_COMMAND_PATTERNGENERATOR:
+ memcpy(&adev->config.hdmi_pattern_generator_cmd,
+ &config->pattern_generator_format,
+ sizeof(struct av8100_pattern_generator_format_cmd));
+ break;
+
+ case AV8100_COMMAND_FUSE_AES_KEY:
+ memcpy(&adev->config.hdmi_fuse_aes_key_cmd,
+ &config->fuse_aes_key_format,
+ sizeof(struct av8100_fuse_aes_key_format_cmd));
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(av8100_conf_prep);
+
+int av8100_conf_w(enum av8100_command_type command_type,
+ u8 *return_buffer_length,
+ u8 *return_buffer, enum interface_type if_type)
+{
+ int retval = 0;
+ u8 cmd_buffer[AV8100_COMMAND_MAX_LENGTH];
+ u32 cmd_length = 0;
+ struct i2c_client *i2c;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ if (return_buffer_length)
+ *return_buffer_length = 0;
+
+ i2c = adev->config.client;
+
+ memset(&cmd_buffer, 0x00, AV8100_COMMAND_MAX_LENGTH);
+
+#define PRNK_MODE(_m) dev_dbg(adev->dev, "cmd: " #_m "\n");
+
+ /* Fill the command buffer with configuration data */
+ switch (command_type) {
+ case AV8100_COMMAND_VIDEO_INPUT_FORMAT:
+ PRNK_MODE(AV8100_COMMAND_VIDEO_INPUT_FORMAT);
+ configuration_video_input_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_AUDIO_INPUT_FORMAT:
+ PRNK_MODE(AV8100_COMMAND_AUDIO_INPUT_FORMAT);
+ configuration_audio_input_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_VIDEO_OUTPUT_FORMAT:
+ PRNK_MODE(AV8100_COMMAND_VIDEO_OUTPUT_FORMAT);
+ configuration_video_output_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_VIDEO_SCALING_FORMAT:
+ PRNK_MODE(AV8100_COMMAND_VIDEO_SCALING_FORMAT);
+ configuration_video_scaling_get(adev, cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_COLORSPACECONVERSION:
+ PRNK_MODE(AV8100_COMMAND_COLORSPACECONVERSION);
+ configuration_colorspace_conversion_get(adev, cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_WRITE:
+ PRNK_MODE(AV8100_COMMAND_CEC_MESSAGE_WRITE);
+ configuration_cec_message_write_get(adev, cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_CEC_MESSAGE_READ_BACK:
+ PRNK_MODE(AV8100_COMMAND_CEC_MESSAGE_READ_BACK);
+ configuration_cec_message_read_get(cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_DENC:
+ PRNK_MODE(AV8100_COMMAND_DENC);
+ configuration_denc_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_HDMI:
+ PRNK_MODE(AV8100_COMMAND_HDMI);
+ configuration_hdmi_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_HDCP_SENDKEY:
+ PRNK_MODE(AV8100_COMMAND_HDCP_SENDKEY);
+ configuration_hdcp_sendkey_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_HDCP_MANAGEMENT:
+ PRNK_MODE(AV8100_COMMAND_HDCP_MANAGEMENT);
+ configuration_hdcp_management_get(adev, cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_INFOFRAMES:
+ PRNK_MODE(AV8100_COMMAND_INFOFRAMES);
+ configuration_infoframe_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_EDID_SECTION_READBACK:
+ PRNK_MODE(AV8100_COMMAND_EDID_SECTION_READBACK);
+ av8100_edid_section_readback_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ case AV8100_COMMAND_PATTERNGENERATOR:
+ PRNK_MODE(AV8100_COMMAND_PATTERNGENERATOR);
+ configuration_pattern_generator_get(adev, cmd_buffer,
+ &cmd_length);
+ break;
+
+ case AV8100_COMMAND_FUSE_AES_KEY:
+ PRNK_MODE(AV8100_COMMAND_FUSE_AES_KEY);
+ configuration_fuse_aes_key_get(adev, cmd_buffer, &cmd_length);
+ break;
+
+ default:
+ dev_dbg(adev->dev, "Invalid command type\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ LOCK_AV8100_HW;
+
+ if (if_type == I2C_INTERFACE) {
+ int cnt = 0;
+ int cnt_max;
+
+ dev_dbg(adev->dev, "av8100_conf_w cmd_type:%02x length:%02x ",
+ command_type, cmd_length);
+ dev_dbg(adev->dev, "buffer: ");
+ while (cnt < cmd_length) {
+ dev_dbg(adev->dev, "%02x ", cmd_buffer[cnt]);
+ cnt++;
+ }
+
+ /* Write the command buffer */
+ retval = write_multi_byte(i2c,
+ AV8100_CMD_BUF_OFFSET, cmd_buffer, cmd_length);
+ if (retval) {
+ UNLOCK_AV8100_HW;
+ return retval;
+ }
+
+ /* Write the command */
+ retval = write_single_byte(i2c, AV8100_COMMAND_OFFSET,
+ command_type);
+ if (retval) {
+ UNLOCK_AV8100_HW;
+ return retval;
+ }
+
+
+ /* Get the first return byte */
+ mdelay(AV8100_WAITTIME_1MS);
+ cnt = 0;
+ cnt_max = sizeof(waittime_retry) / sizeof(waittime_retry[0]);
+ retval = get_command_return_first(i2c, command_type);
+ while (retval && (cnt < cnt_max)) {
+ mdelay(waittime_retry[cnt]);
+ retval = get_command_return_first(i2c, command_type);
+ cnt++;
+ }
+ dev_dbg(adev->dev, "first return cnt:%d\n", cnt);
+
+ if (retval) {
+ UNLOCK_AV8100_HW;
+ return retval;
+ }
+
+ retval = get_command_return_data(i2c, command_type, cmd_buffer,
+ return_buffer_length, return_buffer);
+ } else if (if_type == DSI_INTERFACE) {
+ /* TODO */
+ } else {
+ retval = -EINVAL;
+ dev_dbg(adev->dev, "Invalid command type\n");
+ }
+
+ if (command_type == AV8100_COMMAND_HDMI) {
+ adev->status.hdmi_on = ((adev->config.hdmi_cmd.
+ hdmi_mode == AV8100_HDMI_ON) &&
+ (adev->config.hdmi_cmd.hdmi_format == AV8100_HDMI));
+ }
+
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_conf_w);
+
+int av8100_conf_w_raw(enum av8100_command_type command_type,
+ u8 buffer_length,
+ u8 *buffer,
+ u8 *return_buffer_length,
+ u8 *return_buffer)
+{
+ int retval = 0;
+ struct i2c_client *i2c;
+ int cnt;
+ int cnt_max;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ if (av8100_status_get().av8100_state <= AV8100_OPMODE_SHUTDOWN)
+ return -EINVAL;
+
+ LOCK_AV8100_HW;
+
+ if (return_buffer_length)
+ *return_buffer_length = 0;
+
+ i2c = adev->config.client;
+
+ /* Write the command buffer */
+ retval = write_multi_byte(i2c,
+ AV8100_CMD_BUF_OFFSET, buffer, buffer_length);
+ if (retval)
+ goto av8100_conf_w_raw_out;
+
+ /* Write the command */
+ retval = write_single_byte(i2c, AV8100_COMMAND_OFFSET,
+ command_type);
+ if (retval)
+ goto av8100_conf_w_raw_out;
+
+
+ /* Get the first return byte */
+ mdelay(AV8100_WAITTIME_1MS);
+ cnt = 0;
+ cnt_max = sizeof(waittime_retry) / sizeof(waittime_retry[0]);
+ retval = get_command_return_first(i2c, command_type);
+ while (retval && (cnt < cnt_max)) {
+ mdelay(waittime_retry[cnt]);
+ retval = get_command_return_first(i2c, command_type);
+ cnt++;
+ }
+ dev_dbg(adev->dev, "first return cnt:%d\n", cnt);
+ if (retval)
+ goto av8100_conf_w_raw_out;
+
+ retval = get_command_return_data(i2c, command_type, buffer,
+ return_buffer_length, return_buffer);
+
+av8100_conf_w_raw_out:
+ UNLOCK_AV8100_HW;
+ return retval;
+}
+EXPORT_SYMBOL(av8100_conf_w_raw);
+
+struct av8100_status av8100_status_get(void)
+{
+ struct av8100_status status = {0};
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (adev)
+ return adev->status;
+ else
+ return status;
+}
+EXPORT_SYMBOL(av8100_status_get);
+
+enum av8100_output_CEA_VESA av8100_video_output_format_get(int xres,
+ int yres,
+ int htot,
+ int vtot,
+ int pixelclk,
+ bool interlaced)
+{
+ enum av8100_output_CEA_VESA index = 1;
+ int yres_div = !interlaced ? 1 : 2;
+ int hres_div = 1;
+ long freq1;
+ long freq2;
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ /*
+ * 720_576_I need a divider for hact and htot since
+ * these params need to be twice as large as expected in av8100_all_cea,
+ * which is used as input parameter to video input config.
+ */
+ if ((xres == 720) && (yres == 576) && (interlaced == true))
+ hres_div = 2;
+
+ freq1 = 1000000 / htot * 1000000 / vtot / pixelclk + 1;
+ while (index < sizeof(av8100_all_cea)/sizeof(struct av8100_cea)) {
+ freq2 = av8100_all_cea[index].frequence /
+ av8100_all_cea[index].htotale /
+ av8100_all_cea[index].vtotale;
+
+ dev_dbg(adev->dev, "freq1:%ld freq2:%ld\n", freq1, freq2);
+ if ((xres == av8100_all_cea[index].hactive / hres_div) &&
+ (yres == av8100_all_cea[index].vactive * yres_div) &&
+ (htot == av8100_all_cea[index].htotale / hres_div) &&
+ (vtot == av8100_all_cea[index].vtotale) &&
+ (abs(freq1 - freq2) < 2)) {
+ goto av8100_video_output_format_get_out;
+ }
+ index++;
+ }
+
+av8100_video_output_format_get_out:
+ dev_dbg(adev->dev, "av8100_video_output_format_get %d %d %d %d %d\n",
+ xres, yres, htot, vtot, index);
+ return index;
+}
+EXPORT_SYMBOL(av8100_video_output_format_get);
+
+void av8100_hdmi_event_cb_set(void (*hdmi_ev_cb)(enum av8100_hdmi_event))
+{
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (adev)
+ adev->params.hdmi_ev_cb = hdmi_ev_cb;
+}
+EXPORT_SYMBOL(av8100_hdmi_event_cb_set);
+
+u8 av8100_ver_get(void)
+{
+ struct av8100_device *adev;
+
+ adev = devnr_to_adev(AV8100_DEVNR_DEFAULT);
+ if (!adev)
+ return -EINVAL;
+
+ return adev->chip_version;
+}
+EXPORT_SYMBOL(av8100_ver_get);
+
+static const struct color_conversion_cmd *get_color_transform_cmd(
+ struct av8100_device *adev,
+ enum av8100_color_transform transform)
+{
+ const struct color_conversion_cmd *result;
+
+ switch (transform) {
+ case AV8100_COLOR_TRANSFORM_INDENTITY:
+ result = &col_trans_identity;
+ break;
+ case AV8100_COLOR_TRANSFORM_INDENTITY_CLAMP_YUV:
+ result = &col_trans_identity_clamp_yuv;
+ break;
+ case AV8100_COLOR_TRANSFORM_YUV_TO_RGB:
+ if (adev->chip_version == AV8100_CHIPVER_1)
+ result = &col_trans_yuv_to_rgb_v1;
+ else
+ result = &col_trans_yuv_to_rgb_v2;
+ break;
+ case AV8100_COLOR_TRANSFORM_YUV_TO_DENC:
+ result = &col_trans_yuv_to_denc;
+ break;
+ case AV8100_COLOR_TRANSFORM_RGB_TO_DENC:
+ result = &col_trans_rgb_to_denc;
+ break;
+ default:
+ dev_warn(adev->dev, "Unknown color space transform\n");
+ result = &col_trans_identity;
+ break;
+ }
+ return result;
+}
+
+static int av8100_open(struct inode *inode, struct file *filp)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int av8100_release(struct inode *inode, struct file *filp)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static long av8100_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+int av8100_device_register(struct av8100_device *adev)
+{
+ adev->miscdev.minor = MISC_DYNAMIC_MINOR;
+ adev->miscdev.name = "av8100";
+ adev->miscdev.fops = &av8100_fops;
+
+ if (misc_register(&adev->miscdev)) {
+ pr_err("av8100 misc_register failed\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int av8100_init_device(struct av8100_device *adev, struct device *dev)
+{
+ adev->dev = dev;
+
+ if (av8100_config_init(adev)) {
+ dev_info(dev, "av8100_config_init failed\n");
+ return -EFAULT;
+ }
+
+ if (av8100_params_init(adev)) {
+ dev_info(dev, "av8100_params_init failed\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int __devinit av8100_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ int ret = 0;
+ struct av8100_platform_data *pdata = i2c_client->dev.platform_data;
+ struct device *dev;
+ struct av8100_device *adev;
+
+ dev = &i2c_client->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ /* Allocate device data */
+ adev = kzalloc(sizeof(struct av8100_device), GFP_KERNEL);
+ if (!adev) {
+ dev_info(dev, "%s: Alloc failure\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Add to list */
+ list_add_tail(&adev->list, &av8100_device_list);
+
+ av8100_device_register(adev);
+
+ av8100_init_device(adev, dev);
+
+ av8100_set_state(adev, AV8100_OPMODE_UNDEFINED);
+
+ if (!i2c_check_functionality(i2c_client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA)) {
+ ret = -ENODEV;
+ dev_info(dev, "av8100 i2c_check_functionality failed\n");
+ goto err1;
+ }
+
+ init_waitqueue_head(&adev->event);
+
+ adev->config.client = i2c_client;
+ adev->config.id = (struct i2c_device_id *) id;
+ i2c_set_clientdata(i2c_client, &adev->config);
+
+ kthread_run(av8100_thread, adev, "av8100_thread");
+
+ /* Get regulator resource */
+ if (pdata->regulator_pwr_id) {
+ adev->params.regulator_pwr = regulator_get(dev,
+ pdata->regulator_pwr_id);
+ if (IS_ERR(adev->params.regulator_pwr)) {
+ ret = PTR_ERR(adev->params.regulator_pwr);
+ dev_warn(dev,
+ "%s: Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_pwr_id);
+ adev->params.regulator_pwr = NULL;
+ goto err1;
+ }
+ }
+
+ /* Get clock resource */
+ if (pdata->inputclk_id) {
+ adev->params.inputclk = clk_get(NULL, pdata->inputclk_id);
+ if (IS_ERR(adev->params.inputclk)) {
+ adev->params.inputclk = NULL;
+ dev_warn(dev, "%s: Failed to get clock '%s'\n",
+ __func__, pdata->inputclk_id);
+ }
+ }
+
+ av8100_set_state(adev, AV8100_OPMODE_SHUTDOWN);
+
+
+ if (av8100_powerup1(adev)) {
+ dev_err(adev->dev, "av8100_powerup1 fail\n");
+ ret = -EFAULT;
+ goto err1;
+ }
+
+ /* Obtain the chip version */
+ ret = av8100_reg_stby_pend_int_r(NULL, NULL, NULL,
+ &adev->chip_version);
+ if (ret) {
+ dev_err(adev->dev, "Failed to read chip version\n");
+ goto err2;
+ }
+
+ dev_info(adev->dev, "chip version:%d\n", adev->chip_version);
+
+ switch (adev->chip_version) {
+ case AV8100_CHIPVER_1:
+ case AV8100_CHIPVER_2:
+ break;
+
+ default:
+ dev_err(adev->dev, "Unsupported chip version:%d\n",
+ adev->chip_version);
+ ret = -EINVAL;
+ goto err2;
+ break;
+ }
+err2:
+ (void) av8100_powerdown();
+err1:
+ return ret;
+}
+
+static int __devexit av8100_remove(struct i2c_client *i2c_client)
+{
+ struct av8100_device *adev;
+
+ adev = dev_to_adev(&i2c_client->dev);
+ if (!adev)
+ return -EFAULT;
+
+ dev_dbg(adev->dev, "%s\n", __func__);
+
+ if (adev->params.inputclk)
+ clk_put(adev->params.inputclk);
+
+ /* Release regulator resource */
+ if (adev->params.regulator_pwr)
+ regulator_put(adev->params.regulator_pwr);
+
+ misc_deregister(&adev->miscdev);
+
+ /* Remove from list */
+ list_del(&adev->list);
+
+ /* Free device data */
+ kfree(adev);
+
+ return 0;
+}
+
+int av8100_init(void)
+{
+ pr_debug("%s\n", __func__);
+
+ if (i2c_add_driver(&av8100_driver)) {
+ pr_err("av8100 i2c_add_driver failed\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+module_init(av8100_init);
+
+void av8100_exit(void)
+{
+ pr_debug("%s\n", __func__);
+
+ i2c_del_driver(&av8100_driver);
+}
+module_exit(av8100_exit);
+
+MODULE_AUTHOR("Per Persson <per.xb.persson@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson hdmi display driver");
diff --git a/drivers/video/av8100/av8100_regs.h b/drivers/video/av8100/av8100_regs.h
new file mode 100644
index 00000000000..6ed9000987a
--- /dev/null
+++ b/drivers/video/av8100/av8100_regs.h
@@ -0,0 +1,346 @@
+
+#define AV8100_VAL2REG(__reg, __fld, __val) \
+ (((__val) << __reg##_##__fld##_SHIFT) & __reg##_##__fld##_MASK)
+#define AV8100_REG2VAL(__reg, __fld, __val) \
+ (((__val) & __reg##_##__fld##_MASK) >> __reg##_##__fld##_SHIFT)
+
+#define AV8100_STANDBY 0x00000000
+#define AV8100_STANDBY_CPD_SHIFT 0
+#define AV8100_STANDBY_CPD_MASK 0x00000001
+#define AV8100_STANDBY_CPD_HIGH 1
+#define AV8100_STANDBY_CPD_LOW 0
+#define AV8100_STANDBY_CPD(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY, CPD, __x)
+#define AV8100_STANDBY_CPD_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY, CPD, __x)
+#define AV8100_STANDBY_STBY_SHIFT 1
+#define AV8100_STANDBY_STBY_MASK 0x00000002
+#define AV8100_STANDBY_STBY_HIGH 1
+#define AV8100_STANDBY_STBY_LOW 0
+#define AV8100_STANDBY_STBY(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY, STBY, __x)
+#define AV8100_STANDBY_STBY_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY, STBY, __x)
+#define AV8100_STANDBY_HPDS_SHIFT 2
+#define AV8100_STANDBY_HPDS_MASK 0x00000004
+#define AV8100_STANDBY_HPDS(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY, HPDS, __x)
+#define AV8100_STANDBY_HPDS_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY, HPDS, __x)
+#define AV8100_STANDBY_CPDS_SHIFT 3
+#define AV8100_STANDBY_CPDS_MASK 0x00000008
+#define AV8100_STANDBY_CPDS(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY, CPDS, __x)
+#define AV8100_STANDBY_CPDS_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY, CPDS, __x)
+#define AV8100_STANDBY_MCLKRNG_SHIFT 4
+#define AV8100_STANDBY_MCLKRNG_MASK 0x000000F0
+#define AV8100_STANDBY_MCLKRNG(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY, MCLKRNG, __x)
+#define AV8100_STANDBY_MCLKRNG_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY, MCLKRNG, __x)
+#define AV8100_HDMI_5_VOLT_TIME 0x00000001
+#define AV8100_HDMI_5_VOLT_TIME_OFF_TIME_SHIFT 0
+#define AV8100_HDMI_5_VOLT_TIME_OFF_TIME_MASK 0x0000001F
+#define AV8100_HDMI_5_VOLT_TIME_OFF_TIME(__x) \
+ AV8100_VAL2REG(AV8100_HDMI_5_VOLT_TIME, OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_OFF_TIME_GET(__x) \
+ AV8100_REG2VAL(AV8100_HDMI_5_VOLT_TIME, OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME_SHIFT 0
+#define AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME_MASK 0x00000003
+#define AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME(__x) \
+ AV8100_VAL2REG(AV8100_HDMI_5_VOLT_TIME, DAC_OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_DAC_OFF_TIME_GET(__x) \
+ AV8100_REG2VAL(AV8100_HDMI_5_VOLT_TIME, DAC_OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME_SHIFT 2
+#define AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME_MASK 0x0000001C
+#define AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME(__x) \
+ AV8100_VAL2REG(AV8100_HDMI_5_VOLT_TIME, SU_OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_SU_OFF_TIME_GET(__x) \
+ AV8100_REG2VAL(AV8100_HDMI_5_VOLT_TIME, SU_OFF_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_ON_TIME_SHIFT 5
+#define AV8100_HDMI_5_VOLT_TIME_ON_TIME_MASK 0x000000E0
+#define AV8100_HDMI_5_VOLT_TIME_ON_TIME(__x) \
+ AV8100_VAL2REG(AV8100_HDMI_5_VOLT_TIME, ON_TIME, __x)
+#define AV8100_HDMI_5_VOLT_TIME_ON_TIME_GET(__x) \
+ AV8100_REG2VAL(AV8100_HDMI_5_VOLT_TIME, ON_TIME, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK 0x00000002
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM_SHIFT 0
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM_MASK 0x00000001
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM_HIGH 1
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM_LOW 0
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_INTERRUPT_MASK, HPDM, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_HPDM_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_INTERRUPT_MASK, HPDM, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM_SHIFT 1
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM_MASK 0x00000002
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM_HIGH 1
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM_LOW 0
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_INTERRUPT_MASK, CPDM, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_CPDM_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_INTERRUPT_MASK, CPDM, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_SHIFT 2
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_MASK 0x0000000C
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_INPUT 0x00
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_ALT 0x01
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_OUTPUT0 0x02
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_OUTPUT1 0x03
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_INTERRUPT_MASK, STBYGPIOCFG, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_STBYGPIOCFG_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_INTERRUPT_MASK, STBYGPIOCFG, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL_SHIFT 7
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL_MASK 0x00000080
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL_HIGH 1
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL_LOW 0
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_INTERRUPT_MASK, IPOL, __x)
+#define AV8100_STANDBY_INTERRUPT_MASK_IPOL_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_INTERRUPT_MASK, IPOL, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT 0x00000003
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI_SHIFT 0
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI_MASK 0x00000001
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI_HIGH 1
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI_LOW 0
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_PENDING_INTERRUPT, HPDI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_HPDI_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_PENDING_INTERRUPT, HPDI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI_SHIFT 1
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI_MASK 0x00000002
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI_HIGH 1
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI_LOW 0
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_PENDING_INTERRUPT, CPDI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_CPDI_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_PENDING_INTERRUPT, CPDI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI_SHIFT 2
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI_MASK 0x00000004
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI_HIGH 1
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI_LOW 0
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_PENDING_INTERRUPT, ONI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_ONI_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_PENDING_INTERRUPT, ONI, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_SID_SHIFT 4
+#define AV8100_STANDBY_PENDING_INTERRUPT_SID_MASK 0x000000F0
+#define AV8100_STANDBY_PENDING_INTERRUPT_SID(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_PENDING_INTERRUPT, SID, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_SID_GET(__x) \
+ AV8100_REG2VAL(AV8100_STANDBY_PENDING_INTERRUPT, SID, __x)
+#define AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_SHIFT 6
+#define AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_MASK 0x00000040
+#define AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_HIGH 1
+#define AV8100_STANDBY_PENDING_INTERRUPT_BPDIG_LOW 0
+#define AV8100_STANDBY_PENDING_INTERRUPT_BPDIG(__x) \
+ AV8100_VAL2REG(AV8100_STANDBY_PENDING_INTERRUPT, BPDIG, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK 0x00000004
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM_SHIFT 0
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM_MASK 0x00000001
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, EOCM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_EOCM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, EOCM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM_SHIFT 1
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM_MASK 0x00000002
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, VSIM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_VSIM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, VSIM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM_SHIFT 2
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM_MASK 0x00000004
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, VSOM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_VSOM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, VSOM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM_SHIFT 3
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM_MASK 0x00000008
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, CECM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_CECM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, CECM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM_SHIFT 4
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM_MASK 0x00000010
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, HDCPM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_HDCPM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, HDCPM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM_SHIFT 5
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM_MASK 0x00000020
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, UOVBM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_UOVBM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, UOVBM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM_SHIFT 6
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM_MASK 0x00000040
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM_HIGH 1
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM_LOW 0
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT_MASK, TEM, __x)
+#define AV8100_GENERAL_INTERRUPT_MASK_TEM_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT_MASK, TEM, __x)
+#define AV8100_GENERAL_INTERRUPT 0x00000005
+#define AV8100_GENERAL_INTERRUPT_EOCI_SHIFT 0
+#define AV8100_GENERAL_INTERRUPT_EOCI_MASK 0x00000001
+#define AV8100_GENERAL_INTERRUPT_EOCI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, EOCI, __x)
+#define AV8100_GENERAL_INTERRUPT_EOCI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, EOCI, __x)
+#define AV8100_GENERAL_INTERRUPT_VSII_SHIFT 1
+#define AV8100_GENERAL_INTERRUPT_VSII_MASK 0x00000002
+#define AV8100_GENERAL_INTERRUPT_VSII(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, VSII, __x)
+#define AV8100_GENERAL_INTERRUPT_VSII_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, VSII, __x)
+#define AV8100_GENERAL_INTERRUPT_VSOI_SHIFT 2
+#define AV8100_GENERAL_INTERRUPT_VSOI_MASK 0x00000004
+#define AV8100_GENERAL_INTERRUPT_VSOI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, VSOI, __x)
+#define AV8100_GENERAL_INTERRUPT_VSOI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, VSOI, __x)
+#define AV8100_GENERAL_INTERRUPT_CECI_SHIFT 3
+#define AV8100_GENERAL_INTERRUPT_CECI_MASK 0x00000008
+#define AV8100_GENERAL_INTERRUPT_CECI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, CECI, __x)
+#define AV8100_GENERAL_INTERRUPT_CECI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, CECI, __x)
+#define AV8100_GENERAL_INTERRUPT_HDCPI_SHIFT 4
+#define AV8100_GENERAL_INTERRUPT_HDCPI_MASK 0x00000010
+#define AV8100_GENERAL_INTERRUPT_HDCPI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, HDCPI, __x)
+#define AV8100_GENERAL_INTERRUPT_HDCPI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, HDCPI, __x)
+#define AV8100_GENERAL_INTERRUPT_UOVBI_SHIFT 5
+#define AV8100_GENERAL_INTERRUPT_UOVBI_MASK 0x00000020
+#define AV8100_GENERAL_INTERRUPT_UOVBI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, UOVBI, __x)
+#define AV8100_GENERAL_INTERRUPT_UOVBI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, UOVBI, __x)
+#define AV8100_GENERAL_INTERRUPT_TEI_SHIFT 6
+#define AV8100_GENERAL_INTERRUPT_TEI_MASK 0x00000040
+#define AV8100_GENERAL_INTERRUPT_TEI(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_INTERRUPT, TEI, __x)
+#define AV8100_GENERAL_INTERRUPT_TEI_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_INTERRUPT, TEI, __x)
+#define AV8100_GENERAL_STATUS 0x00000006
+#define AV8100_GENERAL_STATUS_CECTXERR_SHIFT 0
+#define AV8100_GENERAL_STATUS_CECTXERR_MASK 0x00000001
+#define AV8100_GENERAL_STATUS_CECTXERR_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, CECTXERR, __x)
+#define AV8100_GENERAL_STATUS_CECREC_SHIFT 1
+#define AV8100_GENERAL_STATUS_CECREC_MASK 0x00000002
+#define AV8100_GENERAL_STATUS_CECREC_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, CECREC, __x)
+#define AV8100_GENERAL_STATUS_CECTRX_SHIFT 2
+#define AV8100_GENERAL_STATUS_CECTRX_MASK 0x00000004
+#define AV8100_GENERAL_STATUS_CECTRX_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, CECTRX, __x)
+#define AV8100_GENERAL_STATUS_UC_SHIFT 3
+#define AV8100_GENERAL_STATUS_UC_MASK 0x00000008
+#define AV8100_GENERAL_STATUS_UC_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, UC, __x)
+#define AV8100_GENERAL_STATUS_ONUVB_SHIFT 4
+#define AV8100_GENERAL_STATUS_ONUVB_MASK 0x00000010
+#define AV8100_GENERAL_STATUS_ONUVB_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, ONUVB, __x)
+#define AV8100_GENERAL_STATUS_HDCPS_SHIFT 5
+#define AV8100_GENERAL_STATUS_HDCPS_MASK 0x000000E0
+#define AV8100_GENERAL_STATUS_HDCPS_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_STATUS, HDCPS, __x)
+#define AV8100_GPIO_CONFIGURATION 0x00000007
+#define AV8100_GPIO_CONFIGURATION_DAT3DIR_SHIFT 0
+#define AV8100_GPIO_CONFIGURATION_DAT3DIR_MASK 0x00000001
+#define AV8100_GPIO_CONFIGURATION_DAT3DIR(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT3DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT3DIR_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT3DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT3VAL_SHIFT 1
+#define AV8100_GPIO_CONFIGURATION_DAT3VAL_MASK 0x00000002
+#define AV8100_GPIO_CONFIGURATION_DAT3VAL(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT3VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT3VAL_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT3VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT2DIR_SHIFT 2
+#define AV8100_GPIO_CONFIGURATION_DAT2DIR_MASK 0x00000004
+#define AV8100_GPIO_CONFIGURATION_DAT2DIR(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT2DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT2DIR_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT2DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT2VAL_SHIFT 3
+#define AV8100_GPIO_CONFIGURATION_DAT2VAL_MASK 0x00000008
+#define AV8100_GPIO_CONFIGURATION_DAT2VAL(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT2VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT2VAL_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT2VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT1DIR_SHIFT 4
+#define AV8100_GPIO_CONFIGURATION_DAT1DIR_MASK 0x00000010
+#define AV8100_GPIO_CONFIGURATION_DAT1DIR(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT1DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT1DIR_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT1DIR, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT1VAL_SHIFT 5
+#define AV8100_GPIO_CONFIGURATION_DAT1VAL_MASK 0x00000020
+#define AV8100_GPIO_CONFIGURATION_DAT1VAL(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, DAT1VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_DAT1VAL_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, DAT1VAL, __x)
+#define AV8100_GPIO_CONFIGURATION_UCDBG_SHIFT 6
+#define AV8100_GPIO_CONFIGURATION_UCDBG_MASK 0x00000040
+#define AV8100_GPIO_CONFIGURATION_UCDBG(__x) \
+ AV8100_VAL2REG(AV8100_GPIO_CONFIGURATION, UCDBG, __x)
+#define AV8100_GPIO_CONFIGURATION_UCDBG_GET(__x) \
+ AV8100_REG2VAL(AV8100_GPIO_CONFIGURATION, UCDBG, __x)
+#define AV8100_GENERAL_CONTROL 0x00000008
+#define AV8100_GENERAL_CONTROL_FDL_SHIFT 4
+#define AV8100_GENERAL_CONTROL_FDL_MASK 0x00000010
+#define AV8100_GENERAL_CONTROL_FDL_HIGH 1
+#define AV8100_GENERAL_CONTROL_FDL_LOW 0
+#define AV8100_GENERAL_CONTROL_FDL(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_CONTROL, FDL, __x)
+#define AV8100_GENERAL_CONTROL_FDL_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_CONTROL, FDL, __x)
+#define AV8100_GENERAL_CONTROL_HLD_SHIFT 5
+#define AV8100_GENERAL_CONTROL_HLD_MASK 0x00000020
+#define AV8100_GENERAL_CONTROL_HLD_HIGH 1
+#define AV8100_GENERAL_CONTROL_HLD_LOW 0
+#define AV8100_GENERAL_CONTROL_HLD(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_CONTROL, HLD, __x)
+#define AV8100_GENERAL_CONTROL_HLD_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_CONTROL, HLD, __x)
+#define AV8100_GENERAL_CONTROL_WA_SHIFT 6
+#define AV8100_GENERAL_CONTROL_WA_MASK 0x00000040
+#define AV8100_GENERAL_CONTROL_WA_HIGH 1
+#define AV8100_GENERAL_CONTROL_WA_LOW 0
+#define AV8100_GENERAL_CONTROL_WA(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_CONTROL, WA, __x)
+#define AV8100_GENERAL_CONTROL_WA_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_CONTROL, WA, __x)
+#define AV8100_GENERAL_CONTROL_RA_SHIFT 7
+#define AV8100_GENERAL_CONTROL_RA_MASK 0x00000080
+#define AV8100_GENERAL_CONTROL_RA_HIGH 1
+#define AV8100_GENERAL_CONTROL_RA_LOW 0
+#define AV8100_GENERAL_CONTROL_RA(__x) \
+ AV8100_VAL2REG(AV8100_GENERAL_CONTROL, RA, __x)
+#define AV8100_GENERAL_CONTROL_RA_GET(__x) \
+ AV8100_REG2VAL(AV8100_GENERAL_CONTROL, RA, __x)
+#define AV8100_FIRMWARE_DOWNLOAD_ENTRY 0x0000000F
+#define AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY_SHIFT 0
+#define AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY_MASK 0x000000FF
+#define AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY(__x) \
+ AV8100_VAL2REG(AV8100_FIRMWARE_DOWNLOAD_ENTRY, MBYTE_CODE_ENTRY, __x)
+#define AV8100_FIRMWARE_DOWNLOAD_ENTRY_MBYTE_CODE_ENTRY_GET(__x) \
+ AV8100_REG2VAL(AV8100_FIRMWARE_DOWNLOAD_ENTRY, MBYTE_CODE_ENTRY, __x)
diff --git a/drivers/video/av8100/hdmi.c b/drivers/video/av8100/hdmi.c
new file mode 100644
index 00000000000..3159c4446f1
--- /dev/null
+++ b/drivers/video/av8100/hdmi.c
@@ -0,0 +1,2479 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson HDMI driver
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/uaccess.h>
+#include <video/av8100.h>
+#include <video/hdmi.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+#include <linux/ctype.h>
+#include "hdmi_loc.h"
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+
+#define SYSFS_EVENT_FILENAME "evread"
+#define HDMI_DEVNR_DEFAULT 0
+
+DEFINE_MUTEX(hdmi_events_mutex);
+#define LOCK_HDMI_EVENTS mutex_lock(&hdmi_events_mutex)
+#define UNLOCK_HDMI_EVENTS mutex_unlock(&hdmi_events_mutex)
+#define EVENTS_MASK 0xFF
+
+struct hdmi_device {
+ struct list_head list;
+ struct miscdevice miscdev;
+ struct device *dev;
+ struct hdmi_sysfs_data sysfs_data;
+ int events;
+ int events_mask;
+ wait_queue_head_t event_wq;
+ bool events_received;
+ int devnr;
+};
+
+/* List of devices */
+static LIST_HEAD(hdmi_device_list);
+
+static ssize_t store_storeastext(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_plugdeten(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_edidread(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_edidread(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t store_ceceven(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_cecread(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t store_cecsend(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_infofrsend(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_hdcpeven(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_hdcpchkaesotp(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_hdcpfuseaes(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_hdcpfuseaes(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_hdcploadaes(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_hdcploadaes(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_hdcpauthencr(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_hdcpauthencr(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t show_hdcpstateget(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t show_evread(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t store_evclr(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_audiocfg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_plugstatus(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_poweronoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_poweronoff(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_evwakeup(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static const struct device_attribute hdmi_sysfs_attrs[] = {
+ __ATTR(storeastext, S_IWUSR, NULL, store_storeastext),
+ __ATTR(plugdeten, S_IWUSR, NULL, store_plugdeten),
+ __ATTR(edidread, S_IRUGO | S_IWUSR, show_edidread, store_edidread),
+ __ATTR(ceceven, S_IWUSR, NULL, store_ceceven),
+ __ATTR(cecread, S_IRUGO, show_cecread, NULL),
+ __ATTR(cecsend, S_IWUSR, NULL, store_cecsend),
+ __ATTR(infofrsend, S_IWUSR, NULL, store_infofrsend),
+ __ATTR(hdcpeven, S_IWUSR, NULL, store_hdcpeven),
+ __ATTR(hdcpchkaesotp, S_IRUGO, show_hdcpchkaesotp, NULL),
+ __ATTR(hdcpfuseaes, S_IRUGO | S_IWUSR, show_hdcpfuseaes,
+ store_hdcpfuseaes),
+ __ATTR(hdcploadaes, S_IRUGO | S_IWUSR, show_hdcploadaes,
+ store_hdcploadaes),
+ __ATTR(hdcpauthencr, S_IRUGO | S_IWUSR, show_hdcpauthencr,
+ store_hdcpauthencr),
+ __ATTR(hdcpstateget, S_IRUGO, show_hdcpstateget, NULL),
+ __ATTR(evread, S_IRUGO, show_evread, NULL),
+ __ATTR(evclr, S_IWUSR, NULL, store_evclr),
+ __ATTR(audiocfg, S_IWUSR, NULL, store_audiocfg),
+ __ATTR(plugstatus, S_IRUGO, show_plugstatus, NULL),
+ __ATTR(poweronoff, S_IRUGO | S_IWUSR, show_poweronoff,
+ store_poweronoff),
+ __ATTR(evwakeup, S_IWUSR, NULL, store_evwakeup),
+ __ATTR_NULL
+};
+
+/* Hex to int conversion */
+static unsigned int htoi(const char *ptr)
+{
+ unsigned int value = 0;
+ char ch;
+
+ if (!ptr)
+ return 0;
+
+ ch = *ptr;
+ if (isdigit(ch))
+ value = ch - '0';
+ else
+ value = toupper(ch) - 'A' + 10;
+
+ value <<= 4;
+ ch = *(++ptr);
+
+ if (isdigit(ch))
+ value += ch - '0';
+ else
+ value += toupper(ch) - 'A' + 10;
+
+ return value;
+}
+
+static struct hdmi_device *dev_to_hdev(struct device *dev)
+{
+ /* Get device from list of devices */
+ struct list_head *element;
+ struct hdmi_device *hdmi_dev;
+ int cnt = 0;
+
+ list_for_each(element, &hdmi_device_list) {
+ hdmi_dev = list_entry(element, struct hdmi_device, list);
+ if (hdmi_dev->dev == dev)
+ return hdmi_dev;
+ cnt++;
+ }
+
+ return NULL;
+}
+
+static struct hdmi_device *devnr_to_hdev(int devnr)
+{
+ /* Get device from list of devices */
+ struct list_head *element;
+ struct hdmi_device *hdmi_dev;
+ int cnt = 0;
+
+ list_for_each(element, &hdmi_device_list) {
+ hdmi_dev = list_entry(element, struct hdmi_device, list);
+ if (cnt == devnr)
+ return hdmi_dev;
+ cnt++;
+ }
+
+ return NULL;
+}
+
+static int event_enable(struct hdmi_device *hdev, bool enable,
+ enum hdmi_event ev)
+{
+ struct kobject *kobj = &hdev->dev->kobj;
+
+ dev_dbg(hdev->dev, "enable_event %d %02x\n", enable, ev);
+ if (enable)
+ hdev->events_mask |= ev;
+ else
+ hdev->events_mask &= ~ev;
+
+ if (hdev->events & ev) {
+ /* Report pending event */
+ /* Wake up application waiting for event via call to poll() */
+ sysfs_notify(kobj, NULL, SYSFS_EVENT_FILENAME);
+
+ LOCK_HDMI_EVENTS;
+ hdev->events_received = true;
+ UNLOCK_HDMI_EVENTS;
+
+ wake_up_interruptible(&hdev->event_wq);
+ }
+
+ return 0;
+}
+
+static int plugdeten(struct hdmi_device *hdev, struct plug_detect *pldet)
+{
+ struct av8100_status status;
+ u8 denc_off_time = 0;
+ int retval;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ event_enable(hdev, pldet->hdmi_detect_enable != 0,
+ HDMI_EVENT_HDMI_PLUGIN);
+ event_enable(hdev, pldet->hdmi_detect_enable != 0,
+ HDMI_EVENT_HDMI_PLUGOUT);
+
+ av8100_reg_hdmi_5_volt_time_r(&denc_off_time, NULL, NULL);
+
+ retval = av8100_reg_hdmi_5_volt_time_w(
+ denc_off_time,
+ pldet->hdmi_off_time,
+ pldet->on_time);
+
+ if (retval) {
+ dev_err(hdev->dev, "Failed to write the value to av8100 "
+ "register\n");
+ return -EFAULT;
+ }
+
+ return retval;
+}
+
+static int edidread(struct hdmi_device *hdev, struct edid_read *edidread,
+ u8 *len, u8 *data)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.edid_section_readback_format.address = edidread->address;
+ config.edid_section_readback_format.block_number = edidread->block_nr;
+
+ dev_dbg(hdev->dev, "addr:%0x blnr:%0x",
+ config.edid_section_readback_format.address,
+ config.edid_section_readback_format.block_number);
+
+ if (av8100_conf_prep(AV8100_COMMAND_EDID_SECTION_READBACK,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_EDID_SECTION_READBACK,
+ len, data, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(hdev->dev, "len:%0x\n", *len);
+
+ return 0;
+}
+
+static int cecread(struct hdmi_device *hdev, u8 *src, u8 *dest, u8 *data_len,
+ u8 *data)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+ u8 buf_len;
+ u8 buff[HDMI_CEC_READ_MAXSIZE];
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ if (av8100_conf_prep(AV8100_COMMAND_CEC_MESSAGE_READ_BACK,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_CEC_MESSAGE_READ_BACK,
+ &buf_len, buff, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ if (buf_len > 0) {
+ *src = (buff[0] & 0xF0) >> 4;
+ *dest = buff[0] & 0x0F;
+ *data_len = buf_len - 1;
+ memcpy(data, &buff[1], buf_len - 1);
+ } else
+ *data_len = 0;
+
+ return 0;
+}
+
+/* CEC tx status can be set or read */
+static bool cec_tx_status(struct hdmi_device *hdev,
+ enum cec_tx_status_action action)
+{
+ static bool cec_tx_busy;
+
+ switch (action) {
+ case CEC_TX_SET_FREE:
+ cec_tx_busy = false;
+ dev_dbg(hdev->dev, "cec_tx_busy set:%d\n", cec_tx_busy);
+ break;
+
+ case CEC_TX_SET_BUSY:
+ cec_tx_busy = true;
+ dev_dbg(hdev->dev, "cec_tx_busy set:%d\n", cec_tx_busy);
+ break;
+
+ case CEC_TX_CHECK:
+ default:
+ dev_dbg(hdev->dev, "cec_tx_busy chk:%d\n", cec_tx_busy);
+ break;
+ }
+
+ return cec_tx_busy;
+}
+
+static int cecsend(struct hdmi_device *hdev, u8 src, u8 dest, u8 data_len,
+ u8 *data)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+ int cnt;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.cec_message_write_format.buffer[0] = ((src & 0x0F) << 4) +
+ (dest & 0x0F);
+ config.cec_message_write_format.buffer_length = data_len + 1;
+ memcpy(&config.cec_message_write_format.buffer[1], data, data_len);
+
+ if (av8100_conf_prep(AV8100_COMMAND_CEC_MESSAGE_WRITE,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_enable_interrupt() != 0) {
+ dev_err(hdev->dev, "av8100_ei FAIL\n");
+ return -EINVAL;
+ }
+
+ cnt = 0;
+ while ((cnt < CECTX_TRY) && cec_tx_status(hdev, CEC_TX_CHECK)) {
+ /* Wait for pending CEC to be finished */
+ msleep(CECTX_WAITTIME);
+ cnt++;
+ }
+ dev_dbg(hdev->dev, "cectxcnt:%d\n", cnt);
+
+ if (av8100_conf_w(AV8100_COMMAND_CEC_MESSAGE_WRITE,
+ NULL, NULL, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+ cec_tx_status(hdev, CEC_TX_SET_BUSY);
+
+ return 0;
+}
+
+static int infofrsend(struct hdmi_device *hdev, u8 type, u8 version, u8 crc,
+ u8 data_len, u8 *data)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ if ((data_len < 1) || (data_len > HDMI_INFOFRAME_MAX_SIZE))
+ return -EINVAL;
+
+ config.infoframes_format.type = type;
+ config.infoframes_format.version = version;
+ config.infoframes_format.crc = crc;
+ config.infoframes_format.length = data_len;
+ memcpy(&config.infoframes_format.data, data, data_len);
+ if (av8100_conf_prep(AV8100_COMMAND_INFOFRAMES,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_INFOFRAMES,
+ NULL, NULL, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hdcpchkaesotp(struct hdmi_device *hdev, u8 *crc, u8 *progged)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+ u8 buf_len;
+ u8 buf[2];
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.fuse_aes_key_format.fuse_operation = AV8100_FUSE_READ;
+ memset(config.fuse_aes_key_format.key, 0, AV8100_FUSE_KEY_SIZE);
+ if (av8100_conf_prep(AV8100_COMMAND_FUSE_AES_KEY,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_FUSE_AES_KEY,
+ &buf_len, buf, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ if (buf_len == 2) {
+ *crc = buf[0];
+ *progged = buf[1];
+ }
+
+ return 0;
+}
+
+static int hdcpfuseaes(struct hdmi_device *hdev, u8 *key, u8 crc, u8 *result)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+ u8 buf_len;
+ u8 buf[2];
+
+ /* Default not OK */
+ *result = HDMI_RESULT_NOT_OK;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.fuse_aes_key_format.fuse_operation = AV8100_FUSE_WRITE;
+ memcpy(config.fuse_aes_key_format.key, key, AV8100_FUSE_KEY_SIZE);
+ if (av8100_conf_prep(AV8100_COMMAND_FUSE_AES_KEY,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_FUSE_AES_KEY,
+ &buf_len, buf, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ if (buf_len == 2) {
+ dev_dbg(hdev->dev, "buf[0]:%02x buf[1]:%02x\n", buf[0], buf[1]);
+ if ((crc == buf[0]) && (buf[1] == 1))
+ /* OK */
+ *result = HDMI_RESULT_OK;
+ else
+ *result = HDMI_RESULT_CRC_MISMATCH;
+ }
+
+ return 0;
+}
+
+static int hdcploadaes(struct hdmi_device *hdev, u8 block, u8 key_len, u8 *key,
+ u8 *result, u8 *crc32)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+ u8 buf_len;
+ u8 buf[CRC32_SIZE];
+
+ /* Default not OK */
+ *result = HDMI_RESULT_NOT_OK;
+
+ dev_dbg(hdev->dev, "%s block:%d\n", __func__, block);
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.hdcp_send_key_format.key_number = block;
+ config.hdcp_send_key_format.data_len = key_len;
+ memcpy(config.hdcp_send_key_format.data, key, key_len);
+ if (av8100_conf_prep(AV8100_COMMAND_HDCP_SENDKEY, &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_HDCP_SENDKEY,
+ &buf_len, buf, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ if ((buf_len == CRC32_SIZE) && (crc32)) {
+ memcpy(crc32, buf, CRC32_SIZE);
+ dev_dbg(hdev->dev, "crc32:%02x%02x%02x%02x\n",
+ crc32[0], crc32[1], crc32[2], crc32[3]);
+ }
+
+ *result = HDMI_RESULT_OK;
+
+ return 0;
+}
+
+static int hdcpauthencr(struct hdmi_device *hdev, u8 auth_type, u8 encr_type,
+ u8 *len, u8 *data)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ switch (auth_type) {
+ case HDMI_HDCP_AUTH_OFF:
+ default:
+ config.hdcp_management_format.req_type =
+ AV8100_HDCP_AUTH_REQ_OFF;
+ break;
+
+ case HDMI_HDCP_AUTH_START:
+ config.hdcp_management_format.req_type =
+ AV8100_HDCP_AUTH_REQ_ON;
+ break;
+
+ case HDMI_HDCP_AUTH_REV_LIST_REQ:
+ config.hdcp_management_format.req_type =
+ AV8100_HDCP_REV_LIST_REQ;
+ break;
+ case HDMI_HDCP_AUTH_CONT:
+ config.hdcp_management_format.req_type =
+ AV8100_HDCP_AUTH_CONT;
+ break;
+ }
+
+ switch (encr_type) {
+ case HDMI_HDCP_ENCR_OESS:
+ default:
+ config.hdcp_management_format.encr_use =
+ AV8100_HDCP_ENCR_USE_OESS;
+ break;
+
+ case HDMI_HDCP_ENCR_EESS:
+ config.hdcp_management_format.encr_use =
+ AV8100_HDCP_ENCR_USE_EESS;
+ break;
+ }
+
+ if (av8100_conf_prep(AV8100_COMMAND_HDCP_MANAGEMENT,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_HDCP_MANAGEMENT,
+ len, data, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u8 events_read(struct hdmi_device *hdev)
+{
+ int ret;
+
+ LOCK_HDMI_EVENTS;
+ ret = hdev->events;
+ dev_dbg(hdev->dev, "%s %02x\n", __func__, hdev->events);
+ UNLOCK_HDMI_EVENTS;
+
+ return ret;
+}
+
+static int events_clear(struct hdmi_device *hdev, u8 ev)
+{
+ dev_dbg(hdev->dev, "%s %02x\n", __func__, ev);
+
+ LOCK_HDMI_EVENTS;
+ hdev->events &= ~ev & EVENTS_MASK;
+ UNLOCK_HDMI_EVENTS;
+
+ return 0;
+}
+
+static int event_wakeup(struct hdmi_device *hdev)
+{
+ struct kobject *kobj = &hdev->dev->kobj;
+
+ dev_dbg(hdev->dev, "%s", __func__);
+
+ LOCK_HDMI_EVENTS;
+ hdev->events |= HDMI_EVENT_WAKEUP;
+ hdev->events_received = true;
+ UNLOCK_HDMI_EVENTS;
+
+ /* Wake up application waiting for event via call to poll() */
+ sysfs_notify(kobj, NULL, SYSFS_EVENT_FILENAME);
+ wake_up_interruptible(&hdev->event_wq);
+
+ return 0;
+}
+
+static int audiocfg(struct hdmi_device *hdev, struct audio_cfg *cfg)
+{
+ union av8100_configuration config;
+ struct av8100_status status;
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_INIT) {
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ config.audio_input_format.audio_input_if_format = cfg->if_format;
+ config.audio_input_format.i2s_input_nb = cfg->i2s_entries;
+ config.audio_input_format.sample_audio_freq = cfg->freq;
+ config.audio_input_format.audio_word_lg = cfg->word_length;
+ config.audio_input_format.audio_format = cfg->format;
+ config.audio_input_format.audio_if_mode = cfg->if_mode;
+ config.audio_input_format.audio_mute = cfg->mute;
+
+ if (av8100_conf_prep(AV8100_COMMAND_AUDIO_INPUT_FORMAT,
+ &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_AUDIO_INPUT_FORMAT,
+ NULL, NULL, I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* sysfs */
+static ssize_t store_storeastext(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if ((count != HDMI_STOREASTEXT_BIN_SIZE) &&
+ (count != HDMI_STOREASTEXT_TEXT_SIZE) &&
+ (count != HDMI_STOREASTEXT_TEXT_SIZE + 1))
+ return -EINVAL;
+
+ if ((count == HDMI_STOREASTEXT_BIN_SIZE) && (*buf == 0x1))
+ hdev->sysfs_data.store_as_hextext = true;
+ else if (((count == HDMI_STOREASTEXT_TEXT_SIZE) ||
+ (count == HDMI_STOREASTEXT_TEXT_SIZE + 1)) && (*buf == '0') &&
+ (*(buf + 1) == '1')) {
+ hdev->sysfs_data.store_as_hextext = true;
+ } else {
+ hdev->sysfs_data.store_as_hextext = false;
+ }
+
+ dev_dbg(hdev->dev, "store_as_hextext:%0d\n",
+ hdev->sysfs_data.store_as_hextext);
+
+ return count;
+}
+
+static ssize_t store_plugdeten(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct plug_detect plug_detect;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_PLUGDETEN_TEXT_SIZE) &&
+ (count != HDMI_PLUGDETEN_TEXT_SIZE + 1))
+ return -EINVAL;
+ plug_detect.hdmi_detect_enable = htoi(buf + index);
+ index += 2;
+ plug_detect.on_time = htoi(buf + index);
+ index += 2;
+ plug_detect.hdmi_off_time = htoi(buf + index);
+ index += 2;
+ } else {
+ if (count != HDMI_PLUGDETEN_BIN_SIZE)
+ return -EINVAL;
+ plug_detect.hdmi_detect_enable = *(buf + index++);
+ plug_detect.on_time = *(buf + index++);
+ plug_detect.hdmi_off_time = *(buf + index++);
+ }
+
+ if (plugdeten(hdev, &plug_detect))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t store_edidread(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct edid_read edid_read;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+ dev_dbg(hdev->dev, "count:%d\n", count);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_EDIDREAD_TEXT_SIZE) &&
+ (count != HDMI_EDIDREAD_TEXT_SIZE + 1))
+ return -EINVAL;
+ edid_read.address = htoi(buf + index);
+ index += 2;
+ edid_read.block_nr = htoi(buf + index);
+ index += 2;
+ } else {
+ if (count != HDMI_EDIDREAD_BIN_SIZE)
+ return -EINVAL;
+ edid_read.address = *(buf + index++);
+ edid_read.block_nr = *(buf + index++);
+ }
+
+ if (edidread(hdev, &edid_read, &hdev->sysfs_data.edid_data.buf_len,
+ hdev->sysfs_data.edid_data.buf))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t show_edidread(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int len;
+ int index = 0;
+ int cnt;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ len = hdev->sysfs_data.edid_data.buf_len;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", len);
+ index += 2;
+ } else
+ *(buf + index++) = len;
+
+ dev_dbg(hdev->dev, "len:%02x\n", len);
+
+ cnt = 0;
+ while (cnt < len) {
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x",
+ hdev->sysfs_data.edid_data.buf[cnt]);
+ index += 2;
+ } else
+ *(buf + index++) =
+ hdev->sysfs_data.edid_data.buf[cnt];
+
+ dev_dbg(hdev->dev, "%02x ",
+ hdev->sysfs_data.edid_data.buf[cnt]);
+
+ cnt++;
+ }
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_ceceven(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ bool enable = false;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_CECEVEN_TEXT_SIZE) &&
+ (count != HDMI_CECEVEN_TEXT_SIZE + 1))
+ return -EINVAL;
+ if ((*buf == '0') && (*(buf + 1) == '1'))
+ enable = true;
+ } else {
+ if (count != HDMI_CECEVEN_BIN_SIZE)
+ return -EINVAL;
+ if (*buf == 0x01)
+ enable = true;
+ }
+
+ event_enable(hdev, enable, HDMI_EVENT_CEC | HDMI_EVENT_CECTXERR |
+ HDMI_EVENT_CECTX);
+
+ return count;
+}
+
+static ssize_t show_cecread(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct cec_rw cec_read;
+ int index = 0;
+ int cnt;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (cecread(hdev, &cec_read.src, &cec_read.dest, &cec_read.length,
+ cec_read.data))
+ return -EINVAL;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", cec_read.src);
+ index += 2;
+ snprintf(buf + index, 3, "%02x", cec_read.dest);
+ index += 2;
+ snprintf(buf + index, 3, "%02x", cec_read.length);
+ index += 2;
+ } else {
+ *(buf + index++) = cec_read.src;
+ *(buf + index++) = cec_read.dest;
+ *(buf + index++) = cec_read.length;
+ }
+
+ dev_dbg(hdev->dev, "len:%02x\n", cec_read.length);
+
+ cnt = 0;
+ while (cnt < cec_read.length) {
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", cec_read.data[cnt]);
+ index += 2;
+ } else
+ *(buf + index++) = cec_read.data[cnt];
+
+ dev_dbg(hdev->dev, "%02x ", cec_read.data[cnt]);
+
+ cnt++;
+ }
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_cecsend(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct cec_rw cec_w;
+ int index = 0;
+ int cnt;
+ int store_as_text;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if ((*buf == 'F') || (*buf == 'f'))
+ /* To be able to override bin format for test purpose */
+ store_as_text = 1;
+ else
+ store_as_text = hdev->sysfs_data.store_as_hextext;
+
+ if (store_as_text) {
+ if ((count < HDMI_CECSEND_TEXT_SIZE_MIN) ||
+ (count > HDMI_CECSEND_TEXT_SIZE_MAX))
+ return -EINVAL;
+
+ cec_w.src = htoi(buf + index) & 0x0F;
+ index += 2;
+ cec_w.dest = htoi(buf + index);
+ index += 2;
+ cec_w.length = htoi(buf + index);
+ index += 2;
+ if (cec_w.length > HDMI_CEC_WRITE_MAXSIZE)
+ return -EINVAL;
+ cnt = 0;
+ while (cnt < cec_w.length) {
+ cec_w.data[cnt] = htoi(buf + index);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ", cec_w.data[cnt]);
+ cnt++;
+ }
+ } else {
+ if ((count < HDMI_CECSEND_BIN_SIZE_MIN) ||
+ (count > HDMI_CECSEND_BIN_SIZE_MAX))
+ return -EINVAL;
+
+ cec_w.src = *(buf + index++);
+ cec_w.dest = *(buf + index++);
+ cec_w.length = *(buf + index++);
+ if (cec_w.length > HDMI_CEC_WRITE_MAXSIZE)
+ return -EINVAL;
+ memcpy(cec_w.data, buf + index, cec_w.length);
+ }
+
+ if (cecsend(hdev, cec_w.src, cec_w.dest, cec_w.length, cec_w.data))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t store_infofrsend(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct info_fr info_fr;
+ int index = 0;
+ int cnt;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count < HDMI_INFOFRSEND_TEXT_SIZE_MIN) ||
+ (count > HDMI_INFOFRSEND_TEXT_SIZE_MAX))
+ return -EINVAL;
+
+ info_fr.type = htoi(&buf[index]);
+ index += 2;
+ info_fr.ver = htoi(&buf[index]);
+ index += 2;
+ info_fr.crc = htoi(&buf[index]);
+ index += 2;
+ info_fr.length = htoi(&buf[index]);
+ index += 2;
+
+ if (info_fr.length > HDMI_INFOFRAME_MAX_SIZE)
+ return -EINVAL;
+ cnt = 0;
+ while (cnt < info_fr.length) {
+ info_fr.data[cnt] = htoi(buf + index);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ", info_fr.data[cnt]);
+ cnt++;
+ }
+ } else {
+ if ((count < HDMI_INFOFRSEND_BIN_SIZE_MIN) ||
+ (count > HDMI_INFOFRSEND_BIN_SIZE_MAX))
+ return -EINVAL;
+
+ info_fr.type = *(buf + index++);
+ info_fr.ver = *(buf + index++);
+ info_fr.crc = *(buf + index++);
+ info_fr.length = *(buf + index++);
+
+ if (info_fr.length > HDMI_INFOFRAME_MAX_SIZE)
+ return -EINVAL;
+ memcpy(info_fr.data, buf + index, info_fr.length);
+ }
+
+ if (infofrsend(hdev, info_fr.type, info_fr.ver, info_fr.crc,
+ info_fr.length, info_fr.data))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t store_hdcpeven(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ bool enable = false;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_HDCPEVEN_TEXT_SIZE) &&
+ (count != HDMI_HDCPEVEN_TEXT_SIZE + 1))
+ return -EINVAL;
+ if ((*buf == '0') && (*(buf + 1) == '1'))
+ enable = true;
+ } else {
+ if (count != HDMI_HDCPEVEN_BIN_SIZE)
+ return -EINVAL;
+ if (*buf == 0x01)
+ enable = true;
+ }
+
+ event_enable(hdev, enable, HDMI_EVENT_HDCP);
+
+ return count;
+}
+
+static ssize_t show_hdcpchkaesotp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ u8 crc;
+ u8 progged;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdcpchkaesotp(hdev, &crc, &progged))
+ return -EINVAL;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", progged);
+ index += 2;
+ } else {
+ *(buf + index++) = progged;
+ }
+
+ dev_dbg(hdev->dev, "progged:%02x\n", progged);
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_hdcpfuseaes(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct hdcp_fuseaes hdcp_fuseaes;
+ int index = 0;
+ int cnt;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ /* Default not OK */
+ hdev->sysfs_data.fuse_result = HDMI_RESULT_NOT_OK;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_HDCP_FUSEAES_TEXT_SIZE) &&
+ (count != HDMI_HDCP_FUSEAES_TEXT_SIZE + 1))
+ return -EINVAL;
+
+ cnt = 0;
+ while (cnt < HDMI_HDCP_FUSEAES_KEYSIZE) {
+ hdcp_fuseaes.key[cnt] = htoi(buf + index);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ", hdcp_fuseaes.key[cnt]);
+ cnt++;
+ }
+ hdcp_fuseaes.crc = htoi(&buf[index]);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ", hdcp_fuseaes.crc);
+ } else {
+ if (count != HDMI_HDCP_FUSEAES_BIN_SIZE)
+ return -EINVAL;
+
+ memcpy(hdcp_fuseaes.key, buf + index,
+ HDMI_HDCP_FUSEAES_KEYSIZE);
+ index += HDMI_HDCP_FUSEAES_KEYSIZE;
+ hdcp_fuseaes.crc = *(buf + index++);
+ }
+
+ if (hdcpfuseaes(hdev, hdcp_fuseaes.key, hdcp_fuseaes.crc,
+ &hdcp_fuseaes.result))
+ return -EINVAL;
+
+ dev_dbg(hdev->dev, "fuseresult:%02x ", hdcp_fuseaes.result);
+
+ hdev->sysfs_data.fuse_result = hdcp_fuseaes.result;
+
+ return count;
+}
+
+static ssize_t show_hdcpfuseaes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", hdev->sysfs_data.fuse_result);
+ index += 2;
+ } else
+ *(buf + index++) = hdev->sysfs_data.fuse_result;
+
+ dev_dbg(hdev->dev, "status:%02x\n", hdev->sysfs_data.fuse_result);
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_hdcploadaes(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct hdcp_loadaesone hdcp_loadaes;
+ int index = 0;
+ int block_cnt;
+ int cnt;
+ u8 crc32_rcvd[CRC32_SIZE];
+ u8 crc;
+ u8 progged;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ /* Default not OK */
+ hdev->sysfs_data.loadaes_result = HDMI_RESULT_NOT_OK;
+
+ if (hdcpchkaesotp(hdev, &crc, &progged))
+ return -EINVAL;
+
+ if (!progged) {
+ /* AES is not fused */
+ hdcp_loadaes.result = HDMI_AES_NOT_FUSED;
+ goto store_hdcploadaes_err;
+ }
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_HDCP_LOADAES_TEXT_SIZE) &&
+ (count != HDMI_HDCP_LOADAES_TEXT_SIZE + 1)) {
+ dev_err(hdev->dev, "%s", "count mismatch\n");
+ return -EINVAL;
+ }
+
+ /* AES */
+ block_cnt = 0;
+ while (block_cnt < HDMI_HDCP_AES_NR_OF_BLOCKS) {
+ cnt = 0;
+ while (cnt < HDMI_HDCP_AES_KEYSIZE) {
+ hdcp_loadaes.key[cnt] = htoi(buf + index);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ",
+ hdcp_loadaes.key[cnt]);
+ cnt++;
+ }
+
+ if (hdcploadaes(hdev,
+ block_cnt + HDMI_HDCP_AES_BLOCK_START,
+ HDMI_HDCP_AES_KEYSIZE,
+ hdcp_loadaes.key,
+ &hdcp_loadaes.result,
+ crc32_rcvd)) {
+ dev_err(hdev->dev, "%s %d\n",
+ "hdcploadaes err aes block",
+ block_cnt + HDMI_HDCP_AES_BLOCK_START);
+ return -EINVAL;
+ }
+
+ if (hdcp_loadaes.result)
+ goto store_hdcploadaes_err;
+
+ block_cnt++;
+ }
+
+ /* KSV */
+ memset(hdcp_loadaes.key, 0, HDMI_HDCP_AES_KSVZEROESSIZE);
+ cnt = HDMI_HDCP_AES_KSVZEROESSIZE;
+ while (cnt < HDMI_HDCP_AES_KSVSIZE +
+ HDMI_HDCP_AES_KSVZEROESSIZE) {
+ hdcp_loadaes.key[cnt] =
+ htoi(&buf[index]);
+ index += 2;
+ dev_dbg(hdev->dev, "%02x ", hdcp_loadaes.key[cnt]);
+ cnt++;
+ }
+
+ if (hdcploadaes(hdev, HDMI_HDCP_KSV_BLOCK,
+ HDMI_HDCP_AES_KSVSIZE +
+ HDMI_HDCP_AES_KSVZEROESSIZE,
+ hdcp_loadaes.key,
+ &hdcp_loadaes.result,
+ NULL)) {
+ dev_err(hdev->dev,
+ "%s %d\n", "hdcploadaes err in ksv\n",
+ block_cnt + HDMI_HDCP_AES_BLOCK_START);
+ return -EINVAL;
+ }
+
+ if (hdcp_loadaes.result)
+ goto store_hdcploadaes_err;
+
+ /* CRC32 */
+ for (cnt = 0; cnt < CRC32_SIZE; cnt++) {
+ hdcp_loadaes.crc32[cnt] = htoi(buf + index);
+ index += 2;
+ }
+
+ if (memcmp(hdcp_loadaes.crc32, crc32_rcvd, CRC32_SIZE)) {
+ dev_dbg(hdev->dev, "crc32exp:%02x%02x%02x%02x\n",
+ hdcp_loadaes.crc32[0],
+ hdcp_loadaes.crc32[1],
+ hdcp_loadaes.crc32[2],
+ hdcp_loadaes.crc32[3]);
+ hdcp_loadaes.result = HDMI_RESULT_CRC_MISMATCH;
+ goto store_hdcploadaes_err;
+ }
+ } else {
+ if (count != HDMI_HDCP_LOADAES_BIN_SIZE) {
+ dev_err(hdev->dev, "%s", "count mismatch\n");
+ return -EINVAL;
+ }
+
+ /* AES */
+ block_cnt = 0;
+ while (block_cnt < HDMI_HDCP_AES_NR_OF_BLOCKS) {
+ memcpy(hdcp_loadaes.key, buf + index,
+ HDMI_HDCP_AES_KEYSIZE);
+ index += HDMI_HDCP_AES_KEYSIZE;
+
+ if (hdcploadaes(hdev,
+ block_cnt + HDMI_HDCP_AES_BLOCK_START,
+ HDMI_HDCP_AES_KEYSIZE,
+ hdcp_loadaes.key,
+ &hdcp_loadaes.result,
+ crc32_rcvd)) {
+ dev_err(hdev->dev, "%s %d\n",
+ "hdcploadaes err aes block",
+ block_cnt + HDMI_HDCP_AES_BLOCK_START);
+ return -EINVAL;
+ }
+
+ if (hdcp_loadaes.result)
+ goto store_hdcploadaes_err;
+
+ block_cnt++;
+ }
+
+ /* KSV */
+ memset(hdcp_loadaes.key, 0, HDMI_HDCP_AES_KSVZEROESSIZE);
+ memcpy(hdcp_loadaes.key + HDMI_HDCP_AES_KSVZEROESSIZE,
+ buf + index,
+ HDMI_HDCP_AES_KSVSIZE);
+ index += HDMI_HDCP_AES_KSVSIZE;
+
+ if (hdcploadaes(hdev, HDMI_HDCP_KSV_BLOCK,
+ HDMI_HDCP_AES_KSVSIZE +
+ HDMI_HDCP_AES_KSVZEROESSIZE,
+ hdcp_loadaes.key,
+ &hdcp_loadaes.result,
+ NULL)) {
+ dev_err(hdev->dev, "%s %d\n",
+ "hdcploadaes err in ksv\n",
+ block_cnt + HDMI_HDCP_AES_BLOCK_START);
+ return -EINVAL;
+ }
+
+ memcpy(hdcp_loadaes.crc32, buf + index, CRC32_SIZE);
+ index += CRC32_SIZE;
+
+ /* CRC32 */
+ if (memcmp(hdcp_loadaes.crc32, crc32_rcvd, CRC32_SIZE)) {
+ dev_dbg(hdev->dev, "crc32exp:%02x%02x%02x%02x\n",
+ hdcp_loadaes.crc32[0],
+ hdcp_loadaes.crc32[1],
+ hdcp_loadaes.crc32[2],
+ hdcp_loadaes.crc32[3]);
+ hdcp_loadaes.result = HDMI_RESULT_CRC_MISMATCH;
+ }
+ }
+
+store_hdcploadaes_err:
+ hdev->sysfs_data.loadaes_result = hdcp_loadaes.result;
+ return count;
+}
+
+static ssize_t show_hdcploadaes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x",
+ hdev->sysfs_data.loadaes_result);
+ index += 2;
+ } else
+ *(buf + index++) = hdev->sysfs_data.loadaes_result;
+
+ dev_dbg(hdev->dev, "result:%02x\n", hdev->sysfs_data.loadaes_result);
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_hdcpauthencr(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct hdcp_authencr hdcp_authencr;
+ int index = 0;
+ u8 crc;
+ u8 progged;
+ int result = HDMI_RESULT_NOT_OK;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ /* Default */
+ hdev->sysfs_data.authencr.buf_len = 0;
+
+ if (hdcpchkaesotp(hdev, &crc, &progged)) {
+ result = HDMI_AES_NOT_FUSED;
+ goto store_hdcpauthencr_end;
+ }
+
+ if (!progged) {
+ /* AES is not fused */
+ result = HDMI_AES_NOT_FUSED;
+ goto store_hdcpauthencr_end;
+ }
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_HDCPAUTHENCR_TEXT_SIZE) &&
+ (count != HDMI_HDCPAUTHENCR_TEXT_SIZE + 1))
+ goto store_hdcpauthencr_end;
+
+ hdcp_authencr.auth_type = htoi(buf + index);
+ index += 2;
+ hdcp_authencr.encr_type = htoi(buf + index);
+ index += 2;
+ } else {
+ if (count != HDMI_HDCPAUTHENCR_BIN_SIZE)
+ goto store_hdcpauthencr_end;
+
+ hdcp_authencr.auth_type = *(buf + index++);
+ hdcp_authencr.encr_type = *(buf + index++);
+ }
+
+ if (hdcpauthencr(hdev, hdcp_authencr.auth_type, hdcp_authencr.encr_type,
+ &hdev->sysfs_data.authencr.buf_len,
+ hdev->sysfs_data.authencr.buf))
+ goto store_hdcpauthencr_end;
+
+ result = HDMI_RESULT_OK;
+
+store_hdcpauthencr_end:
+ hdev->sysfs_data.authencr.result = result;
+ return count;
+}
+
+static ssize_t show_hdcpauthencr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int len;
+ int index = 0;
+ int cnt;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ /* result */
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x",
+ hdev->sysfs_data.authencr.result);
+ index += 2;
+ } else
+ *(buf + index++) = hdev->sysfs_data.authencr.result;
+
+ dev_dbg(hdev->dev, "result:%02x\n", hdev->sysfs_data.authencr.result);
+
+ /* resp_size */
+ len = hdev->sysfs_data.authencr.buf_len;
+ if (len > AUTH_BUF_LEN)
+ len = AUTH_BUF_LEN;
+ dev_dbg(hdev->dev, "resp_size:%d\n", len);
+
+ /* resp */
+ cnt = 0;
+ while (cnt < len) {
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x",
+ hdev->sysfs_data.authencr.buf[cnt]);
+ index += 2;
+
+ dev_dbg(hdev->dev, "%02x ",
+ hdev->sysfs_data.authencr.buf[cnt]);
+
+ } else
+ *(buf + index++) = hdev->sysfs_data.authencr.buf[cnt];
+
+ cnt++;
+ }
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t show_hdcpstateget(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ u8 hdcp_state;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (av8100_reg_gen_status_r(NULL, NULL, NULL, NULL, NULL, &hdcp_state))
+ return -EINVAL;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", hdcp_state);
+ index += 2;
+ } else
+ *(buf + index++) = hdcp_state;
+
+ dev_dbg(hdev->dev, "status:%02x\n", hdcp_state);
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t show_evread(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int index = 0;
+ u8 ev;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ ev = events_read(hdev);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", ev);
+ index += 2;
+ } else
+ *(buf + index++) = ev;
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ /* Events are read: clear events */
+ events_clear(hdev, EVENTS_MASK);
+
+ return index;
+}
+
+static ssize_t store_evclr(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ u8 ev;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_EVCLR_TEXT_SIZE) &&
+ (count != HDMI_EVCLR_TEXT_SIZE + 1))
+ return -EINVAL;
+
+ ev = htoi(&buf[index]);
+ index += 2;
+ } else {
+ if (count != HDMI_EVCLR_BIN_SIZE)
+ return -EINVAL;
+
+ ev = *(buf + index++);
+ }
+
+ events_clear(hdev, ev);
+
+ return count;
+}
+
+static ssize_t store_audiocfg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ struct audio_cfg audio_cfg;
+ int index = 0;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_AUDIOCFG_TEXT_SIZE) &&
+ (count != HDMI_AUDIOCFG_TEXT_SIZE + 1))
+ return -EINVAL;
+
+ audio_cfg.if_format = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.i2s_entries = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.freq = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.word_length = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.format = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.if_mode = htoi(&buf[index]);
+ index += 2;
+ audio_cfg.mute = htoi(&buf[index]);
+ index += 2;
+ } else {
+ if (count != HDMI_AUDIOCFG_BIN_SIZE)
+ return -EINVAL;
+
+ audio_cfg.if_format = *(buf + index++);
+ audio_cfg.i2s_entries = *(buf + index++);
+ audio_cfg.freq = *(buf + index++);
+ audio_cfg.word_length = *(buf + index++);
+ audio_cfg.format = *(buf + index++);
+ audio_cfg.if_mode = *(buf + index++);
+ audio_cfg.mute = *(buf + index++);
+ }
+
+ audiocfg(hdev, &audio_cfg);
+
+ return count;
+}
+
+static ssize_t show_plugstatus(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int index = 0;
+ struct av8100_status av8100_status;
+ u8 plstat;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ av8100_status = av8100_status_get();
+ plstat = av8100_status.av8100_plugin_status == AV8100_HDMI_PLUGIN;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", plstat);
+ index += 2;
+ } else
+ *(buf + index++) = plstat;
+
+ if (hdev->sysfs_data.store_as_hextext)
+ index++;
+
+ return index;
+}
+
+static ssize_t store_poweronoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ bool enable = false;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ if ((count != HDMI_POWERONOFF_TEXT_SIZE) &&
+ (count != HDMI_POWERONOFF_TEXT_SIZE + 1))
+ return -EINVAL;
+ if ((*buf == '0') && (*(buf + 1) == '1'))
+ enable = true;
+ } else {
+ if (count != HDMI_POWERONOFF_BIN_SIZE)
+ return -EINVAL;
+ if (*buf == 0x01)
+ enable = true;
+ }
+
+ if (enable == 0) {
+ if (av8100_powerdown() != 0) {
+ dev_err(hdev->dev, "av8100_powerdown FAIL\n");
+ return -EINVAL;
+ }
+ } else {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup FAIL\n");
+ return -EINVAL;
+ }
+ }
+
+ return count;
+}
+
+static ssize_t show_poweronoff(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+ int index = 0;
+ struct av8100_status status;
+ u8 power_state;
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_SCAN)
+ power_state = 0;
+ else
+ power_state = 1;
+
+ if (hdev->sysfs_data.store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", power_state);
+ index += 3;
+ } else {
+ *(buf + index++) = power_state;
+ }
+
+ return index;
+}
+
+static ssize_t store_evwakeup(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct hdmi_device *hdev = dev_to_hdev(dev);
+
+ if (!hdev)
+ return -EFAULT;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ event_wakeup(hdev);
+
+ return count;
+}
+
+static int hdmi_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int hdmi_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/* ioctl */
+static long hdmi_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ u8 value = 0;
+ struct hdmi_register reg;
+ struct av8100_status status;
+ u8 aes_status;
+ struct hdmi_device *hdev = devnr_to_hdev(HDMI_DEVNR_DEFAULT);
+
+ switch (cmd) {
+ case IOC_PLUG_DETECT_ENABLE:
+ {
+ struct plug_detect plug_detect;
+
+ if (copy_from_user(&plug_detect, (void *)arg,
+ sizeof(struct plug_detect)))
+ return -EINVAL;
+
+ if (plugdeten(hdev, &plug_detect))
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_EDID_READ:
+ {
+ struct edid_read edid_read;
+
+ if (copy_from_user(&edid_read, (void *)arg,
+ sizeof(struct edid_read)))
+ return -EINVAL;
+
+ if (edidread(hdev, &edid_read, &edid_read.data_length,
+ edid_read.data))
+ return -EINVAL;
+
+ if (copy_to_user((void *)arg, (void *)&edid_read,
+ sizeof(struct edid_read))) {
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_CEC_EVENT_ENABLE:
+ if (copy_from_user(&value, (void *)arg, sizeof(u8)))
+ return -EINVAL;
+
+ event_enable(hdev, value != 0,
+ HDMI_EVENT_CEC | HDMI_EVENT_CECTXERR |
+ HDMI_EVENT_CECTX);
+ break;
+
+ case IOC_CEC_READ:
+ {
+ struct cec_rw cec_read;
+
+ if (cecread(hdev, &cec_read.src, &cec_read.dest,
+ &cec_read.length, cec_read.data))
+ return -EINVAL;
+
+ if (copy_to_user((void *)arg, (void *)&cec_read,
+ sizeof(struct cec_rw))) {
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_CEC_SEND:
+ {
+ struct cec_rw cec_send;
+
+ if (copy_from_user(&cec_send, (void *)arg,
+ sizeof(struct cec_rw)))
+ return -EINVAL;
+
+ if (cecsend(hdev, cec_send.src, cec_send.dest, cec_send.length,
+ cec_send.data))
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_INFOFRAME_SEND:
+ {
+ struct info_fr info_fr;
+
+ if (copy_from_user(&info_fr, (void *)arg,
+ sizeof(struct info_fr)))
+ return -EINVAL;
+
+ if (infofrsend(hdev, info_fr.type, info_fr.ver, info_fr.crc,
+ info_fr.length, info_fr.data))
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDCP_EVENT_ENABLE:
+ if (copy_from_user(&value, (void *)arg, sizeof(u8)))
+ return -EINVAL;
+
+ event_enable(hdev, value != 0, HDMI_EVENT_HDCP);
+ break;
+
+ case IOC_HDCP_CHKAESOTP:
+ if (hdcpchkaesotp(hdev, &value, &aes_status))
+ return -EINVAL;
+
+ if (copy_to_user((void *)arg, (void *)&aes_status,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDCP_FUSEAES:
+ {
+ struct hdcp_fuseaes hdcp_fuseaes;
+
+ if (copy_from_user(&hdcp_fuseaes, (void *)arg,
+ sizeof(struct hdcp_fuseaes)))
+ return -EINVAL;
+
+ if (hdcpfuseaes(hdev, hdcp_fuseaes.key, hdcp_fuseaes.crc,
+ &hdcp_fuseaes.result))
+ return -EINVAL;
+
+ if (copy_to_user((void *)arg, (void *)&hdcp_fuseaes,
+ sizeof(struct hdcp_fuseaes))) {
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_HDCP_LOADAES:
+ {
+ int block_cnt;
+ struct hdcp_loadaesone hdcp_loadaesone;
+ struct hdcp_loadaesall hdcp_loadaesall;
+
+ if (copy_from_user(&hdcp_loadaesall, (void *)arg,
+ sizeof(struct hdcp_loadaesall)))
+ return -EINVAL;
+
+ if (hdcpchkaesotp(hdev, &value, &aes_status))
+ return -EINVAL;
+
+ if (!aes_status) {
+ /* AES is not fused */
+ hdcp_loadaesone.result = HDMI_AES_NOT_FUSED;
+ goto ioc_hdcploadaes_err;
+ }
+
+ /* AES */
+ block_cnt = 0;
+ while (block_cnt < HDMI_HDCP_AES_NR_OF_BLOCKS) {
+ memcpy(hdcp_loadaesone.key, hdcp_loadaesall.key +
+ block_cnt * HDMI_HDCP_AES_KEYSIZE,
+ HDMI_HDCP_AES_KEYSIZE);
+
+ if (hdcploadaes(hdev,
+ block_cnt + HDMI_HDCP_AES_BLOCK_START,
+ HDMI_HDCP_AES_KEYSIZE,
+ hdcp_loadaesone.key,
+ &hdcp_loadaesone.result,
+ hdcp_loadaesone.crc32))
+ return -EINVAL;
+
+ if (hdcp_loadaesone.result)
+ return -EINVAL;
+
+ block_cnt++;
+ }
+
+ /* KSV */
+ memset(hdcp_loadaesone.key, 0, HDMI_HDCP_AES_KSVZEROESSIZE);
+ memcpy(hdcp_loadaesone.key + HDMI_HDCP_AES_KSVZEROESSIZE,
+ hdcp_loadaesall.ksv, HDMI_HDCP_AES_KSVSIZE);
+
+ if (hdcploadaes(hdev, HDMI_HDCP_KSV_BLOCK,
+ HDMI_HDCP_AES_KSVSIZE +
+ HDMI_HDCP_AES_KSVZEROESSIZE,
+ hdcp_loadaesone.key,
+ &hdcp_loadaesone.result,
+ NULL))
+ return -EINVAL;
+
+ if (hdcp_loadaesone.result)
+ return -EINVAL;
+
+ /* CRC32 */
+ if (memcmp(hdcp_loadaesall.crc32, hdcp_loadaesone.crc32,
+ CRC32_SIZE)) {
+ dev_dbg(hdev->dev, "crc32exp:%02x%02x%02x%02x\n",
+ hdcp_loadaesall.crc32[0],
+ hdcp_loadaesall.crc32[1],
+ hdcp_loadaesall.crc32[2],
+ hdcp_loadaesall.crc32[3]);
+ hdcp_loadaesone.result = HDMI_RESULT_CRC_MISMATCH;
+ goto ioc_hdcploadaes_err;
+ }
+
+ioc_hdcploadaes_err:
+ hdcp_loadaesall.result = hdcp_loadaesone.result;
+
+ if (copy_to_user((void *)arg, (void *)&hdcp_loadaesall,
+ sizeof(struct hdcp_loadaesall))) {
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_HDCP_AUTHENCR_REQ:
+ {
+ struct hdcp_authencr hdcp_authencr;
+ int result = HDMI_RESULT_NOT_OK;
+
+ u8 buf[AUTH_BUF_LEN];
+
+ if (copy_from_user(&hdcp_authencr, (void *)arg,
+ sizeof(struct hdcp_authencr)))
+ return -EINVAL;
+
+ /* Default not OK */
+ hdcp_authencr.resp_size = 0;
+
+ if (hdcpchkaesotp(hdev, &value, &aes_status)) {
+ result = HDMI_AES_NOT_FUSED;
+ goto hdcp_authencr_end;
+ }
+
+ if (!aes_status) {
+ /* AES is not fused */
+ result = HDMI_AES_NOT_FUSED;
+ goto hdcp_authencr_end;
+ }
+
+ if (hdcpauthencr(hdev, hdcp_authencr.auth_type,
+ hdcp_authencr.encr_type,
+ &value,
+ buf)) {
+ result = HDMI_RESULT_NOT_OK;
+ goto hdcp_authencr_end;
+ }
+
+ if (value > AUTH_BUF_LEN)
+ value = AUTH_BUF_LEN;
+
+ result = HDMI_RESULT_OK;
+ hdcp_authencr.resp_size = value;
+ memcpy(hdcp_authencr.resp, buf, value);
+
+hdcp_authencr_end:
+ hdcp_authencr.result = result;
+ if (copy_to_user((void *)arg, (void *)&hdcp_authencr,
+ sizeof(struct hdcp_authencr)))
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDCP_STATE_GET:
+ if (av8100_reg_gen_status_r(NULL, NULL, NULL, NULL, NULL,
+ &value))
+ return -EINVAL;
+
+ if (copy_to_user((void *)arg, (void *)&value,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_EVENTS_READ:
+ value = events_read(hdev);
+
+ if (copy_to_user((void *)arg, (void *)&value,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+
+ /* Events are read: clear events */
+ events_clear(hdev, EVENTS_MASK);
+ break;
+
+ case IOC_EVENTS_CLEAR:
+ if (copy_from_user(&value, (void *)arg, sizeof(u8)))
+ return -EINVAL;
+
+ events_clear(hdev, value);
+ break;
+
+ case IOC_AUDIO_CFG:
+ {
+ struct audio_cfg audio_cfg;
+
+ if (copy_from_user(&audio_cfg, (void *)arg,
+ sizeof(struct audio_cfg)))
+ return -EINVAL;
+
+ audiocfg(hdev, &audio_cfg);
+ }
+ break;
+
+ case IOC_PLUG_STATUS:
+ status = av8100_status_get();
+ value = status.av8100_plugin_status == AV8100_HDMI_PLUGIN;
+
+ if (copy_to_user((void *)arg, (void *)&value,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_POWERONOFF:
+ /* Get desired power state on or off */
+ if (copy_from_user(&value, (void *)arg, sizeof(u8)))
+ return -EINVAL;
+
+ if (value == 0) {
+ if (av8100_powerdown() != 0) {
+ dev_err(hdev->dev, "av8100_powerdown FAIL\n");
+ return -EINVAL;
+ }
+ } else {
+ if (av8100_powerup() != 0) {
+ dev_err(hdev->dev, "av8100_powerup FAIL\n");
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_EVENT_WAKEUP:
+ /* Trigger event */
+ event_wakeup(hdev);
+ break;
+
+ case IOC_POWERSTATE:
+ status = av8100_status_get();
+ value = status.av8100_state >= AV8100_OPMODE_SCAN;
+
+ if (copy_to_user((void *)arg, (void *)&value,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+ break;
+
+ /* Internal */
+ case IOC_HDMI_ENABLE_INTERRUPTS:
+ av8100_disable_interrupt();
+ if (av8100_enable_interrupt() != 0) {
+ dev_err(hdev->dev, "av8100_ei FAIL\n");
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDMI_DOWNLOAD_FW:
+ if (av8100_download_firmware(I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100 dl fw FAIL\n");
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDMI_ONOFF:
+ {
+ union av8100_configuration config;
+
+ /* Get desired HDMI mode on or off */
+ if (copy_from_user(&value, (void *)arg, sizeof(u8)))
+ return -EFAULT;
+
+ if (av8100_conf_get(AV8100_COMMAND_HDMI, &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_get FAIL\n");
+ return -EINVAL;
+ }
+ if (value == 0)
+ config.hdmi_format.hdmi_mode = AV8100_HDMI_OFF;
+ else
+ config.hdmi_format.hdmi_mode = AV8100_HDMI_ON;
+
+ if (av8100_conf_prep(AV8100_COMMAND_HDMI, &config) != 0) {
+ dev_err(hdev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+ if (av8100_conf_w(AV8100_COMMAND_HDMI, NULL, NULL,
+ I2C_INTERFACE) != 0) {
+ dev_err(hdev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case IOC_HDMI_REGISTER_WRITE:
+ if (copy_from_user(&reg, (void *)arg,
+ sizeof(struct hdmi_register))) {
+ return -EINVAL;
+ }
+
+ if (av8100_reg_w(reg.offset, reg.value) != 0) {
+ dev_err(hdev->dev, "hdmi_register_write FAIL\n");
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDMI_REGISTER_READ:
+ if (copy_from_user(&reg, (void *)arg,
+ sizeof(struct hdmi_register))) {
+ return -EINVAL;
+ }
+
+ if (av8100_reg_r(reg.offset, &reg.value) != 0) {
+ dev_err(hdev->dev, "hdmi_register_write FAIL\n");
+ return -EINVAL;
+ }
+
+ if (copy_to_user((void *)arg, (void *)&reg,
+ sizeof(struct hdmi_register))) {
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDMI_STATUS_GET:
+ status = av8100_status_get();
+
+ if (copy_to_user((void *)arg, (void *)&status,
+ sizeof(struct av8100_status))) {
+ return -EINVAL;
+ }
+ break;
+
+ case IOC_HDMI_CONFIGURATION_WRITE:
+ {
+ struct hdmi_command_register command_reg;
+
+ if (copy_from_user(&command_reg, (void *)arg,
+ sizeof(struct hdmi_command_register)) != 0) {
+ dev_err(hdev->dev, "IOC_HDMI_CONFIGURATION_WRITE "
+ "fail 1\n");
+ command_reg.return_status = EINVAL;
+ } else {
+ command_reg.return_status = 0;
+ if (av8100_conf_w_raw(command_reg.cmd_id,
+ command_reg.buf_len,
+ command_reg.buf,
+ &(command_reg.buf_len),
+ command_reg.buf) != 0) {
+ dev_err(hdev->dev,
+ "IOC_HDMI_CONFIGURATION_WRITE "
+ "fail 2\n");
+ command_reg.return_status = EINVAL;
+ }
+ }
+
+ if (copy_to_user((void *)arg, (void *)&command_reg,
+ sizeof(struct hdmi_command_register)) != 0) {
+ return -EINVAL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static unsigned int
+hdmi_poll(struct file *filp, poll_table *wait)
+{
+ unsigned int mask = 0;
+ struct hdmi_device *hdev;
+
+ hdev = devnr_to_hdev(HDMI_DEVNR_DEFAULT);
+ if (!hdev)
+ return 0;
+
+ dev_dbg(hdev->dev, "%s\n", __func__);
+
+ poll_wait(filp, &hdev->event_wq , wait);
+
+ LOCK_HDMI_EVENTS;
+ if (hdev->events_received == true) {
+ hdev->events_received = false;
+ mask = POLLIN | POLLRDNORM;
+ }
+ UNLOCK_HDMI_EVENTS;
+
+ return mask;
+}
+
+static const struct file_operations hdmi_fops = {
+ .owner = THIS_MODULE,
+ .open = hdmi_open,
+ .release = hdmi_release,
+ .unlocked_ioctl = hdmi_ioctl,
+ .poll = hdmi_poll
+};
+
+/* Event callback function called by hw driver */
+void hdmi_event(enum av8100_hdmi_event ev)
+{
+ int events_old;
+ int events_new;
+ struct hdmi_device *hdev;
+ struct kobject *kobj;
+
+ hdev = devnr_to_hdev(HDMI_DEVNR_DEFAULT);
+ if (!hdev)
+ return;
+
+ dev_dbg(hdev->dev, "hdmi_event %02x\n", ev);
+
+ kobj = &(hdev->dev->kobj);
+
+ LOCK_HDMI_EVENTS;
+
+ events_old = hdev->events;
+
+ /* Set event */
+ switch (ev) {
+ case AV8100_HDMI_EVENT_HDMI_PLUGIN:
+ hdev->events &= ~HDMI_EVENT_HDMI_PLUGOUT;
+ hdev->events |= HDMI_EVENT_HDMI_PLUGIN;
+ break;
+
+ case AV8100_HDMI_EVENT_HDMI_PLUGOUT:
+ hdev->events &= ~HDMI_EVENT_HDMI_PLUGIN;
+ hdev->events |= HDMI_EVENT_HDMI_PLUGOUT;
+ cec_tx_status(hdev, CEC_TX_SET_FREE);
+ break;
+
+ case AV8100_HDMI_EVENT_CEC:
+ hdev->events |= HDMI_EVENT_CEC;
+ break;
+
+ case AV8100_HDMI_EVENT_HDCP:
+ hdev->events |= HDMI_EVENT_HDCP;
+ break;
+
+ case AV8100_HDMI_EVENT_CECTXERR:
+ hdev->events |= HDMI_EVENT_CECTXERR;
+ cec_tx_status(hdev, CEC_TX_SET_FREE);
+ break;
+
+ case AV8100_HDMI_EVENT_CECTX:
+ hdev->events |= HDMI_EVENT_CECTX;
+ cec_tx_status(hdev, CEC_TX_SET_FREE);
+ break;
+
+ default:
+ break;
+ }
+
+ events_new = hdev->events_mask & hdev->events;
+
+ UNLOCK_HDMI_EVENTS;
+
+ dev_dbg(hdev->dev, "hdmi events:%02x, events_old:%02x mask:%02x\n",
+ events_new, events_old, hdev->events_mask);
+
+ if (events_new != events_old) {
+ /* Wake up application waiting for event via call to poll() */
+ sysfs_notify(kobj, NULL, SYSFS_EVENT_FILENAME);
+
+ LOCK_HDMI_EVENTS;
+ hdev->events_received = true;
+ UNLOCK_HDMI_EVENTS;
+
+ wake_up_interruptible(&hdev->event_wq);
+ }
+}
+EXPORT_SYMBOL(hdmi_event);
+
+int hdmi_device_register(struct hdmi_device *hdev)
+{
+ hdev->miscdev.minor = MISC_DYNAMIC_MINOR;
+ hdev->miscdev.name = "hdmi";
+ hdev->miscdev.fops = &hdmi_fops;
+
+ if (misc_register(&hdev->miscdev)) {
+ pr_err("hdmi misc_register failed\n");
+ return -EFAULT;
+ }
+
+ hdev->dev = hdev->miscdev.this_device;
+
+ return 0;
+}
+
+int __init hdmi_init(void)
+{
+ struct hdmi_device *hdev;
+ int i;
+ int ret;
+
+ /* Allocate device data */
+ hdev = kzalloc(sizeof(struct hdmi_device), GFP_KERNEL);
+ if (!hdev) {
+ pr_err("%s: Alloc failure\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Add to list */
+ list_add_tail(&hdev->list, &hdmi_device_list);
+
+ if (hdmi_device_register(hdev)) {
+ pr_err("%s: Alloc failure\n", __func__);
+ return -EFAULT;
+ }
+
+ hdev->devnr = HDMI_DEVNR_DEFAULT;
+
+ /* Default sysfs file format is hextext */
+ hdev->sysfs_data.store_as_hextext = true;
+
+ init_waitqueue_head(&hdev->event_wq);
+
+ /* Create sysfs attrs */
+ for (i = 0; attr_name(hdmi_sysfs_attrs[i]); i++) {
+ ret = device_create_file(hdev->dev, &hdmi_sysfs_attrs[i]);
+ if (ret)
+ dev_err(hdev->dev,
+ "Unable to create sysfs attr %s (%d)\n",
+ hdmi_sysfs_attrs[i].attr.name, ret);
+ }
+
+ /* Register event callback */
+ av8100_hdmi_event_cb_set(hdmi_event);
+
+ return 0;
+}
+late_initcall(hdmi_init);
+
+void hdmi_exit(void)
+{
+ struct hdmi_device *hdev = NULL;
+ int i;
+
+ if (list_empty(&hdmi_device_list))
+ return;
+ else
+ hdev = list_entry(hdmi_device_list.next,
+ struct hdmi_device, list);
+
+ /* Deregister event callback */
+ av8100_hdmi_event_cb_set(NULL);
+
+ /* Remove sysfs attrs */
+ for (i = 0; attr_name(hdmi_sysfs_attrs[i]); i++)
+ device_remove_file(hdev->dev, &hdmi_sysfs_attrs[i]);
+
+ misc_deregister(&hdev->miscdev);
+
+ /* Remove from list */
+ list_del(&hdev->list);
+
+ /* Free device data */
+ kfree(hdev);
+}
diff --git a/drivers/video/av8100/hdmi_loc.h b/drivers/video/av8100/hdmi_loc.h
new file mode 100644
index 00000000000..20314910db9
--- /dev/null
+++ b/drivers/video/av8100/hdmi_loc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __HDMI_LOC__H__
+#define __HDMI_LOC__H__
+
+#define EDID_BUF_LEN 128
+#define COMMAND_BUF_LEN 128
+#define AES_KEY_SIZE 16
+#define CRC32_SIZE 4
+#define AUTH_BUF_LEN 126
+#define CECTX_TRY 20
+#define CECTX_WAITTIME 25
+
+struct edid_data {
+ u8 buf_len;
+ u8 buf[EDID_BUF_LEN];
+};
+
+struct authencr {
+ int result;
+ u8 buf_len;
+ u8 buf[AUTH_BUF_LEN];
+};
+
+struct hdmi_register {
+ unsigned char value;
+ unsigned char offset;
+};
+
+struct hdcp_loadaesone {
+ u8 key[AES_KEY_SIZE];
+ u8 result;
+ u8 crc32[CRC32_SIZE];
+};
+
+struct hdmi_sysfs_data {
+ bool store_as_hextext;
+ struct plug_detect plug_detect;
+ bool enable_cec_event;
+ struct edid_data edid_data;
+ struct cec_rw cec_read;
+ bool fuse_result;
+ int loadaes_result;
+ struct authencr authencr;
+};
+
+struct hdmi_command_register {
+ unsigned char cmd_id; /* input */
+ unsigned char buf_len; /* input, output */
+ unsigned char buf[COMMAND_BUF_LEN]; /* input, output */
+ unsigned char return_status; /* output */
+};
+
+enum cec_tx_status_action {
+ CEC_TX_SET_FREE,
+ CEC_TX_SET_BUSY,
+ CEC_TX_CHECK
+};
+
+/* Internal */
+#define IOC_HDMI_ENABLE_INTERRUPTS _IOWR(HDMI_IOC_MAGIC, 32, int)
+#define IOC_HDMI_DOWNLOAD_FW _IOWR(HDMI_IOC_MAGIC, 33, int)
+#define IOC_HDMI_ONOFF _IOWR(HDMI_IOC_MAGIC, 34, int)
+#define IOC_HDMI_REGISTER_WRITE _IOWR(HDMI_IOC_MAGIC, 35, int)
+#define IOC_HDMI_REGISTER_READ _IOWR(HDMI_IOC_MAGIC, 36, int)
+#define IOC_HDMI_STATUS_GET _IOWR(HDMI_IOC_MAGIC, 37, int)
+#define IOC_HDMI_CONFIGURATION_WRITE _IOWR(HDMI_IOC_MAGIC, 38, int)
+
+#endif /* __HDMI_LOC__H__ */
diff --git a/drivers/video/b2r2/Kconfig b/drivers/video/b2r2/Kconfig
new file mode 100644
index 00000000000..8cc81876de7
--- /dev/null
+++ b/drivers/video/b2r2/Kconfig
@@ -0,0 +1,134 @@
+config FB_B2R2
+ tristate "B2R2 engine support"
+ default n
+ help
+ B2R2 engine does various bit-blitting operations,post-processor operations
+ and various compositions.
+
+config B2R2_PLUG_CONF
+ bool "B2R2 bus plug configuration"
+ depends on FB_B2R2
+ default n
+ help
+ Configures how B2R2 access the memory bus. Enabling this will increase
+ the performance of B2R2 at the cost of using the bus more heavily.
+
+ If this is set to 'n', the hardware defaults will be used.
+
+choice
+ prompt "Opcode size"
+ depends on B2R2_PLUG_CONF
+ default B2R2_OPSIZE_64
+
+ config B2R2_OPSIZE_8
+ bool "8 bytes"
+ config B2R2_OPSIZE_16
+ bool "16 bytes"
+ config B2R2_OPSIZE_32
+ bool "32 bytes"
+ config B2R2_OPSIZE_64
+ bool "64 bytes"
+
+endchoice
+
+choice
+ prompt "Chunk size"
+ depends on B2R2_PLUG_CONF
+ default B2R2_CHSIZE_128
+
+ config B2R2_CHSIZE_1
+ bool "1 op"
+ config B2R2_CHSIZE_2
+ bool "2 ops"
+ config B2R2_CHSIZE_4
+ bool "4 ops"
+ config B2R2_CHSIZE_8
+ bool "8 ops"
+ config B2R2_CHSIZE_16
+ bool "16 ops"
+ config B2R2_CHSIZE_32
+ bool "32 ops"
+ config B2R2_CHSIZE_64
+ bool "64 ops"
+ config B2R2_CHSIZE_128
+ bool "128 ops"
+endchoice
+
+choice
+ prompt "Message size"
+ depends on B2R2_PLUG_CONF
+ default B2R2_MGSIZE_128
+
+ config B2R2_MGSIZE_1
+ bool "1 chunk"
+ config B2R2_MGSIZE_2
+ bool "2 chunks"
+ config B2R2_MGSIZE_4
+ bool "4 chunks"
+ config B2R2_MGSIZE_8
+ bool "8 s"
+ config B2R2_MGSIZE_16
+ bool "16 chunks"
+ config B2R2_MGSIZE_32
+ bool "32 chunks"
+ config B2R2_MGSIZE_64
+ bool "64 chunks"
+ config B2R2_MGSIZE_128
+ bool "128 chunks"
+endchoice
+
+choice
+ prompt "Page size"
+ depends on B2R2_PLUG_CONF
+ default B2R2_PGSIZE_256
+
+ config B2R2_PGSIZE_64
+ bool "64 bytes"
+ config B2R2_PGSIZE_128
+ bool "128 bytes"
+ config B2R2_PGSIZE_256
+ bool "256 bytes"
+endchoice
+
+config B2R2_DEBUG
+ bool "B2R2 debugging"
+ default n
+ depends on FB_B2R2
+ help
+ Enable debugging features for the B2R2 driver.
+
+config B2R2_PROFILER
+ tristate "B2R2 profiler"
+ default n
+ depends on FB_B2R2
+ help
+ Enables the profiler for the B2R2 driver.
+
+ It is recommended to build this as a module, since the configuration
+ of filters etc. is done at load time.
+
+config B2R2_GENERIC
+ bool "B2R2 generic path"
+ default y
+ depends on FB_B2R2
+ help
+ Enables support for the generic path in the B2R2 driver. This path should
+ be used when there is no optimized implementation for a request.
+
+choice
+ prompt "Generic usage mode"
+ depends on B2R2_GENERIC
+ default B2R2_GENERIC_FALLBACK
+
+ config B2R2_GENERIC_FALLBACK
+ bool "Fallback"
+ help
+ The optimized path will be used for all supported operations, and the
+ generic path will be used as a fallback for the ones not implemented.
+
+ config B2R2_GENERIC_ONLY
+ bool "Always"
+ help
+ The generic path will be used for all operations.
+
+endchoice
diff --git a/drivers/video/b2r2/Makefile b/drivers/video/b2r2/Makefile
new file mode 100644
index 00000000000..f271f4e7ea1
--- /dev/null
+++ b/drivers/video/b2r2/Makefile
@@ -0,0 +1,15 @@
+# Make file for compiling and loadable module B2R2
+
+obj-$(CONFIG_FB_B2R2) += b2r2.o
+
+b2r2-objs = b2r2_api.o b2r2_blt_main.o b2r2_core.o b2r2_mem_alloc.o b2r2_generic.o b2r2_node_gen.o b2r2_node_split.o b2r2_profiler_socket.o b2r2_timing.o b2r2_filters.o b2r2_utils.o b2r2_input_validation.o b2r2_hw_convert.o
+
+ifdef CONFIG_B2R2_DEBUG
+b2r2-objs += b2r2_debug.o
+endif
+
+ifeq ($(CONFIG_FB_B2R2),m)
+obj-y += b2r2_kernel_if.o
+endif
+
+obj-$(CONFIG_B2R2_PROFILER) += b2r2_profiler/
diff --git a/drivers/video/b2r2/b2r2_api.c b/drivers/video/b2r2/b2r2_api.c
new file mode 100644
index 00000000000..0361e85ebf3
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_api.c
@@ -0,0 +1,1643 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010/2012
+ *
+ * ST-Ericsson B2R2 Blitter module API
+ *
+ * Author: Jorgen Nilsson <jorgen.nilsson@stericsson.com>
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+#include <asm/cacheflush.h>
+#include <linux/smp.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/hwmem.h>
+#include <linux/kref.h>
+
+#include "b2r2_internal.h"
+#include "b2r2_control.h"
+#include "b2r2_core.h"
+#include "b2r2_timing.h"
+#include "b2r2_utils.h"
+#include "b2r2_debug.h"
+#include "b2r2_input_validation.h"
+#include "b2r2_profiler_socket.h"
+#include "b2r2_hw.h"
+
+/*
+ * TODO:
+ * Implementation of query cap
+ * Support for user space virtual pointer to physically consecutive memory
+ * Support for user space virtual pointer to physically scattered memory
+ * Callback reads lagging behind in blt_api_stress app
+ * Store smaller items in the report list instead of the whole request
+ * Support read of many report records at once.
+ */
+
+#define DATAS_START_SIZE 10
+#define DATAS_GROW_SIZE 5
+
+/**
+ * @miscdev: The miscdev presenting b2r2 to the system
+ */
+struct b2r2_blt {
+ spinlock_t lock;
+ int next_job_id;
+ struct miscdevice miscdev;
+ struct device *dev;
+ struct mutex datas_lock;
+ /**
+ * datas - Stores the b2r2_blt_data mapped to the cliend handle
+ */
+ struct b2r2_blt_data **datas;
+ /**
+ * data_count - The current maximum of active datas
+ */
+ int data_count;
+};
+
+struct b2r2_blt_data {
+ struct b2r2_control_instance *ctl_instace[B2R2_MAX_NBR_DEVICES];
+};
+
+/**
+ * Used to keep track of coming and going b2r2 cores and
+ * the number of active instance references
+ */
+struct b2r2_control_ref {
+ struct b2r2_control *b2r2_control;
+ spinlock_t lock;
+};
+
+/**
+ * b2r2_blt - The blitter device, /dev/b2r2_blt
+ */
+struct kref blt_refcount;
+static struct b2r2_blt *b2r2_blt;
+
+/**
+ * b2r2_control - The core controls and synchronization mechanism
+ */
+static struct b2r2_control_ref b2r2_controls[B2R2_MAX_NBR_DEVICES];
+
+/**
+ * b2r2_blt_add_control - Add the b2r2 core control
+ */
+void b2r2_blt_add_control(struct b2r2_control *cont)
+{
+ unsigned long flags;
+ BUG_ON(cont->id < 0 || cont->id >= B2R2_MAX_NBR_DEVICES);
+
+ spin_lock_irqsave(&b2r2_controls[cont->id].lock, flags);
+ if (b2r2_controls[cont->id].b2r2_control == NULL)
+ b2r2_controls[cont->id].b2r2_control = cont;
+ spin_unlock_irqrestore(&b2r2_controls[cont->id].lock, flags);
+}
+
+/**
+ * b2r2_blt_remove_control - Remove the b2r2 core control
+ */
+void b2r2_blt_remove_control(struct b2r2_control *cont)
+{
+ unsigned long flags;
+ BUG_ON(cont->id < 0 || cont->id >= B2R2_MAX_NBR_DEVICES);
+
+ spin_lock_irqsave(&b2r2_controls[cont->id].lock, flags);
+ b2r2_controls[cont->id].b2r2_control = NULL;
+ spin_unlock_irqrestore(&b2r2_controls[cont->id].lock, flags);
+}
+
+/**
+ * b2r2_blt_get_control - Lock control for writing/removal
+ */
+static struct b2r2_control *b2r2_blt_get_control(int i)
+{
+ struct b2r2_control *cont;
+ unsigned long flags;
+ BUG_ON(i < 0 || i >= B2R2_MAX_NBR_DEVICES);
+
+ spin_lock_irqsave(&b2r2_controls[i].lock, flags);
+ cont = (struct b2r2_control *) b2r2_controls[i].b2r2_control;
+ if (cont != NULL) {
+ if (!cont->enabled)
+ cont = NULL;
+ else
+ kref_get(&cont->ref);
+ }
+ spin_unlock_irqrestore(&b2r2_controls[i].lock, flags);
+
+ return cont;
+}
+
+/**
+ * b2r2_blt_release_control - Unlock control for writing/removal
+ */
+static void b2r2_blt_release_control(int i)
+{
+ struct b2r2_control *cont;
+ unsigned long flags;
+ BUG_ON(i < 0 || i >= B2R2_MAX_NBR_DEVICES);
+
+ spin_lock_irqsave(&b2r2_controls[i].lock, flags);
+ cont = (struct b2r2_control *) b2r2_controls[i].b2r2_control;
+ spin_unlock_irqrestore(&b2r2_controls[i].lock, flags);
+ if (cont != NULL)
+ kref_put(&cont->ref, b2r2_core_release);
+}
+
+/**
+ * Increase size of array containing b2r2 handles
+ */
+static int grow_datas(void)
+{
+ struct b2r2_blt_data **new_datas = NULL;
+ int new_data_count = b2r2_blt->data_count + DATAS_GROW_SIZE;
+ int ret = 0;
+
+ new_datas = kzalloc(new_data_count * sizeof(*new_datas), GFP_KERNEL);
+ if (new_datas == NULL) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ memcpy(new_datas, b2r2_blt->datas,
+ b2r2_blt->data_count * sizeof(*b2r2_blt->datas));
+
+ kfree(b2r2_blt->datas);
+
+ b2r2_blt->data_count = new_data_count;
+ b2r2_blt->datas = new_datas;
+exit:
+ return ret;
+}
+
+/**
+ * Allocate and/or reserve a b2r2 handle
+ */
+static int alloc_handle(struct b2r2_blt_data *blt_data)
+{
+ int handle;
+ int ret;
+
+ mutex_lock(&b2r2_blt->datas_lock);
+
+ if (b2r2_blt->datas == NULL) {
+ b2r2_blt->datas = kzalloc(
+ DATAS_START_SIZE * sizeof(*b2r2_blt->datas),
+ GFP_KERNEL);
+ if (b2r2_blt->datas == NULL) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+ b2r2_blt->data_count = DATAS_START_SIZE;
+ }
+
+ for (handle = 0; handle < b2r2_blt->data_count; handle++) {
+ if (b2r2_blt->datas[handle] == NULL) {
+ b2r2_blt->datas[handle] = blt_data;
+ break;
+ }
+
+ if (handle == b2r2_blt->data_count - 1) {
+ ret = grow_datas();
+ if (ret < 0)
+ goto exit;
+ }
+ }
+ ret = handle;
+exit:
+ mutex_unlock(&b2r2_blt->datas_lock);
+
+ return ret;
+}
+
+/**
+ * Get b2r2 data from b2r2 handle
+ */
+static struct b2r2_blt_data *get_data(int handle)
+{
+ if (handle >= b2r2_blt->data_count || handle < 0)
+ return NULL;
+ else
+ return b2r2_blt->datas[handle];
+}
+
+/**
+ * Unreserve b2r2 handle
+ */
+static void free_handle(int handle)
+{
+ if (handle < b2r2_blt->data_count && handle >= 0)
+ b2r2_blt->datas[handle] = NULL;
+}
+
+/**
+ * Get the next job number. This is the one returned to the client
+ * if the blit request was successful.
+ */
+static int get_next_job_id(void)
+{
+ int job_id;
+ unsigned long flags;
+
+ spin_lock_irqsave(&b2r2_blt->lock, flags);
+ if (b2r2_blt->next_job_id < 1)
+ b2r2_blt->next_job_id = 1;
+ job_id = b2r2_blt->next_job_id++;
+ spin_unlock_irqrestore(&b2r2_blt->lock, flags);
+
+ return job_id;
+}
+
+/**
+ * Limit the number of cores used in some "easy" and impossible cases
+ */
+static int limit_blits(int n_split, struct b2r2_blt_req *user_req)
+{
+ if (n_split <= 1)
+ return n_split;
+
+ if (user_req->dst_rect.width < 24 && user_req->dst_rect.height < 24)
+ return 1;
+
+ if (user_req->src_rect.width < n_split &&
+ user_req->src_rect.height < n_split)
+ return 1;
+
+ return n_split;
+}
+
+/**
+ * Check if the format inherently requires the b2r2 scaling engine to be active
+ */
+static bool is_scaling_fmt(enum b2r2_blt_fmt fmt)
+{
+ /* Plane separated formats must be treated as scaling */
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Check for macroblock formats
+ */
+static bool is_mb_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Split a request rectangle on available cores
+ */
+static int b2r2_blt_split_request(struct b2r2_blt_data *blt_data,
+ struct b2r2_blt_req *user_req,
+ struct b2r2_blt_request **split_requests,
+ struct b2r2_control_instance **ctl,
+ int *n_split)
+{
+ int sstep_x, sstep_y, dstep_x, dstep_y;
+ int dstart_x, dstart_y;
+ int bstart_x, bstart_y;
+ int dpos_x, dpos_y;
+ int bpos_x, bpos_y;
+ int dso_x = 1;
+ int dso_y = 1;
+ int sf_x, sf_y;
+ int i;
+ int srw, srh;
+ int drw, drh;
+ bool ssplit_x = true;
+ bool dsplit_x = true;
+ enum b2r2_blt_transform transform;
+ bool is_rotation = false;
+ bool is_scaling = false;
+ bool bg_blend = false;
+ u32 core_mask = 0;
+
+ srw = user_req->src_rect.width;
+ srh = user_req->src_rect.height;
+ drw = user_req->dst_rect.width;
+ drh = user_req->dst_rect.height;
+ transform = user_req->transform;
+
+ /* Early exit in the basic cases */
+ if (*n_split == 0) {
+ return -ENOSYS;
+ } else if (*n_split == 1 ||
+ (srw < *n_split && srh < *n_split) ||
+ (drw < *n_split && drh < *n_split) ||
+ is_mb_fmt(user_req->src_img.fmt)) {
+ /* Handle macroblock formats with one
+ * core for now since there seems to be some bug
+ * related to macroblock access patterns
+ */
+ memcpy(&split_requests[0]->user_req,
+ user_req,
+ sizeof(*user_req));
+ split_requests[0]->core_mask = 1;
+ *n_split = 1;
+ return 0;
+ }
+
+ /*
+ * TODO: fix the load balancing algorithm
+ */
+
+ is_rotation = (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) != 0;
+
+ /* Check for scaling */
+ if (is_rotation) {
+ is_scaling = (user_req->src_rect.width !=
+ user_req->dst_rect.height) ||
+ (user_req->src_rect.height !=
+ user_req->dst_rect.width);
+ } else {
+ is_scaling = (user_req->src_rect.width !=
+ user_req->dst_rect.width) ||
+ (user_req->src_rect.height !=
+ user_req->dst_rect.height);
+ }
+
+ is_scaling = is_scaling ||
+ is_scaling_fmt(user_req->src_img.fmt) ||
+ is_scaling_fmt(user_req->dst_img.fmt);
+
+ bg_blend = ((user_req->flags & B2R2_BLT_FLAG_BG_BLEND) != 0);
+
+ /*
+ * Split the request
+ */
+
+ b2r2_log_info(b2r2_blt->dev, "%s: In (t:0x%08X, f:0x%08X):\n"
+ "\tsrc_rect x:%d, y:%d, w:%d, h:%d src fmt:0x%x\n"
+ "\tdst_rect x:%d, y:%d, w:%d, h:%d dst fmt:0x%x\n",
+ __func__,
+ user_req->transform,
+ user_req->flags,
+ user_req->src_rect.x,
+ user_req->src_rect.y,
+ user_req->src_rect.width,
+ user_req->src_rect.height,
+ user_req->src_img.fmt,
+ user_req->dst_rect.x,
+ user_req->dst_rect.y,
+ user_req->dst_rect.width,
+ user_req->dst_rect.height,
+ user_req->dst_img.fmt);
+
+ /* TODO: We need sub pixel precision here,
+ * or a better way to split rects */
+ dstart_x = user_req->dst_rect.x;
+ dstart_y = user_req->dst_rect.y;
+ if (bg_blend) {
+ bstart_x = user_req->bg_rect.x;
+ bstart_y = user_req->bg_rect.y;
+ }
+
+ if (srw && srh) {
+ if ((srw < srh) && !is_scaling) {
+ ssplit_x = false;
+ sstep_y = srh / *n_split;
+ /* Round up */
+ if (srh % (*n_split))
+ sstep_y++;
+
+ if (srh > 16)
+ sstep_y = ((sstep_y + 16) >> 4) << 4;
+
+ if (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ sf_y = (drw << 10) / srh;
+ dstep_x = (sf_y * sstep_y) >> 10;
+ } else {
+ dsplit_x = false;
+ sf_y = (drh << 10) / srh;
+ dstep_y = (sf_y * sstep_y) >> 10;
+ }
+ } else {
+ sstep_x = srw / *n_split;
+ /* Round up */
+ if (srw % (*n_split))
+ sstep_x++;
+
+ if (is_scaling) {
+ int scale_step_size =
+ B2R2_RESCALE_MAX_WIDTH - 1;
+ int pad = (scale_step_size -
+ (sstep_x % scale_step_size));
+ if ((sstep_x + pad) < srw)
+ sstep_x += pad;
+ } else {
+ /* Aim for even 16px multiples */
+ if ((sstep_x & 0xF) && ((sstep_x + 16) < srw))
+ sstep_x = ((sstep_x + 16) >> 4) << 4;
+ }
+
+ if (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ dsplit_x = false;
+ sf_x = (drh << 10) / srw;
+ dstep_y = (sf_x * sstep_x) >> 10;
+ } else {
+ sf_x = (drw << 10) / srw;
+ dstep_x = (sf_x * sstep_x) >> 10;
+ }
+ }
+
+ } else {
+ sstep_x = sstep_y = 0;
+
+ if (drw < drh) {
+ dsplit_x = false;
+ dstep_y = drh / *n_split;
+ /* Round up */
+ if (drh % *n_split)
+ dstep_y++;
+
+ /* Aim for even 16px multiples */
+ if ((dstep_y & 0xF) && ((dstep_y + 16) < drh))
+ dstep_y = ((dstep_y + 16) >> 4) << 4;
+ } else {
+ dstep_x = drw / *n_split;
+ /* Round up */
+ if (drw % *n_split)
+ dstep_x++;
+
+ /* Aim for even 16px multiples */
+ if ((dstep_x & 0xF) && ((dstep_x + 16) < drw))
+ dstep_x = ((dstep_x + 16) >> 4) << 4;
+ }
+ }
+
+ /* Check for flip and rotate to establish destination
+ * step order */
+ if (transform & B2R2_BLT_TRANSFORM_FLIP_H) {
+ dstart_x += drw;
+ if (bg_blend)
+ bstart_x += drw;
+ dso_x = -1;
+ }
+ if ((transform & B2R2_BLT_TRANSFORM_FLIP_V) ||
+ (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90)) {
+ dstart_y += drh;
+ if (bg_blend)
+ bstart_y += drh;
+ dso_y = -1;
+ }
+
+ /* Set scan starting position */
+ dpos_x = dstart_x;
+ dpos_y = dstart_y;
+ if (bg_blend) {
+ bpos_x = bstart_x;
+ bpos_y = bstart_y;
+ }
+
+ for (i = 0; i < *n_split; i++) {
+ struct b2r2_blt_req *sreq =
+ &split_requests[i]->user_req;
+
+ /* First mimic all */
+ memcpy(sreq, user_req, sizeof(*user_req));
+
+ /* Then change the rects */
+ if (srw && srh) {
+ if (ssplit_x) {
+ if (sstep_x > 0) {
+ sreq->src_rect.width =
+ min(sstep_x, srw);
+ sreq->src_rect.x += i*sstep_x;
+ srw -= sstep_x;
+ } else {
+ sreq->src_rect.width = srw;
+ }
+ } else {
+ if (sstep_y > 0) {
+ sreq->src_rect.y += i*sstep_y;
+ sreq->src_rect.height =
+ min(sstep_y, srh);
+ srh -= sstep_y;
+ } else {
+ sreq->src_rect.height = srh;
+ }
+ }
+ }
+
+ if (dsplit_x) {
+ int sx = min(dstep_x, drw);
+ if (dso_x < 0) {
+ dpos_x += dso_x * sx;
+ if (bg_blend)
+ bpos_x += dso_x * sx;
+ }
+ sreq->dst_rect.width = sx;
+ sreq->dst_rect.x = dpos_x;
+ if (bg_blend) {
+ sreq->bg_rect.width = sx;
+ sreq->bg_rect.x = bpos_x;
+ }
+ if (dso_x > 0) {
+ dpos_x += dso_x * sx;
+ if (bg_blend)
+ bpos_x += dso_x * sx;
+ }
+ drw -= sx;
+ } else {
+ int sy = min(dstep_y, drh);
+ if (dso_y < 0) {
+ dpos_y += dso_y * sy;
+ if (bg_blend)
+ bpos_y += dso_y * sy;
+ }
+ sreq->dst_rect.height = sy;
+ sreq->dst_rect.y = dpos_y;
+ if (bg_blend) {
+ sreq->bg_rect.height = sy;
+ sreq->bg_rect.y = bpos_y;
+ }
+ if (dso_y > 0) {
+ dpos_y += dso_y * sy;
+ if (bg_blend)
+ bpos_y += dso_y * sy;
+ }
+ drh -= sy;
+ }
+
+ b2r2_log_info(b2r2_blt->dev, "%s: Out:\n"
+ "\tsrc_rect x:%d, y:%d, w:%d, h:%d\n"
+ "\tdst_rect x:%d, y:%d, w:%d, h:%d\n"
+ "\tbg_rect x:%d, y:%d, w:%d, h:%d\n",
+ __func__,
+ sreq->src_rect.x,
+ sreq->src_rect.y,
+ sreq->src_rect.width,
+ sreq->src_rect.height,
+ sreq->dst_rect.x,
+ sreq->dst_rect.y,
+ sreq->dst_rect.width,
+ sreq->dst_rect.height,
+ sreq->bg_rect.x,
+ sreq->bg_rect.y,
+ sreq->bg_rect.width,
+ sreq->bg_rect.height);
+
+ core_mask |= (1 << i);
+ }
+
+ for (i = 0; i < *n_split; i++)
+ split_requests[i]->core_mask = core_mask;
+
+ return 0;
+}
+
+/**
+ * Get available b2r2 control instances. It will be limited
+ * to the number of cores available at the current point in time.
+ * It will also cause the cores to stay active during the time until
+ * release_control_instances is called.
+ */
+static void get_control_instances(struct b2r2_blt_data *blt_data,
+ struct b2r2_control_instance **ctl, int max_size,
+ int *count)
+{
+ int i;
+
+ *count = 0;
+ for (i = 0; i < max_size; i++) {
+ struct b2r2_control_instance *ci = blt_data->ctl_instace[i];
+ if (ci) {
+ struct b2r2_control *cont =
+ b2r2_blt_get_control(ci->control_id);
+ if (cont) {
+ ctl[*count] = ci;
+ *count += 1;
+ }
+ }
+ }
+}
+
+/**
+ * Release b2r2 control instances. The cores allocated for the request
+ * are given back.
+ */
+static void release_control_instances(struct b2r2_control_instance **ctl,
+ int count)
+{
+ int i;
+
+ /* Release the handles to the core controls */
+ for (i = 0; i < count; i++) {
+ if (ctl[i])
+ b2r2_blt_release_control(ctl[i]->control_id);
+ }
+}
+
+/**
+ * Free b2r2 request
+ */
+static void b2r2_free_request(struct b2r2_blt_request *request)
+{
+ if (request) {
+ /* Free requests in split_requests */
+ if (request->clut)
+ dma_free_coherent(b2r2_blt->dev,
+ CLUT_SIZE,
+ request->clut,
+ request->clut_phys_addr);
+ request->clut = NULL;
+ request->clut_phys_addr = 0;
+ kfree(request);
+ }
+}
+
+/**
+ * Allocate internal b2r2 request based on user input.
+ */
+static int b2r2_alloc_request(struct b2r2_blt_req *user_req,
+ bool us_req, struct b2r2_blt_request **request_out)
+{
+ int ret = 0;
+ struct b2r2_blt_request *request =
+ kzalloc(sizeof(*request), GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ /* Initialize the structure */
+ INIT_LIST_HEAD(&request->list);
+
+ /*
+ * If the user specified a color look-up table,
+ * make a copy that the HW can use.
+ */
+ if ((user_req->flags &
+ B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) != 0) {
+ request->clut = dma_alloc_coherent(
+ b2r2_blt->dev,
+ CLUT_SIZE,
+ &(request->clut_phys_addr),
+ GFP_DMA | GFP_KERNEL);
+ if (request->clut == NULL) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s CLUT allocation "
+ "failed.\n", __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ if (us_req) {
+ if (copy_from_user(request->clut,
+ user_req->clut, CLUT_SIZE)) {
+ b2r2_log_err(b2r2_blt->dev, "%s: CLUT "
+ "copy_from_user failed\n",
+ __func__);
+ ret = -EFAULT;
+ goto exit;
+ }
+ } else {
+ memcpy(request->clut, user_req->clut,
+ CLUT_SIZE);
+ }
+ }
+
+ request->profile = is_profiler_registered_approx();
+
+ *request_out = request;
+exit:
+ if (ret != 0)
+ b2r2_free_request(request);
+
+ return ret;
+}
+
+/**
+ * Do the blit job split on available cores.
+ */
+static int b2r2_blt_blit_internal(int handle,
+ struct b2r2_blt_req *user_req,
+ bool us_req)
+{
+ int request_id;
+ int i;
+ int n_instance = 0;
+ int n_blit = 0;
+ int ret = 0;
+ struct b2r2_blt_data *blt_data;
+ struct b2r2_blt_req ureq;
+
+ /* The requests and the designated workers */
+ struct b2r2_blt_request *split_requests[B2R2_MAX_NBR_DEVICES];
+ struct b2r2_control_instance *ctl[B2R2_MAX_NBR_DEVICES];
+
+ blt_data = get_data(handle);
+ if (blt_data == NULL) {
+ b2r2_log_warn(b2r2_blt->dev,
+ "%s, blitter instance not found (handle=%d)\n",
+ __func__, handle);
+ return -ENOSYS;
+ }
+
+ /* Get the b2r2 core controls for the job */
+ get_control_instances(blt_data, ctl, B2R2_MAX_NBR_DEVICES, &n_instance);
+ if (n_instance == 0) {
+ b2r2_log_err(b2r2_blt->dev, "%s: No b2r2 cores available.\n",
+ __func__);
+ return -ENOSYS;
+ }
+
+ /* Get the user data */
+ if (us_req) {
+ if (copy_from_user(&ureq, user_req, sizeof(ureq))) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: copy_from_user failed\n",
+ __func__);
+ ret = -EFAULT;
+ goto exit;
+ }
+ } else {
+ memcpy(&ureq, user_req, sizeof(ureq));
+ }
+
+ /*
+ * B2R2 cannot handle destination clipping on buffers
+ * allocated close to 64MiB bank boundaries.
+ * recalculate src_ and dst_rect to avoid clipping.
+ *
+ * Also this is needed to ensure the request split
+ * operates on visible areas
+ */
+ b2r2_recalculate_rects(b2r2_blt->dev, &ureq);
+
+ if (!b2r2_validate_user_req(b2r2_blt->dev, &ureq)) {
+ b2r2_log_warn(b2r2_blt->dev,
+ "%s: b2r2_validate_user_req failed.\n",
+ __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /* Don't split small requests */
+ n_blit = limit_blits(n_instance, &ureq);
+
+ /* The id needs to be universal on
+ * all cores */
+ request_id = get_next_job_id();
+
+#ifdef CONFIG_B2R2_GENERIC_ONLY
+ /* Limit the generic only solution to one core (for now) */
+ n_blit = 1;
+#endif
+
+ for (i = 0; i < n_blit; i++) {
+ ret = b2r2_alloc_request(&ureq, us_req, &split_requests[i]);
+ if (ret < 0 || !split_requests[i]) {
+ b2r2_log_err(b2r2_blt->dev, "%s: Failed to alloc mem\n",
+ __func__);
+ ret = -ENOMEM;
+ break;
+ }
+ split_requests[i]->instance = ctl[i];
+ split_requests[i]->job.job_id = request_id;
+ split_requests[i]->job.data = (int) ctl[i]->control->data;
+ }
+
+ /* Split the request */
+ if (ret >= 0)
+ ret = b2r2_blt_split_request(blt_data, &ureq,
+ &split_requests[0], &ctl[0], &n_blit);
+
+ /* If anything failed, clean up allocated memory */
+ if (ret < 0) {
+ for (i = 0; i < n_blit; i++)
+ b2r2_free_request(split_requests[i]);
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: b2r2_blt_split_request failed.\n",
+ __func__);
+ goto exit;
+ }
+
+#ifdef CONFIG_B2R2_GENERIC_ONLY
+ if (ureq.flags & B2R2_BLT_FLAG_BG_BLEND) {
+ /* No support for BG BLEND in generic
+ * implementation yet */
+ b2r2_log_warn(b2r2_blt->dev, "%s: Unsupported: "
+ "Background blend in b2r2_generic_blt\n",
+ __func__);
+ ret = -ENOSYS;
+ b2r2_free_request(split_requests[0]);
+ goto exit;
+ }
+ /* Use the generic path for all operations */
+ ret = b2r2_generic_blt(split_requests[0]);
+#else
+ /* Call each blitter control */
+ for (i = 0; i < n_blit; i++) {
+ ret = b2r2_control_blt(split_requests[i]);
+ if (ret < 0) {
+ b2r2_log_warn(b2r2_blt->dev,
+ "%s: b2r2_control_blt failed.\n", __func__);
+ break;
+ }
+ }
+ if (ret != -ENOSYS) {
+ int j;
+ /* TODO: if one blitter fails then cancel the jobs added */
+
+ /* Call waitjob for successful jobs
+ * (synchs if specified in request) */
+ if (ureq.flags & B2R2_BLT_FLAG_DRY_RUN)
+ goto exit;
+
+ for (j = 0; j < i; j++) {
+ int rtmp;
+
+ rtmp = b2r2_control_waitjob(split_requests[j]);
+ if (rtmp < 0) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: b2r2_control_waitjob failed.\n",
+ __func__);
+ }
+
+ /* Save just the one error */
+ ret = (ret >= 0) ? rtmp : ret;
+ }
+ }
+#endif
+#ifdef CONFIG_B2R2_GENERIC_FALLBACK
+ if (ret == -ENOSYS) {
+ struct b2r2_blt_request *request_gen = NULL;
+ if (ureq.flags & B2R2_BLT_FLAG_BG_BLEND) {
+ /* No support for BG BLEND in generic
+ * implementation yet */
+ b2r2_log_warn(b2r2_blt->dev, "%s: Unsupported: "
+ "Background blend in b2r2_generic_blt\n",
+ __func__);
+ goto exit;
+ }
+
+ b2r2_log_info(b2r2_blt->dev,
+ "b2r2_blt=%d Going generic.\n", ret);
+ ret = b2r2_alloc_request(&ureq, us_req, &request_gen);
+ if (ret < 0 || !request_gen) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: Failed to alloc mem for "
+ "request_gen\n", __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ /* Initialize the structure */
+ request_gen->instance = ctl[0];
+ memcpy(&request_gen->user_req, &ureq,
+ sizeof(request_gen->user_req));
+ request_gen->core_mask = 1;
+ request_gen->job.job_id = request_id;
+ request_gen->job.data = (int) ctl[0]->control->data;
+
+ ret = b2r2_generic_blt(request_gen);
+ b2r2_log_info(b2r2_blt->dev, "\nb2r2_generic_blt=%d "
+ "Generic done.\n", ret);
+ }
+#endif
+exit:
+ release_control_instances(ctl, n_instance);
+
+ ret = ret >= 0 ? request_id : ret;
+
+ return ret;
+}
+
+/**
+ * Free the memory used for the b2r2_blt device
+ */
+static void b2r2_blt_release(struct kref *ref)
+{
+ BUG_ON(b2r2_blt == NULL);
+ if (b2r2_blt == NULL)
+ return;
+ kfree(b2r2_blt->datas);
+ kfree(b2r2_blt);
+ b2r2_blt = NULL;
+}
+
+int b2r2_blt_open(void)
+{
+ int ret = 0;
+ struct b2r2_blt_data *blt_data = NULL;
+ int i;
+
+ if (!atomic_inc_not_zero(&blt_refcount.refcount))
+ return -ENOSYS;
+
+ /* Allocate blitter instance data structure */
+ blt_data = (struct b2r2_blt_data *)
+ kzalloc(sizeof(*blt_data), GFP_KERNEL);
+ if (!blt_data) {
+ b2r2_log_err(b2r2_blt->dev, "%s: Failed to alloc\n", __func__);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++) {
+ struct b2r2_control *control = b2r2_blt_get_control(i);
+ if (control != NULL) {
+ struct b2r2_control_instance *ci;
+
+ /* Allocate and initialize the control instance */
+ ci = kzalloc(sizeof(*ci), GFP_KERNEL);
+ if (!ci) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: Failed to alloc\n",
+ __func__);
+ ret = -ENOMEM;
+ b2r2_blt_release_control(i);
+ goto err;
+ }
+ ci->control_id = i;
+ ci->control = control;
+ ret = b2r2_control_open(ci);
+ if (ret < 0) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: Failed to open b2r2 control %d\n",
+ __func__, i);
+ kfree(ci);
+ b2r2_blt_release_control(i);
+ goto err;
+ }
+ blt_data->ctl_instace[i] = ci;
+ b2r2_blt_release_control(i);
+ } else {
+ blt_data->ctl_instace[i] = NULL;
+ }
+ }
+
+ /* TODO: Create kernel worker kthread */
+
+ ret = alloc_handle(blt_data);
+ if (ret < 0)
+ goto err;
+
+ kref_put(&blt_refcount, b2r2_blt_release);
+
+ return ret;
+
+err:
+ /* Destroy the blitter instance data structure */
+ if (blt_data) {
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++)
+ kfree(blt_data->ctl_instace[i]);
+ kfree(blt_data);
+ }
+
+ kref_put(&blt_refcount, b2r2_blt_release);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_blt_open);
+
+int b2r2_blt_close(int handle)
+{
+ int i;
+ struct b2r2_blt_data *blt_data;
+ int ret = 0;
+
+ if (!atomic_inc_not_zero(&blt_refcount.refcount))
+ return -ENOSYS;
+
+ b2r2_log_info(b2r2_blt->dev, "%s\n", __func__);
+
+ blt_data = get_data(handle);
+ if (blt_data == NULL) {
+ b2r2_log_warn(b2r2_blt->dev,
+ "%s, blitter data not found (handle=%d)\n",
+ __func__, handle);
+ ret = -ENOSYS;
+ goto exit;
+ }
+ free_handle(handle);
+
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++) {
+ struct b2r2_control_instance *ci =
+ blt_data->ctl_instace[i];
+ if (ci != NULL) {
+ struct b2r2_control *cont =
+ b2r2_blt_get_control(ci->control_id);
+ if (cont) {
+ /* Release the instance */
+ b2r2_control_release(ci);
+ b2r2_blt_release_control(ci->control_id);
+ }
+ kfree(ci);
+ }
+ }
+ kfree(blt_data);
+
+exit:
+ kref_put(&blt_refcount, b2r2_blt_release);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_blt_close);
+
+int b2r2_blt_request(int handle,
+ struct b2r2_blt_req *user_req)
+{
+ int ret = 0;
+
+ if (!atomic_inc_not_zero(&blt_refcount.refcount))
+ return -ENOSYS;
+
+ /* Exclude some currently unsupported cases */
+ if ((user_req->flags & B2R2_BLT_FLAG_REPORT_WHEN_DONE) ||
+ (user_req->flags & B2R2_BLT_FLAG_REPORT_PERFORMANCE) ||
+ (user_req->report1 != 0)) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s No callback support in the kernel API\n",
+ __func__);
+ ret = -ENOSYS;
+ goto exit;
+ }
+
+ ret = b2r2_blt_blit_internal(handle, user_req, false);
+
+exit:
+ kref_put(&blt_refcount, b2r2_blt_release);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_blt_request);
+
+int b2r2_blt_synch(int handle, int request_id)
+{
+ int ret = 0;
+ int i;
+ int n_synch = 0;
+ struct b2r2_control_instance *ctl[B2R2_MAX_NBR_DEVICES];
+ struct b2r2_blt_data *blt_data;
+
+ if (!atomic_inc_not_zero(&blt_refcount.refcount))
+ return -ENOSYS;
+
+ b2r2_log_info(b2r2_blt->dev, "%s\n", __func__);
+
+ blt_data = get_data(handle);
+ if (blt_data == NULL) {
+ b2r2_log_warn(b2r2_blt->dev,
+ "%s, blitter data not found (handle=%d)\n",
+ __func__, handle);
+ ret = -ENOSYS;
+ goto exit;
+ }
+
+ /* Get the b2r2 core controls for the job */
+ get_control_instances(blt_data, ctl, B2R2_MAX_NBR_DEVICES, &n_synch);
+ if (n_synch == 0) {
+ b2r2_log_err(b2r2_blt->dev, "%s: No b2r2 cores available.\n",
+ __func__);
+ ret = -ENOSYS;
+ goto exit;
+ }
+
+ for (i = 0; i < n_synch; i++) {
+ ret = b2r2_control_synch(ctl[i], request_id);
+ if (ret != 0) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: b2r2_control_synch failed.\n",
+ __func__);
+ break;
+ }
+ }
+
+ /* Release the handles to the core controls */
+ release_control_instances(ctl, n_synch);
+
+exit:
+ kref_put(&blt_refcount, b2r2_blt_release);
+
+ b2r2_log_info(b2r2_blt->dev,
+ "%s, request_id=%d, returns %d\n", __func__, request_id, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_blt_synch);
+
+/**
+ * The user space API
+ */
+
+/**
+ * b2r2_blt_open_us - Implements file open on the b2r2_blt device
+ *
+ * @inode: File system inode
+ * @filp: File pointer
+ *
+ * A b2r2_blt_data handle is created and stored in the file structure.
+ */
+static int b2r2_blt_open_us(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+ int handle;
+
+ handle = b2r2_blt_open();
+ if (handle < 0) {
+ b2r2_log_err(b2r2_blt->dev, "%s: Failed to open handle\n",
+ __func__);
+ ret = handle;
+ goto exit;
+ }
+ filp->private_data = (void *) handle;
+exit:
+ return ret;
+}
+
+/**
+ * b2r2_blt_release_us - Implements last close on an instance of
+ * the b2r2_blt device
+ *
+ * @inode: File system inode
+ * @filp: File pointer
+ *
+ * All active jobs are finished or cancelled and allocated data
+ * is released.
+ */
+static int b2r2_blt_release_us(struct inode *inode, struct file *filp)
+{
+ int ret;
+ ret = b2r2_blt_close((int) filp->private_data);
+ return ret;
+}
+
+/**
+ * Query B2R2 capabilities
+ *
+ * @blt_data: The B2R2 BLT instance
+ * @query_cap: The structure receiving the capabilities
+ */
+static int b2r2_blt_query_cap(struct b2r2_blt_data *blt_data,
+ struct b2r2_blt_query_cap *query_cap)
+{
+ /* FIXME: Not implemented yet */
+ return -ENOSYS;
+}
+
+/**
+ * b2r2_blt_ioctl_us - This routine implements b2r2_blt ioctl interface
+ *
+ * @file: file pointer.
+ * @cmd :ioctl command.
+ * @arg: input argument for ioctl.
+ *
+ * Returns 0 if OK else negative error code
+ */
+static long b2r2_blt_ioctl_us(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ int handle = (int) file->private_data;
+
+ /** Process actual ioctl */
+ b2r2_log_info(b2r2_blt->dev, "%s\n", __func__);
+
+ /* Get the instance from the file structure */
+ switch (cmd) {
+ case B2R2_BLT_IOC: {
+ /* arg is user pointer to struct b2r2_blt_request */
+ ret = b2r2_blt_blit_internal(handle,
+ (struct b2r2_blt_req *) arg, true);
+ break;
+ }
+
+ case B2R2_BLT_SYNCH_IOC:
+ /* arg is request_id */
+ ret = b2r2_blt_synch(handle, (int) arg);
+ break;
+
+ case B2R2_BLT_QUERY_CAP_IOC: {
+ /* Arg is struct b2r2_blt_query_cap */
+ struct b2r2_blt_query_cap query_cap;
+ struct b2r2_blt_data *blt_data = get_data(handle);
+
+ /* Get the user data */
+ if (copy_from_user(&query_cap, (void *)arg,
+ sizeof(query_cap))) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: copy_from_user failed\n",
+ __func__);
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ /* Fill in our capabilities */
+ ret = b2r2_blt_query_cap(blt_data, &query_cap);
+
+ /* Return data to user */
+ if (copy_to_user((void *)arg, &query_cap,
+ sizeof(query_cap))) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: copy_to_user failed\n",
+ __func__);
+ ret = -EFAULT;
+ goto exit;
+ }
+ break;
+ }
+
+ default:
+ /* Unknown command */
+ b2r2_log_err(b2r2_blt->dev, "%s: Unknown cmd %d\n",
+ __func__, cmd);
+ ret = -EINVAL;
+ break;
+
+ }
+
+exit:
+ if (ret < 0)
+ b2r2_log_err(b2r2_blt->dev, "%s: Return with error %d!\n",
+ __func__, -ret);
+
+ return ret;
+}
+
+/**
+ * b2r2_blt_poll - Support for user-space poll, select & epoll.
+ * Used for user-space callback
+ *
+ * @filp: File to poll on
+ * @wait: Poll table to wait on
+ *
+ * This function checks if there are anything to read
+ */
+static unsigned b2r2_blt_poll_us(struct file *filp, poll_table *wait)
+{
+ struct b2r2_blt_data *blt_data =
+ (struct b2r2_blt_data *) filp->private_data;
+ struct b2r2_control_instance *ctl[B2R2_MAX_NBR_DEVICES];
+ unsigned int ret = POLLIN | POLLRDNORM;
+ int n_poll = 0;
+ int i;
+
+ b2r2_log_info(b2r2_blt->dev, "%s\n", __func__);
+
+ /* Get the b2r2 core controls for the job */
+ get_control_instances(blt_data, ctl, B2R2_MAX_NBR_DEVICES, &n_poll);
+ if (n_poll == 0) {
+ b2r2_log_err(b2r2_blt->dev, "%s: No b2r2 cores available.\n",
+ __func__);
+ ret = -ENOSYS;
+ goto exit;
+ }
+
+ /* Poll each core control instance */
+ for (i = 0; i < n_poll && ret != 0; i++) {
+ poll_wait(filp, &ctl[i]->report_list_waitq, wait);
+ mutex_lock(&ctl[i]->lock);
+ if (list_empty(&ctl[i]->report_list))
+ ret = 0; /* No reports */
+ mutex_unlock(&ctl[i]->lock);
+ }
+
+ /* Release the handles to the core controls */
+ release_control_instances(ctl, n_poll);
+
+exit:
+ b2r2_log_info(b2r2_blt->dev, "%s: returns %d, n_poll: %d\n",
+ __func__, ret, n_poll);
+
+ return ret;
+}
+
+/**
+ * b2r2_blt_read - Read report data, user for user-space callback
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static ssize_t b2r2_blt_read_us(struct file *filp,
+ char __user *buf, size_t count, loff_t *f_pos)
+{
+ int ret = 0;
+ int n_read = 0;
+ int i;
+ int first_index = 0;
+ struct b2r2_blt_report report;
+ struct b2r2_blt_request *requests[B2R2_MAX_NBR_DEVICES];
+ struct b2r2_blt_data *blt_data =
+ (struct b2r2_blt_data *) filp->private_data;
+ struct b2r2_control_instance *ctl[B2R2_MAX_NBR_DEVICES];
+ struct b2r2_control_instance *first = NULL;
+ bool block = ((filp->f_flags & O_NONBLOCK) == 0);
+ u32 core_mask = 0;
+
+ b2r2_log_info(b2r2_blt->dev, "%s\n", __func__);
+
+ /*
+ * We return only complete report records, one at a time.
+ * Might be more efficient to support read of many.
+ */
+ count = (count / sizeof(struct b2r2_blt_report)) *
+ sizeof(struct b2r2_blt_report);
+ if (count > sizeof(struct b2r2_blt_report))
+ count = sizeof(struct b2r2_blt_report);
+ if (count == 0)
+ return count;
+
+ memset(ctl, 0, sizeof(*ctl) * B2R2_MAX_NBR_DEVICES);
+ /* Get the b2r2 core controls for the job */
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++) {
+ struct b2r2_control_instance *ci = blt_data->ctl_instace[i];
+ if (ci) {
+ struct b2r2_control *cont =
+ b2r2_blt_get_control(ci->control_id);
+ if (cont) {
+ ctl[i] = ci;
+ n_read++;
+ }
+ }
+ }
+ if (n_read == 0) {
+ b2r2_log_err(b2r2_blt->dev, "%s: No b2r2 cores available.\n",
+ __func__);
+ return -ENOSYS;
+ }
+
+ /* Find which control to ask for a report first */
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++) {
+ if (ctl[i] != NULL) {
+ first = ctl[i];
+ first_index = i;
+ break;
+ }
+ }
+ if (!first) {
+ b2r2_log_err(b2r2_blt->dev, "%s: Internal error.\n",
+ __func__);
+ return -ENOSYS;
+ }
+
+ memset(requests, 0, sizeof(*requests) * B2R2_MAX_NBR_DEVICES);
+ /* Read report from core 0 */
+ ret = b2r2_control_read(first, &requests[first_index], block);
+ if (ret <= 0 || requests[0] == NULL) {
+ b2r2_log_err(b2r2_blt->dev, "%s: b2r2_control_read failed.\n",
+ __func__);
+ ret = -EFAULT;
+ goto exit;
+ }
+ core_mask = requests[first_index]->core_mask >> 1;
+ core_mask &= ~(1 << first_index);
+
+ /* If there are any more cores, try reading the report
+ * with the specific ID from the other cores */
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++) {
+ if ((core_mask & 1) && (ctl[i] != NULL)) {
+ /* TODO: Do we need to wait here? */
+ ret = b2r2_control_read_id(ctl[i], &requests[i], block,
+ requests[first_index]->request_id);
+ if (ret <= 0 || requests[i] == NULL) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: b2r2_control_read failed.\n",
+ __func__);
+ break;
+ }
+ }
+ core_mask = core_mask >> 1;
+ }
+
+ if (ret > 0) {
+ /* Construct a report and copy to userland */
+ report.request_id = requests[0]->request_id;
+ report.report1 = requests[0]->user_req.report1;
+ report.report2 = requests[0]->user_req.report2;
+ report.usec_elapsed = 0; /* TBD */
+
+ if (copy_to_user(buf, &report, sizeof(report))) {
+ b2r2_log_err(b2r2_blt->dev,
+ "%s: copy_to_user failed.\n",
+ __func__);
+ ret = -EFAULT;
+ }
+ }
+
+ if (ret > 0) {
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++)
+ /*
+ * Release matching the addref when the job was put
+ * into the report list
+ */
+ if (requests[i] != NULL)
+ b2r2_core_job_release(&requests[i]->job,
+ __func__);
+ } else {
+ /* We failed at one core or copy to user failed */
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++)
+ if (requests[i] != NULL)
+ list_add(&requests[i]->list,
+ &ctl[i]->report_list);
+ goto exit;
+ }
+
+ ret = count;
+
+exit:
+ /* Release the handles to the core controls */
+ release_control_instances(ctl, n_read);
+
+ return ret;
+}
+
+/**
+ * b2r2_blt_fops - File operations for b2r2_blt
+ */
+static const struct file_operations b2r2_blt_fops = {
+ .owner = THIS_MODULE,
+ .open = b2r2_blt_open_us,
+ .release = b2r2_blt_release_us,
+ .unlocked_ioctl = b2r2_blt_ioctl_us,
+ .poll = b2r2_blt_poll_us,
+ .read = b2r2_blt_read_us,
+};
+
+
+/**
+ * b2r2_probe() - This routine loads the B2R2 core driver
+ *
+ * @pdev: platform device.
+ */
+static int b2r2_blt_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int i;
+
+ BUG_ON(pdev == NULL);
+
+ dev_info(&pdev->dev, "%s start.\n", __func__);
+
+ if (!b2r2_blt) {
+ b2r2_blt = kzalloc(sizeof(*b2r2_blt), GFP_KERNEL);
+ if (!b2r2_blt) {
+ dev_err(&pdev->dev, "b2r2_blt alloc failed\n");
+ ret = -EINVAL;
+ goto error_exit;
+ }
+
+ /* Init b2r2 core control reference counters */
+ for (i = 0; i < B2R2_MAX_NBR_DEVICES; i++)
+ spin_lock_init(&b2r2_controls[i].lock);
+ }
+
+ mutex_init(&b2r2_blt->datas_lock);
+ spin_lock_init(&b2r2_blt->lock);
+ b2r2_blt->dev = &pdev->dev;
+
+ /* Register b2r2 driver */
+ b2r2_blt->miscdev.parent = b2r2_blt->dev;
+ b2r2_blt->miscdev.minor = MISC_DYNAMIC_MINOR;
+ b2r2_blt->miscdev.name = "b2r2_blt";
+ b2r2_blt->miscdev.fops = &b2r2_blt_fops;
+
+ ret = misc_register(&b2r2_blt->miscdev);
+ if (ret != 0) {
+ printk(KERN_WARNING "%s: registering misc device fails\n",
+ __func__);
+ goto error_exit;
+ }
+
+ b2r2_blt->dev = b2r2_blt->miscdev.this_device;
+ b2r2_blt->dev->coherent_dma_mask = 0xFFFFFFFF;
+
+ kref_init(&blt_refcount);
+
+ dev_info(&pdev->dev, "%s done.\n", __func__);
+
+ return ret;
+
+/** Recover from any error if something fails */
+error_exit:
+
+ kfree(b2r2_blt);
+
+ dev_info(&pdev->dev, "%s done with errors (%d).\n", __func__, ret);
+
+ return ret;
+}
+
+/**
+ * b2r2_blt_remove - This routine unloads b2r2_blt driver
+ *
+ * @pdev: platform device.
+ */
+static int b2r2_blt_remove(struct platform_device *pdev)
+{
+ BUG_ON(pdev == NULL);
+ dev_info(&pdev->dev, "%s started.\n", __func__);
+ misc_deregister(&b2r2_blt->miscdev);
+ kref_put(&blt_refcount, b2r2_blt_release);
+ return 0;
+}
+
+/**
+ * b2r2_blt_suspend() - This routine puts the B2R2 blitter in to sustend state.
+ * @pdev: platform device.
+ *
+ * This routine stores the current state of the b2r2 device and puts in to
+ * suspend state.
+ *
+ */
+int b2r2_blt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+/**
+ * b2r2_blt_resume() - This routine resumes the B2R2 blitter from sustend state.
+ * @pdev: platform device.
+ *
+ * This routine restore back the current state of the b2r2 device resumes.
+ *
+ */
+int b2r2_blt_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+/**
+ * struct platform_b2r2_driver - Platform driver configuration for the
+ * B2R2 core driver
+ */
+static struct platform_driver platform_b2r2_blt_driver = {
+ .remove = b2r2_blt_remove,
+ .driver = {
+ .name = "b2r2_blt",
+ },
+ .suspend = b2r2_blt_suspend,
+ .resume = b2r2_blt_resume,
+};
+
+/**
+ * b2r2_init() - Module init function for the B2R2 core module
+ */
+static int __init b2r2_blt_init(void)
+{
+ printk(KERN_INFO "%s\n", __func__);
+ return platform_driver_probe(&platform_b2r2_blt_driver, b2r2_blt_probe);
+}
+module_init(b2r2_blt_init);
+
+/**
+ * b2r2_exit() - Module exit function for the B2R2 core module
+ */
+static void __exit b2r2_blt_exit(void)
+{
+ printk(KERN_INFO "%s\n", __func__);
+ platform_driver_unregister(&platform_b2r2_blt_driver);
+ return;
+}
+module_exit(b2r2_blt_exit);
+
+MODULE_AUTHOR("Robert Fekete <robert.fekete@stericsson.com>");
+MODULE_DESCRIPTION("ST-Ericsson B2R2 Blitter module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/b2r2/b2r2_blt_main.c b/drivers/video/b2r2/b2r2_blt_main.c
new file mode 100644
index 00000000000..3727f742bf1
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_blt_main.c
@@ -0,0 +1,2840 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 Blitter module
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+#include <asm/cacheflush.h>
+#include <linux/smp.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/hwmem.h>
+
+#include "b2r2_internal.h"
+#include "b2r2_control.h"
+#include "b2r2_node_split.h"
+#include "b2r2_generic.h"
+#include "b2r2_mem_alloc.h"
+#include "b2r2_profiler_socket.h"
+#include "b2r2_timing.h"
+#include "b2r2_debug.h"
+#include "b2r2_utils.h"
+#include "b2r2_input_validation.h"
+#include "b2r2_core.h"
+#include "b2r2_filters.h"
+
+#define B2R2_HEAP_SIZE (4 * PAGE_SIZE)
+#define MAX_TMP_BUF_SIZE (128 * PAGE_SIZE)
+
+/*
+ * TODO:
+ * Implementation of query cap
+ * Support for user space virtual pointer to physically consecutive memory
+ * Support for user space virtual pointer to physically scattered memory
+ * Callback reads lagging behind in blt_api_stress app
+ * Store smaller items in the report list instead of the whole request
+ * Support read of many report records at once.
+ */
+
+/* Local functions */
+static void inc_stat(struct b2r2_control *cont, unsigned long *stat);
+static void dec_stat(struct b2r2_control *cont, unsigned long *stat);
+
+#ifndef CONFIG_B2R2_GENERIC_ONLY
+static void job_callback(struct b2r2_core_job *job);
+static void job_release(struct b2r2_core_job *job);
+static int job_acquire_resources(struct b2r2_core_job *job, bool atomic);
+static void job_release_resources(struct b2r2_core_job *job, bool atomic);
+#endif
+
+#ifdef CONFIG_B2R2_GENERIC
+static void job_callback_gen(struct b2r2_core_job *job);
+static void job_release_gen(struct b2r2_core_job *job);
+static int job_acquire_resources_gen(struct b2r2_core_job *job, bool atomic);
+static void job_release_resources_gen(struct b2r2_core_job *job, bool atomic);
+static void tile_job_callback_gen(struct b2r2_core_job *job);
+static void tile_job_release_gen(struct b2r2_core_job *job);
+#endif
+
+
+static int resolve_buf(struct b2r2_control *cont,
+ struct b2r2_blt_img *img, struct b2r2_blt_rect *rect_2b_used,
+ bool is_dst, struct b2r2_resolved_buf *resolved);
+static void unresolve_buf(struct b2r2_control *cont,
+ struct b2r2_blt_buf *buf, struct b2r2_resolved_buf *resolved);
+static void sync_buf(struct b2r2_control *cont, struct b2r2_blt_img *img,
+ struct b2r2_resolved_buf *resolved, bool is_dst,
+ struct b2r2_blt_rect *rect);
+static bool is_report_list_empty(struct b2r2_control_instance *instance);
+static bool is_synching(struct b2r2_control_instance *instance);
+static void get_actual_dst_rect(struct b2r2_blt_req *req,
+ struct b2r2_blt_rect *actual_dst_rect);
+static void set_up_hwmem_region(struct b2r2_control *cont,
+ struct b2r2_blt_img *img, struct b2r2_blt_rect *rect,
+ struct hwmem_region *region);
+static int resolve_hwmem(struct b2r2_control *cont, struct b2r2_blt_img *img,
+ struct b2r2_blt_rect *rect_2b_used, bool is_dst,
+ struct b2r2_resolved_buf *resolved_buf);
+static void unresolve_hwmem(struct b2r2_resolved_buf *resolved_buf);
+
+/**
+ * struct sync_args - Data for clean/flush
+ *
+ * @start: Virtual start address
+ * @end: Virtual end address
+ */
+struct sync_args {
+ unsigned long start;
+ unsigned long end;
+};
+/**
+ * flush_l1_cache_range_curr_cpu() - Cleans and invalidates L1 cache on the
+ * current CPU
+ *
+ * @arg: Pointer to sync_args structure
+ */
+static inline void flush_l1_cache_range_curr_cpu(void *arg)
+{
+ struct sync_args *sa = (struct sync_args *)arg;
+
+ dmac_flush_range((void *)sa->start, (void *)sa->end);
+}
+
+#ifdef CONFIG_SMP
+/**
+ * inv_l1_cache_range_all_cpus() - Cleans and invalidates L1 cache on all CPU:s
+ *
+ * @sa: Pointer to sync_args structure
+ */
+static void flush_l1_cache_range_all_cpus(struct sync_args *sa)
+{
+ on_each_cpu(flush_l1_cache_range_curr_cpu, sa, 1);
+}
+#endif
+
+/**
+ * clean_l1_cache_range_curr_cpu() - Cleans L1 cache on current CPU
+ *
+ * Ensures that data is written out from the CPU:s L1 cache,
+ * it will still be in the cache.
+ *
+ * @arg: Pointer to sync_args structure
+ */
+static inline void clean_l1_cache_range_curr_cpu(void *arg)
+{
+ struct sync_args *sa = (struct sync_args *)arg;
+
+ dmac_map_area((void *)sa->start,
+ (void *)sa->end - (void *)sa->start,
+ DMA_TO_DEVICE);
+}
+
+#ifdef CONFIG_SMP
+/**
+ * clean_l1_cache_range_all_cpus() - Cleans L1 cache on all CPU:s
+ *
+ * Ensures that data is written out from all CPU:s L1 cache,
+ * it will still be in the cache.
+ *
+ * @sa: Pointer to sync_args structure
+ */
+static void clean_l1_cache_range_all_cpus(struct sync_args *sa)
+{
+ on_each_cpu(clean_l1_cache_range_curr_cpu, sa, 1);
+}
+#endif
+
+/**
+ * b2r2_blt_open - Implements file open on the b2r2_blt device
+ *
+ * @inode: File system inode
+ * @filp: File pointer
+ *
+ * A B2R2 BLT instance is created and stored in the file structure.
+ */
+int b2r2_control_open(struct b2r2_control_instance *instance)
+{
+ int ret = 0;
+ struct b2r2_control *cont = instance->control;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+ inc_stat(cont, &cont->stat_n_in_open);
+
+ INIT_LIST_HEAD(&instance->report_list);
+ mutex_init(&instance->lock);
+ init_waitqueue_head(&instance->report_list_waitq);
+ init_waitqueue_head(&instance->synch_done_waitq);
+ dec_stat(cont, &cont->stat_n_in_open);
+
+ return ret;
+}
+
+/**
+ * b2r2_blt_release - Implements last close on an instance of
+ * the b2r2_blt device
+ *
+ * @inode: File system inode
+ * @filp: File pointer
+ *
+ * All active jobs are finished or cancelled and allocated data
+ * is released.
+ */
+int b2r2_control_release(struct b2r2_control_instance *instance)
+{
+ int ret;
+ struct b2r2_control *cont = instance->control;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ inc_stat(cont, &cont->stat_n_in_release);
+
+ /* Finish all outstanding requests */
+ ret = b2r2_control_synch(instance, 0);
+ if (ret < 0)
+ b2r2_log_warn(cont->dev, "%s: b2r2_blt_sync failed with %d\n",
+ __func__, ret);
+
+ /* Now cancel any remaining outstanding request */
+ if (instance->no_of_active_requests) {
+ struct b2r2_core_job *job;
+
+ b2r2_log_warn(cont->dev, "%s: %d active requests\n", __func__,
+ instance->no_of_active_requests);
+
+ /* Find and cancel all jobs belonging to us */
+ job = b2r2_core_job_find_first_with_tag(cont,
+ (int) instance);
+ while (job) {
+ b2r2_core_job_cancel(job);
+ /* Matches addref in b2r2_core_job_find... */
+ b2r2_core_job_release(job, __func__);
+ job = b2r2_core_job_find_first_with_tag(cont,
+ (int) instance);
+ }
+
+ b2r2_log_warn(cont->dev, "%s: %d active requests after "
+ "cancel\n", __func__, instance->no_of_active_requests);
+ }
+
+ /* Release jobs in report list */
+ mutex_lock(&instance->lock);
+ while (!list_empty(&instance->report_list)) {
+ struct b2r2_blt_request *request = list_first_entry(
+ &instance->report_list,
+ struct b2r2_blt_request,
+ list);
+ list_del_init(&request->list);
+ mutex_unlock(&instance->lock);
+ /*
+ * This release matches the addref when the job was put into
+ * the report list
+ */
+ b2r2_core_job_release(&request->job, __func__);
+ mutex_lock(&instance->lock);
+ }
+ mutex_unlock(&instance->lock);
+
+ dec_stat(cont, &cont->stat_n_in_release);
+
+ return 0;
+}
+
+size_t b2r2_control_read(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block)
+{
+ struct b2r2_blt_request *request = NULL;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_control *cont = instance->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /*
+ * Loop and wait here until we have anything to return or
+ * until interrupted
+ */
+ mutex_lock(&instance->lock);
+ while (list_empty(&instance->report_list)) {
+ mutex_unlock(&instance->lock);
+
+ /* Return if non blocking read */
+ if (!block)
+ return -EAGAIN;
+
+ b2r2_log_info(cont->dev, "%s - Going to sleep\n", __func__);
+ if (wait_event_interruptible(
+ instance->report_list_waitq,
+ !is_report_list_empty(instance)))
+ /* signal: tell the fs layer to handle it */
+ return -ERESTARTSYS;
+
+ /* Otherwise loop, but first reaquire the lock */
+ mutex_lock(&instance->lock);
+ }
+
+ if (!list_empty(&instance->report_list))
+ request = list_first_entry(
+ &instance->report_list, struct b2r2_blt_request, list);
+
+ if (request) {
+ /* Remove from list to avoid reading twice */
+ list_del_init(&request->list);
+
+ *request_out = request;
+ }
+ mutex_unlock(&instance->lock);
+
+ if (request)
+ return 1;
+
+ /* No report returned */
+ return 0;
+}
+
+size_t b2r2_control_read_id(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block,
+ int request_id)
+{
+ struct b2r2_blt_request *request = NULL;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_control *cont = instance->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /*
+ * Loop and wait here until we have anything to return or
+ * until interrupted
+ */
+ mutex_lock(&instance->lock);
+ while (list_empty(&instance->report_list)) {
+ mutex_unlock(&instance->lock);
+
+ /* Return if non blocking read */
+ if (!block)
+ return -EAGAIN;
+
+ b2r2_log_info(cont->dev, "%s - Going to sleep\n", __func__);
+ if (wait_event_interruptible(
+ instance->report_list_waitq,
+ !is_report_list_empty(instance)))
+ /* signal: tell the fs layer to handle it */
+ return -ERESTARTSYS;
+
+ /* Otherwise loop, but first reaquire the lock */
+ mutex_lock(&instance->lock);
+ }
+
+ if (!list_empty(&instance->report_list)) {
+ struct b2r2_blt_request *pos;
+ list_for_each_entry(pos, &instance->report_list, list) {
+ if (pos->request_id)
+ request = pos;
+ }
+ }
+
+ if (request) {
+ /* Remove from list to avoid reading twice */
+ list_del_init(&request->list);
+ *request_out = request;
+ }
+ mutex_unlock(&instance->lock);
+
+ if (request)
+ return 1;
+
+ /* No report returned */
+ return 0;
+}
+
+#ifndef CONFIG_B2R2_GENERIC_ONLY
+/**
+ * b2r2_blt - Implementation of the B2R2 blit request
+ *
+ * @instance: The B2R2 BLT instance
+ * @request; The request to perform
+ */
+int b2r2_control_blt(struct b2r2_blt_request *request)
+{
+ int ret = 0;
+ struct b2r2_blt_rect actual_dst_rect;
+ int request_id = 0;
+ struct b2r2_node *last_node = request->first_node;
+ int node_count;
+ struct b2r2_control_instance *instance = request->instance;
+ struct b2r2_control *cont = instance->control;
+
+ u32 thread_runtime_at_start = 0;
+
+ if (request->profile) {
+ request->start_time_nsec = b2r2_get_curr_nsec();
+ thread_runtime_at_start = (u32)task_sched_runtime(current);
+ }
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt);
+
+ /* Debug prints of incoming request */
+ b2r2_log_info(cont->dev,
+ "src.fmt=%#010x src.buf={%d,%d,%d} "
+ "src.w,h={%d,%d} src.rect={%d,%d,%d,%d}\n",
+ request->user_req.src_img.fmt,
+ request->user_req.src_img.buf.type,
+ request->user_req.src_img.buf.fd,
+ request->user_req.src_img.buf.offset,
+ request->user_req.src_img.width,
+ request->user_req.src_img.height,
+ request->user_req.src_rect.x,
+ request->user_req.src_rect.y,
+ request->user_req.src_rect.width,
+ request->user_req.src_rect.height);
+
+ if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND)
+ b2r2_log_info(cont->dev,
+ "bg.fmt=%#010x bg.buf={%d,%d,%d} "
+ "bg.w,h={%d,%d} bg.rect={%d,%d,%d,%d}\n",
+ request->user_req.bg_img.fmt,
+ request->user_req.bg_img.buf.type,
+ request->user_req.bg_img.buf.fd,
+ request->user_req.bg_img.buf.offset,
+ request->user_req.bg_img.width,
+ request->user_req.bg_img.height,
+ request->user_req.bg_rect.x,
+ request->user_req.bg_rect.y,
+ request->user_req.bg_rect.width,
+ request->user_req.bg_rect.height);
+
+ b2r2_log_info(cont->dev,
+ "dst.fmt=%#010x dst.buf={%d,%d,%d} "
+ "dst.w,h={%d,%d} dst.rect={%d,%d,%d,%d}\n",
+ request->user_req.dst_img.fmt,
+ request->user_req.dst_img.buf.type,
+ request->user_req.dst_img.buf.fd,
+ request->user_req.dst_img.buf.offset,
+ request->user_req.dst_img.width,
+ request->user_req.dst_img.height,
+ request->user_req.dst_rect.x,
+ request->user_req.dst_rect.y,
+ request->user_req.dst_rect.width,
+ request->user_req.dst_rect.height);
+
+ inc_stat(cont, &cont->stat_n_in_blt_synch);
+
+ /* Wait here if synch is ongoing */
+ ret = wait_event_interruptible(instance->synch_done_waitq,
+ !is_synching(instance));
+ if (ret) {
+ b2r2_log_warn(cont->dev, "%s: Sync wait interrupted, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ dec_stat(cont, &cont->stat_n_in_blt_synch);
+ goto synch_interrupted;
+ }
+
+ dec_stat(cont, &cont->stat_n_in_blt_synch);
+
+ /* Resolve the buffers */
+
+ /* Source buffer */
+ ret = resolve_buf(cont, &request->user_req.src_img,
+ &request->user_req.src_rect,
+ false, &request->src_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve src buf failed, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_src_buf_failed;
+ }
+
+ /* Background buffer */
+ if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND) {
+ ret = resolve_buf(cont, &request->user_req.bg_img,
+ &request->user_req.bg_rect,
+ false, &request->bg_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve bg buf failed,"
+ " %d\n", __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_bg_buf_failed;
+ }
+ }
+
+ /* Source mask buffer */
+ ret = resolve_buf(cont, &request->user_req.src_mask,
+ &request->user_req.src_rect, false,
+ &request->src_mask_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve src mask buf failed,"
+ " %d\n", __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_src_mask_buf_failed;
+ }
+
+ /* Destination buffer */
+ get_actual_dst_rect(&request->user_req, &actual_dst_rect);
+ ret = resolve_buf(cont, &request->user_req.dst_img, &actual_dst_rect,
+ true, &request->dst_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve dst buf failed, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_dst_buf_failed;
+ }
+
+ /* Debug prints of resolved buffers */
+ b2r2_log_info(cont->dev, "src.rbuf={%X,%p,%d} {%p,%X,%X,%d}\n",
+ request->src_resolved.physical_address,
+ request->src_resolved.virtual_address,
+ request->src_resolved.is_pmem,
+ request->src_resolved.filep,
+ request->src_resolved.file_physical_start,
+ request->src_resolved.file_virtual_start,
+ request->src_resolved.file_len);
+
+ if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND)
+ b2r2_log_info(cont->dev, "bg.rbuf={%X,%p,%d} {%p,%X,%X,%d}\n",
+ request->bg_resolved.physical_address,
+ request->bg_resolved.virtual_address,
+ request->bg_resolved.is_pmem,
+ request->bg_resolved.filep,
+ request->bg_resolved.file_physical_start,
+ request->bg_resolved.file_virtual_start,
+ request->bg_resolved.file_len);
+
+ b2r2_log_info(cont->dev, "dst.rbuf={%X,%p,%d} {%p,%X,%X,%d}\n",
+ request->dst_resolved.physical_address,
+ request->dst_resolved.virtual_address,
+ request->dst_resolved.is_pmem,
+ request->dst_resolved.filep,
+ request->dst_resolved.file_physical_start,
+ request->dst_resolved.file_virtual_start,
+ request->dst_resolved.file_len);
+
+ /* Calculate the number of nodes (and resources) needed for this job */
+ ret = b2r2_node_split_analyze(request, MAX_TMP_BUF_SIZE, &node_count,
+ &request->bufs, &request->buf_count,
+ &request->node_split_job);
+ if (ret == -ENOSYS) {
+ /* There was no optimized path for this request */
+ b2r2_log_info(cont->dev, "%s: No optimized path for request\n",
+ __func__);
+ goto no_optimized_path;
+
+ } else if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Failed to analyze request,"
+ " ret = %d\n", __func__, ret);
+#ifdef CONFIG_DEBUG_FS
+ {
+ /* Failed, dump job to dmesg */
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ b2r2_log_info(cont->dev, "%s: Analyze failed for:\n",
+ __func__);
+ if (Buf != NULL) {
+ sprintf_req(request, Buf, sizeof(char) * 4096);
+ b2r2_log_info(cont->dev, "%s", Buf);
+ kfree(Buf);
+ } else {
+ b2r2_log_info(cont->dev, "Unable to print the"
+ " request. Message buffer"
+ " allocation failed.\n");
+ }
+ }
+#endif
+ goto generate_nodes_failed;
+ }
+
+ /* Allocate the nodes needed */
+#ifdef B2R2_USE_NODE_GEN
+ request->first_node = b2r2_blt_alloc_nodes(cont,
+ node_count);
+ if (request->first_node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: Failed to allocate nodes,"
+ " ret = %d\n", __func__, ret);
+ goto generate_nodes_failed;
+ }
+#else
+ ret = b2r2_node_alloc(cont, node_count, &(request->first_node));
+ if (ret < 0 || request->first_node == NULL) {
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to allocate nodes, ret = %d\n",
+ __func__, ret);
+ goto generate_nodes_failed;
+ }
+#endif
+
+ /* Build the B2R2 node list */
+ ret = b2r2_node_split_configure(cont, &request->node_split_job,
+ request->first_node);
+
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s:"
+ " Failed to perform node split, ret = %d\n",
+ __func__, ret);
+ goto generate_nodes_failed;
+ }
+
+ /* Exit here if dry run */
+ if (request->user_req.flags & B2R2_BLT_FLAG_DRY_RUN)
+ goto exit_dry_run;
+
+ /* Configure the request */
+ last_node = request->first_node;
+ while (last_node && last_node->next)
+ last_node = last_node->next;
+
+ request->job.tag = (int) instance;
+ request->job.data = (int) cont->data;
+ request->job.prio = request->user_req.prio;
+ request->job.first_node_address =
+ request->first_node->physical_address;
+ request->job.last_node_address =
+ last_node->physical_address;
+ request->job.callback = job_callback;
+ request->job.release = job_release;
+ request->job.acquire_resources = job_acquire_resources;
+ request->job.release_resources = job_release_resources;
+
+ /* Synchronize memory occupied by the buffers */
+
+ /* Source buffer */
+ if (!(request->user_req.flags &
+ B2R2_BLT_FLAG_SRC_NO_CACHE_FLUSH) &&
+ (request->user_req.src_img.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.src_img.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.src_img,
+ &request->src_resolved, false,
+ &request->user_req.src_rect);
+
+ /* Background buffer */
+ if ((request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND) &&
+ !(request->user_req.flags &
+ B2R2_BLT_FLAG_BG_NO_CACHE_FLUSH) &&
+ (request->user_req.bg_img.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.bg_img.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.bg_img,
+ &request->bg_resolved, false,
+ &request->user_req.bg_rect);
+
+ /* Source mask buffer */
+ if (!(request->user_req.flags &
+ B2R2_BLT_FLAG_SRC_MASK_NO_CACHE_FLUSH) &&
+ (request->user_req.src_mask.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.src_mask.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.src_mask,
+ &request->src_mask_resolved, false, NULL);
+
+ /* Destination buffer */
+ if (!(request->user_req.flags &
+ B2R2_BLT_FLAG_DST_NO_CACHE_FLUSH) &&
+ (request->user_req.dst_img.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.dst_img.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.dst_img,
+ &request->dst_resolved, true,
+ &request->user_req.dst_rect);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Remember latest request for debugfs */
+ cont->debugfs_latest_request = *request;
+#endif
+
+ /* Submit the job */
+ b2r2_log_info(cont->dev, "%s: Submitting job\n", __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_add);
+
+ if (request->profile)
+ request->nsec_active_in_cpu =
+ (s32)((u32)task_sched_runtime(current) -
+ thread_runtime_at_start);
+
+ mutex_lock(&instance->lock);
+
+ /* Add the job to b2r2_core */
+ request_id = b2r2_core_job_add(cont, &request->job);
+ request->request_id = request_id;
+
+ dec_stat(cont, &cont->stat_n_in_blt_add);
+
+ if (request_id < 0) {
+ b2r2_log_warn(cont->dev, "%s: Failed to add job, ret = %d\n",
+ __func__, request_id);
+ ret = request_id;
+ mutex_unlock(&instance->lock);
+ goto job_add_failed;
+ }
+
+ inc_stat(cont, &cont->stat_n_jobs_added);
+
+ instance->no_of_active_requests++;
+ mutex_unlock(&instance->lock);
+
+ return ret >= 0 ? request_id : ret;
+
+job_add_failed:
+exit_dry_run:
+no_optimized_path:
+generate_nodes_failed:
+ unresolve_buf(cont, &request->user_req.dst_img.buf,
+ &request->dst_resolved);
+resolve_dst_buf_failed:
+ unresolve_buf(cont, &request->user_req.src_mask.buf,
+ &request->src_mask_resolved);
+resolve_src_mask_buf_failed:
+ if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND)
+ unresolve_buf(cont, &request->user_req.bg_img.buf,
+ &request->bg_resolved);
+resolve_bg_buf_failed:
+ unresolve_buf(cont, &request->user_req.src_img.buf,
+ &request->src_resolved);
+resolve_src_buf_failed:
+synch_interrupted:
+ if ((request->user_req.flags & B2R2_BLT_FLAG_DRY_RUN) == 0 || ret)
+ b2r2_log_warn(cont->dev, "%s returns with error %d\n",
+ __func__, ret);
+ job_release(&request->job);
+ dec_stat(cont, &cont->stat_n_jobs_released);
+
+ dec_stat(cont, &cont->stat_n_in_blt);
+
+ return ret;
+}
+
+int b2r2_control_waitjob(struct b2r2_blt_request *request)
+{
+ int ret = 0;
+ struct b2r2_control_instance *instance = request->instance;
+ struct b2r2_control *cont = instance->control;
+
+ /* Wait for the job to be done if synchronous */
+ if ((request->user_req.flags & B2R2_BLT_FLAG_ASYNCH) == 0) {
+ b2r2_log_info(cont->dev, "%s: Synchronous, waiting\n",
+ __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_wait);
+
+ ret = b2r2_core_job_wait(&request->job);
+
+ dec_stat(cont, &cont->stat_n_in_blt_wait);
+
+ if (ret < 0 && ret != -ENOENT)
+ b2r2_log_warn(cont->dev, "%s: Failed to wait job,"
+ " ret = %d\n", __func__, ret);
+ else
+ b2r2_log_info(cont->dev, "%s: Synchronous wait done\n",
+ __func__);
+ }
+
+ /*
+ * Release matching the addref in b2r2_core_job_add,
+ * the request must not be accessed after this call
+ */
+ b2r2_core_job_release(&request->job, __func__);
+ dec_stat(cont, &cont->stat_n_in_blt);
+
+ return ret;
+}
+
+/**
+ * Called when job is done or cancelled
+ *
+ * @job: The job
+ */
+static void job_callback(struct b2r2_core_job *job)
+{
+ struct b2r2_blt_request *request = NULL;
+ struct b2r2_core *core = NULL;
+ struct b2r2_control *cont = NULL;
+
+ request = container_of(job, struct b2r2_blt_request, job);
+ core = (struct b2r2_core *) job->data;
+ cont = core->control;
+
+ if (cont->dev)
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /* Local addref / release within this func */
+ b2r2_core_job_addref(job, __func__);
+
+ /* Unresolve the buffers */
+ unresolve_buf(cont, &request->user_req.src_img.buf,
+ &request->src_resolved);
+ unresolve_buf(cont, &request->user_req.src_mask.buf,
+ &request->src_mask_resolved);
+ unresolve_buf(cont, &request->user_req.dst_img.buf,
+ &request->dst_resolved);
+ if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND)
+ unresolve_buf(cont, &request->user_req.bg_img.buf,
+ &request->bg_resolved);
+
+ /* Move to report list if the job shall be reported */
+ /* FIXME: Use a smaller struct? */
+ /* TODO: In the case of kernel API call, feed an asynch task to the
+ * instance worker (kthread) instead of polling for a report */
+ mutex_lock(&request->instance->lock);
+ if (request->user_req.flags & B2R2_BLT_FLAG_REPORT_WHEN_DONE) {
+ /* Move job to report list */
+ list_add_tail(&request->list,
+ &request->instance->report_list);
+ inc_stat(cont, &cont->stat_n_jobs_in_report_list);
+
+ /* Wake up poll */
+ wake_up_interruptible(
+ &request->instance->report_list_waitq);
+
+ /* Add a reference because we put the job in the report list */
+ b2r2_core_job_addref(job, __func__);
+ }
+
+ /*
+ * Decrease number of active requests and wake up
+ * synching threads if active requests reaches zero
+ */
+ BUG_ON(request->instance->no_of_active_requests == 0);
+ request->instance->no_of_active_requests--;
+ if (request->instance->synching &&
+ request->instance->no_of_active_requests == 0) {
+ request->instance->synching = false;
+ /* Wake up all syncing */
+
+ wake_up_interruptible_all(
+ &request->instance->synch_done_waitq);
+ }
+ mutex_unlock(&request->instance->lock);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Dump job if cancelled */
+ if (job->job_state == B2R2_CORE_JOB_CANCELED) {
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ b2r2_log_info(cont->dev, "%s: Job cancelled:\n", __func__);
+ if (Buf != NULL) {
+ sprintf_req(request, Buf, sizeof(char) * 4096);
+ b2r2_log_info(cont->dev, "%s", Buf);
+ kfree(Buf);
+ } else {
+ b2r2_log_info(cont->dev, "Unable to print the request."
+ " Message buffer allocation failed.\n");
+ }
+ }
+#endif
+
+ if (request->profile) {
+ request->total_time_nsec =
+ (s32)(b2r2_get_curr_nsec() - request->start_time_nsec);
+ b2r2_call_profiler_blt_done(request);
+ }
+
+ /* Local addref / release within this func */
+ b2r2_core_job_release(job, __func__);
+}
+
+/**
+ * Called when job should be released (free memory etc.)
+ *
+ * @job: The job
+ */
+static void job_release(struct b2r2_core_job *job)
+{
+ struct b2r2_blt_request *request = NULL;
+ struct b2r2_core *core = NULL;
+ struct b2r2_control *cont = NULL;
+
+ request = container_of(job, struct b2r2_blt_request, job);
+ core = (struct b2r2_core *) job->data;
+ cont = core->control;
+
+ inc_stat(cont, &cont->stat_n_jobs_released);
+
+ b2r2_log_info(cont->dev, "%s, first_node=%p, ref_count=%d\n",
+ __func__, request->first_node, request->job.ref_count);
+
+ b2r2_node_split_cancel(cont, &request->node_split_job);
+
+ if (request->first_node) {
+ b2r2_debug_job_done(cont, request->first_node);
+#ifdef B2R2_USE_NODE_GEN
+ b2r2_blt_free_nodes(cont, request->first_node);
+#else
+ b2r2_node_free(cont, request->first_node);
+#endif
+ }
+
+ /* Release memory for the request */
+ if (request->clut != NULL) {
+ dma_free_coherent(cont->dev, CLUT_SIZE, request->clut,
+ request->clut_phys_addr);
+ request->clut = NULL;
+ request->clut_phys_addr = 0;
+ }
+ kfree(request);
+}
+
+/**
+ * Tells the job to try to allocate the resources needed to execute the job.
+ * Called just before execution of a job.
+ *
+ * @job: The job
+ * @atomic: true if called from atomic (i.e. interrupt) context. If function
+ * can't allocate in atomic context it should return error, it
+ * will then be called later from non-atomic context.
+ */
+static int job_acquire_resources(struct b2r2_core_job *job, bool atomic)
+{
+ struct b2r2_blt_request *request =
+ container_of(job, struct b2r2_blt_request, job);
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+ int ret;
+ int i;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ if (request->buf_count == 0)
+ return 0;
+
+ if (request->buf_count > MAX_TMP_BUFS_NEEDED) {
+ b2r2_log_err(cont->dev,
+ "%s: request->buf_count > MAX_TMP_BUFS_NEEDED\n",
+ __func__);
+ return -ENOMSG;
+ }
+
+ /*
+ * 1 to 1 mapping between request temp buffers and temp buffers
+ * (request temp buf 0 is always temp buf 0, request temp buf 1 is
+ * always temp buf 1 and so on) to avoid starvation of jobs that
+ * require multiple temp buffers. Not optimal in terms of memory
+ * usage but we avoid get into a situation where lower prio jobs can
+ * delay higher prio jobs that require more temp buffers.
+ */
+ if (cont->tmp_bufs[0].in_use)
+ return -EAGAIN;
+
+ for (i = 0; i < request->buf_count; i++) {
+ if (cont->tmp_bufs[i].buf.size < request->bufs[i].size) {
+ b2r2_log_err(cont->dev, "%s: "
+ "cont->tmp_bufs[i].buf.size < "
+ "request->bufs[i].size\n", __func__);
+ ret = -ENOMSG;
+ goto error;
+ }
+
+ cont->tmp_bufs[i].in_use = true;
+ request->bufs[i].phys_addr = cont->tmp_bufs[i].buf.phys_addr;
+ request->bufs[i].virt_addr = cont->tmp_bufs[i].buf.virt_addr;
+
+ b2r2_log_info(cont->dev, "%s: phys=%p, virt=%p\n",
+ __func__, (void *)request->bufs[i].phys_addr,
+ request->bufs[i].virt_addr);
+
+ ret = b2r2_node_split_assign_buffers(cont,
+ &request->node_split_job,
+ request->first_node, request->bufs,
+ request->buf_count);
+ if (ret < 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ for (i = 0; i < request->buf_count; i++)
+ cont->tmp_bufs[i].in_use = false;
+
+ return ret;
+}
+
+/**
+ * Tells the job to free the resources needed to execute the job.
+ * Called after execution of a job.
+ *
+ * @job: The job
+ * @atomic: true if called from atomic (i.e. interrupt) context. If function
+ * can't allocate in atomic context it should return error, it
+ * will then be called later from non-atomic context.
+ */
+static void job_release_resources(struct b2r2_core_job *job, bool atomic)
+{
+ struct b2r2_blt_request *request =
+ container_of(job, struct b2r2_blt_request, job);
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+ int i;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /* Free any temporary buffers */
+ for (i = 0; i < request->buf_count; i++) {
+
+ b2r2_log_info(cont->dev, "%s: freeing %d bytes\n",
+ __func__, request->bufs[i].size);
+ cont->tmp_bufs[i].in_use = false;
+ memset(&request->bufs[i], 0, sizeof(request->bufs[i]));
+ }
+ request->buf_count = 0;
+
+ /*
+ * Early release of nodes
+ * FIXME: If nodes are to be reused we don't want to release here
+ */
+ if (!atomic && request->first_node) {
+ b2r2_debug_job_done(cont, request->first_node);
+
+#ifdef B2R2_USE_NODE_GEN
+ b2r2_blt_free_nodes(cont, request->first_node);
+#else
+ b2r2_node_free(cont, request->first_node);
+#endif
+ request->first_node = NULL;
+ }
+}
+
+#endif /* !CONFIG_B2R2_GENERIC_ONLY */
+
+#ifdef CONFIG_B2R2_GENERIC
+/**
+ * Called when job for one tile is done or cancelled
+ * in the generic path.
+ *
+ * @job: The job
+ */
+static void tile_job_callback_gen(struct b2r2_core_job *job)
+{
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_core *core =
+ (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /* Local addref / release within this func */
+ b2r2_core_job_addref(job, __func__);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Notify if a tile job is cancelled */
+ if (job->job_state == B2R2_CORE_JOB_CANCELED)
+ b2r2_log_info(cont->dev, "%s: Tile job cancelled:\n",
+ __func__);
+#endif
+
+ /* Local addref / release within this func */
+ b2r2_core_job_release(job, __func__);
+}
+
+/**
+ * Called when job is done or cancelled.
+ * Used for the last tile in the generic path
+ * to notify waiting clients.
+ *
+ * @job: The job
+ */
+static void job_callback_gen(struct b2r2_core_job *job)
+{
+ struct b2r2_blt_request *request =
+ container_of(job, struct b2r2_blt_request, job);
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /* Local addref / release within this func */
+ b2r2_core_job_addref(job, __func__);
+
+ /* Unresolve the buffers */
+ unresolve_buf(cont, &request->user_req.src_img.buf,
+ &request->src_resolved);
+ unresolve_buf(cont, &request->user_req.src_mask.buf,
+ &request->src_mask_resolved);
+ unresolve_buf(cont, &request->user_req.dst_img.buf,
+ &request->dst_resolved);
+
+ /* Move to report list if the job shall be reported */
+ /* FIXME: Use a smaller struct? */
+ /* TODO: In the case of kernel API call, feed an asynch task to the
+ * instance worker (kthread) instead of polling for a report */
+ mutex_lock(&request->instance->lock);
+ if (request->user_req.flags & B2R2_BLT_FLAG_REPORT_WHEN_DONE) {
+ /* Move job to report list */
+ list_add_tail(&request->list,
+ &request->instance->report_list);
+ inc_stat(cont, &cont->stat_n_jobs_in_report_list);
+
+ /* Wake up poll */
+ wake_up_interruptible(
+ &request->instance->report_list_waitq);
+
+ /*
+ * Add a reference because we put the
+ * job in the report list
+ */
+ b2r2_core_job_addref(job, __func__);
+ }
+
+ /*
+ * Decrease number of active requests and wake up
+ * synching threads if active requests reaches zero
+ */
+ BUG_ON(request->instance->no_of_active_requests == 0);
+ request->instance->no_of_active_requests--;
+ if (request->instance->synching &&
+ request->instance->no_of_active_requests == 0) {
+ request->instance->synching = false;
+ /* Wake up all syncing */
+
+ wake_up_interruptible_all(
+ &request->instance->synch_done_waitq);
+ }
+ mutex_unlock(&request->instance->lock);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Dump job if cancelled */
+ if (job->job_state == B2R2_CORE_JOB_CANCELED) {
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ b2r2_log_info(cont->dev, "%s: Job cancelled:\n", __func__);
+ if (Buf != NULL) {
+ sprintf_req(request, Buf, sizeof(char) * 4096);
+ b2r2_log_info(cont->dev, "%s", Buf);
+ kfree(Buf);
+ } else {
+ b2r2_log_info(cont->dev, "Unable to print the request."
+ " Message buffer allocation failed.\n");
+ }
+ }
+#endif
+
+ /* Local addref / release within this func */
+ b2r2_core_job_release(job, __func__);
+}
+
+/**
+ * Called when tile job should be released (free memory etc.)
+ * Should be used only for tile jobs. Tile jobs should only be used
+ * by b2r2_core, thus making ref_count trigger their release.
+ *
+ * @job: The job
+ */
+
+static void tile_job_release_gen(struct b2r2_core_job *job)
+{
+ struct b2r2_core *core =
+ (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+
+ inc_stat(cont, &cont->stat_n_jobs_released);
+
+ b2r2_log_info(cont->dev, "%s, first_node_address=0x%.8x, ref_count="
+ "%d\n", __func__, job->first_node_address,
+ job->ref_count);
+
+ /* Release memory for the job */
+ kfree(job);
+}
+
+/**
+ * Called when job should be released (free memory etc.)
+ *
+ * @job: The job
+ */
+
+static void job_release_gen(struct b2r2_core_job *job)
+{
+ struct b2r2_blt_request *request =
+ container_of(job, struct b2r2_blt_request, job);
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
+
+ inc_stat(cont, &cont->stat_n_jobs_released);
+
+ b2r2_log_info(cont->dev, "%s, first_node=%p, ref_count=%d\n",
+ __func__, request->first_node, request->job.ref_count);
+
+ if (request->first_node) {
+ b2r2_debug_job_done(cont, request->first_node);
+
+ /* Free nodes */
+#ifdef B2R2_USE_NODE_GEN
+ b2r2_blt_free_nodes(cont, request->first_node);
+#else
+ b2r2_node_free(cont, request->first_node);
+#endif
+ }
+
+ /* Release memory for the request */
+ if (request->clut != NULL) {
+ dma_free_coherent(cont->dev, CLUT_SIZE, request->clut,
+ request->clut_phys_addr);
+ request->clut = NULL;
+ request->clut_phys_addr = 0;
+ }
+ kfree(request);
+}
+
+static int job_acquire_resources_gen(struct b2r2_core_job *job, bool atomic)
+{
+ /* Nothing so far. Temporary buffers are pre-allocated */
+ return 0;
+}
+static void job_release_resources_gen(struct b2r2_core_job *job, bool atomic)
+{
+ /* Nothing so far. Temporary buffers are pre-allocated */
+}
+
+/**
+ * b2r2_generic_blt - Generic implementation of the B2R2 blit request
+ *
+ * @request; The request to perform
+ */
+int b2r2_generic_blt(struct b2r2_blt_request *request)
+{
+ int ret = 0;
+ struct b2r2_blt_rect actual_dst_rect;
+ int request_id = 0;
+ struct b2r2_node *last_node = request->first_node;
+ int node_count;
+ s32 tmp_buf_width = 0;
+ s32 tmp_buf_height = 0;
+ u32 tmp_buf_count = 0;
+ s32 x;
+ s32 y;
+ const struct b2r2_blt_rect *dst_rect = &(request->user_req.dst_rect);
+ const s32 dst_img_width = request->user_req.dst_img.width;
+ const s32 dst_img_height = request->user_req.dst_img.height;
+ const enum b2r2_blt_flag flags = request->user_req.flags;
+ /* Descriptors for the temporary buffers */
+ struct b2r2_work_buf work_bufs[4];
+ struct b2r2_blt_rect dst_rect_tile;
+ int i;
+ struct b2r2_control_instance *instance = request->instance;
+ struct b2r2_control *cont = instance->control;
+
+ u32 thread_runtime_at_start = 0;
+ s32 nsec_active_in_b2r2 = 0;
+
+ /*
+ * Early exit if zero blt.
+ * dst_rect outside of dst_img or
+ * dst_clip_rect outside of dst_img.
+ */
+ if (dst_rect->x + dst_rect->width <= 0 ||
+ dst_rect->y + dst_rect->height <= 0 ||
+ dst_img_width <= dst_rect->x ||
+ dst_img_height <= dst_rect->y ||
+ ((flags & B2R2_BLT_FLAG_DESTINATION_CLIP) != 0 &&
+ (dst_img_width <= request->user_req.dst_clip_rect.x ||
+ dst_img_height <= request->user_req.dst_clip_rect.y ||
+ request->user_req.dst_clip_rect.x +
+ request->user_req.dst_clip_rect.width <= 0 ||
+ request->user_req.dst_clip_rect.y +
+ request->user_req.dst_clip_rect.height <= 0))) {
+ goto zero_blt;
+ }
+
+ if (request->profile) {
+ request->start_time_nsec = b2r2_get_curr_nsec();
+ thread_runtime_at_start = (u32)task_sched_runtime(current);
+ }
+
+ memset(work_bufs, 0, sizeof(work_bufs));
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt);
+
+ /* Debug prints of incoming request */
+ b2r2_log_info(cont->dev,
+ "src.fmt=%#010x flags=0x%.8x src.buf={%d,%d,0x%.8x}\n"
+ "src.w,h={%d,%d} src.rect={%d,%d,%d,%d}\n",
+ request->user_req.src_img.fmt,
+ request->user_req.flags,
+ request->user_req.src_img.buf.type,
+ request->user_req.src_img.buf.fd,
+ request->user_req.src_img.buf.offset,
+ request->user_req.src_img.width,
+ request->user_req.src_img.height,
+ request->user_req.src_rect.x,
+ request->user_req.src_rect.y,
+ request->user_req.src_rect.width,
+ request->user_req.src_rect.height);
+ b2r2_log_info(cont->dev,
+ "dst.fmt=%#010x dst.buf={%d,%d,0x%.8x}\n"
+ "dst.w,h={%d,%d} dst.rect={%d,%d,%d,%d}\n"
+ "dst_clip_rect={%d,%d,%d,%d}\n",
+ request->user_req.dst_img.fmt,
+ request->user_req.dst_img.buf.type,
+ request->user_req.dst_img.buf.fd,
+ request->user_req.dst_img.buf.offset,
+ request->user_req.dst_img.width,
+ request->user_req.dst_img.height,
+ request->user_req.dst_rect.x,
+ request->user_req.dst_rect.y,
+ request->user_req.dst_rect.width,
+ request->user_req.dst_rect.height,
+ request->user_req.dst_clip_rect.x,
+ request->user_req.dst_clip_rect.y,
+ request->user_req.dst_clip_rect.width,
+ request->user_req.dst_clip_rect.height);
+
+ inc_stat(cont, &cont->stat_n_in_blt_synch);
+
+ /* Wait here if synch is ongoing */
+ ret = wait_event_interruptible(instance->synch_done_waitq,
+ !is_synching(instance));
+ if (ret) {
+ b2r2_log_warn(cont->dev, "%s: Sync wait interrupted, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ dec_stat(cont, &cont->stat_n_in_blt_synch);
+ goto synch_interrupted;
+ }
+
+ dec_stat(cont, &cont->stat_n_in_blt_synch);
+
+ /* Resolve the buffers */
+
+ /* Source buffer */
+ ret = resolve_buf(cont, &request->user_req.src_img,
+ &request->user_req.src_rect, false, &request->src_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve src buf failed, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_src_buf_failed;
+ }
+
+ /* Source mask buffer */
+ ret = resolve_buf(cont, &request->user_req.src_mask,
+ &request->user_req.src_rect, false,
+ &request->src_mask_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev,
+ "%s: Resolve src mask buf failed, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_src_mask_buf_failed;
+ }
+
+ /* Destination buffer */
+ get_actual_dst_rect(&request->user_req, &actual_dst_rect);
+ ret = resolve_buf(cont, &request->user_req.dst_img, &actual_dst_rect,
+ true, &request->dst_resolved);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Resolve dst buf failed, %d\n",
+ __func__, ret);
+ ret = -EAGAIN;
+ goto resolve_dst_buf_failed;
+ }
+
+ /* Debug prints of resolved buffers */
+ b2r2_log_info(cont->dev, "src.rbuf={%X,%p,%d} {%p,%X,%X,%d}\n",
+ request->src_resolved.physical_address,
+ request->src_resolved.virtual_address,
+ request->src_resolved.is_pmem,
+ request->src_resolved.filep,
+ request->src_resolved.file_physical_start,
+ request->src_resolved.file_virtual_start,
+ request->src_resolved.file_len);
+
+ b2r2_log_info(cont->dev, "dst.rbuf={%X,%p,%d} {%p,%X,%X,%d}\n",
+ request->dst_resolved.physical_address,
+ request->dst_resolved.virtual_address,
+ request->dst_resolved.is_pmem,
+ request->dst_resolved.filep,
+ request->dst_resolved.file_physical_start,
+ request->dst_resolved.file_virtual_start,
+ request->dst_resolved.file_len);
+
+ /* Calculate the number of nodes (and resources) needed for this job */
+ ret = b2r2_generic_analyze(request, &tmp_buf_width,
+ &tmp_buf_height, &tmp_buf_count, &node_count);
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to analyze request, ret = %d\n",
+ __func__, ret);
+#ifdef CONFIG_DEBUG_FS
+ {
+ /* Failed, dump job to dmesg */
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ b2r2_log_info(cont->dev,
+ "%s: Analyze failed for:\n", __func__);
+ if (Buf != NULL) {
+ sprintf_req(request, Buf, sizeof(char) * 4096);
+ b2r2_log_info(cont->dev, "%s", Buf);
+ kfree(Buf);
+ } else {
+ b2r2_log_info(cont->dev,
+ "Unable to print the request. "
+ "Message buffer allocation failed.\n");
+ }
+ }
+#endif
+ goto generate_nodes_failed;
+ }
+
+ /* Allocate the nodes needed */
+#ifdef B2R2_USE_NODE_GEN
+ request->first_node = b2r2_blt_alloc_nodes(cont, node_count);
+ if (request->first_node == NULL) {
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to allocate nodes, ret = %d\n",
+ __func__, ret);
+ goto generate_nodes_failed;
+ }
+#else
+ ret = b2r2_node_alloc(cont, node_count, &(request->first_node));
+ if (ret < 0 || request->first_node == NULL) {
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to allocate nodes, ret = %d\n",
+ __func__, ret);
+ goto generate_nodes_failed;
+ }
+#endif
+
+ /* Allocate the temporary buffers */
+ for (i = 0; i < tmp_buf_count; i++) {
+ void *virt;
+ work_bufs[i].size = tmp_buf_width * tmp_buf_height * 4;
+
+ virt = dma_alloc_coherent(cont->dev,
+ work_bufs[i].size,
+ &(work_bufs[i].phys_addr),
+ GFP_DMA | GFP_KERNEL);
+ if (virt == NULL) {
+ ret = -ENOMEM;
+ goto alloc_work_bufs_failed;
+ }
+
+ work_bufs[i].virt_addr = virt;
+ memset(work_bufs[i].virt_addr, 0xff, work_bufs[i].size);
+ }
+ ret = b2r2_generic_configure(request,
+ request->first_node, &work_bufs[0], tmp_buf_count);
+
+ if (ret < 0) {
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to perform generic configure, ret = %d\n",
+ __func__, ret);
+ goto generic_conf_failed;
+ }
+
+ /* Exit here if dry run */
+ if (flags & B2R2_BLT_FLAG_DRY_RUN)
+ goto exit_dry_run;
+
+ /*
+ * Configure the request and make sure
+ * that its job is run only for the LAST tile.
+ * This is when the request is complete
+ * and waiting clients should be notified.
+ */
+ last_node = request->first_node;
+ while (last_node && last_node->next)
+ last_node = last_node->next;
+
+ request->job.tag = (int) instance;
+ request->job.data = (int) cont->data;
+ request->job.prio = request->user_req.prio;
+ request->job.first_node_address =
+ request->first_node->physical_address;
+ request->job.last_node_address =
+ last_node->physical_address;
+ request->job.callback = job_callback_gen;
+ request->job.release = job_release_gen;
+ /* Work buffers and nodes are pre-allocated */
+ request->job.acquire_resources = job_acquire_resources_gen;
+ request->job.release_resources = job_release_resources_gen;
+
+ /* Flush the L1/L2 cache for the buffers */
+
+ /* Source buffer */
+ if (!(flags & B2R2_BLT_FLAG_SRC_NO_CACHE_FLUSH) &&
+ (request->user_req.src_img.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.src_img.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.src_img,
+ &request->src_resolved,
+ false, /*is_dst*/
+ &request->user_req.src_rect);
+
+ /* Source mask buffer */
+ if (!(flags & B2R2_BLT_FLAG_SRC_MASK_NO_CACHE_FLUSH) &&
+ (request->user_req.src_mask.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.src_mask.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.src_mask,
+ &request->src_mask_resolved,
+ false, /*is_dst*/
+ NULL);
+
+ /* Destination buffer */
+ if (!(flags & B2R2_BLT_FLAG_DST_NO_CACHE_FLUSH) &&
+ (request->user_req.dst_img.buf.type !=
+ B2R2_BLT_PTR_PHYSICAL) &&
+ !b2r2_is_mb_fmt(request->user_req.dst_img.fmt))
+ /* MB formats are never touched by SW */
+ sync_buf(cont, &request->user_req.dst_img,
+ &request->dst_resolved,
+ true, /*is_dst*/
+ &request->user_req.dst_rect);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Remember latest request */
+ cont->debugfs_latest_request = *request;
+#endif
+
+ /*
+ * Same nodes are reused for all the jobs needed to complete the blit.
+ * Nodes are NOT released together with associated job,
+ * as is the case with optimized b2r2_blt() path.
+ */
+ mutex_lock(&instance->lock);
+ instance->no_of_active_requests++;
+ mutex_unlock(&instance->lock);
+ /*
+ * Process all but the last row in the destination rectangle.
+ * Consider only the tiles that will actually end up inside
+ * the destination image.
+ * dst_rect->height - tmp_buf_height being <=0 is allright.
+ * The loop will not be entered since y will always be equal to or
+ * greater than zero.
+ * Early exit check at the beginning handles the cases when nothing
+ * at all should be processed.
+ */
+ y = 0;
+ if (dst_rect->y < 0)
+ y = -dst_rect->y;
+
+ for (; y < dst_rect->height - tmp_buf_height &&
+ y + dst_rect->y < dst_img_height - tmp_buf_height;
+ y += tmp_buf_height) {
+ /* Tile in the destination rectangle being processed */
+ struct b2r2_blt_rect dst_rect_tile;
+ dst_rect_tile.y = y;
+ dst_rect_tile.width = tmp_buf_width;
+ dst_rect_tile.height = tmp_buf_height;
+
+ x = 0;
+ if (dst_rect->x < 0)
+ x = -dst_rect->x;
+
+ for (; x < dst_rect->width && x + dst_rect->x < dst_img_width;
+ x += tmp_buf_width) {
+ /*
+ * Tile jobs are freed by the supplied release function
+ * when ref_count on a tile_job reaches zero.
+ */
+ struct b2r2_core_job *tile_job =
+ kmalloc(sizeof(*tile_job), GFP_KERNEL);
+ if (tile_job == NULL) {
+ /*
+ * Skip this tile. Do not abort,
+ * just hope for better luck
+ * with rest of the tiles.
+ * Memory might become available.
+ */
+ b2r2_log_info(cont->dev, "%s: Failed to alloc "
+ "job. Skipping tile at (x, y)="
+ "(%d, %d)\n", __func__, x, y);
+ continue;
+ }
+ tile_job->job_id = request->job.job_id;
+ tile_job->tag = request->job.tag;
+ tile_job->data = request->job.data;
+ tile_job->prio = request->job.prio;
+ tile_job->first_node_address =
+ request->job.first_node_address;
+ tile_job->last_node_address =
+ request->job.last_node_address;
+ tile_job->callback = tile_job_callback_gen;
+ tile_job->release = tile_job_release_gen;
+ /* Work buffers and nodes are pre-allocated */
+ tile_job->acquire_resources =
+ job_acquire_resources_gen;
+ tile_job->release_resources =
+ job_release_resources_gen;
+
+ dst_rect_tile.x = x;
+ if (x + dst_rect->x + tmp_buf_width > dst_img_width) {
+ /*
+ * Only a part of the tile can be written.
+ * Limit imposed by buffer size.
+ */
+ dst_rect_tile.width =
+ dst_img_width - (x + dst_rect->x);
+ } else if (x + tmp_buf_width > dst_rect->width) {
+ /*
+ * Only a part of the tile can be written.
+ * In this case limit imposed by dst_rect size.
+ */
+ dst_rect_tile.width = dst_rect->width - x;
+ } else {
+ /* Whole tile can be written. */
+ dst_rect_tile.width = tmp_buf_width;
+ }
+ /*
+ * Where applicable, calculate area in src buffer
+ * that is needed to generate the specified part
+ * of destination rectangle.
+ */
+ b2r2_generic_set_areas(request,
+ request->first_node, &dst_rect_tile);
+ /* Submit the job */
+ b2r2_log_info(cont->dev,
+ "%s: Submitting job\n", __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_add);
+
+ mutex_lock(&instance->lock);
+
+ request_id = b2r2_core_job_add(cont, tile_job);
+
+ dec_stat(cont, &cont->stat_n_in_blt_add);
+
+ if (request_id < 0) {
+ b2r2_log_warn(cont->dev, "%s: "
+ "Failed to add tile job, ret = %d\n",
+ __func__, request_id);
+ ret = request_id;
+ mutex_unlock(&instance->lock);
+ goto job_add_failed;
+ }
+
+ inc_stat(cont, &cont->stat_n_jobs_added);
+
+ mutex_unlock(&instance->lock);
+
+ /* Wait for the job to be done */
+ b2r2_log_info(cont->dev, "%s: Synchronous, waiting\n",
+ __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_wait);
+
+ ret = b2r2_core_job_wait(tile_job);
+
+ dec_stat(cont, &cont->stat_n_in_blt_wait);
+
+ if (ret < 0 && ret != -ENOENT)
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to wait job, ret = %d\n",
+ __func__, ret);
+ else {
+ b2r2_log_info(cont->dev,
+ "%s: Synchronous wait done\n",
+ __func__);
+
+ nsec_active_in_b2r2 +=
+ tile_job->nsec_active_in_hw;
+ }
+ /* Release matching the addref in b2r2_core_job_add */
+ b2r2_core_job_release(tile_job, __func__);
+ }
+ }
+
+ x = 0;
+ if (dst_rect->x < 0)
+ x = -dst_rect->x;
+
+ for (; x < dst_rect->width &&
+ x + dst_rect->x < dst_img_width; x += tmp_buf_width) {
+ struct b2r2_core_job *tile_job = NULL;
+ if (x + tmp_buf_width < dst_rect->width &&
+ x + dst_rect->x + tmp_buf_width <
+ dst_img_width) {
+ /*
+ * Tile jobs are freed by the supplied release function
+ * when ref_count on a tile_job reaches zero.
+ * Do NOT allocate a tile_job for the last tile.
+ * Send the job from the request. This way clients
+ * will be notified when the whole blit is complete
+ * and not just part of it.
+ */
+ tile_job = kmalloc(sizeof(*tile_job), GFP_KERNEL);
+ if (tile_job == NULL) {
+ b2r2_log_info(cont->dev, "%s: Failed to alloc "
+ "job. Skipping tile at (x, y)="
+ "(%d, %d)\n", __func__, x, y);
+ continue;
+ }
+ tile_job->job_id = request->job.job_id;
+ tile_job->tag = request->job.tag;
+ tile_job->data = request->job.data;
+ tile_job->prio = request->job.prio;
+ tile_job->first_node_address =
+ request->job.first_node_address;
+ tile_job->last_node_address =
+ request->job.last_node_address;
+ tile_job->callback = tile_job_callback_gen;
+ tile_job->release = tile_job_release_gen;
+ tile_job->acquire_resources =
+ job_acquire_resources_gen;
+ tile_job->release_resources =
+ job_release_resources_gen;
+ }
+
+ dst_rect_tile.x = x;
+ if (x + dst_rect->x + tmp_buf_width > dst_img_width) {
+ /*
+ * Only a part of the tile can be written.
+ * Limit imposed by buffer size.
+ */
+ dst_rect_tile.width = dst_img_width - (x + dst_rect->x);
+ } else if (x + tmp_buf_width > dst_rect->width) {
+ /*
+ * Only a part of the tile can be written.
+ * In this case limit imposed by dst_rect size.
+ */
+ dst_rect_tile.width = dst_rect->width - x;
+ } else {
+ /* Whole tile can be written. */
+ dst_rect_tile.width = tmp_buf_width;
+ }
+ /*
+ * y is now the last row. Either because the whole dst_rect
+ * has been processed, or because the last row that will be
+ * written to dst_img has been reached. Limits imposed in
+ * the same way as for width.
+ */
+ dst_rect_tile.y = y;
+ if (y + dst_rect->y + tmp_buf_height > dst_img_height)
+ dst_rect_tile.height =
+ dst_img_height - (y + dst_rect->y);
+ else if (y + tmp_buf_height > dst_rect->height)
+ dst_rect_tile.height = dst_rect->height - y;
+ else
+ dst_rect_tile.height = tmp_buf_height;
+
+ b2r2_generic_set_areas(request,
+ request->first_node, &dst_rect_tile);
+
+ b2r2_log_info(cont->dev, "%s: Submitting job\n", __func__);
+ inc_stat(cont, &cont->stat_n_in_blt_add);
+
+ mutex_lock(&instance->lock);
+ if (x + tmp_buf_width < dst_rect->width &&
+ x + dst_rect->x + tmp_buf_width <
+ dst_img_width) {
+ request_id = b2r2_core_job_add(cont, tile_job);
+ } else {
+ /*
+ * Last tile. Send the job-struct from the request.
+ * Clients will be notified once it completes.
+ */
+ request_id = b2r2_core_job_add(cont, &request->job);
+ }
+
+ dec_stat(cont, &cont->stat_n_in_blt_add);
+
+ if (request_id < 0) {
+ b2r2_log_warn(cont->dev, "%s: Failed to add tile job, "
+ "ret = %d\n", __func__, request_id);
+ ret = request_id;
+ mutex_unlock(&instance->lock);
+ if (tile_job != NULL)
+ kfree(tile_job);
+ goto job_add_failed;
+ }
+
+ inc_stat(cont, &cont->stat_n_jobs_added);
+ mutex_unlock(&instance->lock);
+
+ b2r2_log_info(cont->dev, "%s: Synchronous, waiting\n",
+ __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_wait);
+ if (x + tmp_buf_width < dst_rect->width &&
+ x + dst_rect->x + tmp_buf_width <
+ dst_img_width) {
+ ret = b2r2_core_job_wait(tile_job);
+ } else {
+ /*
+ * This is the last tile. Wait for the job-struct from
+ * the request.
+ */
+ ret = b2r2_core_job_wait(&request->job);
+ }
+ dec_stat(cont, &cont->stat_n_in_blt_wait);
+
+ if (ret < 0 && ret != -ENOENT)
+ b2r2_log_warn(cont->dev,
+ "%s: Failed to wait job, ret = %d\n",
+ __func__, ret);
+ else {
+ b2r2_log_info(cont->dev,
+ "%s: Synchronous wait done\n", __func__);
+
+ if (x + tmp_buf_width < dst_rect->width &&
+ x + dst_rect->x + tmp_buf_width <
+ dst_img_width)
+ nsec_active_in_b2r2 +=
+ tile_job->nsec_active_in_hw;
+ else
+ nsec_active_in_b2r2 +=
+ request->job.nsec_active_in_hw;
+ }
+
+ /*
+ * Release matching the addref in b2r2_core_job_add.
+ * Make sure that the correct job-struct is released
+ * when the last tile is processed.
+ */
+ if (x + tmp_buf_width < dst_rect->width &&
+ x + dst_rect->x + tmp_buf_width <
+ dst_img_width) {
+ b2r2_core_job_release(tile_job, __func__);
+ } else {
+ /*
+ * Update profiling information before
+ * the request is released together with
+ * its core_job.
+ */
+ if (request->profile) {
+ request->nsec_active_in_cpu =
+ (s32)((u32)task_sched_runtime(current) -
+ thread_runtime_at_start);
+ request->total_time_nsec =
+ (s32)(b2r2_get_curr_nsec() -
+ request->start_time_nsec);
+ request->job.nsec_active_in_hw =
+ nsec_active_in_b2r2;
+
+ b2r2_call_profiler_blt_done(request);
+ }
+
+ b2r2_core_job_release(&request->job, __func__);
+ }
+ }
+
+ dec_stat(cont, &cont->stat_n_in_blt);
+
+ for (i = 0; i < tmp_buf_count; i++) {
+ dma_free_coherent(cont->dev,
+ work_bufs[i].size,
+ work_bufs[i].virt_addr,
+ work_bufs[i].phys_addr);
+ memset(&(work_bufs[i]), 0, sizeof(work_bufs[i]));
+ }
+
+ return request_id;
+
+job_add_failed:
+exit_dry_run:
+generic_conf_failed:
+alloc_work_bufs_failed:
+ for (i = 0; i < 4; i++) {
+ if (work_bufs[i].virt_addr != 0) {
+ dma_free_coherent(cont->dev,
+ work_bufs[i].size,
+ work_bufs[i].virt_addr,
+ work_bufs[i].phys_addr);
+ memset(&(work_bufs[i]), 0, sizeof(work_bufs[i]));
+ }
+ }
+
+generate_nodes_failed:
+ unresolve_buf(cont, &request->user_req.dst_img.buf,
+ &request->dst_resolved);
+resolve_dst_buf_failed:
+ unresolve_buf(cont, &request->user_req.src_mask.buf,
+ &request->src_mask_resolved);
+resolve_src_mask_buf_failed:
+ unresolve_buf(cont, &request->user_req.src_img.buf,
+ &request->src_resolved);
+resolve_src_buf_failed:
+synch_interrupted:
+zero_blt:
+ job_release_gen(&request->job);
+ dec_stat(cont, &cont->stat_n_jobs_released);
+ dec_stat(cont, &cont->stat_n_in_blt);
+
+ b2r2_log_info(cont->dev, "b2r2:%s ret=%d", __func__, ret);
+ return ret;
+}
+#endif /* CONFIG_B2R2_GENERIC */
+
+/**
+ * b2r2_blt_synch - Implements wait for all or a specified job
+ *
+ * @instance: The B2R2 BLT instance
+ * @request_id: If 0, wait for all requests on this instance to finish.
+ * Else wait for request with given request id to finish.
+ */
+int b2r2_control_synch(struct b2r2_control_instance *instance,
+ int request_id)
+{
+ int ret = 0;
+ struct b2r2_control *cont = instance->control;
+
+ b2r2_log_info(cont->dev, "%s, request_id=%d\n", __func__, request_id);
+
+ if (request_id == 0) {
+ /* Wait for all requests */
+ inc_stat(cont, &cont->stat_n_in_synch_0);
+
+ /* Enter state "synching" if we have any active request */
+ mutex_lock(&instance->lock);
+ if (instance->no_of_active_requests)
+ instance->synching = true;
+ mutex_unlock(&instance->lock);
+
+ /* Wait until no longer in state synching */
+ ret = wait_event_interruptible(instance->synch_done_waitq,
+ !is_synching(instance));
+ dec_stat(cont, &cont->stat_n_in_synch_0);
+ } else {
+ struct b2r2_core_job *job;
+
+ inc_stat(cont, &cont->stat_n_in_synch_job);
+
+ /* Wait for specific job */
+ job = b2r2_core_job_find(cont, request_id);
+ if (job) {
+ /* Wait on find job */
+ ret = b2r2_core_job_wait(job);
+ /* Release matching the addref in b2r2_core_job_find */
+ b2r2_core_job_release(job, __func__);
+ }
+
+ /* If job not found we assume that is has been run */
+ dec_stat(cont, &cont->stat_n_in_synch_job);
+ }
+
+ b2r2_log_info(cont->dev,
+ "%s, request_id=%d, returns %d\n", __func__, request_id, ret);
+
+ return ret;
+}
+
+static void get_actual_dst_rect(struct b2r2_blt_req *req,
+ struct b2r2_blt_rect *actual_dst_rect)
+{
+ struct b2r2_blt_rect dst_img_bounds;
+
+ b2r2_get_img_bounding_rect(&req->dst_img, &dst_img_bounds);
+
+ b2r2_intersect_rects(&req->dst_rect, &dst_img_bounds, actual_dst_rect);
+
+ if (req->flags & B2R2_BLT_FLAG_DESTINATION_CLIP)
+ b2r2_intersect_rects(actual_dst_rect, &req->dst_clip_rect,
+ actual_dst_rect);
+}
+
+static void set_up_hwmem_region(struct b2r2_control *cont,
+ struct b2r2_blt_img *img, struct b2r2_blt_rect *rect,
+ struct hwmem_region *region)
+{
+ s32 img_size;
+
+ memset(region, 0, sizeof(*region));
+
+ if (b2r2_is_zero_area_rect(rect))
+ return;
+
+ img_size = b2r2_get_img_size(cont->dev, img);
+
+ if (b2r2_is_single_plane_fmt(img->fmt) &&
+ b2r2_is_independent_pixel_fmt(img->fmt)) {
+ int img_fmt_bpp = b2r2_get_fmt_bpp(cont->dev, img->fmt);
+ u32 img_pitch = b2r2_get_img_pitch(cont->dev, img);
+
+ region->offset = (u32)(img->buf.offset + (rect->y *
+ img_pitch));
+ region->count = (u32)rect->height;
+ region->start = (u32)((rect->x * img_fmt_bpp) / 8);
+ region->end = (u32)b2r2_div_round_up(
+ (rect->x + rect->width) * img_fmt_bpp, 8);
+ region->size = img_pitch;
+ } else {
+ /*
+ * TODO: Locking entire buffer as a quick safe solution. In the
+ * future we should lock less to avoid unecessary cache
+ * synching. Pixel interleaved YCbCr formats should be quite
+ * easy, just align start and stop points on 2.
+ */
+ region->offset = (u32)img->buf.offset;
+ region->count = 1;
+ region->start = 0;
+ region->end = (u32)img_size;
+ region->size = (u32)img_size;
+ }
+}
+
+static int resolve_hwmem(struct b2r2_control *cont,
+ struct b2r2_blt_img *img,
+ struct b2r2_blt_rect *rect_2b_used,
+ bool is_dst,
+ struct b2r2_resolved_buf *resolved_buf)
+{
+ int return_value = 0;
+ enum hwmem_mem_type mem_type;
+ enum hwmem_access access;
+ enum hwmem_access required_access;
+ struct hwmem_mem_chunk mem_chunk;
+ size_t mem_chunk_length = 1;
+ struct hwmem_region region;
+
+ resolved_buf->hwmem_alloc =
+ hwmem_resolve_by_name(img->buf.hwmem_buf_name);
+ if (IS_ERR(resolved_buf->hwmem_alloc)) {
+ return_value = PTR_ERR(resolved_buf->hwmem_alloc);
+ b2r2_log_info(cont->dev, "%s: hwmem_resolve_by_name failed, "
+ "error code: %i\n", __func__, return_value);
+ goto resolve_failed;
+ }
+
+ hwmem_get_info(resolved_buf->hwmem_alloc, &resolved_buf->file_len,
+ &mem_type, &access);
+
+ required_access = (is_dst ? HWMEM_ACCESS_WRITE : HWMEM_ACCESS_READ) |
+ HWMEM_ACCESS_IMPORT;
+ if ((required_access & access) != required_access) {
+ b2r2_log_info(cont->dev,
+ "%s: Insufficient access to hwmem (%d, requires %d)"
+ "buffer.\n", __func__, access, required_access);
+ return_value = -EACCES;
+ goto access_check_failed;
+ }
+
+ if (mem_type != HWMEM_MEM_CONTIGUOUS_SYS) {
+ b2r2_log_info(cont->dev, "%s: Hwmem buffer is scattered.\n",
+ __func__);
+ return_value = -EINVAL;
+ goto buf_scattered;
+ }
+
+ if (resolved_buf->file_len <
+ img->buf.offset +
+ (__u32)b2r2_get_img_size(cont->dev, img)) {
+ b2r2_log_info(cont->dev, "%s: Hwmem buffer too small. (%d < "
+ "%d)\n", __func__, resolved_buf->file_len,
+ img->buf.offset +
+ (__u32)b2r2_get_img_size(cont->dev, img));
+ return_value = -EINVAL;
+ goto size_check_failed;
+ }
+
+ return_value = hwmem_pin(resolved_buf->hwmem_alloc, &mem_chunk,
+ &mem_chunk_length);
+ if (return_value < 0) {
+ b2r2_log_info(cont->dev, "%s: hwmem_pin failed, "
+ "error code: %i\n", __func__, return_value);
+ goto pin_failed;
+ }
+ resolved_buf->file_physical_start = mem_chunk.paddr;
+
+ set_up_hwmem_region(cont, img, rect_2b_used, &region);
+ return_value = hwmem_set_domain(resolved_buf->hwmem_alloc,
+ required_access, HWMEM_DOMAIN_SYNC, &region);
+ if (return_value < 0) {
+ b2r2_log_info(cont->dev, "%s: hwmem_set_domain failed, "
+ "error code: %i\n", __func__, return_value);
+ goto set_domain_failed;
+ }
+
+ resolved_buf->physical_address =
+ resolved_buf->file_physical_start + img->buf.offset;
+
+ goto out;
+
+set_domain_failed:
+ hwmem_unpin(resolved_buf->hwmem_alloc);
+pin_failed:
+size_check_failed:
+buf_scattered:
+access_check_failed:
+ hwmem_release(resolved_buf->hwmem_alloc);
+resolve_failed:
+
+out:
+ return return_value;
+}
+
+static void unresolve_hwmem(struct b2r2_resolved_buf *resolved_buf)
+{
+ hwmem_unpin(resolved_buf->hwmem_alloc);
+ hwmem_release(resolved_buf->hwmem_alloc);
+}
+
+/**
+ * unresolve_buf() - Must be called after resolve_buf
+ *
+ * @buf: The buffer specification as supplied from user space
+ * @resolved: Gathered information about the buffer
+ *
+ * Returns 0 if OK else negative error code
+ */
+static void unresolve_buf(struct b2r2_control *cont,
+ struct b2r2_blt_buf *buf,
+ struct b2r2_resolved_buf *resolved)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ if (resolved->is_pmem && resolved->filep)
+ put_pmem_file(resolved->filep);
+#endif
+ if (resolved->hwmem_alloc != NULL)
+ unresolve_hwmem(resolved);
+}
+
+/**
+ * get_fb_info() - Fill buf with framebuffer info
+ *
+ * @file: The framebuffer file
+ * @buf: Gathered information about the buffer
+ * @img_offset: Image offset info frame buffer
+ *
+ * Returns 0 if OK else negative error code
+ */
+static int get_fb_info(struct file *file,
+ struct b2r2_resolved_buf *buf,
+ __u32 img_offset)
+{
+#ifdef CONFIG_FB
+ if (file && buf &&
+ MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ int i;
+ /*
+ * (OK to do it like this, no locking???)
+ */
+ for (i = 0; i < num_registered_fb; i++) {
+ struct fb_info *info = registered_fb[i];
+
+ if (info && info->dev &&
+ MINOR(info->dev->devt) ==
+ MINOR(file->f_dentry->d_inode->i_rdev)) {
+ buf->file_physical_start = info->fix.smem_start;
+ buf->file_virtual_start = (u32)info->screen_base;
+ buf->file_len = info->fix.smem_len;
+ buf->physical_address = buf->file_physical_start +
+ img_offset;
+ buf->virtual_address =
+ (void *) (buf->file_virtual_start +
+ img_offset);
+ return 0;
+ }
+ }
+ }
+#endif
+ return -EINVAL;
+}
+
+/**
+ * resolve_buf() - Returns the physical & virtual addresses of a B2R2 blt buffer
+ *
+ * @img: The image specification as supplied from user space
+ * @rect_2b_used: The part of the image b2r2 will use.
+ * @usage: Specifies how the buffer will be used.
+ * @resolved: Gathered information about the buffer
+ *
+ * Returns 0 if OK else negative error code
+ */
+static int resolve_buf(struct b2r2_control *cont,
+ struct b2r2_blt_img *img,
+ struct b2r2_blt_rect *rect_2b_used,
+ bool is_dst,
+ struct b2r2_resolved_buf *resolved)
+{
+ int ret = 0;
+
+ memset(resolved, 0, sizeof(*resolved));
+
+ switch (img->buf.type) {
+ case B2R2_BLT_PTR_NONE:
+ break;
+
+ case B2R2_BLT_PTR_PHYSICAL:
+ resolved->physical_address = img->buf.offset;
+ resolved->file_len = img->buf.len;
+ break;
+
+ /* FD + OFFSET type */
+ case B2R2_BLT_PTR_FD_OFFSET: {
+ /*
+ * TODO: Do we need to check if the process is allowed to
+ * read/write (depending on if it's dst or src) to the file?
+ */
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(
+ img->buf.fd,
+ (unsigned long *) &resolved->file_physical_start,
+ (unsigned long *) &resolved->file_virtual_start,
+ (unsigned long *) &resolved->file_len,
+ &resolved->filep)) {
+ resolved->physical_address =
+ resolved->file_physical_start +
+ img->buf.offset;
+ resolved->virtual_address = (void *)
+ (resolved->file_virtual_start +
+ img->buf.offset);
+ resolved->is_pmem = true;
+ } else
+#endif
+ {
+ int fput_needed;
+ struct file *file;
+
+ file = fget_light(img->buf.fd, &fput_needed);
+ if (file == NULL)
+ return -EINVAL;
+
+ ret = get_fb_info(file, resolved,
+ img->buf.offset);
+ fput_light(file, fput_needed);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Check bounds */
+ if (img->buf.offset + img->buf.len >
+ resolved->file_len) {
+ ret = -ESPIPE;
+ unresolve_buf(cont, &img->buf, resolved);
+ }
+
+ break;
+ }
+
+ case B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET:
+ ret = resolve_hwmem(cont, img, rect_2b_used, is_dst, resolved);
+ break;
+
+ default:
+ b2r2_log_warn(cont->dev, "%s: Failed to resolve buf type %d\n",
+ __func__, img->buf.type);
+
+ ret = -EINVAL;
+ break;
+
+ }
+
+ return ret;
+}
+
+/**
+ * sync_buf - Synchronizes the memory occupied by an image buffer.
+ *
+ * @buf: User buffer specification
+ * @resolved_buf: Gathered info (physical address etc.) about buffer
+ * @is_dst: true if the buffer is a destination buffer, false if the buffer is a
+ * source buffer.
+ * @rect: rectangle in the image buffer that should be synced.
+ * NULL if the buffer is a source mask.
+ * @img_width: width of the complete image buffer
+ * @fmt: buffer format
+*/
+static void sync_buf(struct b2r2_control *cont,
+ struct b2r2_blt_img *img,
+ struct b2r2_resolved_buf *resolved,
+ bool is_dst,
+ struct b2r2_blt_rect *rect)
+{
+ struct sync_args sa;
+ u32 start_phys, end_phys;
+
+ if (B2R2_BLT_PTR_NONE == img->buf.type ||
+ B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET == img->buf.type)
+ return;
+
+ start_phys = resolved->physical_address;
+ end_phys = resolved->physical_address + img->buf.len;
+
+ /*
+ * TODO: Very ugly. We should find out whether the memory is coherent in
+ * some generic way but cache handling will be rewritten soon so there
+ * is no use spending time on it. In the new design this will probably
+ * not be a problem.
+ */
+ /* Frame buffer is coherent, at least now. */
+ if (!resolved->is_pmem) {
+ /*
+ * Drain the write buffers as they are not always part of the
+ * coherent concept.
+ */
+ wmb();
+
+ return;
+ }
+
+ /*
+ * src_mask does not have rect.
+ * Also flush full buffer for planar and semiplanar YUV formats
+ */
+ if (rect == NULL ||
+ (img->fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR) ||
+ (img->fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR) ||
+ (img->fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR) ||
+ (img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR) ||
+ (img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR) ||
+ (img->fmt ==
+ B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE) ||
+ (img->fmt ==
+ B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE)) {
+ sa.start = (unsigned long)resolved->virtual_address;
+ sa.end = (unsigned long)resolved->virtual_address +
+ img->buf.len;
+ start_phys = resolved->physical_address;
+ end_phys = resolved->physical_address + img->buf.len;
+ } else {
+ /*
+ * buffer is not a src_mask so make use of rect when
+ * clean & flush caches
+ */
+ u32 bpp; /* Bits per pixel */
+ u32 pitch;
+
+ switch (img->fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444: /* Fall through */
+ case B2R2_BLT_FMT_16_BIT_ARGB1555: /* Fall through */
+ case B2R2_BLT_FMT_16_BIT_RGB565: /* Fall through */
+ case B2R2_BLT_FMT_Y_CB_Y_CR: /* Fall through */
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ bpp = 16;
+ break;
+ case B2R2_BLT_FMT_24_BIT_RGB888: /* Fall through */
+ case B2R2_BLT_FMT_24_BIT_ARGB8565: /* Fall through */
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ bpp = 24;
+ break;
+ case B2R2_BLT_FMT_32_BIT_ARGB8888: /* Fall through */
+ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Fall through */
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ bpp = 32;
+ break;
+ default:
+ bpp = 12;
+ }
+ if (img->pitch == 0)
+ pitch = (img->width * bpp) / 8;
+ else
+ pitch = img->pitch;
+
+ /*
+ * For 422I formats 2 horizontal pixels share color data.
+ * Thus, the x position must be aligned down to closest even
+ * number and width must be aligned up.
+ */
+ {
+ s32 x;
+ s32 width;
+
+ switch (img->fmt) {
+ case B2R2_BLT_FMT_Y_CB_Y_CR: /* Fall through */
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ x = (rect->x / 2) * 2;
+ width = ((rect->width + 1) / 2) * 2;
+ break;
+ default:
+ x = rect->x;
+ width = rect->width;
+ break;
+ }
+
+ sa.start = (unsigned long)resolved->virtual_address +
+ rect->y * pitch + (x * bpp) / 8;
+ sa.end = (unsigned long)sa.start +
+ (rect->height - 1) * pitch +
+ (width * bpp) / 8;
+
+ start_phys = resolved->physical_address +
+ rect->y * pitch + (x * bpp) / 8;
+ end_phys = start_phys +
+ (rect->height - 1) * pitch +
+ (width * bpp) / 8;
+ }
+ }
+
+ /*
+ * The virtual address to a pmem buffer is retrieved from ioremap, not
+ * sure if it's ok to use such an address as a kernel virtual address.
+ * When doing it at a higher level such as dma_map_single it triggers an
+ * error but at lower levels such as dmac_clean_range it seems to work,
+ * hence the low level stuff.
+ */
+
+ if (is_dst) {
+ /*
+ * According to ARM's docs you must clean before invalidating
+ * (ie flush) to avoid loosing data.
+ */
+
+ /* Flush L1 cache */
+#ifdef CONFIG_SMP
+ flush_l1_cache_range_all_cpus(&sa);
+#else
+ flush_l1_cache_range_curr_cpu(&sa);
+#endif
+
+ /* Flush L2 cache */
+ outer_flush_range(start_phys, end_phys);
+ } else {
+ /* Clean L1 cache */
+#ifdef CONFIG_SMP
+ clean_l1_cache_range_all_cpus(&sa);
+#else
+ clean_l1_cache_range_curr_cpu(&sa);
+#endif
+
+ /* Clean L2 cache */
+ outer_clean_range(start_phys, end_phys);
+ }
+}
+
+/**
+ * is_report_list_empty() - Spin lock protected check of report list
+ *
+ * @instance: The B2R2 BLT instance
+ */
+static bool is_report_list_empty(struct b2r2_control_instance *instance)
+{
+ bool is_empty;
+
+ mutex_lock(&instance->lock);
+ is_empty = list_empty(&instance->report_list);
+ mutex_unlock(&instance->lock);
+
+ return is_empty;
+}
+
+/**
+ * is_synching() - Spin lock protected check if synching
+ *
+ * @instance: The B2R2 BLT instance
+ */
+static bool is_synching(struct b2r2_control_instance *instance)
+{
+ bool is_synching;
+
+ mutex_lock(&instance->lock);
+ is_synching = instance->synching;
+ mutex_unlock(&instance->lock);
+
+ return is_synching;
+}
+
+/**
+ * inc_stat() - Spin lock protected increment of statistics variable
+ *
+ * @stat: Pointer to statistics variable that should be incremented
+ */
+static void inc_stat(struct b2r2_control *cont, unsigned long *stat)
+{
+ mutex_lock(&cont->stat_lock);
+ (*stat)++;
+ mutex_unlock(&cont->stat_lock);
+}
+
+/**
+ * inc_stat() - Spin lock protected decrement of statistics variable
+ *
+ * @stat: Pointer to statistics variable that should be decremented
+ */
+static void dec_stat(struct b2r2_control *cont, unsigned long *stat)
+{
+ mutex_lock(&cont->stat_lock);
+ (*stat)--;
+ mutex_unlock(&cont->stat_lock);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * debugfs_b2r2_blt_request_read() - Implements debugfs read for B2R2 register
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_blt_request_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ size_t dev_size = 0;
+ int ret = 0;
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+ struct b2r2_control *cont = filp->f_dentry->d_inode->i_private;
+
+ if (Buf == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_size = sprintf_req(&cont->debugfs_latest_request, Buf,
+ sizeof(char) * 4096);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, Buf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ if (Buf != NULL)
+ kfree(Buf);
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_blt_request_fops - File operations for B2R2 request debugfs
+ */
+static const struct file_operations debugfs_b2r2_blt_request_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_blt_request_read,
+};
+
+/**
+ * struct debugfs_reg - Represents a B2R2 node "register"
+ *
+ * @name: Register name
+ * @offset: Offset within the node
+ */
+struct debugfs_reg {
+ const char name[30];
+ u32 offset;
+};
+
+/**
+ * debugfs_node_regs - Array with all the registers in a B2R2 node, for debug
+ */
+static const struct debugfs_reg debugfs_node_regs[] = {
+ {"GROUP0.B2R2_NIP", offsetof(struct b2r2_link_list, GROUP0.B2R2_NIP)},
+ {"GROUP0.B2R2_CIC", offsetof(struct b2r2_link_list, GROUP0.B2R2_CIC)},
+ {"GROUP0.B2R2_INS", offsetof(struct b2r2_link_list, GROUP0.B2R2_INS)},
+ {"GROUP0.B2R2_ACK", offsetof(struct b2r2_link_list, GROUP0.B2R2_ACK)},
+
+ {"GROUP1.B2R2_TBA", offsetof(struct b2r2_link_list, GROUP1.B2R2_TBA)},
+ {"GROUP1.B2R2_TTY", offsetof(struct b2r2_link_list, GROUP1.B2R2_TTY)},
+ {"GROUP1.B2R2_TXY", offsetof(struct b2r2_link_list, GROUP1.B2R2_TXY)},
+ {"GROUP1.B2R2_TSZ", offsetof(struct b2r2_link_list, GROUP1.B2R2_TSZ)},
+
+ {"GROUP2.B2R2_S1CF", offsetof(struct b2r2_link_list, GROUP2.B2R2_S1CF)},
+ {"GROUP2.B2R2_S2CF", offsetof(struct b2r2_link_list, GROUP2.B2R2_S2CF)},
+
+ {"GROUP3.B2R2_SBA", offsetof(struct b2r2_link_list, GROUP3.B2R2_SBA)},
+ {"GROUP3.B2R2_STY", offsetof(struct b2r2_link_list, GROUP3.B2R2_STY)},
+ {"GROUP3.B2R2_SXY", offsetof(struct b2r2_link_list, GROUP3.B2R2_SXY)},
+ {"GROUP3.B2R2_SSZ", offsetof(struct b2r2_link_list, GROUP3.B2R2_SSZ)},
+
+ {"GROUP4.B2R2_SBA", offsetof(struct b2r2_link_list, GROUP4.B2R2_SBA)},
+ {"GROUP4.B2R2_STY", offsetof(struct b2r2_link_list, GROUP4.B2R2_STY)},
+ {"GROUP4.B2R2_SXY", offsetof(struct b2r2_link_list, GROUP4.B2R2_SXY)},
+ {"GROUP4.B2R2_SSZ", offsetof(struct b2r2_link_list, GROUP4.B2R2_SSZ)},
+
+ {"GROUP5.B2R2_SBA", offsetof(struct b2r2_link_list, GROUP5.B2R2_SBA)},
+ {"GROUP5.B2R2_STY", offsetof(struct b2r2_link_list, GROUP5.B2R2_STY)},
+ {"GROUP5.B2R2_SXY", offsetof(struct b2r2_link_list, GROUP5.B2R2_SXY)},
+ {"GROUP5.B2R2_SSZ", offsetof(struct b2r2_link_list, GROUP5.B2R2_SSZ)},
+
+ {"GROUP6.B2R2_CWO", offsetof(struct b2r2_link_list, GROUP6.B2R2_CWO)},
+ {"GROUP6.B2R2_CWS", offsetof(struct b2r2_link_list, GROUP6.B2R2_CWS)},
+
+ {"GROUP7.B2R2_CCO", offsetof(struct b2r2_link_list, GROUP7.B2R2_CCO)},
+ {"GROUP7.B2R2_CML", offsetof(struct b2r2_link_list, GROUP7.B2R2_CML)},
+
+ {"GROUP8.B2R2_FCTL", offsetof(struct b2r2_link_list, GROUP8.B2R2_FCTL)},
+ {"GROUP8.B2R2_PMK", offsetof(struct b2r2_link_list, GROUP8.B2R2_PMK)},
+
+ {"GROUP9.B2R2_RSF", offsetof(struct b2r2_link_list, GROUP9.B2R2_RSF)},
+ {"GROUP9.B2R2_RZI", offsetof(struct b2r2_link_list, GROUP9.B2R2_RZI)},
+ {"GROUP9.B2R2_HFP", offsetof(struct b2r2_link_list, GROUP9.B2R2_HFP)},
+ {"GROUP9.B2R2_VFP", offsetof(struct b2r2_link_list, GROUP9.B2R2_VFP)},
+
+ {"GROUP10.B2R2_RSF", offsetof(struct b2r2_link_list, GROUP10.B2R2_RSF)},
+ {"GROUP10.B2R2_RZI", offsetof(struct b2r2_link_list, GROUP10.B2R2_RZI)},
+ {"GROUP10.B2R2_HFP", offsetof(struct b2r2_link_list, GROUP10.B2R2_HFP)},
+ {"GROUP10.B2R2_VFP", offsetof(struct b2r2_link_list, GROUP10.B2R2_VFP)},
+
+ {"GROUP11.B2R2_FF0", offsetof(struct b2r2_link_list,
+ GROUP11.B2R2_FF0)},
+ {"GROUP11.B2R2_FF1", offsetof(struct b2r2_link_list,
+ GROUP11.B2R2_FF1)},
+ {"GROUP11.B2R2_FF2", offsetof(struct b2r2_link_list,
+ GROUP11.B2R2_FF2)},
+ {"GROUP11.B2R2_FF3", offsetof(struct b2r2_link_list,
+ GROUP11.B2R2_FF3)},
+
+ {"GROUP12.B2R2_KEY1", offsetof(struct b2r2_link_list,
+ GROUP12.B2R2_KEY1)},
+ {"GROUP12.B2R2_KEY2", offsetof(struct b2r2_link_list,
+ GROUP12.B2R2_KEY2)},
+
+ {"GROUP13.B2R2_XYL", offsetof(struct b2r2_link_list, GROUP13.B2R2_XYL)},
+ {"GROUP13.B2R2_XYP", offsetof(struct b2r2_link_list, GROUP13.B2R2_XYP)},
+
+ {"GROUP14.B2R2_SAR", offsetof(struct b2r2_link_list, GROUP14.B2R2_SAR)},
+ {"GROUP14.B2R2_USR", offsetof(struct b2r2_link_list, GROUP14.B2R2_USR)},
+
+ {"GROUP15.B2R2_VMX0", offsetof(struct b2r2_link_list,
+ GROUP15.B2R2_VMX0)},
+ {"GROUP15.B2R2_VMX1", offsetof(struct b2r2_link_list,
+ GROUP15.B2R2_VMX1)},
+ {"GROUP15.B2R2_VMX2", offsetof(struct b2r2_link_list,
+ GROUP15.B2R2_VMX2)},
+ {"GROUP15.B2R2_VMX3", offsetof(struct b2r2_link_list,
+ GROUP15.B2R2_VMX3)},
+
+ {"GROUP16.B2R2_VMX0", offsetof(struct b2r2_link_list,
+ GROUP16.B2R2_VMX0)},
+ {"GROUP16.B2R2_VMX1", offsetof(struct b2r2_link_list,
+ GROUP16.B2R2_VMX1)},
+ {"GROUP16.B2R2_VMX2", offsetof(struct b2r2_link_list,
+ GROUP16.B2R2_VMX2)},
+ {"GROUP16.B2R2_VMX3", offsetof(struct b2r2_link_list,
+ GROUP16.B2R2_VMX3)},
+};
+
+/**
+ * debugfs_b2r2_blt_stat_read() - Implements debugfs read for B2R2 BLT
+ * statistics
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_blt_stat_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ size_t dev_size = 0;
+ int ret = 0;
+ char *Buf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+ struct b2r2_control *cont = filp->f_dentry->d_inode->i_private;
+
+ if (Buf == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mutex_lock(&cont->stat_lock);
+ dev_size += sprintf(Buf + dev_size, "Added jobs : %lu\n",
+ cont->stat_n_jobs_added);
+ dev_size += sprintf(Buf + dev_size, "Released jobs : %lu\n",
+ cont->stat_n_jobs_released);
+ dev_size += sprintf(Buf + dev_size, "Jobs in report list : %lu\n",
+ cont->stat_n_jobs_in_report_list);
+ dev_size += sprintf(Buf + dev_size, "Clients in open : %lu\n",
+ cont->stat_n_in_open);
+ dev_size += sprintf(Buf + dev_size, "Clients in release : %lu\n",
+ cont->stat_n_in_release);
+ dev_size += sprintf(Buf + dev_size, "Clients in blt : %lu\n",
+ cont->stat_n_in_blt);
+ dev_size += sprintf(Buf + dev_size, " synch : %lu\n",
+ cont->stat_n_in_blt_synch);
+ dev_size += sprintf(Buf + dev_size, " add : %lu\n",
+ cont->stat_n_in_blt_add);
+ dev_size += sprintf(Buf + dev_size, " wait : %lu\n",
+ cont->stat_n_in_blt_wait);
+ dev_size += sprintf(Buf + dev_size, "Clients in synch 0 : %lu\n",
+ cont->stat_n_in_synch_0);
+ dev_size += sprintf(Buf + dev_size, "Clients in synch job : %lu\n",
+ cont->stat_n_in_synch_job);
+ dev_size += sprintf(Buf + dev_size, "Clients in query_cap : %lu\n",
+ cont->stat_n_in_query_cap);
+ mutex_unlock(&cont->stat_lock);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, Buf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ if (Buf != NULL)
+ kfree(Buf);
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_blt_stat_fops() - File operations for B2R2 BLT
+ * statistics debugfs
+ */
+static const struct file_operations debugfs_b2r2_blt_stat_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_blt_stat_read,
+};
+#endif
+
+static void init_tmp_bufs(struct b2r2_control *cont)
+{
+ int i = 0;
+
+ for (i = 0; i < (sizeof(cont->tmp_bufs) / sizeof(struct tmp_buf));
+ i++) {
+ cont->tmp_bufs[i].buf.virt_addr = dma_alloc_coherent(
+ cont->dev, MAX_TMP_BUF_SIZE,
+ &cont->tmp_bufs[i].buf.phys_addr, GFP_DMA);
+ if (cont->tmp_bufs[i].buf.virt_addr != NULL)
+ cont->tmp_bufs[i].buf.size = MAX_TMP_BUF_SIZE;
+ else {
+ b2r2_log_err(cont->dev, "%s: Failed to allocate temp "
+ "buffer %i\n", __func__, i);
+ cont->tmp_bufs[i].buf.size = 0;
+ }
+ }
+}
+
+static void destroy_tmp_bufs(struct b2r2_control *cont)
+{
+ int i = 0;
+
+ for (i = 0; i < MAX_TMP_BUFS_NEEDED; i++) {
+ if (cont->tmp_bufs[i].buf.size != 0) {
+ dma_free_coherent(cont->dev,
+ cont->tmp_bufs[i].buf.size,
+ cont->tmp_bufs[i].buf.virt_addr,
+ cont->tmp_bufs[i].buf.phys_addr);
+
+ cont->tmp_bufs[i].buf.size = 0;
+ }
+ }
+}
+
+/**
+ * b2r2_blt_module_init() - Module init function
+ *
+ * Returns 0 if OK else negative error code
+ */
+int b2r2_control_init(struct b2r2_control *cont)
+{
+ int ret;
+
+ mutex_init(&cont->stat_lock);
+
+#ifdef CONFIG_B2R2_GENERIC
+ /* Initialize generic path */
+ b2r2_generic_init(cont);
+#endif
+ /* Initialize node splitter */
+ ret = b2r2_node_split_init(cont);
+ if (ret) {
+ printk(KERN_WARNING "%s: node split init fails\n", __func__);
+ goto b2r2_node_split_init_fail;
+ }
+
+ b2r2_log_info(cont->dev, "%s: device registered\n", __func__);
+
+ cont->dev->coherent_dma_mask = 0xFFFFFFFF;
+ init_tmp_bufs(cont);
+ ret = b2r2_filters_init(cont);
+ if (ret) {
+ b2r2_log_warn(cont->dev, "%s: failed to init filters\n",
+ __func__);
+ goto b2r2_filter_init_fail;
+ }
+
+ /* Initialize memory allocator */
+ ret = b2r2_mem_init(cont, B2R2_HEAP_SIZE,
+ 4, sizeof(struct b2r2_node));
+ if (ret) {
+ printk(KERN_WARNING "%s: initializing B2R2 memhandler fails\n",
+ __func__);
+ goto b2r2_mem_init_fail;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ /* Register debug fs */
+ if (!IS_ERR_OR_NULL(cont->debugfs_root_dir)) {
+ debugfs_create_file("last_request", 0666,
+ cont->debugfs_root_dir,
+ cont, &debugfs_b2r2_blt_request_fops);
+ debugfs_create_file("stats", 0666,
+ cont->debugfs_root_dir,
+ cont, &debugfs_b2r2_blt_stat_fops);
+ }
+#endif
+
+ b2r2_log_info(cont->dev, "%s: done\n", __func__);
+
+ return ret;
+
+b2r2_mem_init_fail:
+ b2r2_filters_exit(cont);
+b2r2_filter_init_fail:
+ b2r2_node_split_exit(cont);
+b2r2_node_split_init_fail:
+#ifdef CONFIG_B2R2_GENERIC
+ b2r2_generic_exit(cont);
+#endif
+ return ret;
+}
+
+/**
+ * b2r2_control_exit() - Module exit function
+ */
+void b2r2_control_exit(struct b2r2_control *cont)
+{
+ if (cont) {
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+#ifdef CONFIG_DEBUG_FS
+ if (!IS_ERR_OR_NULL(cont->debugfs_root_dir)) {
+ debugfs_remove_recursive(cont->debugfs_root_dir);
+ cont->debugfs_root_dir = NULL;
+ }
+#endif
+ b2r2_mem_exit(cont);
+ destroy_tmp_bufs(cont);
+ b2r2_node_split_exit(cont);
+#if defined(CONFIG_B2R2_GENERIC)
+ b2r2_generic_exit(cont);
+#endif
+ b2r2_filters_exit(cont);
+ }
+}
+
+MODULE_AUTHOR("Robert Fekete <robert.fekete@stericsson.com>");
+MODULE_DESCRIPTION("ST-Ericsson B2R2 Blitter module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/b2r2/b2r2_control.h b/drivers/video/b2r2/b2r2_control.h
new file mode 100644
index 00000000000..d13d2188618
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_control.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * ST-Ericsson B2R2 internal definitions
+ *
+ * Author: Jorgen Nilsson <jorgen.nilsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_CONTROL_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_CONTROL_H_
+
+#include "b2r2_internal.h"
+
+int b2r2_control_init(struct b2r2_control *cont);
+void b2r2_control_exit(struct b2r2_control *cont);
+int b2r2_control_open(struct b2r2_control_instance *instance);
+int b2r2_control_release(struct b2r2_control_instance *instance);
+
+int b2r2_control_blt(struct b2r2_blt_request *request);
+int b2r2_generic_blt(struct b2r2_blt_request *request);
+int b2r2_control_waitjob(struct b2r2_blt_request *request);
+int b2r2_control_synch(struct b2r2_control_instance *instance,
+ int request_id);
+size_t b2r2_control_read(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block);
+size_t b2r2_control_read_id(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block,
+ int request_id);
+
+#endif
diff --git a/drivers/video/b2r2/b2r2_core.c b/drivers/video/b2r2/b2r2_core.c
new file mode 100644
index 00000000000..02071d5f989
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_core.c
@@ -0,0 +1,2763 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 core driver
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+/*
+ * TODO: Clock address from platform data
+ * Platform data should have string id instead of numbers
+ * b2r2_remove, some type of runtime problem when kernel hacking
+ * debug features on
+ *
+ * Is there already a priority list in kernel?
+ * Is it possible to handle clock using clock framework?
+ * uTimeOut, use mdelay instead?
+ * Measure performance
+ *
+ * Exchange our home-cooked ref count with kernel kref? See
+ * http://lwn.net/Articles/336224/
+ *
+ * B2R2:
+ * Source fill 2 bug
+ * Check with Symbian?
+ */
+
+/* include file */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/kref.h>
+
+#include "b2r2_internal.h"
+#include "b2r2_core.h"
+#include "b2r2_global.h"
+#include "b2r2_structures.h"
+#include "b2r2_control.h"
+#include "b2r2_profiler_api.h"
+#include "b2r2_timing.h"
+#include "b2r2_debug.h"
+
+/**
+ * B2R2 Hardware defines below
+ */
+
+/* - BLT_AQ_CTL */
+#define B2R2_AQ_Enab (0x80000000)
+#define B2R2_AQ_PRIOR_0 (0x0)
+#define B2R2_AQ_PRIOR_1 (0x1)
+#define B2R2_AQ_PRIOR_2 (0x2)
+#define B2R2_AQ_PRIOR_3 (0x3)
+#define B2R2_AQ_NODE_REPEAT_INT (0x100000)
+#define B2R2_AQ_STOP_INT (0x200000)
+#define B2R2_AQ_LNA_REACH_INT (0x400000)
+#define B2R2_AQ_COMPLETED_INT (0x800000)
+
+/* - BLT_CTL */
+#define B2R2BLT_CTLGLOBAL_soft_reset (0x80000000)
+#define B2R2BLT_CTLStep_By_Step (0x20000000)
+#define B2R2BLT_CTLBig_not_little (0x10000000)
+#define B2R2BLT_CTLMask (0xb0000000)
+#define B2R2BLT_CTLTestMask (0xb0000000)
+#define B2R2BLT_CTLInitialValue (0x0)
+#define B2R2BLT_CTLAccessType (INITIAL_TEST)
+#define B2R2BLT_CTL (0xa00)
+
+/* - BLT_ITS */
+#define B2R2BLT_ITSRLD_ERROR (0x80000000)
+#define B2R2BLT_ITSAQ4_Node_Notif (0x8000000)
+#define B2R2BLT_ITSAQ4_Node_repeat (0x4000000)
+#define B2R2BLT_ITSAQ4_Stopped (0x2000000)
+#define B2R2BLT_ITSAQ4_LNA_Reached (0x1000000)
+#define B2R2BLT_ITSAQ3_Node_Notif (0x800000)
+#define B2R2BLT_ITSAQ3_Node_repeat (0x400000)
+#define B2R2BLT_ITSAQ3_Stopped (0x200000)
+#define B2R2BLT_ITSAQ3_LNA_Reached (0x100000)
+#define B2R2BLT_ITSAQ2_Node_Notif (0x80000)
+#define B2R2BLT_ITSAQ2_Node_repeat (0x40000)
+#define B2R2BLT_ITSAQ2_Stopped (0x20000)
+#define B2R2BLT_ITSAQ2_LNA_Reached (0x10000)
+#define B2R2BLT_ITSAQ1_Node_Notif (0x8000)
+#define B2R2BLT_ITSAQ1_Node_repeat (0x4000)
+#define B2R2BLT_ITSAQ1_Stopped (0x2000)
+#define B2R2BLT_ITSAQ1_LNA_Reached (0x1000)
+#define B2R2BLT_ITSCQ2_Repaced (0x80)
+#define B2R2BLT_ITSCQ2_Node_Notif (0x40)
+#define B2R2BLT_ITSCQ2_retriggered (0x20)
+#define B2R2BLT_ITSCQ2_completed (0x10)
+#define B2R2BLT_ITSCQ1_Repaced (0x8)
+#define B2R2BLT_ITSCQ1_Node_Notif (0x4)
+#define B2R2BLT_ITSCQ1_retriggered (0x2)
+#define B2R2BLT_ITSCQ1_completed (0x1)
+#define B2R2BLT_ITSMask (0x8ffff0ff)
+#define B2R2BLT_ITSTestMask (0x8ffff0ff)
+#define B2R2BLT_ITSInitialValue (0x0)
+#define B2R2BLT_ITSAccessType (INITIAL_TEST)
+#define B2R2BLT_ITS (0xa04)
+
+/* - BLT_STA1 */
+#define B2R2BLT_STA1BDISP_IDLE (0x1)
+#define B2R2BLT_STA1Mask (0x1)
+#define B2R2BLT_STA1TestMask (0x1)
+#define B2R2BLT_STA1InitialValue (0x1)
+#define B2R2BLT_STA1AccessType (INITIAL_TEST)
+#define B2R2BLT_STA1 (0xa08)
+
+/**
+ * b2r2_core - Quick link to administration data for B2R2
+ */
+static struct b2r2_core *b2r2_core[B2R2_MAX_NBR_DEVICES];
+
+/* Local functions */
+static void check_prio_list(struct b2r2_core *core, bool atomic);
+static void clear_interrupts(struct b2r2_core *core);
+static void trigger_job(struct b2r2_core *core, struct b2r2_core_job *job);
+static void exit_job_list(struct b2r2_core *core,
+ struct list_head *job_list);
+static void job_work_function(struct work_struct *ptr);
+static void init_job(struct b2r2_core_job *job);
+static void insert_into_prio_list(struct b2r2_core *core,
+ struct b2r2_core_job *job);
+static struct b2r2_core_job *find_job_in_list(int job_id,
+ struct list_head *list);
+static struct b2r2_core_job *find_job_in_active_jobs(struct b2r2_core *core,
+ int job_id);
+static struct b2r2_core_job *find_tag_in_list(struct b2r2_core *core,
+ int tag, struct list_head *list);
+static struct b2r2_core_job *find_tag_in_active_jobs(struct b2r2_core *core,
+ int tag);
+
+static int domain_enable(struct b2r2_core *core);
+static void domain_disable(struct b2r2_core *core);
+
+static void stop_queue(enum b2r2_core_queue queue);
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+static void printk_regs(struct b2r2_core *core);
+static int hw_reset(struct b2r2_core *core);
+static void timeout_work_function(struct work_struct *ptr);
+#endif
+
+static void reset_hw_timer(struct b2r2_core_job *job);
+static void start_hw_timer(struct b2r2_core_job *job);
+static void stop_hw_timer(struct b2r2_core *core,
+ struct b2r2_core_job *job);
+
+static int init_hw(struct b2r2_core *core);
+static void exit_hw(struct b2r2_core *core);
+
+/* Tracking release bug... */
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+/**
+ * ar_add() - Adds an addref or a release to the array
+ *
+ * @core: The b2r2 core entity
+ * @job: The job that has been referenced
+ * @caller: The caller of addref / release
+ * @addref: true if it is an addref else false for release
+ */
+static void ar_add(struct b2r2_core *core, struct b2r2_core_job *job,
+ const char *caller, bool addref)
+{
+ core->ar[core->ar_write].addref = addref;
+ core->ar[core->ar_write].job = job;
+ core->ar[core->ar_write].caller = caller;
+ core->ar[core->ar_write].ref_count = job->ref_count;
+ core->ar_write = (core->ar_write + 1) %
+ ARRAY_SIZE(core->ar);
+ if (core->ar_write == core->ar_read)
+ core->ar_read = (core->ar_read + 1) %
+ ARRAY_SIZE(core->ar);
+}
+
+/**
+ * sprintf_ar() - Writes all addref / release to a string buffer
+ *
+ * @core: The b2r2 core entity
+ * @buf: Receiving character bufefr
+ * @job: Which job to write or NULL for all
+ *
+ * NOTE! No buffer size check!!
+ */
+static char *sprintf_ar(struct b2r2_core *core, char *buf,
+ struct b2r2_core_job *job)
+{
+ int i;
+ int size = 0;
+
+ for (i = core->ar_read; i != core->ar_write;
+ i = (i + 1) % ARRAY_SIZE(core->ar)) {
+ struct addref_release *ar = &core->ar[i];
+ if (!job || job == ar->job)
+ size += sprintf(buf + size,
+ "%s on %p from %s, ref = %d\n",
+ ar->addref ? "addref" : "release",
+ ar->job, ar->caller, ar->ref_count);
+ }
+
+ return buf;
+}
+
+/**
+ * printk_ar() - Writes all addref / release using dev_info
+ *
+ * @core: The b2r2 core entity
+ * @job: Which job to write or NULL for all
+ */
+static void printk_ar(struct b2r2_core *core, struct b2r2_core_job *job)
+{
+ int i;
+
+ for (i = core->ar_read; i != core->ar_write;
+ i = (i + 1) % ARRAY_SIZE(core->ar)) {
+ struct addref_release *ar = &core->ar[i];
+ if (!job || job == ar->job)
+ b2r2_log_info(core->dev, "%s on %p from %s,"
+ " ref = %d\n",
+ ar->addref ? "addref" : "release",
+ ar->job, ar->caller, ar->ref_count);
+ }
+}
+#endif
+
+/**
+ * internal_job_addref() - Increments the reference count for a job
+ *
+ * @core: The b2r2 core entity
+ * @job: Which job to increment reference count for
+ * @caller: Name of function calling addref (for debug)
+ *
+ * Note that core->lock _must_ be held
+ */
+static void internal_job_addref(struct b2r2_core *core,
+ struct b2r2_core_job *job, const char *caller)
+{
+ u32 ref_count;
+
+ /* Sanity checks */
+ BUG_ON(core == NULL);
+ BUG_ON(job == NULL);
+
+ b2r2_log_info(core->dev, "%s (core: %p, job: %p) (from %s)\n",
+ __func__, core, job, caller);
+
+
+ if (job->start_sentinel != START_SENTINEL ||
+ job->end_sentinel != END_SENTINEL ||
+ job->ref_count == 0 || job->ref_count > 10) {
+ b2r2_log_info(core->dev, "%s: (core: %p, job: %p) "
+ "start=%X end=%X ref_count=%d\n",
+ __func__, core, job, job->start_sentinel,
+ job->end_sentinel, job->ref_count);
+
+ /* Something is wrong, print the addref / release array */
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+ printk_ar(core, NULL);
+#endif
+ }
+
+
+ BUG_ON(job->start_sentinel != START_SENTINEL);
+ BUG_ON(job->end_sentinel != END_SENTINEL);
+
+ /* Do the actual reference count increment */
+ ref_count = ++job->ref_count;
+
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+ /* Keep track of addref / release */
+ ar_add(core, job, caller, true);
+#endif
+
+ b2r2_log_info(core->dev, "%s called from %s (core: %p, job: %p): Ref "
+ "Count is %d\n", __func__, caller, core, job, job->ref_count);
+}
+
+/**
+ * internal_job_release() - Decrements the reference count for a job
+ *
+ * @core: The b2r2 core entity
+ * @job: Which job to decrement reference count for
+ * @caller: Name of function calling release (for debug)
+ *
+ * Returns true if job_release should be called by caller
+ * (reference count reached zero).
+ *
+ * Note that core->lock _must_ be held
+ */
+static bool internal_job_release(struct b2r2_core *core,
+ struct b2r2_core_job *job, const char *caller)
+{
+ u32 ref_count;
+ bool call_release = false;
+
+ /* Sanity checks */
+ BUG_ON(job == NULL);
+
+ b2r2_log_info(core->dev, "%s (core: %p, job: %p) (from %s)\n",
+ __func__, core, job, caller);
+
+ if (job->start_sentinel != START_SENTINEL ||
+ job->end_sentinel != END_SENTINEL ||
+ job->ref_count == 0 || job->ref_count > 10) {
+ b2r2_log_info(core->dev, "%s: (core: %p, job: %p) start=%X "
+ "end=%X ref_count=%d\n", __func__, core, job,
+ job->start_sentinel, job->end_sentinel,
+ job->ref_count);
+
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+ printk_ar(core, NULL);
+#endif
+ }
+
+ BUG_ON(job->start_sentinel != START_SENTINEL);
+ BUG_ON(job->end_sentinel != END_SENTINEL);
+ BUG_ON(job->ref_count == 0 || job->ref_count > 10);
+
+ /* Do the actual decrement */
+ ref_count = --job->ref_count;
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+ ar_add(core, job, caller, false);
+#endif
+ b2r2_log_info(core->dev, "%s called from %s (core: %p, job: %p) "
+ "Ref Count is %d\n", __func__, caller, core, job, ref_count);
+
+ if (!ref_count && job->release) {
+ call_release = true;
+ /* Job will now cease to exist */
+ job->start_sentinel = 0xFFFFFFFF;
+ job->end_sentinel = 0xFFFFFFFF;
+ }
+ return call_release;
+}
+
+
+
+/* Exported functions */
+
+/**
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+void b2r2_core_job_addref(struct b2r2_core_job *job, const char *caller)
+{
+ unsigned long flags;
+ struct b2r2_core *core;
+
+ BUG_ON(job == NULL || job->data == 0);
+ core = (struct b2r2_core *) job->data;
+
+ spin_lock_irqsave(&core->lock, flags);
+ internal_job_addref(core, job, caller);
+ spin_unlock_irqrestore(&core->lock, flags);
+}
+
+/**
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+void b2r2_core_job_release(struct b2r2_core_job *job, const char *caller)
+{
+ unsigned long flags;
+ bool call_release = false;
+ struct b2r2_core *core;
+
+ BUG_ON(job == NULL || job->data == 0);
+ core = (struct b2r2_core *) job->data;
+
+ spin_lock_irqsave(&core->lock, flags);
+ call_release = internal_job_release(core, job, caller);
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ if (call_release)
+ job->release(job);
+}
+
+/**
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+int b2r2_core_job_add(struct b2r2_control *control,
+ struct b2r2_core_job *job)
+{
+ unsigned long flags;
+ struct b2r2_core *core = control->data;
+
+ b2r2_log_info(core->dev, "%s (core: %p, job: %p)\n",
+ __func__, core, job);
+
+ /* Enable B2R2 */
+ domain_enable(core);
+
+ spin_lock_irqsave(&core->lock, flags);
+ /* Check that we have not been powered down */
+ if (!core->domain_enabled) {
+ spin_unlock_irqrestore(&core->lock, flags);
+ return -ENOSYS;
+ }
+
+ core->stat_n_jobs_added++;
+
+ /* Initialise internal job data */
+ init_job(job);
+
+ /* Initial reference, should be released by caller of this function */
+ job->ref_count = 1;
+
+ /* Insert job into prio list */
+ insert_into_prio_list(core, job);
+
+ /* Check if we can dispatch job */
+ check_prio_list(core, false);
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return job->job_id;
+}
+
+/**
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+struct b2r2_core_job *b2r2_core_job_find(struct b2r2_control *control,
+ int job_id)
+{
+ unsigned long flags;
+ struct b2r2_core_job *job;
+ struct b2r2_core *core = control->data;
+
+ b2r2_log_info(core->dev, "%s (core: %p, job_id: %d)\n",
+ __func__, core, job_id);
+
+ spin_lock_irqsave(&core->lock, flags);
+ /* Look through prio queue */
+ job = find_job_in_list(job_id, &core->prio_queue);
+
+ if (!job)
+ job = find_job_in_active_jobs(core, job_id);
+
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return job;
+}
+
+/**
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+struct b2r2_core_job *b2r2_core_job_find_first_with_tag(
+ struct b2r2_control *control, int tag)
+{
+ unsigned long flags;
+ struct b2r2_core_job *job;
+ struct b2r2_core *core = control->data;
+
+ b2r2_log_info(core->dev,
+ "%s (core: %p, tag: %d)\n", __func__, core, tag);
+
+ spin_lock_irqsave(&core->lock, flags);
+ /* Look through prio queue */
+ job = find_tag_in_list(core, tag, &core->prio_queue);
+
+ if (!job)
+ job = find_tag_in_active_jobs(core, tag);
+
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return job;
+}
+
+/**
+ * is_job_done() - Spin lock protected check if job is done
+ *
+ * @job: Job to check
+ *
+ * Returns true if job is done or cancelled
+ *
+ * core->lock must _NOT_ be held when calling this function
+ */
+static bool is_job_done(struct b2r2_core_job *job)
+{
+ unsigned long flags;
+ bool job_is_done;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+
+ spin_lock_irqsave(&core->lock, flags);
+ job_is_done =
+ job->job_state != B2R2_CORE_JOB_QUEUED &&
+ job->job_state != B2R2_CORE_JOB_RUNNING;
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return job_is_done;
+}
+
+/**
+ * b2r2_core_job_wait()
+ *
+ * @job:
+ *
+ * core->lock _must_ _NOT_ be held when calling this function
+ */
+int b2r2_core_job_wait(struct b2r2_core_job *job)
+{
+ int ret = 0;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+#endif
+
+ b2r2_log_info(core->dev, "%s (core: %p, job: %p)\n",
+ __func__, core, job);
+ /* Check that we have the job */
+ if (job->job_state == B2R2_CORE_JOB_IDLE) {
+ /* Never or not queued */
+ b2r2_log_info(core->dev, "%s: Job not queued\n", __func__);
+ return -ENOENT;
+ }
+
+ /* Wait for the job to be done */
+ ret = wait_event_interruptible(
+ job->event,
+ is_job_done(job));
+
+ if (ret)
+ b2r2_log_warn(core->dev,
+ "%s: wait_event_interruptible returns %d state is %d",
+ __func__, ret, job->job_state);
+ return ret;
+}
+
+/**
+ * cancel_job() - Cancels a job (removes it from prio list or active jobs) and
+ * calls the job callback
+ *
+ * @job: Job to cancel
+ *
+ * Returns true if the job was found and cancelled
+ *
+ * core->lock must be held when calling this function
+ */
+static bool cancel_job(struct b2r2_core *core, struct b2r2_core_job *job)
+{
+ bool found_job = false;
+ bool job_was_active = false;
+
+ /* Remove from prio list */
+ if (job->job_state == B2R2_CORE_JOB_QUEUED) {
+ list_del_init(&job->list);
+ found_job = true;
+ }
+
+ /* Remove from active jobs */
+ if (!found_job && core->n_active_jobs > 0) {
+ int i;
+
+ /* Look for timeout:ed jobs and put them in tmp list */
+ for (i = 0; i < ARRAY_SIZE(core->active_jobs); i++) {
+ if (core->active_jobs[i] == job) {
+ stop_queue((enum b2r2_core_queue)i);
+ stop_hw_timer(core, job);
+ core->active_jobs[i] = NULL;
+ core->n_active_jobs--;
+ found_job = true;
+ job_was_active = true;
+ }
+ }
+ }
+
+ /* Handle done list & callback */
+ if (found_job) {
+ /* Job is canceled */
+ job->job_state = B2R2_CORE_JOB_CANCELED;
+
+ queue_work(core->work_queue, &job->work);
+
+ /* Statistics */
+ if (!job_was_active)
+ core->stat_n_jobs_in_prio_list--;
+
+ }
+
+ return found_job;
+}
+
+/* core->lock _must_ _NOT_ be held when calling this function */
+int b2r2_core_job_cancel(struct b2r2_core_job *job)
+{
+ unsigned long flags;
+ int ret = 0;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+
+ b2r2_log_info(core->dev, "%s (core: %p, job: %p) (st: %d)\n",
+ __func__, core, job, job->job_state);
+ /* Check that we have the job */
+ if (job->job_state == B2R2_CORE_JOB_IDLE) {
+ /* Never or not queued */
+ b2r2_log_info(core->dev, "%s: Job not queued\n", __func__);
+ return -ENOENT;
+ }
+
+ /* Remove from prio list */
+ spin_lock_irqsave(&core->lock, flags);
+ cancel_job(core, job);
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return ret;
+}
+
+/* LOCAL FUNCTIONS BELOW */
+
+/**
+ * domain_disable_work_function()
+ *
+ * @core: The b2r2 core entity
+ */
+static void domain_disable_work_function(struct work_struct *work)
+{
+ struct delayed_work *twork = to_delayed_work(work);
+ struct b2r2_core *core = container_of(
+ twork, struct b2r2_core, domain_disable_work);
+
+ if (!mutex_trylock(&core->domain_lock))
+ return;
+
+ if (core->domain_request_count == 0) {
+ core->valid = false;
+ exit_hw(core);
+ clk_disable(core->b2r2_clock);
+ regulator_disable(core->b2r2_reg);
+ core->domain_enabled = false;
+ }
+
+ mutex_unlock(&core->domain_lock);
+}
+
+/**
+ * domain_enable()
+ *
+ * @core: The b2r2 core entity
+ */
+static int domain_enable(struct b2r2_core *core)
+{
+ mutex_lock(&core->domain_lock);
+ core->domain_request_count++;
+
+ if (!core->domain_enabled) {
+ int retry = 0;
+ int ret;
+again:
+ /*
+ * Since regulator_enable() may sleep we have to handle
+ * interrupts.
+ */
+ ret = regulator_enable(core->b2r2_reg);
+ if ((ret == -EAGAIN) &&
+ ((retry++) < B2R2_REGULATOR_RETRY_COUNT))
+ goto again;
+ else if (ret < 0)
+ goto regulator_enable_failed;
+
+ ret = clk_enable(core->b2r2_clock);
+ if (ret < 0) {
+ b2r2_log_err(core->dev,
+ "%s: Could not enable clock\n", __func__);
+ goto enable_clk_failed;
+ }
+ if (init_hw(core) < 0)
+ goto init_hw_failed;
+ core->domain_enabled = true;
+ core->valid = true;
+ }
+
+ mutex_unlock(&core->domain_lock);
+
+ return 0;
+
+init_hw_failed:
+ b2r2_log_err(core->dev,
+ "%s: Could not initialize hardware!\n", __func__);
+ clk_disable(core->b2r2_clock);
+
+enable_clk_failed:
+ if (regulator_disable(core->b2r2_reg) < 0)
+ b2r2_log_err(core->dev, "%s: regulator_disable failed!\n",
+ __func__);
+
+regulator_enable_failed:
+ core->domain_request_count--;
+ mutex_unlock(&core->domain_lock);
+
+ return -EFAULT;
+}
+
+/**
+ * domain_disable()
+ *
+ * @core: The b2r2 core entity
+ */
+static void domain_disable(struct b2r2_core *core)
+{
+ mutex_lock(&core->domain_lock);
+
+ if (core->domain_request_count == 0) {
+ b2r2_log_err(core->dev,
+ "%s: Unbalanced domain_disable()\n", __func__);
+ } else {
+ core->domain_request_count--;
+
+ /* Cancel any existing work */
+ cancel_delayed_work_sync(&core->domain_disable_work);
+
+ /* Add a work to disable the power and clock after a delay */
+ queue_delayed_work(core->work_queue, &core->domain_disable_work,
+ B2R2_DOMAIN_DISABLE_TIMEOUT);
+ }
+
+ mutex_unlock(&core->domain_lock);
+}
+
+/**
+ * stop_queue() - Stops the specified queue.
+ */
+static void stop_queue(enum b2r2_core_queue queue)
+{
+ /* TODO: Implement! If this function is not implemented canceled jobs
+ * will use b2r2 which is a waste of resources. Not stopping jobs will
+ * also screw up the hardware timing, the job the canceled job
+ * intrerrupted (if any) will be billed for the time between the point
+ * where the job is cancelled and when it stops. */
+}
+
+/**
+ * exit_job_list() - Empties a job queue by canceling the jobs
+ *
+ * @core: The b2r2 core entity
+ *
+ * core->lock _must_ be held when calling this function
+ */
+static void exit_job_list(struct b2r2_core *core,
+ struct list_head *job_queue)
+{
+ while (!list_empty(job_queue)) {
+ struct b2r2_core_job *job =
+ list_entry(job_queue->next,
+ struct b2r2_core_job,
+ list);
+ /* Add reference to prevent job from disappearing
+ in the middle of our work, released below */
+ internal_job_addref(core, job, __func__);
+
+ cancel_job(core, job);
+
+ /* Matching release to addref above */
+ internal_job_release(core, job, __func__);
+
+ }
+}
+
+/**
+ * job_work_function() - Work queue function that calls callback(s) and
+ * checks if B2R2 can accept a new job
+ *
+ * @ptr: Pointer to work struct (embedded in struct b2r2_core_job)
+ */
+static void job_work_function(struct work_struct *ptr)
+{
+ unsigned long flags;
+ struct b2r2_core_job *job =
+ container_of(ptr, struct b2r2_core_job, work);
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+
+ /* Disable B2R2 */
+ domain_disable(core);
+
+ /* Release resources */
+ if (job->release_resources)
+ job->release_resources(job, false);
+
+ spin_lock_irqsave(&core->lock, flags);
+
+ /* Dispatch a new job if possible */
+ check_prio_list(core, false);
+
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ /* Tell the client */
+ if (job->callback)
+ job->callback(job);
+
+ /* Drop our reference, matches the
+ addref in handle_queue_event or b2r2_core_job_cancel */
+ b2r2_core_job_release(job, __func__);
+}
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+/**
+ * timeout_work_function() - Work queue function that checks for
+ * timeout:ed jobs. B2R2 might silently refuse
+ * to execute some jobs, i.e. SRC2 fill
+ *
+ * @ptr: Pointer to work struct (embedded in struct b2r2_core)
+ *
+ */
+static void timeout_work_function(struct work_struct *ptr)
+{
+ unsigned long flags;
+ struct list_head job_list;
+ struct delayed_work *twork = to_delayed_work(ptr);
+ struct b2r2_core *core = container_of(twork, struct b2r2_core,
+ timeout_work);
+
+ INIT_LIST_HEAD(&job_list);
+
+ /* Cancel all jobs if too long time since last irq */
+ spin_lock_irqsave(&core->lock, flags);
+ if (core->n_active_jobs > 0) {
+ unsigned long diff =
+ (long) jiffies - (long) core->jiffies_last_irq;
+ if (diff > JOB_TIMEOUT) {
+ /* Active jobs and more than a second since last irq! */
+ int i;
+
+ b2r2_core_print_stats(core);
+
+ /* Look for timeout:ed jobs and put them in tmp list.
+ * It's important that the application queues are
+ * killed in order of decreasing priority */
+ for (i = 0; i < ARRAY_SIZE(core->active_jobs); i++) {
+ struct b2r2_core_job *job =
+ core->active_jobs[i];
+
+ if (job) {
+ stop_hw_timer(core, job);
+ core->active_jobs[i] = NULL;
+ core->n_active_jobs--;
+ list_add_tail(&job->list, &job_list);
+ }
+ }
+
+ /* Print the B2R2 register and reset B2R2 */
+ printk_regs(core);
+ hw_reset(core);
+ }
+ }
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ /* Handle timeout:ed jobs */
+ spin_lock_irqsave(&core->lock, flags);
+ while (!list_empty(&job_list)) {
+ struct b2r2_core_job *job =
+ list_entry(job_list.next,
+ struct b2r2_core_job,
+ list);
+
+ b2r2_log_warn(core->dev, "%s: Job timeout\n", __func__);
+
+ list_del_init(&job->list);
+
+ /* Job is cancelled */
+ job->job_state = B2R2_CORE_JOB_CANCELED;
+
+ /* Handle done */
+ wake_up_interruptible(&job->event);
+
+ /* Job callbacks handled via work queue */
+ queue_work(core->work_queue, &job->work);
+ }
+
+ /* Requeue delayed work */
+ if (core->n_active_jobs)
+ queue_delayed_work(
+ core->work_queue,
+ &core->timeout_work, JOB_TIMEOUT);
+
+ spin_unlock_irqrestore(&core->lock, flags);
+}
+#endif
+
+/**
+ * reset_hw_timer() - Resets a job's hardware timer. Must be called before
+ * the timer is used.
+ *
+ * @job: Pointer to job struct
+ *
+ * core->lock _must_ be held when calling this function
+ */
+static void reset_hw_timer(struct b2r2_core_job *job)
+{
+ job->nsec_active_in_hw = 0;
+}
+
+/**
+ * start_hw_timer() - Times how long a job spends in hardware (active).
+ * Should be called immediatly before starting the
+ * hardware.
+ *
+ * @job: Pointer to job struct
+ *
+ * core->lock _must_ be held when calling this function
+ */
+static void start_hw_timer(struct b2r2_core_job *job)
+{
+ job->hw_start_time = b2r2_get_curr_nsec();
+}
+
+/**
+ * stop_hw_timer() - Times how long a job spends in hardware (active).
+ * Should be called immediatly after the hardware has
+ * finished.
+ *
+ * @core: The b2r2 core entity
+ * @job: Pointer to job struct
+ *
+ * core->lock _must_ be held when calling this function
+ */
+static void stop_hw_timer(struct b2r2_core *core, struct b2r2_core_job *job)
+{
+ /* Assumes only app queues are used, which is the case right now. */
+ /* Not 100% accurate. When a higher prio job interrupts a lower prio job it does
+ so after the current node of the low prio job has finished. Currently we can not
+ sense when the actual switch takes place so the time reported for a job that
+ interrupts a lower prio job will on average contain the time it takes to process
+ half a node in the lower prio job in addition to the time it takes to process the
+ job's own nodes. This could possibly be solved by adding node notifications but
+ that would involve a significant amount of work and consume system resources due
+ to the extra interrupts. */
+ /* If a job takes more than ~2s (absolute time, including idleing in the hardware)
+ the state of the hardware timer will be corrupted and it will not report valid
+ values until b2r2 becomes idle (no active jobs on any queues). The maximum length
+ can possibly be increased by using 64 bit integers. */
+
+ int i;
+
+ u32 stop_time_raw = b2r2_get_curr_nsec();
+ /* We'll add an offset to all positions in time to make the current time equal to
+ 0xFFFFFFFF. This way we can compare positions in time to each other without having
+ to wory about wrapping (so long as all positions in time are in the past). */
+ u32 stop_time = 0xFFFFFFFF;
+ u32 time_pos_offset = 0xFFFFFFFF - stop_time_raw;
+ u32 nsec_in_hw = stop_time - (job->hw_start_time + time_pos_offset);
+ job->nsec_active_in_hw += (s32)nsec_in_hw;
+
+ /* Check if we have delayed the start of higher prio jobs. Can happen as queue
+ switching only can be done between nodes. */
+ for (i = (int)job->queue - 1; i >= (int)B2R2_CORE_QUEUE_AQ1; i--) {
+ struct b2r2_core_job *queue_active_job = core->active_jobs[i];
+ if (NULL == queue_active_job)
+ continue;
+
+ queue_active_job->hw_start_time = stop_time_raw;
+ }
+
+ /* Check if the job has stolen time from lower prio jobs */
+ for (i = (int)job->queue + 1; i < B2R2_NUM_APPLICATIONS_QUEUES; i++) {
+ struct b2r2_core_job *queue_active_job = core->active_jobs[i];
+ u32 queue_active_job_hw_start_time;
+
+ if (NULL == queue_active_job)
+ continue;
+
+ queue_active_job_hw_start_time =
+ queue_active_job->hw_start_time +
+ time_pos_offset;
+
+ if (queue_active_job_hw_start_time < stop_time) {
+ u32 queue_active_job_nsec_in_hw = stop_time -
+ queue_active_job_hw_start_time;
+ u32 num_stolen_nsec = min(queue_active_job_nsec_in_hw,
+ nsec_in_hw);
+
+ queue_active_job->nsec_active_in_hw -= (s32)num_stolen_nsec;
+
+ nsec_in_hw -= num_stolen_nsec;
+ stop_time -= num_stolen_nsec;
+ }
+
+ if (0 == nsec_in_hw)
+ break;
+ }
+}
+
+/**
+ * init_job() - Initializes a job structure from filled in client data.
+ * Reference count will be set to 1
+ *
+ * @job: Job to initialize
+ */
+static void init_job(struct b2r2_core_job *job)
+{
+
+ job->start_sentinel = START_SENTINEL;
+ job->end_sentinel = END_SENTINEL;
+
+ /* Job is idle, never queued */
+ job->job_state = B2R2_CORE_JOB_IDLE;
+
+ /* Initialize internal data */
+ INIT_LIST_HEAD(&job->list);
+ init_waitqueue_head(&job->event);
+ INIT_WORK(&job->work, job_work_function);
+
+ /* Map given prio to B2R2 queues */
+ if (job->prio < B2R2_CORE_LOWEST_PRIO)
+ job->prio = B2R2_CORE_LOWEST_PRIO;
+ else if (job->prio > B2R2_CORE_HIGHEST_PRIO)
+ job->prio = B2R2_CORE_HIGHEST_PRIO;
+
+ if (job->prio > 10) {
+ job->queue = B2R2_CORE_QUEUE_AQ1;
+ job->interrupt_context =
+ (B2R2BLT_ITSAQ1_LNA_Reached);
+ job->control = (B2R2_AQ_Enab | B2R2_AQ_PRIOR_3);
+ } else if (job->prio > 0) {
+ job->queue = B2R2_CORE_QUEUE_AQ2;
+ job->interrupt_context =
+ (B2R2BLT_ITSAQ2_LNA_Reached);
+ job->control = (B2R2_AQ_Enab | B2R2_AQ_PRIOR_2);
+ } else if (job->prio > -10) {
+ job->queue = B2R2_CORE_QUEUE_AQ3;
+ job->interrupt_context =
+ (B2R2BLT_ITSAQ3_LNA_Reached);
+ job->control = (B2R2_AQ_Enab | B2R2_AQ_PRIOR_1);
+ } else {
+ job->queue = B2R2_CORE_QUEUE_AQ4;
+ job->interrupt_context =
+ (B2R2BLT_ITSAQ4_LNA_Reached);
+ job->control = (B2R2_AQ_Enab | B2R2_AQ_PRIOR_0);
+ }
+}
+
+/**
+ * clear_interrupts() - Disables all interrupts
+ *
+ * core->lock _must_ be held
+ */
+static void clear_interrupts(struct b2r2_core *core)
+{
+ writel(0x0, &core->hw->BLT_ITM0);
+ writel(0x0, &core->hw->BLT_ITM1);
+ writel(0x0, &core->hw->BLT_ITM2);
+ writel(0x0, &core->hw->BLT_ITM3);
+}
+
+/**
+ * insert_into_prio_list() - Inserts the job into the sorted list of jobs.
+ * The list is sorted by priority.
+ *
+ * @core: The b2r2 core entity
+ * @job: Job to insert
+ *
+ * core->lock _must_ be held
+ */
+static void insert_into_prio_list(struct b2r2_core *core,
+ struct b2r2_core_job *job)
+{
+ /* Ref count is increased when job put in list,
+ should be released when job is removed from list */
+ internal_job_addref(core, job, __func__);
+
+ core->stat_n_jobs_in_prio_list++;
+
+ /* Sort in the job */
+ if (list_empty(&core->prio_queue))
+ list_add_tail(&job->list, &core->prio_queue);
+ else {
+ struct b2r2_core_job *first_job = list_entry(
+ core->prio_queue.next,
+ struct b2r2_core_job, list);
+ struct b2r2_core_job *last_job = list_entry(
+ core->prio_queue.prev,
+ struct b2r2_core_job, list);
+
+ if (job->prio > first_job->prio)
+ list_add(&job->list, &core->prio_queue);
+ else if (job->prio <= last_job->prio)
+ list_add_tail(&job->list, &core->prio_queue);
+ else {
+ /* We need to find where to put it */
+ struct list_head *ptr;
+
+ list_for_each(ptr, &core->prio_queue) {
+ struct b2r2_core_job *list_job =
+ list_entry(ptr, struct b2r2_core_job,
+ list);
+ if (job->prio > list_job->prio) {
+ list_add_tail(&job->list,
+ &list_job->list);
+ break;
+ }
+ }
+ }
+ }
+ /* The job is now queued */
+ job->job_state = B2R2_CORE_JOB_QUEUED;
+}
+
+/**
+ * check_prio_list() - Checks if the first job(s) in the prio list can
+ * be dispatched to B2R2
+ *
+ * @core: The b2r2 core entity
+ * @atomic: true if in atomic context (i.e. interrupt context)
+ *
+ * core->lock _must_ be held
+ */
+static void check_prio_list(struct b2r2_core *core, bool atomic)
+{
+ bool dispatched_job;
+ int n_dispatched = 0;
+ struct b2r2_core_job *job;
+
+ do {
+ dispatched_job = false;
+
+ /* Do we have anything in our prio list? */
+ if (list_empty(&core->prio_queue))
+ break;
+
+ /* The first job waiting */
+ job = list_first_entry(&core->prio_queue,
+ struct b2r2_core_job, list);
+
+ /* Is the B2R2 queue available? */
+ if (core->active_jobs[job->queue] != NULL)
+ break;
+
+ /* Can we acquire resources? */
+ if (!job->acquire_resources ||
+ job->acquire_resources(job, atomic) == 0) {
+ /* Ok to dispatch job */
+
+ /* Remove from list */
+ list_del_init(&job->list);
+
+ /* The job is now active */
+ core->active_jobs[job->queue] = job;
+ core->n_active_jobs++;
+ job->jiffies = jiffies;
+ core->jiffies_last_active = jiffies;
+
+ /* Kick off B2R2 */
+ trigger_job(core, job);
+ dispatched_job = true;
+ n_dispatched++;
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+ /* Check in one half second if it hangs */
+ queue_delayed_work(core->work_queue,
+ &core->timeout_work, JOB_TIMEOUT);
+#endif
+ } else {
+ /* No resources */
+ if (!atomic && core->n_active_jobs == 0) {
+ b2r2_log_warn(core->dev,
+ "%s: No resource", __func__);
+ cancel_job(core, job);
+ }
+ }
+ } while (dispatched_job);
+
+ core->stat_n_jobs_in_prio_list -= n_dispatched;
+}
+
+/**
+ * find_job_in_list() - Finds job with job_id in list
+ *
+ * @jobid: Job id to find
+ * @list: List to find job id in
+ *
+ * Reference count will be incremented for found job.
+ *
+ * core->lock _must_ be held
+ */
+static struct b2r2_core_job *find_job_in_list(int job_id,
+ struct list_head *list)
+{
+ struct list_head *ptr;
+
+ list_for_each(ptr, list) {
+ struct b2r2_core_job *job = list_entry(
+ ptr, struct b2r2_core_job, list);
+ if (job->job_id == job_id) {
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ /* Increase reference count, should be released by
+ the caller of b2r2_core_job_find */
+ internal_job_addref(core, job, __func__);
+ return job;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * find_job_in_active_jobs() - Finds job in active job queues
+ *
+ * @core: The b2r2 core entity
+ * @job_id: Job id to find
+ *
+ * Reference count will be incremented for found job.
+ *
+ * core->lock _must_ be held
+ */
+static struct b2r2_core_job *find_job_in_active_jobs(struct b2r2_core *core,
+ int job_id)
+{
+ int i;
+ struct b2r2_core_job *found_job = NULL;
+
+ if (core->n_active_jobs) {
+ for (i = 0; i < ARRAY_SIZE(core->active_jobs); i++) {
+ struct b2r2_core_job *job = core->active_jobs[i];
+
+ if (job && job->job_id == job_id) {
+ internal_job_addref(core, job, __func__);
+ found_job = job;
+ break;
+ }
+ }
+ }
+ return found_job;
+}
+
+/**
+ * find_tag_in_list() - Finds first job with tag in list
+ *
+ * @tag: Tag to find
+ * @list: List to find job id in
+ *
+ * Reference count will be incremented for found job.
+ *
+ * core->lock must be held
+ */
+static struct b2r2_core_job *find_tag_in_list(struct b2r2_core *core,
+ int tag, struct list_head *list)
+{
+ struct list_head *ptr;
+
+ list_for_each(ptr, list) {
+ struct b2r2_core_job *job =
+ list_entry(ptr, struct b2r2_core_job, list);
+ if (job->tag == tag) {
+ /* Increase reference count, should be released by
+ the caller of b2r2_core_job_find */
+ internal_job_addref(core, job, __func__);
+ return job;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * find_tag_in_active_jobs() - Finds job with tag in active job queues
+ *
+ * @tag: Tag to find
+ *
+ * Reference count will be incremented for found job.
+ *
+ * core->lock must be held
+ */
+static struct b2r2_core_job *find_tag_in_active_jobs(struct b2r2_core *core,
+ int tag)
+{
+ int i;
+ struct b2r2_core_job *found_job = NULL;
+
+ if (core->n_active_jobs) {
+ for (i = 0; i < ARRAY_SIZE(core->active_jobs); i++) {
+ struct b2r2_core_job *job = core->active_jobs[i];
+
+ if (job && job->tag == tag) {
+ internal_job_addref(core, job, __func__);
+ found_job = job;
+ break;
+ }
+ }
+ }
+ return found_job;
+}
+
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+/**
+ * hw_reset() - Resets B2R2 hardware
+ *
+ * core->lock must be held
+ */
+static int hw_reset(struct b2r2_core *core)
+{
+ u32 uTimeOut = B2R2_RESET_TIMEOUT_VALUE;
+
+ /* Tell B2R2 to reset */
+ writel(readl(&core->hw->BLT_CTL) | B2R2BLT_CTLGLOBAL_soft_reset,
+ &core->hw->BLT_CTL);
+ writel(0x00000000, &core->hw->BLT_CTL);
+
+ b2r2_log_info(core->dev, "wait for B2R2 to be idle..\n");
+
+ /** Wait for B2R2 to be idle (on a timeout rather than while loop) */
+ while ((uTimeOut > 0) &&
+ ((readl(&core->hw->BLT_STA1) &
+ B2R2BLT_STA1BDISP_IDLE) == 0x0))
+ uTimeOut--;
+
+ if (uTimeOut == 0) {
+ b2r2_log_warn(core->dev,
+ "error-> after software reset B2R2 is not idle\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+
+}
+#endif
+
+/**
+ * trigger_job() - Put job in B2R2 HW queue
+ *
+ * @job: Job to trigger
+ *
+ * core->lock must be held
+ */
+static void trigger_job(struct b2r2_core *core, struct b2r2_core_job *job)
+{
+ /* Debug prints */
+ b2r2_log_info(core->dev, "queue 0x%x\n", job->queue);
+ b2r2_log_info(core->dev, "BLT TRIG_IP 0x%x (first node)\n",
+ job->first_node_address);
+ b2r2_log_info(core->dev, "BLT LNA_CTL 0x%x (last node)\n",
+ job->last_node_address);
+ b2r2_log_info(core->dev, "BLT TRIG_CTL 0x%x\n", job->control);
+ b2r2_log_info(core->dev, "BLT PACE_CTL 0x%x\n", job->pace_control);
+
+ reset_hw_timer(job);
+ job->job_state = B2R2_CORE_JOB_RUNNING;
+
+ /* Enable interrupt */
+ writel(readl(&core->hw->BLT_ITM0) | job->interrupt_context,
+ &core->hw->BLT_ITM0);
+
+ writel(min_t(u8, max_t(u8, core->op_size, B2R2_PLUG_OPCODE_SIZE_8),
+ B2R2_PLUG_OPCODE_SIZE_64), &core->hw->PLUGS1_OP2);
+ writel(min_t(u8, core->ch_size, B2R2_PLUG_CHUNK_SIZE_128),
+ &core->hw->PLUGS1_CHZ);
+ writel(min_t(u8, core->mg_size, B2R2_PLUG_MESSAGE_SIZE_128) |
+ (core->min_req_time << 16), &core->hw->PLUGS1_MSZ);
+ writel(min_t(u8, core->pg_size, B2R2_PLUG_PAGE_SIZE_256),
+ &core->hw->PLUGS1_PGZ);
+
+ writel(min_t(u8, max_t(u8, core->op_size, B2R2_PLUG_OPCODE_SIZE_8),
+ B2R2_PLUG_OPCODE_SIZE_64), &core->hw->PLUGS2_OP2);
+ writel(min_t(u8, core->ch_size, B2R2_PLUG_CHUNK_SIZE_128),
+ &core->hw->PLUGS2_CHZ);
+ writel(min_t(u8, core->mg_size, B2R2_PLUG_MESSAGE_SIZE_128) |
+ (core->min_req_time << 16), &core->hw->PLUGS2_MSZ);
+ writel(min_t(u8, core->pg_size, B2R2_PLUG_PAGE_SIZE_256),
+ &core->hw->PLUGS2_PGZ);
+
+ writel(min_t(u8, max_t(u8, core->op_size, B2R2_PLUG_OPCODE_SIZE_8),
+ B2R2_PLUG_OPCODE_SIZE_64), &core->hw->PLUGS3_OP2);
+ writel(min_t(u8, core->ch_size, B2R2_PLUG_CHUNK_SIZE_128),
+ &core->hw->PLUGS3_CHZ);
+ writel(min_t(u8, core->mg_size, B2R2_PLUG_MESSAGE_SIZE_128) |
+ (core->min_req_time << 16), &core->hw->PLUGS3_MSZ);
+ writel(min_t(u8, core->pg_size, B2R2_PLUG_PAGE_SIZE_256),
+ &core->hw->PLUGS3_PGZ);
+
+ writel(min_t(u8, max_t(u8, core->op_size, B2R2_PLUG_OPCODE_SIZE_8),
+ B2R2_PLUG_OPCODE_SIZE_64), &core->hw->PLUGT_OP2);
+ writel(min_t(u8, core->ch_size, B2R2_PLUG_CHUNK_SIZE_128),
+ &core->hw->PLUGT_CHZ);
+ writel(min_t(u8, core->mg_size, B2R2_PLUG_MESSAGE_SIZE_128) |
+ (core->min_req_time << 16), &core->hw->PLUGT_MSZ);
+ writel(min_t(u8, core->pg_size, B2R2_PLUG_PAGE_SIZE_256),
+ &core->hw->PLUGT_PGZ);
+
+ /* B2R2 kicks off when LNA is written, LNA write must be last! */
+ switch (job->queue) {
+ case B2R2_CORE_QUEUE_CQ1:
+ writel(job->first_node_address, &core->hw->BLT_CQ1_TRIG_IP);
+ writel(job->control, &core->hw->BLT_CQ1_TRIG_CTL);
+ writel(job->pace_control, &core->hw->BLT_CQ1_PACE_CTL);
+ break;
+
+ case B2R2_CORE_QUEUE_CQ2:
+ writel(job->first_node_address, &core->hw->BLT_CQ2_TRIG_IP);
+ writel(job->control, &core->hw->BLT_CQ2_TRIG_CTL);
+ writel(job->pace_control, &core->hw->BLT_CQ2_PACE_CTL);
+ break;
+
+ case B2R2_CORE_QUEUE_AQ1:
+ writel(job->control, &core->hw->BLT_AQ1_CTL);
+ writel(job->first_node_address, &core->hw->BLT_AQ1_IP);
+ wmb();
+ start_hw_timer(job);
+ writel(job->last_node_address, &core->hw->BLT_AQ1_LNA);
+ break;
+
+ case B2R2_CORE_QUEUE_AQ2:
+ writel(job->control, &core->hw->BLT_AQ2_CTL);
+ writel(job->first_node_address, &core->hw->BLT_AQ2_IP);
+ wmb();
+ start_hw_timer(job);
+ writel(job->last_node_address, &core->hw->BLT_AQ2_LNA);
+ break;
+
+ case B2R2_CORE_QUEUE_AQ3:
+ writel(job->control, &core->hw->BLT_AQ3_CTL);
+ writel(job->first_node_address, &core->hw->BLT_AQ3_IP);
+ wmb();
+ start_hw_timer(job);
+ writel(job->last_node_address, &core->hw->BLT_AQ3_LNA);
+ break;
+
+ case B2R2_CORE_QUEUE_AQ4:
+ writel(job->control, &core->hw->BLT_AQ4_CTL);
+ writel(job->first_node_address, &core->hw->BLT_AQ4_IP);
+ wmb();
+ start_hw_timer(job);
+ writel(job->last_node_address, &core->hw->BLT_AQ4_LNA);
+ break;
+
+ /** Handle the default case */
+ default:
+ break;
+
+ } /* end switch */
+
+}
+
+/**
+ * handle_queue_event() - Handles interrupt event for specified B2R2 queue
+ *
+ * @queue: Queue to handle event for
+ *
+ * core->lock must be held
+ */
+static void handle_queue_event(struct b2r2_core *core,
+ enum b2r2_core_queue queue)
+{
+ struct b2r2_core_job *job;
+
+ job = core->active_jobs[queue];
+ if (job) {
+ if (job->job_state != B2R2_CORE_JOB_RUNNING)
+ /* Should be running
+ Severe error. TBD */
+ b2r2_log_warn(core->dev,
+ "%s: Job is not running", __func__);
+
+ stop_hw_timer(core, job);
+
+ /* Remove from queue */
+ BUG_ON(core->n_active_jobs == 0);
+ core->active_jobs[queue] = NULL;
+ core->n_active_jobs--;
+ }
+
+ if (!job) {
+ /* No job, error? */
+ b2r2_log_warn(core->dev, "%s: No job", __func__);
+ return;
+ }
+
+
+ /* Atomic context release resources, release resources will
+ be called again later from process context (work queue) */
+ if (job->release_resources)
+ job->release_resources(job, true);
+
+ /* Job is done */
+ job->job_state = B2R2_CORE_JOB_DONE;
+
+ /* Handle done */
+ wake_up_interruptible(&job->event);
+
+ /* Dispatch to work queue to handle callbacks */
+ queue_work(core->work_queue, &job->work);
+}
+
+/**
+ * process_events() - Handles interrupt events
+ *
+ * @status: Contents of the B2R2 ITS register
+ */
+static void process_events(struct b2r2_core *core, u32 status)
+{
+ u32 mask = 0xF;
+ u32 disable_itm_mask = 0;
+
+ b2r2_log_info(core->dev, "Enters process_events\n");
+ b2r2_log_info(core->dev, "status 0x%x\n", status);
+
+ /* Composition queue 1 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_CQ1);
+ disable_itm_mask |= mask;
+ }
+ mask <<= 4;
+
+ /* Composition queue 2 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_CQ2);
+ disable_itm_mask |= mask;
+ }
+ mask <<= 8;
+
+ /* Application queue 1 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_AQ1);
+ disable_itm_mask |= mask;
+ }
+ mask <<= 4;
+
+ /* Application queue 2 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_AQ2);
+ disable_itm_mask |= mask;
+ }
+ mask <<= 4;
+
+ /* Application queue 3 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_AQ3);
+ disable_itm_mask |= mask;
+ }
+ mask <<= 4;
+
+ /* Application queue 4 */
+ if (status & mask) {
+ handle_queue_event(core, B2R2_CORE_QUEUE_AQ4);
+ disable_itm_mask |= mask;
+ }
+
+ /* Clear received interrupt flags */
+ writel(status, &core->hw->BLT_ITS);
+ /* Disable handled interrupts */
+ writel(readl(&core->hw->BLT_ITM0) & ~disable_itm_mask,
+ &core->hw->BLT_ITM0);
+
+ b2r2_log_info(core->dev, "Returns process_events\n");
+}
+
+/**
+ * b2r2_irq_handler() - B2R2 interrupt handler
+ *
+ * @irq: Interrupt number (not used)
+ * @dev_id: A pointer to the b2r2 core entity
+ */
+static irqreturn_t b2r2_irq_handler(int irq, void *dev_id)
+{
+ unsigned long flags;
+ struct b2r2_core* core = (struct b2r2_core *) dev_id;
+
+ /* Spin lock is need in irq handler (SMP) */
+ spin_lock_irqsave(&core->lock, flags);
+
+ /* Make a quick exit if this device was not interrupting */
+ if (!core->valid ||
+ ((readl(&core->hw->BLT_ITS) & B2R2_ITS_MASK) == 0)) {
+ core->stat_n_irq_skipped++;
+ spin_unlock_irqrestore(&core->lock, flags);
+ return IRQ_NONE;
+ }
+
+ /* Remember time for last irq (for timeout mgmt) */
+ core->jiffies_last_irq = jiffies;
+ core->stat_n_irq++;
+
+ /* Handle the interrupt(s) */
+ process_events(core, readl(&core->hw->BLT_ITS));
+
+ /* Check if we can dispatch new jobs */
+ check_prio_list(core, true);
+
+ core->stat_n_irq_exit++;
+
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * struct debugfs_reg - Represents one B2R2 register in debugfs
+ *
+ * @name: Register name
+ * @offset: Byte offset in B2R2 for register
+ */
+struct debugfs_reg {
+ const char name[30];
+ u32 offset;
+};
+
+/**
+ * debugfs_regs - Array of B2R2 debugfs registers
+ */
+static const struct debugfs_reg debugfs_regs[] = {
+ {"BLT_SSBA17", offsetof(struct b2r2_memory_map, BLT_SSBA17)},
+ {"BLT_SSBA18", offsetof(struct b2r2_memory_map, BLT_SSBA18)},
+ {"BLT_SSBA19", offsetof(struct b2r2_memory_map, BLT_SSBA19)},
+ {"BLT_SSBA20", offsetof(struct b2r2_memory_map, BLT_SSBA20)},
+ {"BLT_SSBA21", offsetof(struct b2r2_memory_map, BLT_SSBA21)},
+ {"BLT_SSBA22", offsetof(struct b2r2_memory_map, BLT_SSBA22)},
+ {"BLT_SSBA23", offsetof(struct b2r2_memory_map, BLT_SSBA23)},
+ {"BLT_SSBA24", offsetof(struct b2r2_memory_map, BLT_SSBA24)},
+ {"BLT_STBA5", offsetof(struct b2r2_memory_map, BLT_STBA5)},
+ {"BLT_STBA6", offsetof(struct b2r2_memory_map, BLT_STBA6)},
+ {"BLT_STBA7", offsetof(struct b2r2_memory_map, BLT_STBA7)},
+ {"BLT_STBA8", offsetof(struct b2r2_memory_map, BLT_STBA8)},
+ {"BLT_CTL", offsetof(struct b2r2_memory_map, BLT_CTL)},
+ {"BLT_ITS", offsetof(struct b2r2_memory_map, BLT_ITS)},
+ {"BLT_STA1", offsetof(struct b2r2_memory_map, BLT_STA1)},
+ {"BLT_SSBA1", offsetof(struct b2r2_memory_map, BLT_SSBA1)},
+ {"BLT_SSBA2", offsetof(struct b2r2_memory_map, BLT_SSBA2)},
+ {"BLT_SSBA3", offsetof(struct b2r2_memory_map, BLT_SSBA3)},
+ {"BLT_SSBA4", offsetof(struct b2r2_memory_map, BLT_SSBA4)},
+ {"BLT_SSBA5", offsetof(struct b2r2_memory_map, BLT_SSBA5)},
+ {"BLT_SSBA6", offsetof(struct b2r2_memory_map, BLT_SSBA6)},
+ {"BLT_SSBA7", offsetof(struct b2r2_memory_map, BLT_SSBA7)},
+ {"BLT_SSBA8", offsetof(struct b2r2_memory_map, BLT_SSBA8)},
+ {"BLT_STBA1", offsetof(struct b2r2_memory_map, BLT_STBA1)},
+ {"BLT_STBA2", offsetof(struct b2r2_memory_map, BLT_STBA2)},
+ {"BLT_STBA3", offsetof(struct b2r2_memory_map, BLT_STBA3)},
+ {"BLT_STBA4", offsetof(struct b2r2_memory_map, BLT_STBA4)},
+ {"BLT_CQ1_TRIG_IP", offsetof(struct b2r2_memory_map, BLT_CQ1_TRIG_IP)},
+ {"BLT_CQ1_TRIG_CTL", offsetof(struct b2r2_memory_map,
+ BLT_CQ1_TRIG_CTL)},
+ {"BLT_CQ1_PACE_CTL", offsetof(struct b2r2_memory_map,
+ BLT_CQ1_PACE_CTL)},
+ {"BLT_CQ1_IP", offsetof(struct b2r2_memory_map, BLT_CQ1_IP)},
+ {"BLT_CQ2_TRIG_IP", offsetof(struct b2r2_memory_map, BLT_CQ2_TRIG_IP)},
+ {"BLT_CQ2_TRIG_CTL", offsetof(struct b2r2_memory_map,
+ BLT_CQ2_TRIG_CTL)},
+ {"BLT_CQ2_PACE_CTL", offsetof(struct b2r2_memory_map,
+ BLT_CQ2_PACE_CTL)},
+ {"BLT_CQ2_IP", offsetof(struct b2r2_memory_map, BLT_CQ2_IP)},
+ {"BLT_AQ1_CTL", offsetof(struct b2r2_memory_map, BLT_AQ1_CTL)},
+ {"BLT_AQ1_IP", offsetof(struct b2r2_memory_map, BLT_AQ1_IP)},
+ {"BLT_AQ1_LNA", offsetof(struct b2r2_memory_map, BLT_AQ1_LNA)},
+ {"BLT_AQ1_STA", offsetof(struct b2r2_memory_map, BLT_AQ1_STA)},
+ {"BLT_AQ2_CTL", offsetof(struct b2r2_memory_map, BLT_AQ2_CTL)},
+ {"BLT_AQ2_IP", offsetof(struct b2r2_memory_map, BLT_AQ2_IP)},
+ {"BLT_AQ2_LNA", offsetof(struct b2r2_memory_map, BLT_AQ2_LNA)},
+ {"BLT_AQ2_STA", offsetof(struct b2r2_memory_map, BLT_AQ2_STA)},
+ {"BLT_AQ3_CTL", offsetof(struct b2r2_memory_map, BLT_AQ3_CTL)},
+ {"BLT_AQ3_IP", offsetof(struct b2r2_memory_map, BLT_AQ3_IP)},
+ {"BLT_AQ3_LNA", offsetof(struct b2r2_memory_map, BLT_AQ3_LNA)},
+ {"BLT_AQ3_STA", offsetof(struct b2r2_memory_map, BLT_AQ3_STA)},
+ {"BLT_AQ4_CTL", offsetof(struct b2r2_memory_map, BLT_AQ4_CTL)},
+ {"BLT_AQ4_IP", offsetof(struct b2r2_memory_map, BLT_AQ4_IP)},
+ {"BLT_AQ4_LNA", offsetof(struct b2r2_memory_map, BLT_AQ4_LNA)},
+ {"BLT_AQ4_STA", offsetof(struct b2r2_memory_map, BLT_AQ4_STA)},
+ {"BLT_SSBA9", offsetof(struct b2r2_memory_map, BLT_SSBA9)},
+ {"BLT_SSBA10", offsetof(struct b2r2_memory_map, BLT_SSBA10)},
+ {"BLT_SSBA11", offsetof(struct b2r2_memory_map, BLT_SSBA11)},
+ {"BLT_SSBA12", offsetof(struct b2r2_memory_map, BLT_SSBA12)},
+ {"BLT_SSBA13", offsetof(struct b2r2_memory_map, BLT_SSBA13)},
+ {"BLT_SSBA14", offsetof(struct b2r2_memory_map, BLT_SSBA14)},
+ {"BLT_SSBA15", offsetof(struct b2r2_memory_map, BLT_SSBA15)},
+ {"BLT_SSBA16", offsetof(struct b2r2_memory_map, BLT_SSBA16)},
+ {"BLT_SGA1", offsetof(struct b2r2_memory_map, BLT_SGA1)},
+ {"BLT_SGA2", offsetof(struct b2r2_memory_map, BLT_SGA2)},
+ {"BLT_ITM0", offsetof(struct b2r2_memory_map, BLT_ITM0)},
+ {"BLT_ITM1", offsetof(struct b2r2_memory_map, BLT_ITM1)},
+ {"BLT_ITM2", offsetof(struct b2r2_memory_map, BLT_ITM2)},
+ {"BLT_ITM3", offsetof(struct b2r2_memory_map, BLT_ITM3)},
+ {"BLT_DFV2", offsetof(struct b2r2_memory_map, BLT_DFV2)},
+ {"BLT_DFV1", offsetof(struct b2r2_memory_map, BLT_DFV1)},
+ {"BLT_PRI", offsetof(struct b2r2_memory_map, BLT_PRI)},
+ {"PLUGS1_OP2", offsetof(struct b2r2_memory_map, PLUGS1_OP2)},
+ {"PLUGS1_CHZ", offsetof(struct b2r2_memory_map, PLUGS1_CHZ)},
+ {"PLUGS1_MSZ", offsetof(struct b2r2_memory_map, PLUGS1_MSZ)},
+ {"PLUGS1_PGZ", offsetof(struct b2r2_memory_map, PLUGS1_PGZ)},
+ {"PLUGS2_OP2", offsetof(struct b2r2_memory_map, PLUGS2_OP2)},
+ {"PLUGS2_CHZ", offsetof(struct b2r2_memory_map, PLUGS2_CHZ)},
+ {"PLUGS2_MSZ", offsetof(struct b2r2_memory_map, PLUGS2_MSZ)},
+ {"PLUGS2_PGZ", offsetof(struct b2r2_memory_map, PLUGS2_PGZ)},
+ {"PLUGS3_OP2", offsetof(struct b2r2_memory_map, PLUGS3_OP2)},
+ {"PLUGS3_CHZ", offsetof(struct b2r2_memory_map, PLUGS3_CHZ)},
+ {"PLUGS3_MSZ", offsetof(struct b2r2_memory_map, PLUGS3_MSZ)},
+ {"PLUGS3_PGZ", offsetof(struct b2r2_memory_map, PLUGS3_PGZ)},
+ {"PLUGT_OP2", offsetof(struct b2r2_memory_map, PLUGT_OP2)},
+ {"PLUGT_CHZ", offsetof(struct b2r2_memory_map, PLUGT_CHZ)},
+ {"PLUGT_MSZ", offsetof(struct b2r2_memory_map, PLUGT_MSZ)},
+ {"PLUGT_PGZ", offsetof(struct b2r2_memory_map, PLUGT_PGZ)},
+ {"BLT_NIP", offsetof(struct b2r2_memory_map, BLT_NIP)},
+ {"BLT_CIC", offsetof(struct b2r2_memory_map, BLT_CIC)},
+ {"BLT_INS", offsetof(struct b2r2_memory_map, BLT_INS)},
+ {"BLT_ACK", offsetof(struct b2r2_memory_map, BLT_ACK)},
+ {"BLT_TBA", offsetof(struct b2r2_memory_map, BLT_TBA)},
+ {"BLT_TTY", offsetof(struct b2r2_memory_map, BLT_TTY)},
+ {"BLT_TXY", offsetof(struct b2r2_memory_map, BLT_TXY)},
+ {"BLT_TSZ", offsetof(struct b2r2_memory_map, BLT_TSZ)},
+ {"BLT_S1CF", offsetof(struct b2r2_memory_map, BLT_S1CF)},
+ {"BLT_S2CF", offsetof(struct b2r2_memory_map, BLT_S2CF)},
+ {"BLT_S1BA", offsetof(struct b2r2_memory_map, BLT_S1BA)},
+ {"BLT_S1TY", offsetof(struct b2r2_memory_map, BLT_S1TY)},
+ {"BLT_S1XY", offsetof(struct b2r2_memory_map, BLT_S1XY)},
+ {"BLT_S2BA", offsetof(struct b2r2_memory_map, BLT_S2BA)},
+ {"BLT_S2TY", offsetof(struct b2r2_memory_map, BLT_S2TY)},
+ {"BLT_S2XY", offsetof(struct b2r2_memory_map, BLT_S2XY)},
+ {"BLT_S2SZ", offsetof(struct b2r2_memory_map, BLT_S2SZ)},
+ {"BLT_S3BA", offsetof(struct b2r2_memory_map, BLT_S3BA)},
+ {"BLT_S3TY", offsetof(struct b2r2_memory_map, BLT_S3TY)},
+ {"BLT_S3XY", offsetof(struct b2r2_memory_map, BLT_S3XY)},
+ {"BLT_S3SZ", offsetof(struct b2r2_memory_map, BLT_S3SZ)},
+ {"BLT_CWO", offsetof(struct b2r2_memory_map, BLT_CWO)},
+ {"BLT_CWS", offsetof(struct b2r2_memory_map, BLT_CWS)},
+ {"BLT_CCO", offsetof(struct b2r2_memory_map, BLT_CCO)},
+ {"BLT_CML", offsetof(struct b2r2_memory_map, BLT_CML)},
+ {"BLT_FCTL", offsetof(struct b2r2_memory_map, BLT_FCTL)},
+ {"BLT_PMK", offsetof(struct b2r2_memory_map, BLT_PMK)},
+ {"BLT_RSF", offsetof(struct b2r2_memory_map, BLT_RSF)},
+ {"BLT_RZI", offsetof(struct b2r2_memory_map, BLT_RZI)},
+ {"BLT_HFP", offsetof(struct b2r2_memory_map, BLT_HFP)},
+ {"BLT_VFP", offsetof(struct b2r2_memory_map, BLT_VFP)},
+ {"BLT_Y_RSF", offsetof(struct b2r2_memory_map, BLT_Y_RSF)},
+ {"BLT_Y_RZI", offsetof(struct b2r2_memory_map, BLT_Y_RZI)},
+ {"BLT_Y_HFP", offsetof(struct b2r2_memory_map, BLT_Y_HFP)},
+ {"BLT_Y_VFP", offsetof(struct b2r2_memory_map, BLT_Y_VFP)},
+ {"BLT_KEY1", offsetof(struct b2r2_memory_map, BLT_KEY1)},
+ {"BLT_KEY2", offsetof(struct b2r2_memory_map, BLT_KEY2)},
+ {"BLT_SAR", offsetof(struct b2r2_memory_map, BLT_SAR)},
+ {"BLT_USR", offsetof(struct b2r2_memory_map, BLT_USR)},
+ {"BLT_IVMX0", offsetof(struct b2r2_memory_map, BLT_IVMX0)},
+ {"BLT_IVMX1", offsetof(struct b2r2_memory_map, BLT_IVMX1)},
+ {"BLT_IVMX2", offsetof(struct b2r2_memory_map, BLT_IVMX2)},
+ {"BLT_IVMX3", offsetof(struct b2r2_memory_map, BLT_IVMX3)},
+ {"BLT_OVMX0", offsetof(struct b2r2_memory_map, BLT_OVMX0)},
+ {"BLT_OVMX1", offsetof(struct b2r2_memory_map, BLT_OVMX1)},
+ {"BLT_OVMX2", offsetof(struct b2r2_memory_map, BLT_OVMX2)},
+ {"BLT_OVMX3", offsetof(struct b2r2_memory_map, BLT_OVMX3)},
+ {"BLT_VC1R", offsetof(struct b2r2_memory_map, BLT_VC1R)},
+ {"BLT_Y_HFC0", offsetof(struct b2r2_memory_map, BLT_Y_HFC0)},
+ {"BLT_Y_HFC1", offsetof(struct b2r2_memory_map, BLT_Y_HFC1)},
+ {"BLT_Y_HFC2", offsetof(struct b2r2_memory_map, BLT_Y_HFC2)},
+ {"BLT_Y_HFC3", offsetof(struct b2r2_memory_map, BLT_Y_HFC3)},
+ {"BLT_Y_HFC4", offsetof(struct b2r2_memory_map, BLT_Y_HFC4)},
+ {"BLT_Y_HFC5", offsetof(struct b2r2_memory_map, BLT_Y_HFC5)},
+ {"BLT_Y_HFC6", offsetof(struct b2r2_memory_map, BLT_Y_HFC6)},
+ {"BLT_Y_HFC7", offsetof(struct b2r2_memory_map, BLT_Y_HFC7)},
+ {"BLT_Y_HFC8", offsetof(struct b2r2_memory_map, BLT_Y_HFC8)},
+ {"BLT_Y_HFC9", offsetof(struct b2r2_memory_map, BLT_Y_HFC9)},
+ {"BLT_Y_HFC10", offsetof(struct b2r2_memory_map, BLT_Y_HFC10)},
+ {"BLT_Y_HFC11", offsetof(struct b2r2_memory_map, BLT_Y_HFC11)},
+ {"BLT_Y_HFC12", offsetof(struct b2r2_memory_map, BLT_Y_HFC12)},
+ {"BLT_Y_HFC13", offsetof(struct b2r2_memory_map, BLT_Y_HFC13)},
+ {"BLT_Y_HFC14", offsetof(struct b2r2_memory_map, BLT_Y_HFC14)},
+ {"BLT_Y_HFC15", offsetof(struct b2r2_memory_map, BLT_Y_HFC15)},
+ {"BLT_Y_VFC0", offsetof(struct b2r2_memory_map, BLT_Y_VFC0)},
+ {"BLT_Y_VFC1", offsetof(struct b2r2_memory_map, BLT_Y_VFC1)},
+ {"BLT_Y_VFC2", offsetof(struct b2r2_memory_map, BLT_Y_VFC2)},
+ {"BLT_Y_VFC3", offsetof(struct b2r2_memory_map, BLT_Y_VFC3)},
+ {"BLT_Y_VFC4", offsetof(struct b2r2_memory_map, BLT_Y_VFC4)},
+ {"BLT_Y_VFC5", offsetof(struct b2r2_memory_map, BLT_Y_VFC5)},
+ {"BLT_Y_VFC6", offsetof(struct b2r2_memory_map, BLT_Y_VFC6)},
+ {"BLT_Y_VFC7", offsetof(struct b2r2_memory_map, BLT_Y_VFC7)},
+ {"BLT_Y_VFC8", offsetof(struct b2r2_memory_map, BLT_Y_VFC8)},
+ {"BLT_Y_VFC9", offsetof(struct b2r2_memory_map, BLT_Y_VFC9)},
+ {"BLT_HFC0", offsetof(struct b2r2_memory_map, BLT_HFC0)},
+ {"BLT_HFC1", offsetof(struct b2r2_memory_map, BLT_HFC1)},
+ {"BLT_HFC2", offsetof(struct b2r2_memory_map, BLT_HFC2)},
+ {"BLT_HFC3", offsetof(struct b2r2_memory_map, BLT_HFC3)},
+ {"BLT_HFC4", offsetof(struct b2r2_memory_map, BLT_HFC4)},
+ {"BLT_HFC5", offsetof(struct b2r2_memory_map, BLT_HFC5)},
+ {"BLT_HFC6", offsetof(struct b2r2_memory_map, BLT_HFC6)},
+ {"BLT_HFC7", offsetof(struct b2r2_memory_map, BLT_HFC7)},
+ {"BLT_HFC8", offsetof(struct b2r2_memory_map, BLT_HFC8)},
+ {"BLT_HFC9", offsetof(struct b2r2_memory_map, BLT_HFC9)},
+ {"BLT_HFC10", offsetof(struct b2r2_memory_map, BLT_HFC10)},
+ {"BLT_HFC11", offsetof(struct b2r2_memory_map, BLT_HFC11)},
+ {"BLT_HFC12", offsetof(struct b2r2_memory_map, BLT_HFC12)},
+ {"BLT_HFC13", offsetof(struct b2r2_memory_map, BLT_HFC13)},
+ {"BLT_HFC14", offsetof(struct b2r2_memory_map, BLT_HFC14)},
+ {"BLT_HFC15", offsetof(struct b2r2_memory_map, BLT_HFC15)},
+ {"BLT_VFC0", offsetof(struct b2r2_memory_map, BLT_VFC0)},
+ {"BLT_VFC1", offsetof(struct b2r2_memory_map, BLT_VFC1)},
+ {"BLT_VFC2", offsetof(struct b2r2_memory_map, BLT_VFC2)},
+ {"BLT_VFC3", offsetof(struct b2r2_memory_map, BLT_VFC3)},
+ {"BLT_VFC4", offsetof(struct b2r2_memory_map, BLT_VFC4)},
+ {"BLT_VFC5", offsetof(struct b2r2_memory_map, BLT_VFC5)},
+ {"BLT_VFC6", offsetof(struct b2r2_memory_map, BLT_VFC6)},
+ {"BLT_VFC7", offsetof(struct b2r2_memory_map, BLT_VFC7)},
+ {"BLT_VFC8", offsetof(struct b2r2_memory_map, BLT_VFC8)},
+ {"BLT_VFC9", offsetof(struct b2r2_memory_map, BLT_VFC9)},
+};
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+/**
+ * printk_regs() - Print B2R2 registers to printk
+ */
+static void printk_regs(struct b2r2_core *core)
+{
+#ifdef CONFIG_B2R2_DEBUG
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
+ unsigned long value = readl(
+ (unsigned long *) (((u8 *) core->hw) +
+ debugfs_regs[i].offset));
+ b2r2_log_regdump(core->dev, "%s: %08lX\n",
+ debugfs_regs[i].name,
+ value);
+ }
+#endif
+}
+#endif
+
+/**
+ * debugfs_b2r2_reg_read() - Implements debugfs read for B2R2 register
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_reg_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ size_t dev_size;
+ int ret = 0;
+ unsigned long value;
+ char *tmpbuf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ if (tmpbuf == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Read from B2R2 */
+ value = readl((unsigned long *)
+ filp->f_dentry->d_inode->i_private);
+
+ /* Build the string */
+ dev_size = sprintf(tmpbuf, "%8lX\n", value);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ /* Return it to user space */
+ if (copy_to_user(buf, tmpbuf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ if (tmpbuf != NULL)
+ kfree(tmpbuf);
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_reg_write() - Implements debugfs write for B2R2 register
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to write
+ * @f_pos: File position
+ *
+ * Returns number of bytes written or negative error code
+ */
+static int debugfs_b2r2_reg_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ char tmpbuf[80];
+ u32 reg_value;
+ int ret = 0;
+
+ /* Adjust count */
+ if (count >= sizeof(tmpbuf))
+ count = sizeof(tmpbuf) - 1;
+ /* Get it from user space */
+ if (copy_from_user(tmpbuf, buf, count))
+ return -EINVAL;
+ tmpbuf[count] = 0;
+ /* Convert from hex string */
+ if (sscanf(tmpbuf, "%8lX", (unsigned long *) &reg_value) != 1)
+ return -EINVAL;
+
+ writel(reg_value, (u32 *)
+ filp->f_dentry->d_inode->i_private);
+
+ *f_pos += count;
+ ret = count;
+
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_reg_fops() - File operations for B2R2 register debugfs
+ */
+static const struct file_operations debugfs_b2r2_reg_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_reg_read,
+ .write = debugfs_b2r2_reg_write,
+};
+
+/**
+ * debugfs_b2r2_regs_read() - Implements debugfs read for B2R2 register dump
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes written or negative error code
+ */
+static int debugfs_b2r2_regs_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ size_t dev_size = 0;
+ int ret = 0;
+ int i;
+ char *tmpbuf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+
+ if (tmpbuf == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Build a giant string containing all registers */
+ for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
+ unsigned long value =
+ readl((u32 *) (((u8 *)
+ filp->f_dentry->d_inode->i_private) +
+ debugfs_regs[i].offset));
+ dev_size += sprintf(tmpbuf + dev_size, "%s: %08lX\n",
+ debugfs_regs[i].name,
+ value);
+ }
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, tmpbuf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ if (tmpbuf != NULL)
+ kfree(tmpbuf);
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_regs_fops() - File operations for B2R2 register dump debugfs
+ */
+static const struct file_operations debugfs_b2r2_regs_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_regs_read,
+};
+
+/**
+ * debugfs_b2r2_stat_read() - Implements debugfs read for B2R2 statistics
+ *
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_stat_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ size_t dev_size = 0;
+ int ret = 0;
+ int i = 0;
+ char *tmpbuf = kmalloc(sizeof(char) * 4096, GFP_KERNEL);
+ struct b2r2_core *core = filp->f_dentry->d_inode->i_private;
+
+ if (tmpbuf == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Build a string containing all statistics */
+ dev_size += sprintf(tmpbuf + dev_size, "Interrupts : %lu\n",
+ core->stat_n_irq);
+ dev_size += sprintf(tmpbuf + dev_size, "Added jobs : %lu\n",
+ core->stat_n_jobs_added);
+ dev_size += sprintf(tmpbuf + dev_size, "Removed jobs : %lu\n",
+ core->stat_n_jobs_removed);
+ dev_size += sprintf(tmpbuf + dev_size, "Jobs in prio list : %lu\n",
+ core->stat_n_jobs_in_prio_list);
+ dev_size += sprintf(tmpbuf + dev_size, "Active jobs : %lu\n",
+ core->n_active_jobs);
+ for (i = 0; i < ARRAY_SIZE(core->active_jobs); i++)
+ dev_size += sprintf(tmpbuf + dev_size,
+ " Job in queue %d : 0x%08lx\n",
+ i, (unsigned long) core->active_jobs[i]);
+ dev_size += sprintf(tmpbuf + dev_size, "Clock requests : %lu\n",
+ core->clock_request_count);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, tmpbuf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ if (tmpbuf != NULL)
+ kfree(tmpbuf);
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_stat_fops() - File operations for B2R2 statistics debugfs
+ */
+static const struct file_operations debugfs_b2r2_stat_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_stat_read,
+};
+
+
+/**
+ * debugfs_b2r2_clock_read() - Implements debugfs read for
+ * PMU B2R2 clock register
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_clock_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ /* 10 characters hex number + newline + string terminator; */
+ char tmpbuf[10+2];
+ size_t dev_size;
+ int ret = 0;
+ struct b2r2_core *core = filp->f_dentry->d_inode->i_private;
+
+ unsigned long value = clk_get_rate(core->b2r2_clock);
+
+ dev_size = sprintf(tmpbuf, "%#010lx\n", value);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, tmpbuf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_clock_write() - Implements debugfs write for
+ * PMU B2R2 clock register
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to write
+ * @f_pos: File position
+ *
+ * Returns number of bytes written or negative error code
+ */
+static int debugfs_b2r2_clock_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ char tmpbuf[80];
+ u32 reg_value;
+ int ret = 0;
+
+ if (count >= sizeof(tmpbuf))
+ count = sizeof(tmpbuf) - 1;
+ if (copy_from_user(tmpbuf, buf, count))
+ return -EINVAL;
+ tmpbuf[count] = 0;
+ if (sscanf(tmpbuf, "%8lX", (unsigned long *) &reg_value) != 1)
+ return -EINVAL;
+
+ /*not working yet*/
+ /*clk_set_rate(b2r2_core.b2r2_clock, (unsigned long) reg_value);*/
+
+ *f_pos += count;
+ ret = count;
+
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_clock_fops() - File operations for PMU B2R2 clock debugfs
+ */
+static const struct file_operations debugfs_b2r2_clock_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_clock_read,
+ .write = debugfs_b2r2_clock_write,
+};
+
+/**
+ * debugfs_b2r2_enabled_read() - Implements debugfs read for
+ * B2R2 Core Enable/Disable
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to read
+ * @f_pos: File position
+ *
+ * Returns number of bytes read or negative error code
+ */
+static int debugfs_b2r2_enabled_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ /* 4 characters hex number + newline + string terminator; */
+ char tmpbuf[4+2];
+ size_t dev_size;
+ int ret = 0;
+ struct b2r2_core *core = filp->f_dentry->d_inode->i_private;
+
+ dev_size = sprintf(tmpbuf, "%02X\n", core->control->enabled);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, tmpbuf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+out:
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_enabled_write() - Implements debugfs write for
+ * B2R2 Core Enable/Disable
+ * @filp: File pointer
+ * @buf: User space buffer
+ * @count: Number of bytes to write
+ * @f_pos: File position
+ *
+ * Returns number of bytes written or negative error code
+ */
+static int debugfs_b2r2_enabled_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ char tmpbuf[80];
+ unsigned int enable;
+ int ret = 0;
+ struct b2r2_core *core = filp->f_dentry->d_inode->i_private;
+
+ if (count >= sizeof(tmpbuf))
+ count = sizeof(tmpbuf) - 1;
+ if (copy_from_user(tmpbuf, buf, count))
+ return -EINVAL;
+ tmpbuf[count] = 0;
+ if (sscanf(tmpbuf, "%02X", &enable) != 1)
+ return -EINVAL;
+
+ if (enable)
+ core->control->enabled = true;
+ else
+ core->control->enabled = false;
+
+ *f_pos += count;
+ ret = count;
+
+ return ret;
+}
+
+/**
+ * debugfs_b2r2_enabled_fops() - File operations for B2R2 Core Enable/Disable debugfs
+ */
+static const struct file_operations debugfs_b2r2_enabled_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_enabled_read,
+ .write = debugfs_b2r2_enabled_write,
+};
+
+#endif
+
+/**
+ *
+ * init_hw() - B2R2 Hardware reset & initiliaze
+ *
+ * @pdev: B2R2 platform device
+ *
+ * 1)Register interrupt handler
+ *
+ * 2)B2R2 Register map
+ *
+ * 3)For resetting B2R2 hardware,write to B2R2 Control register the
+ * B2R2BLT_CTLGLOBAL_soft_reset and then polling for on
+ * B2R2 status register for B2R2BLT_STA1BDISP_IDLE flag.
+ *
+ * 4)Wait for B2R2 hardware to be idle (on a timeout rather than while loop)
+ *
+ * 5)Driver status reset
+ *
+ * 6)Recover from any error without any leaks.
+ *
+ */
+static int init_hw(struct b2r2_core *core)
+{
+ int result = 0;
+ u32 uTimeOut = B2R2_RESET_TIMEOUT_VALUE;
+
+ /* Put B2R2 into reset */
+ clear_interrupts(core);
+
+ writel(readl(&core->hw->BLT_CTL) | B2R2BLT_CTLGLOBAL_soft_reset,
+ &core->hw->BLT_CTL);
+
+ /* Set up interrupt handler */
+ result = request_irq(core->irq, b2r2_irq_handler, IRQF_SHARED,
+ "b2r2-interrupt", core);
+ if (result) {
+ b2r2_log_err(core->dev,
+ "%s: failed to register IRQ for B2R2\n", __func__);
+ goto b2r2_init_request_irq_failed;
+ }
+
+ b2r2_log_info(core->dev, "do a global reset..\n");
+
+ /* Release reset */
+ writel(0x00000000, &core->hw->BLT_CTL);
+
+ b2r2_log_info(core->dev, "wait for B2R2 to be idle..\n");
+
+ /** Wait for B2R2 to be idle (on a timeout rather than while loop) */
+ while ((uTimeOut > 0) &&
+ ((readl(&core->hw->BLT_STA1) &
+ B2R2BLT_STA1BDISP_IDLE) == 0x0))
+ uTimeOut--;
+ if (uTimeOut == 0) {
+ b2r2_log_err(core->dev,
+ "%s: B2R2 not idle after SW reset\n", __func__);
+ result = -EAGAIN;
+ goto b2r2_core_init_hw_timeout;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ /* Register debug fs files for register access */
+ if (!IS_ERR_OR_NULL(core->debugfs_core_root_dir) &&
+ IS_ERR_OR_NULL(core->debugfs_regs_dir)) {
+ core->debugfs_regs_dir = debugfs_create_dir("regs",
+ core->debugfs_core_root_dir);
+ }
+ if (!IS_ERR_OR_NULL(core->debugfs_regs_dir)) {
+ int i;
+ debugfs_create_file("all", 0666, core->debugfs_regs_dir,
+ (void *)core->hw, &debugfs_b2r2_regs_fops);
+ /* Create debugfs entries for all static registers */
+ for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++)
+ debugfs_create_file(debugfs_regs[i].name, 0666,
+ core->debugfs_regs_dir,
+ (void *)(((u8 *) core->hw) +
+ debugfs_regs[i].offset),
+ &debugfs_b2r2_reg_fops);
+ }
+#endif
+
+ b2r2_log_info(core->dev, "%s ended..\n", __func__);
+ return result;
+
+/** Recover from any error without any leaks */
+b2r2_core_init_hw_timeout:
+ /** Free B2R2 interrupt handler */
+ free_irq(core->irq, core);
+
+b2r2_init_request_irq_failed:
+ if (core->hw)
+ iounmap(core->hw);
+ core->hw = NULL;
+
+ return result;
+}
+
+
+/**
+ * exit_hw() - B2R2 Hardware exit
+ *
+ * core->lock _must_ NOT be held
+ */
+static void exit_hw(struct b2r2_core *core)
+{
+ unsigned long flags;
+
+ b2r2_log_info(core->dev, "%s started..\n", __func__);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Unregister our debugfs entries */
+ if (!IS_ERR_OR_NULL(core->debugfs_regs_dir)) {
+ debugfs_remove_recursive(core->debugfs_regs_dir);
+ core->debugfs_regs_dir = NULL;
+ }
+#endif
+ b2r2_log_debug(core->dev, "%s: locking core->lock\n", __func__);
+ spin_lock_irqsave(&core->lock, flags);
+
+ /* Cancel all pending jobs */
+ b2r2_log_debug(core->dev, "%s: canceling pending jobs\n", __func__);
+ exit_job_list(core, &core->prio_queue);
+
+ /* Soft reset B2R2 (Close all DMA,
+ reset all state to idle, reset regs)*/
+ b2r2_log_debug(core->dev, "%s: putting b2r2 in reset\n", __func__);
+ writel(readl(&core->hw->BLT_CTL) | B2R2BLT_CTLGLOBAL_soft_reset,
+ &core->hw->BLT_CTL);
+
+ b2r2_log_debug(core->dev, "%s: clearing interrupts\n", __func__);
+ clear_interrupts(core);
+
+ /** Free B2R2 interrupt handler */
+ b2r2_log_debug(core->dev, "%s: freeing interrupt handler\n", __func__);
+ free_irq(core->irq, core);
+
+ b2r2_log_debug(core->dev, "%s: unlocking core->lock\n", __func__);
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ b2r2_log_info(core->dev, "%s ended...\n", __func__);
+}
+
+/**
+ * b2r2_probe() - This routine loads the B2R2 core driver
+ *
+ * @pdev: platform device.
+ */
+static int b2r2_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res = NULL;
+ struct b2r2_core *core = NULL;
+ struct b2r2_control *control = NULL;
+ struct b2r2_platform_data *pdata = NULL;
+ int debug_init = 0;
+
+ BUG_ON(pdev == NULL);
+ BUG_ON(pdev->id < 0 || pdev->id >= B2R2_MAX_NBR_DEVICES);
+
+ pdata = pdev->dev.platform_data;
+
+ core = kzalloc(sizeof(*core), GFP_KERNEL);
+ if (!core) {
+ dev_err(&pdev->dev, "b2r2 core alloc failed\n");
+ ret = -EINVAL;
+ goto error_exit;
+ }
+
+ core->dev = &pdev->dev;
+ dev_set_drvdata(core->dev, core);
+ if (pdev->id)
+ snprintf(core->name, sizeof(core->name), "b2r2_%d", pdev->id);
+ else
+ snprintf(core->name, sizeof(core->name), "b2r2");
+
+ dev_info(&pdev->dev, "init started.\n");
+
+ /* Init spin locks */
+ spin_lock_init(&core->lock);
+
+ /* Init job queues */
+ INIT_LIST_HEAD(&core->prio_queue);
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+ /* Create work queue for callbacks & timeout */
+ INIT_DELAYED_WORK(&core->timeout_work, timeout_work_function);
+#endif
+
+ /* Work queue for callbacks and timeout management */
+ core->work_queue = create_workqueue("B2R2");
+ if (!core->work_queue) {
+ ret = -ENOMEM;
+ goto error_exit;
+ }
+
+ /* Get the clock for B2R2 */
+ core->b2r2_clock = clk_get(core->dev, pdata->clock_id);
+ if (IS_ERR(core->b2r2_clock)) {
+ ret = PTR_ERR(core->b2r2_clock);
+ dev_err(&pdev->dev, "clk_get %s failed\n", pdata->clock_id);
+ goto error_exit;
+ }
+
+ /* Get the B2R2 regulator */
+ core->b2r2_reg = regulator_get(core->dev, pdata->regulator_id);
+ if (IS_ERR(core->b2r2_reg)) {
+ ret = PTR_ERR(core->b2r2_reg);
+ dev_err(&pdev->dev, "regulator_get %s failed "
+ "(dev_name=%s)\n", pdata->regulator_id,
+ dev_name(core->dev));
+ goto error_exit;
+ }
+
+ /* Init power management */
+ mutex_init(&core->domain_lock);
+ INIT_DELAYED_WORK_DEFERRABLE(&core->domain_disable_work,
+ domain_disable_work_function);
+ core->domain_enabled = false;
+ core->valid = false;
+
+ /* Map B2R2 into kernel virtual memory space */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ goto error_exit;
+
+ /* Hook up irq */
+ core->irq = platform_get_irq(pdev, 0);
+ if (core->irq <= 0) {
+ dev_err(&pdev->dev, "%s: Failed to request irq (irq=%d)\n",
+ __func__, core->irq);
+ goto error_exit;
+ }
+
+ core->hw = (struct b2r2_memory_map *) ioremap(res->start,
+ res->end - res->start + 1);
+ if (core->hw == NULL) {
+ dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
+ ret = -ENOMEM;
+ goto error_exit;
+ }
+
+ dev_dbg(core->dev, "b2r2 structure address %p\n", core->hw);
+
+ control = kzalloc(sizeof(*control), GFP_KERNEL);
+ if (!control) {
+ dev_err(&pdev->dev, "b2r2 control alloc failed\n");
+ ret = -EINVAL;
+ goto error_exit;
+ }
+
+ control->data = (void *)core;
+ control->id = pdev->id;
+ control->dev = &pdev->dev; /* Temporary device */
+
+ core->op_size = B2R2_PLUG_OPCODE_SIZE_DEFAULT;
+ core->ch_size = B2R2_PLUG_CHUNK_SIZE_DEFAULT;
+ core->pg_size = B2R2_PLUG_PAGE_SIZE_DEFAULT;
+ core->mg_size = B2R2_PLUG_MESSAGE_SIZE_DEFAULT;
+ core->min_req_time = 0;
+
+#ifdef CONFIG_DEBUG_FS
+ core->debugfs_root_dir = debugfs_create_dir(core->name, NULL);
+ if (!IS_ERR_OR_NULL(core->debugfs_root_dir)) {
+ core->debugfs_core_root_dir = debugfs_create_dir("core",
+ core->debugfs_root_dir);
+ control->debugfs_debug_root_dir = debugfs_create_dir("debug",
+ core->debugfs_root_dir);
+ control->mem_heap.debugfs_root_dir = debugfs_create_dir("mem",
+ core->debugfs_root_dir);
+ control->debugfs_root_dir = debugfs_create_dir("blt",
+ core->debugfs_root_dir);
+ }
+
+ if (!IS_ERR_OR_NULL(core->debugfs_core_root_dir)) {
+ debugfs_create_file("stats", 0666, core->debugfs_core_root_dir,
+ core, &debugfs_b2r2_stat_fops);
+ debugfs_create_file("clock", 0666, core->debugfs_core_root_dir,
+ core, &debugfs_b2r2_clock_fops);
+ debugfs_create_file("enabled", 0666,
+ core->debugfs_core_root_dir,
+ core, &debugfs_b2r2_enabled_fops);
+ debugfs_create_u8("op_size", 0666, core->debugfs_core_root_dir,
+ &core->op_size);
+ debugfs_create_u8("ch_size", 0666, core->debugfs_core_root_dir,
+ &core->ch_size);
+ debugfs_create_u8("pg_size", 0666, core->debugfs_core_root_dir,
+ &core->pg_size);
+ debugfs_create_u8("mg_size", 0666, core->debugfs_core_root_dir,
+ &core->mg_size);
+ debugfs_create_u16("min_req_time", 0666,
+ core->debugfs_core_root_dir, &core->min_req_time);
+ }
+#endif
+
+ ret = b2r2_debug_init(control);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "b2r2_debug_init failed\n");
+ goto error_exit;
+ }
+ debug_init = 1;
+
+ /* Initialize b2r2_control */
+ ret = b2r2_control_init(control);
+ if (ret < 0) {
+ b2r2_log_err(&pdev->dev, "b2r2_control_init failed\n");
+ goto error_exit;
+ }
+ core->control = control;
+
+ /* Add the control to the blitter */
+ kref_init(&control->ref);
+ control->enabled = true;
+ b2r2_blt_add_control(control);
+
+ b2r2_core[pdev->id] = core;
+ dev_info(&pdev->dev, "%s done.\n", __func__);
+
+ return ret;
+
+/** Recover from any error if something fails */
+error_exit:
+ kfree(control);
+
+ if (!IS_ERR_OR_NULL(core->b2r2_reg))
+ regulator_put(core->b2r2_reg);
+
+ if (!IS_ERR_OR_NULL(core->b2r2_clock))
+ clk_put(core->b2r2_clock);
+
+ if (!IS_ERR_OR_NULL(core->work_queue))
+ destroy_workqueue(core->work_queue);
+
+ if (debug_init)
+ b2r2_debug_exit();
+
+#ifdef CONFIG_DEBUG_FS
+ if (!IS_ERR_OR_NULL(core->debugfs_root_dir)) {
+ debugfs_remove_recursive(core->debugfs_root_dir);
+ core->debugfs_root_dir = NULL;
+ }
+#endif
+ kfree(core);
+
+ dev_info(&pdev->dev, "%s done with errors (%d).\n", __func__, ret);
+
+ return ret;
+}
+
+void b2r2_core_release(struct kref *control_ref)
+{
+ struct b2r2_control *control = container_of(
+ control_ref, struct b2r2_control, ref);
+ struct b2r2_core *core = control->data;
+ int id = control->id;
+ unsigned long flags;
+#ifdef CONFIG_B2R2_DEBUG
+ struct device *dev = core->dev;
+#endif
+
+ b2r2_log_info(dev, "%s: enter\n", __func__);
+
+ /* Exit b2r2 control module */
+ b2r2_control_exit(control);
+ kfree(control);
+ b2r2_debug_exit();
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+ cancel_delayed_work(&core->timeout_work);
+#endif
+
+ /* Flush B2R2 work queue (call all callbacks for
+ cancelled jobs) */
+ flush_workqueue(core->work_queue);
+
+ /* Make sure the power is turned off */
+ cancel_delayed_work_sync(&core->domain_disable_work);
+
+ /** Unmap B2R2 registers */
+ b2r2_log_info(dev, "%s: unmap b2r2 registers..\n", __func__);
+ if (core->hw) {
+ iounmap(core->hw);
+ core->hw = NULL;
+ }
+
+ destroy_workqueue(core->work_queue);
+
+ spin_lock_irqsave(&core->lock, flags);
+ core->work_queue = NULL;
+ spin_unlock_irqrestore(&core->lock, flags);
+
+ /* Return the clock */
+ clk_put(core->b2r2_clock);
+ regulator_put(core->b2r2_reg);
+
+ core->dev = NULL;
+ kfree(core);
+ b2r2_core[id] = NULL;
+
+ b2r2_log_info(dev, "%s: exit\n", __func__);
+}
+
+
+/**
+ * b2r2_remove - This routine unloads b2r2 driver
+ *
+ * @pdev: platform device.
+ */
+static int b2r2_remove(struct platform_device *pdev)
+{
+ struct b2r2_core *core;
+
+ BUG_ON(pdev == NULL);
+
+ core = dev_get_drvdata(&pdev->dev);
+ BUG_ON(core == NULL);
+ b2r2_log_info(&pdev->dev, "%s: Started\n", __func__);
+
+#ifdef CONFIG_DEBUG_FS
+ if (!IS_ERR_OR_NULL(core->debugfs_root_dir)) {
+ debugfs_remove_recursive(core->debugfs_root_dir);
+ core->debugfs_root_dir = NULL;
+ }
+#endif
+
+ /* Flush B2R2 work queue (call all callbacks) */
+ flush_workqueue(core->work_queue);
+
+ /* Remove control from blitter */
+ core->control->enabled = false;
+ b2r2_blt_remove_control(core->control);
+ kref_put(&core->control->ref, b2r2_core_release);
+
+ b2r2_log_info(&pdev->dev, "%s: Ended\n", __func__);
+
+ return 0;
+}
+/**
+ * b2r2_suspend() - This routine puts the B2R2 device in to sustend state.
+ * @pdev: platform device.
+ *
+ * This routine stores the current state of the b2r2 device and puts in to
+ * suspend state.
+ *
+ */
+int b2r2_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct b2r2_core *core;
+
+ BUG_ON(pdev == NULL);
+ core = dev_get_drvdata(&pdev->dev);
+ BUG_ON(core == NULL);
+ b2r2_log_info(core->dev, "%s\n", __func__);
+
+ /* Flush B2R2 work queue (call all callbacks) */
+ flush_workqueue(core->work_queue);
+
+#ifdef HANDLE_TIMEOUTED_JOBS
+ cancel_delayed_work(&core->timeout_work);
+#endif
+
+ /* Flush B2R2 work queue (call all callbacks for
+ cancelled jobs) */
+ flush_workqueue(core->work_queue);
+
+ /* Make sure power is turned off */
+ cancel_delayed_work_sync(&core->domain_disable_work);
+
+ return 0;
+}
+
+
+/**
+ * b2r2_resume() - This routine resumes the B2R2 device from sustend state.
+ * @pdev: platform device.
+ *
+ * This routine restore back the current state of the b2r2 device resumes.
+ *
+ */
+int b2r2_resume(struct platform_device *pdev)
+{
+ struct b2r2_core *core;
+
+ BUG_ON(pdev == NULL);
+ core = dev_get_drvdata(&pdev->dev);
+ BUG_ON(core == NULL);
+ b2r2_log_info(core->dev, "%s\n", __func__);
+
+ return 0;
+}
+
+void b2r2_core_print_stats(struct b2r2_core *core)
+{
+ b2r2_log_info(core->dev,
+ "%s: n_irq %ld, n_irq_exit %ld, n_irq_skipped %ld,\n"
+ "n_jobs_added %ld, n_active_jobs %ld, "
+ "n_jobs_in_prio_list %ld,\n"
+ "n_jobs_removed %ld\n",
+ __func__,
+ core->stat_n_irq,
+ core->stat_n_irq_exit,
+ core->stat_n_irq_skipped,
+ core->stat_n_jobs_added,
+ core->n_active_jobs,
+ core->stat_n_jobs_in_prio_list,
+ core->stat_n_jobs_removed);
+}
+
+/**
+ * struct platform_b2r2_driver - Platform driver configuration for the
+ * B2R2 core driver
+ */
+static struct platform_driver platform_b2r2_driver = {
+ .remove = b2r2_remove,
+ .driver = {
+ .name = "b2r2",
+ },
+ /** TODO implement power mgmt functions */
+ .suspend = b2r2_suspend,
+ .resume = b2r2_resume,
+};
+
+
+/**
+ * b2r2_init() - Module init function for the B2R2 core module
+ */
+static int __init b2r2_init(void)
+{
+ printk(KERN_INFO "%s\n", __func__);
+ return platform_driver_probe(&platform_b2r2_driver, b2r2_probe);
+}
+module_init(b2r2_init);
+
+/**
+ * b2r2_exit() - Module exit function for the B2R2 core module
+ */
+static void __exit b2r2_exit(void)
+{
+ printk(KERN_INFO "%s\n", __func__);
+ platform_driver_unregister(&platform_b2r2_driver);
+ return;
+}
+module_exit(b2r2_exit);
+
+
+/** Module is having GPL license */
+
+MODULE_LICENSE("GPL");
+
+/** Module author & discription */
+
+MODULE_AUTHOR("Robert Fekete (robert.fekete@stericsson.com)");
+MODULE_DESCRIPTION("B2R2 Core driver");
diff --git a/drivers/video/b2r2/b2r2_core.h b/drivers/video/b2r2/b2r2_core.h
new file mode 100644
index 00000000000..5b9fdcdc2bb
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_core.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 core driver
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __B2R2_CORE_H__
+#define __B2R2_CORE_H__
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+/**
+ * B2R2_RESET_TIMEOUT_VALUE - The number of times to read the status register
+ * waiting for b2r2 to go idle after soft reset.
+ */
+#define B2R2_RESET_TIMEOUT_VALUE (1500)
+
+/**
+ * B2R2_CLK_FLAG - Value to write into clock reg to turn clock on
+ */
+#define B2R2_CLK_FLAG (0x125)
+
+/**
+ * DEBUG_CHECK_ADDREF_RELEASE - Define this to enable addref / release debug
+ */
+#define DEBUG_CHECK_ADDREF_RELEASE 1
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * HANDLE_TIMEOUTED_JOBS - Define this to check jobs for timeout and cancel them
+ */
+#define HANDLE_TIMEOUTED_JOBS
+#define JOB_TIMEOUT (HZ/2)
+#endif
+
+/**
+ * B2R2_CLOCK_ALWAYS_ON - Define this to disable power save clock turn off
+ */
+/* #define B2R2_CLOCK_ALWAYS_ON 1 */
+
+/**
+ * START_SENTINEL - Watch guard to detect job overwrites
+ */
+#define START_SENTINEL 0xBABEDEEA
+
+/**
+ * STOP_SENTINEL - Watch guard to detect job overwrites
+ */
+#define END_SENTINEL 0xDADBDCDD
+
+/**
+ * B2R2_CORE_LOWEST_PRIO - Lowest prio allowed
+ */
+#define B2R2_CORE_LOWEST_PRIO -19
+/**
+ * B2R2_CORE_HIGHEST_PRIO - Highest prio allowed
+ */
+#define B2R2_CORE_HIGHEST_PRIO 20
+
+/**
+ * B2R2_DOMAIN_DISABLE -
+ */
+#define B2R2_DOMAIN_DISABLE_TIMEOUT (HZ/100)
+
+/**
+ * B2R2_REGULATOR_RETRY_COUNT -
+ */
+#define B2R2_REGULATOR_RETRY_COUNT 10
+
+
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+
+/**
+ * struct addref_release - Represents one addref or release. Used
+ * to debug addref / release problems
+ *
+ * @addref: true if this represents an addref else it represents
+ * a release.
+ * @job: The job that was referenced
+ * @caller: The caller of the addref or release
+ * @ref_count: The job reference count after addref / release
+ */
+struct addref_release {
+ bool addref;
+ struct b2r2_core_job *job;
+ const char *caller;
+ int ref_count;
+};
+
+#endif
+
+/**
+ * struct b2r2_core - Administration data for B2R2 core
+ *
+ * @lock: Spin lock protecting the b2r2_core structure and the B2R2 HW
+ * @hw: B2R2 registers memory mapped
+ * @pmu_b2r2_clock: Control of B2R2 clock
+ * @log_dev: Device used for logging via dev_... functions
+ *
+ * @prio_queue: Queue of jobs sorted in priority order
+ * @active_jobs: Array containing pointer to zero or one job per queue
+ * @n_active_jobs: Number of active jobs
+ * @jiffies_last_active: jiffie value when adding last active job
+ * @jiffies_last_irq: jiffie value when last irq occured
+ * @timeout_work: Work structure for timeout work
+ *
+ * @next_job_id: Contains the job id that will be assigned to the next
+ * added job.
+ *
+ * @clock_request_count: When non-zero, clock is on
+ * @clock_off_timer: Kernel timer to handle delayed turn off of clock
+ *
+ * @work_queue: Work queue to handle done jobs (callbacks) and timeouts in
+ * non-interrupt context.
+ *
+ * @stat_n_irq: Number of interrupts (statistics)
+ * @stat_n_jobs_added: Number of jobs added (statistics)
+ * @stat_n_jobs_removed: Number of jobs removed (statistics)
+ * @stat_n_jobs_in_prio_list: Number of jobs in prio list (statistics)
+ *
+ * @debugfs_root_dir: Root directory for B2R2 debugfs
+ *
+ * @ar: Circular array of addref / release debug structs
+ * @ar_write: Where next write will occur
+ * @ar_read: First valid place to read. When ar_read == ar_write then
+ * the array is empty.
+ */
+struct b2r2_core {
+ spinlock_t lock;
+
+ struct b2r2_memory_map *hw;
+
+ u8 op_size;
+ u8 ch_size;
+ u8 pg_size;
+ u8 mg_size;
+ u16 min_req_time;
+ int irq;
+
+ char name[16];
+ struct device *dev;
+
+ struct list_head prio_queue;
+
+ struct b2r2_core_job *active_jobs[B2R2_CORE_QUEUE_NO_OF];
+ unsigned long n_active_jobs;
+
+ unsigned long jiffies_last_active;
+ unsigned long jiffies_last_irq;
+#ifdef HANDLE_TIMEOUTED_JOBS
+ struct delayed_work timeout_work;
+#endif
+ int next_job_id;
+
+ unsigned long clock_request_count;
+ struct timer_list clock_off_timer;
+
+ struct workqueue_struct *work_queue;
+
+ /* Statistics */
+ unsigned long stat_n_irq_exit;
+ unsigned long stat_n_irq_skipped;
+ unsigned long stat_n_irq;
+ unsigned long stat_n_jobs_added;
+ unsigned long stat_n_jobs_removed;
+
+ unsigned long stat_n_jobs_in_prio_list;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_root_dir;
+ struct dentry *debugfs_core_root_dir;
+ struct dentry *debugfs_regs_dir;
+#endif
+
+#ifdef DEBUG_CHECK_ADDREF_RELEASE
+ /* Tracking release bug...*/
+ struct addref_release ar[100];
+ int ar_write;
+ int ar_read;
+#endif
+
+ /* Power management variables */
+ struct mutex domain_lock;
+ struct delayed_work domain_disable_work;
+
+ /*
+ * We need to keep track of both the number of domain_enable/disable()
+ * calls and whether the power was actually turned off, since the
+ * power off is done in a delayed job.
+ */
+ bool domain_enabled;
+ volatile bool valid;
+ int domain_request_count;
+
+ struct clk *b2r2_clock;
+ struct regulator *b2r2_reg;
+
+ struct b2r2_control *control;
+};
+
+/**
+ * b2r2_core_job_add() - Adds a job to B2R2 job queues
+ *
+ * The job reference count will be increased after this function
+ * has been called and b2r2_core_job_release() must be called to
+ * release the reference. The job callback function will be always
+ * be called after the job is done or cancelled.
+ *
+ * @control: The b2r2 control entity
+ * @job: Job to be added
+ *
+ * Returns 0 if OK else negative error code
+ *
+ */
+int b2r2_core_job_add(struct b2r2_control *control,
+ struct b2r2_core_job *job);
+
+/**
+ * b2r2_core_job_wait() - Waits for an added job to be done.
+ *
+ * @job: Job to wait for
+ *
+ * Returns 0 if job done else negative error code
+ *
+ */
+int b2r2_core_job_wait(struct b2r2_core_job *job);
+
+/**
+ * b2r2_core_job_cancel() - Cancel an already added job.
+ *
+ * @job: Job to cancel
+ *
+ * Returns 0 if job cancelled or done else negative error code
+ *
+ */
+int b2r2_core_job_cancel(struct b2r2_core_job *job);
+
+/**
+ * b2r2_core_job_find() - Finds job with given job id
+ *
+ * Reference count will be increased for the found job
+ *
+ * @control: The b2r2 control entity
+ * @job_id: Job id to find
+ *
+ * Returns job if found, else NULL
+ *
+ */
+struct b2r2_core_job *b2r2_core_job_find(struct b2r2_control *control,
+ int job_id);
+
+/**
+ * b2r2_core_job_find_first_with_tag() - Finds first job with given tag
+ *
+ * Reference count will be increased for the found job.
+ * This function can be used to find all jobs for a client, i.e.
+ * when cancelling all jobs for a client.
+ *
+ * @control: The b2r2 control entity
+ * @tag: Tag to find
+ *
+ * Returns job if found, else NULL
+ *
+ */
+struct b2r2_core_job *b2r2_core_job_find_first_with_tag(
+ struct b2r2_control *control, int tag);
+
+/**
+ * b2r2_core_job_addref() - Increase the job reference count.
+ *
+ * @job: Job to increase reference count for.
+ * @caller: The function calling this function (for debug)
+ */
+void b2r2_core_job_addref(struct b2r2_core_job *job, const char *caller);
+
+/**
+ * b2r2_core_job_release() - Decrease the job reference count. The
+ * job will be released (the release() function
+ * will be called) when the reference count
+ * reaches zero.
+ *
+ * @job: Job to decrease reference count for.
+ * @caller: The function calling this function (for debug)
+ */
+void b2r2_core_job_release(struct b2r2_core_job *job, const char *caller);
+
+void b2r2_core_print_stats(struct b2r2_core *core);
+
+void b2r2_core_release(struct kref *control_ref);
+
+#endif /* !defined(__B2R2_CORE_JOB_H__) */
diff --git a/drivers/video/b2r2/b2r2_debug.c b/drivers/video/b2r2/b2r2_debug.c
new file mode 100644
index 00000000000..934ba938ee5
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_debug.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 dynamic debug
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include "b2r2_debug.h"
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+int b2r2_log_levels[B2R2_LOG_LEVEL_COUNT];
+static struct dentry *log_lvl_dir;
+static int module_init;
+
+#define CHARS_IN_NODE_DUMP 1544
+#define DUMPED_NODE_SIZE (CHARS_IN_NODE_DUMP * sizeof(char) + 1)
+
+static void dump_node(char *dst, struct b2r2_node *node)
+{
+ dst += sprintf(dst, "node 0x%08x ------------------\n",
+ (unsigned int)node);
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_NIP:", node->node.GROUP0.B2R2_NIP);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_CIC:", node->node.GROUP0.B2R2_CIC);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_INS:", node->node.GROUP0.B2R2_INS);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_ACK:", node->node.GROUP0.B2R2_ACK);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_TBA:", node->node.GROUP1.B2R2_TBA);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_TTY:", node->node.GROUP1.B2R2_TTY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_TXY:", node->node.GROUP1.B2R2_TXY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_TSZ:", node->node.GROUP1.B2R2_TSZ);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S1CF:", node->node.GROUP2.B2R2_S1CF);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S2CF:", node->node.GROUP2.B2R2_S2CF);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S1BA:", node->node.GROUP3.B2R2_SBA);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S1TY:", node->node.GROUP3.B2R2_STY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S1XY:", node->node.GROUP3.B2R2_SXY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S1SZ:", node->node.GROUP3.B2R2_SSZ);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S2BA:", node->node.GROUP4.B2R2_SBA);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S2TY:", node->node.GROUP4.B2R2_STY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S2XY:", node->node.GROUP4.B2R2_SXY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S2SZ:", node->node.GROUP4.B2R2_SSZ);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S3BA:", node->node.GROUP5.B2R2_SBA);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S3TY:", node->node.GROUP5.B2R2_STY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S3XY:", node->node.GROUP5.B2R2_SXY);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_S3SZ:", node->node.GROUP5.B2R2_SSZ);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_CWO:", node->node.GROUP6.B2R2_CWO);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_CWS:", node->node.GROUP6.B2R2_CWS);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_CCO:", node->node.GROUP7.B2R2_CCO);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_CML:", node->node.GROUP7.B2R2_CML);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_PMK:", node->node.GROUP8.B2R2_PMK);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_FCTL:", node->node.GROUP8.B2R2_FCTL);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_RSF:", node->node.GROUP9.B2R2_RSF);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_RZI:", node->node.GROUP9.B2R2_RZI);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_HFP:", node->node.GROUP9.B2R2_HFP);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_VFP:", node->node.GROUP9.B2R2_VFP);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_Y_RSF:", node->node.GROUP10.B2R2_RSF);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_Y_RZI:", node->node.GROUP10.B2R2_RZI);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_Y_HFP:", node->node.GROUP10.B2R2_HFP);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_Y_VFP:", node->node.GROUP10.B2R2_VFP);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_FF0:", node->node.GROUP11.B2R2_FF0);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_FF1:", node->node.GROUP11.B2R2_FF1);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_FF2:", node->node.GROUP11.B2R2_FF2);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_FF3:", node->node.GROUP11.B2R2_FF3);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_KEY1:", node->node.GROUP12.B2R2_KEY1);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_KEY2:", node->node.GROUP12.B2R2_KEY2);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_XYL:", node->node.GROUP13.B2R2_XYL);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_XYP:", node->node.GROUP13.B2R2_XYP);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_SAR:", node->node.GROUP14.B2R2_SAR);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_USR:", node->node.GROUP14.B2R2_USR);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_IVMX0:", node->node.GROUP15.B2R2_VMX0);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_IVMX1:", node->node.GROUP15.B2R2_VMX1);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_IVMX2:", node->node.GROUP15.B2R2_VMX2);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_IVMX3:", node->node.GROUP15.B2R2_VMX3);
+ dst += sprintf(dst, "--\n");
+
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_OVMX0:", node->node.GROUP16.B2R2_VMX0);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_OVMX1:", node->node.GROUP16.B2R2_VMX1);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_OVMX2:", node->node.GROUP16.B2R2_VMX2);
+ dst += sprintf(dst, "%s\t0x%08x\n",
+ "B2R2_OVMX3:", node->node.GROUP16.B2R2_VMX3);
+ dst += sprintf(dst, "--\n");
+
+}
+
+void b2r2_debug_job_done(struct b2r2_control *cont,
+ struct b2r2_node *first_node)
+{
+ struct b2r2_node *node = first_node;
+ struct b2r2_node **dst_node;
+ unsigned int node_count = 0;
+
+ while (node != NULL) {
+ node_count++;
+ node = node->next;
+ }
+
+ mutex_lock(&cont->last_job_lock);
+
+ if (cont->last_job) {
+ node = cont->last_job;
+ while (node != NULL) {
+ struct b2r2_node *tmp = node->next;
+ kfree(node);
+ node = tmp;
+ }
+ cont->last_job = NULL;
+ }
+
+ node = first_node;
+ dst_node = &cont->last_job;
+ while (node != NULL) {
+ *dst_node = kzalloc(sizeof(**dst_node), GFP_KERNEL);
+ if (!(*dst_node))
+ goto last_job_alloc_failed;
+
+ memcpy(*dst_node, node, sizeof(**dst_node));
+
+ dst_node = &((*dst_node)->next);
+ node = node->next;
+ }
+
+ mutex_unlock(&cont->last_job_lock);
+
+ return;
+
+last_job_alloc_failed:
+ mutex_unlock(&cont->last_job_lock);
+
+ while (cont->last_job != NULL) {
+ struct b2r2_node *tmp = cont->last_job->next;
+ kfree(cont->last_job);
+ cont->last_job = tmp;
+ }
+
+ return;
+}
+
+static ssize_t last_job_read(struct file *filp, char __user *buf,
+ size_t bytes, loff_t *off)
+{
+ struct b2r2_control *cont = filp->f_dentry->d_inode->i_private;
+ struct b2r2_node *node = cont->last_job;
+ int node_count = 0;
+ int i;
+
+ size_t size;
+ size_t count;
+ loff_t offs = *off;
+
+ for (; node != NULL; node = node->next)
+ node_count++;
+
+ size = node_count * DUMPED_NODE_SIZE;
+
+ if (node_count != cont->prev_node_count) {
+ kfree(cont->last_job_chars);
+
+ cont->last_job_chars = kzalloc(size, GFP_KERNEL);
+ if (!cont->last_job_chars)
+ return 0;
+ cont->prev_node_count = node_count;
+ }
+
+ mutex_lock(&cont->last_job_lock);
+ node = cont->last_job;
+ for (i = 0; i < node_count; i++) {
+ BUG_ON(node == NULL);
+ dump_node(cont->last_job_chars +
+ i * DUMPED_NODE_SIZE/sizeof(char),
+ node);
+ node = node->next;
+ }
+ mutex_unlock(&cont->last_job_lock);
+
+ if (offs > size)
+ return 0;
+
+ if (offs + bytes > size)
+ count = size - offs;
+ else
+ count = bytes;
+
+ if (copy_to_user(buf, cont->last_job_chars + offs, count))
+ return -EFAULT;
+
+ *off = offs + count;
+ return count;
+}
+
+static const struct file_operations last_job_fops = {
+ .read = last_job_read,
+};
+
+int b2r2_debug_init(struct b2r2_control *cont)
+{
+ int i;
+
+ if (!module_init) {
+ for (i = 0; i < B2R2_LOG_LEVEL_COUNT; i++)
+ b2r2_log_levels[i] = 0;
+
+#if !defined(CONFIG_DYNAMIC_DEBUG) && defined(CONFIG_DEBUG_FS)
+ /*
+ * If dynamic debug is disabled we need some other way to
+ * control the log prints
+ */
+ log_lvl_dir = debugfs_create_dir("b2r2_log", NULL);
+
+ /* No need to save the files,
+ * they will be removed recursively */
+ if (!IS_ERR_OR_NULL(log_lvl_dir)) {
+ (void)debugfs_create_bool("warnings", 0644, log_lvl_dir,
+ &b2r2_log_levels[B2R2_LOG_LEVEL_WARN]);
+ (void)debugfs_create_bool("info", 0644, log_lvl_dir,
+ &b2r2_log_levels[B2R2_LOG_LEVEL_INFO]);
+ (void)debugfs_create_bool("debug", 0644, log_lvl_dir,
+ &b2r2_log_levels[B2R2_LOG_LEVEL_DEBUG]);
+ (void)debugfs_create_bool("regdumps", 0644, log_lvl_dir,
+ &b2r2_log_levels[B2R2_LOG_LEVEL_REGDUMP]);
+ }
+
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+ /* log_lvl_dir is never used */
+ (void)log_lvl_dir;
+#endif
+ module_init++;
+ }
+
+ if (!IS_ERR_OR_NULL(cont->debugfs_debug_root_dir)) {
+ /* No need to save the file,
+ * it will be removed recursively */
+ (void)debugfs_create_file("last_job", 0444,
+ cont->debugfs_debug_root_dir, cont,
+ &last_job_fops);
+ }
+
+ mutex_init(&cont->last_job_lock);
+
+ return 0;
+}
+
+void b2r2_debug_exit(void)
+{
+#if !defined(CONFIG_DYNAMIC_DEBUG) && defined(CONFIG_DEBUG_FS)
+ module_init--;
+ if (!module_init && !IS_ERR_OR_NULL(log_lvl_dir)) {
+ debugfs_remove_recursive(log_lvl_dir);
+ log_lvl_dir = NULL;
+ }
+#endif
+}
diff --git a/drivers/video/b2r2/b2r2_debug.h b/drivers/video/b2r2/b2r2_debug.h
new file mode 100644
index 00000000000..1b1ac83f6cb
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_debug.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 dynamic debug
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_DEBUG_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_DEBUG_H_
+
+#include <linux/device.h>
+
+#include "b2r2_internal.h"
+
+#ifdef CONFIG_B2R2_DEBUG
+
+/* Log macros */
+enum b2r2_log_levels {
+ B2R2_LOG_LEVEL_WARN,
+ B2R2_LOG_LEVEL_INFO,
+ B2R2_LOG_LEVEL_DEBUG,
+ B2R2_LOG_LEVEL_REGDUMP,
+ B2R2_LOG_LEVEL_COUNT,
+};
+
+/*
+ * Booleans controlling the different log levels. The different log levels are
+ * enabled separately (i.e. you can have info prints without the warn prints).
+ */
+extern int b2r2_log_levels[B2R2_LOG_LEVEL_COUNT];
+
+#define b2r2_log_err(b2r2_log_dev, ...) do { \
+ dev_err(b2r2_log_dev, __VA_ARGS__); \
+ } while (0)
+
+/* If dynamic debug is enabled it should be used instead of loglevels */
+#ifdef CONFIG_DYNAMIC_DEBUG
+# define b2r2_log_warn(b2r2_log_dev, ...) do { \
+ dev_dbg(b2r2_log_dev, "WARN " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_info(b2r2_log_dev, ...) do { \
+ dev_dbg(b2r2_log_dev, "INFO " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_debug(b2r2_log_dev, ...) do { \
+ dev_dbg(b2r2_log_dev, "DEBUG " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_regdump(b2r2_log_dev, ...) do { \
+ dev_dbg(b2r2_log_dev, "REGD " __VA_ARGS__); \
+ } while (0)
+#else
+# define b2r2_log_warn(b2r2_log_dev, ...) do { \
+ if (b2r2_log_levels[B2R2_LOG_LEVEL_WARN]) \
+ dev_warn(b2r2_log_dev, "WARN " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_info(b2r2_log_dev, ...) do { \
+ if (b2r2_log_levels[B2R2_LOG_LEVEL_INFO]) \
+ dev_info(b2r2_log_dev, "INFO " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_debug(b2r2_log_dev, ...) do { \
+ if (b2r2_log_levels[B2R2_LOG_LEVEL_DEBUG]) \
+ dev_dbg(b2r2_log_dev, "DEBUG " __VA_ARGS__); \
+ } while (0)
+# define b2r2_log_regdump(b2r2_log_dev, ...) do { \
+ if (b2r2_log_levels[B2R2_LOG_LEVEL_REGDUMP]) \
+ dev_vdbg(b2r2_log_dev, "REGD " __VA_ARGS__); \
+ } while (0)
+#endif
+
+int b2r2_debug_init(struct b2r2_control *cont);
+void b2r2_debug_exit(void);
+void b2r2_debug_job_done(struct b2r2_control *cont,
+ struct b2r2_node *node);
+
+#else
+
+#define b2r2_log_err(...)
+#define b2r2_log_warn(...)
+#define b2r2_log_info(...)
+#define b2r2_log_debug(...)
+#define b2r2_log_regdump(...)
+
+static inline int b2r2_debug_init(struct b2r2_control *cont)
+{
+ return 0;
+}
+static inline void b2r2_debug_exit(void)
+{
+ return;
+}
+static inline void b2r2_debug_job_done(struct b2r2_control *cont,
+ struct b2r2_node *node)
+{
+ return;
+}
+
+#endif
+
+#endif
diff --git a/drivers/video/b2r2/b2r2_filters.c b/drivers/video/b2r2/b2r2_filters.c
new file mode 100644
index 00000000000..a93eb60d91f
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_filters.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 filters.
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com> for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include "b2r2_filters.h"
+#include "b2r2_internal.h"
+#include "b2r2_debug.h"
+
+/**
+ * struct b2r2_filter_spec filters[] - Filter lookup table
+ *
+ * Lookup table for filters for different scale factors. A filter
+ * will be selected according to "min < scale_factor <= max".
+ */
+static struct b2r2_filter_spec filters[] = {
+ {
+ .min = 1024,
+ .max = 1433,
+ .h_coeffs = {
+ 0x00, 0x00, 0xFA, 0x09, 0x34, 0x09, 0x00, 0x00,
+ 0x00, 0x00, 0xF9, 0x10, 0x32, 0x06, 0xFF, 0x00,
+ 0x00, 0x00, 0xF8, 0x17, 0x2F, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0xF7, 0x20, 0x2A, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0x27, 0x25, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0xFA, 0x2D, 0x1D, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0xFE, 0x31, 0x15, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x35, 0x0D, 0xFC, 0x00, 0x00
+ },
+ .v_coeffs = {
+ 0x00, 0x02, 0x3C, 0x02, 0x00,
+ 0x00, 0x08, 0x3B, 0xFD, 0x00,
+ 0x00, 0x10, 0x35, 0xFB, 0x00,
+ 0x00, 0x18, 0x30, 0xF8, 0x00,
+ 0x00, 0x1F, 0x27, 0xFA, 0x00,
+ 0x00, 0x27, 0x1E, 0xFB, 0x00,
+ 0x00, 0x2E, 0x16, 0xFC, 0x00,
+ 0x00, 0x34, 0x0D, 0xFF, 0x00
+ },
+ },
+ {
+ .min = 1433,
+ .max = 1536,
+ .h_coeffs = {
+ 0xfe, 0x06, 0xf8, 0x0b, 0x30, 0x0b, 0xf8, 0x06,
+ 0xff, 0x06, 0xf7, 0x12, 0x2d, 0x05, 0xfa, 0x06,
+ 0x00, 0x04, 0xf6, 0x18, 0x2c, 0x00, 0xfc, 0x06,
+ 0x01, 0x02, 0xf7, 0x1f, 0x27, 0xfd, 0xff, 0x04,
+ 0x03, 0x00, 0xf9, 0x24, 0x24, 0xf9, 0x00, 0x03,
+ 0x04, 0xff, 0xfd, 0x29, 0x1d, 0xf7, 0x02, 0x01,
+ 0x06, 0xfc, 0x00, 0x2d, 0x17, 0xf6, 0x04, 0x00,
+ 0x06, 0xfa, 0x05, 0x30, 0x0f, 0xf7, 0x06, 0xff
+ },
+ .v_coeffs = {
+ 0xf6, 0x0e, 0x38, 0x0e, 0xf6,
+ 0xf5, 0x15, 0x38, 0x06, 0xf8,
+ 0xf5, 0x1d, 0x33, 0x00, 0xfb,
+ 0xf6, 0x23, 0x2d, 0xfc, 0xfe,
+ 0xf9, 0x28, 0x26, 0xf9, 0x00,
+ 0xfc, 0x2c, 0x1e, 0xf7, 0x03,
+ 0x00, 0x2e, 0x18, 0xf6, 0x04,
+ 0x05, 0x2e, 0x11, 0xf7, 0x05
+ },
+ },
+ {
+ .min = 1536,
+ .max = 3072,
+ .h_coeffs = {
+ 0xfc, 0xfd, 0x06, 0x13, 0x18, 0x13, 0x06, 0xfd,
+ 0xfc, 0xfe, 0x08, 0x15, 0x17, 0x12, 0x04, 0xfc,
+ 0xfb, 0xfe, 0x0a, 0x16, 0x18, 0x10, 0x03, 0xfc,
+ 0xfb, 0x00, 0x0b, 0x18, 0x17, 0x0f, 0x01, 0xfb,
+ 0xfb, 0x00, 0x0d, 0x19, 0x17, 0x0d, 0x00, 0xfb,
+ 0xfb, 0x01, 0x0f, 0x19, 0x16, 0x0b, 0x00, 0xfb,
+ 0xfc, 0x03, 0x11, 0x19, 0x15, 0x09, 0xfe, 0xfb,
+ 0xfc, 0x04, 0x12, 0x1a, 0x12, 0x08, 0xfe, 0xfc
+ },
+ .v_coeffs = {
+ 0x05, 0x10, 0x16, 0x10, 0x05,
+ 0x06, 0x11, 0x16, 0x0f, 0x04,
+ 0x08, 0x13, 0x15, 0x0e, 0x02,
+ 0x09, 0x14, 0x16, 0x0c, 0x01,
+ 0x0b, 0x15, 0x15, 0x0b, 0x00,
+ 0x0d, 0x16, 0x13, 0x0a, 0x00,
+ 0x0f, 0x17, 0x13, 0x08, 0xff,
+ 0x11, 0x18, 0x12, 0x07, 0xfe
+ },
+ },
+ {
+ .min = 3072,
+ .max = 4096,
+ .h_coeffs = {
+ 0xfe, 0x02, 0x09, 0x0f, 0x0e, 0x0f, 0x09, 0x02,
+ 0xff, 0x02, 0x09, 0x0f, 0x10, 0x0e, 0x08, 0x01,
+ 0xff, 0x03, 0x0a, 0x10, 0x10, 0x0d, 0x07, 0x00,
+ 0x00, 0x04, 0x0b, 0x10, 0x0f, 0x0c, 0x06, 0x00,
+ 0x00, 0x05, 0x0c, 0x10, 0x0e, 0x0c, 0x05, 0x00,
+ 0x00, 0x06, 0x0c, 0x11, 0x0e, 0x0b, 0x04, 0x00,
+ 0x00, 0x07, 0x0d, 0x11, 0x0f, 0x0a, 0x03, 0xff,
+ 0x01, 0x08, 0x0e, 0x11, 0x0e, 0x09, 0x02, 0xff
+ },
+ .v_coeffs = {
+ 0x09, 0x0f, 0x10, 0x0f, 0x09,
+ 0x09, 0x0f, 0x12, 0x0e, 0x08,
+ 0x0a, 0x10, 0x11, 0x0e, 0x07,
+ 0x0b, 0x11, 0x11, 0x0d, 0x06,
+ 0x0c, 0x11, 0x12, 0x0c, 0x05,
+ 0x0d, 0x12, 0x11, 0x0c, 0x04,
+ 0x0e, 0x12, 0x11, 0x0b, 0x04,
+ 0x0f, 0x13, 0x11, 0x0a, 0x03
+ },
+ },
+ {
+ .min = 4096,
+ .max = 5120,
+ .h_coeffs = {
+ 0x00, 0x04, 0x09, 0x0c, 0x0e, 0x0c, 0x09, 0x04,
+ 0x01, 0x05, 0x09, 0x0c, 0x0d, 0x0c, 0x08, 0x04,
+ 0x01, 0x05, 0x0a, 0x0c, 0x0e, 0x0b, 0x08, 0x03,
+ 0x02, 0x06, 0x0a, 0x0d, 0x0c, 0x0b, 0x07, 0x03,
+ 0x02, 0x07, 0x0a, 0x0d, 0x0d, 0x0a, 0x07, 0x02,
+ 0x03, 0x07, 0x0b, 0x0d, 0x0c, 0x0a, 0x06, 0x02,
+ 0x03, 0x08, 0x0b, 0x0d, 0x0d, 0x0a, 0x05, 0x01,
+ 0x04, 0x08, 0x0c, 0x0d, 0x0c, 0x09, 0x05, 0x01
+ },
+ .v_coeffs = {
+ 0x0a, 0x0e, 0x10, 0x0e, 0x0a,
+ 0x0b, 0x0e, 0x0f, 0x0e, 0x0a,
+ 0x0b, 0x0f, 0x10, 0x0d, 0x09,
+ 0x0c, 0x0f, 0x10, 0x0d, 0x08,
+ 0x0d, 0x0f, 0x0f, 0x0d, 0x08,
+ 0x0d, 0x10, 0x10, 0x0c, 0x07,
+ 0x0e, 0x10, 0x0f, 0x0c, 0x07,
+ 0x0f, 0x10, 0x10, 0x0b, 0x06
+ },
+ },
+};
+static const size_t filters_size = sizeof(filters)/sizeof(filters[0]);
+
+/**
+ * struct b2r2_filter_spec bilinear_filter - A bilinear filter
+ *
+ * The bilinear filter will be used if no custom filters are specified, or
+ * for upscales not matching any filter in the lookup table.
+ */
+static struct b2r2_filter_spec bilinear_filter = {
+ .min = 0,
+ .max = 0xffff,
+ .h_coeffs = {
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x08, 0x3e, 0xfb, 0x00, 0x00,
+ 0x00, 0x00, 0xfb, 0x13, 0x3b, 0xf7, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0x1f, 0x34, 0xf5, 0x00, 0x00,
+ 0x00, 0x00, 0xf6, 0x2b, 0x2a, 0xf5, 0x00, 0x00,
+ 0x00, 0x00, 0xf6, 0x35, 0x1e, 0xf7, 0x00, 0x00,
+ 0x00, 0x00, 0xf9, 0x3c, 0x12, 0xf9, 0x00, 0x00,
+ 0x00, 0x00, 0xfd, 0x3f, 0x07, 0xfd, 0x00, 0x00
+ },
+ .v_coeffs = {
+ 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x09, 0x3d, 0xfa, 0x00,
+ 0x00, 0x13, 0x39, 0xf4, 0x00,
+ 0x00, 0x1e, 0x31, 0xf1, 0x00,
+ 0x00, 0x27, 0x28, 0xf1, 0x00,
+ 0x00, 0x31, 0x1d, 0xf2, 0x00,
+ 0x00, 0x38, 0x12, 0xf6, 0x00,
+ 0x00, 0x3d, 0x07, 0xfc, 0x00
+ },
+};
+
+/**
+ * struct b2r2_filter_spec default_downscale_filter - Default filter for downscale
+ *
+ * The default downscale filter will be used for downscales not matching any
+ * filter in the lookup table.
+ */
+static struct b2r2_filter_spec default_downscale_filter = {
+ .min = 1 << 10,
+ .max = 0xffff,
+ .h_coeffs = {
+ 0x03, 0x06, 0x09, 0x0b, 0x09, 0x0b, 0x09, 0x06,
+ 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
+ 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
+ 0x04, 0x07, 0x09, 0x0b, 0x0b, 0x0a, 0x08, 0x04,
+ 0x04, 0x07, 0x0a, 0x0b, 0x0b, 0x0a, 0x07, 0x04,
+ 0x04, 0x08, 0x0a, 0x0b, 0x0b, 0x09, 0x07, 0x04,
+ 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03,
+ 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03
+ },
+ .v_coeffs = {
+ 0x0b, 0x0e, 0x0e, 0x0e, 0x0b,
+ 0x0b, 0x0e, 0x0f, 0x0d, 0x0b,
+ 0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
+ 0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
+ 0x0d, 0x0f, 0x0e, 0x0d, 0x09,
+ 0x0d, 0x0f, 0x0f, 0x0c, 0x09,
+ 0x0e, 0x0f, 0x0e, 0x0c, 0x09,
+ 0x0e, 0x0f, 0x0f, 0x0c, 0x08
+ },
+};
+
+/**
+ * struct b2r2_filter_spec blur_filter - Blur filter
+ *
+ * Filter for blurring an image.
+ */
+static struct b2r2_filter_spec blur_filter = {
+ .min = 0,
+ .max = 0xffff,
+ .h_coeffs = {
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+ },
+ .v_coeffs = {
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x10, 0x0c, 0x0c
+ },
+};
+
+/* Private function declarations */
+static int alloc_filter_coeffs(struct device *dev,
+ struct b2r2_filter_spec *filter);
+static void free_filter_coeffs(struct device *dev,
+ struct b2r2_filter_spec *filter);
+
+/* Public functions */
+
+int b2r2_filters_init(struct b2r2_control *cont)
+{
+ int i;
+
+ if (cont->filters_initialized)
+ return 0;
+
+ for (i = 0; i < filters_size; i++) {
+ alloc_filter_coeffs(cont->dev, &filters[i]);
+ }
+
+ alloc_filter_coeffs(cont->dev, &bilinear_filter);
+ alloc_filter_coeffs(cont->dev, &default_downscale_filter);
+ alloc_filter_coeffs(cont->dev, &blur_filter);
+
+ cont->filters_initialized = 1;
+
+ return 0;
+}
+
+void b2r2_filters_exit(struct b2r2_control *cont)
+{
+ int i;
+
+ if (!cont->filters_initialized)
+ return;
+
+ for (i = 0; i < filters_size; i++) {
+ free_filter_coeffs(cont->dev, &filters[i]);
+ }
+
+ free_filter_coeffs(cont->dev, &bilinear_filter);
+ free_filter_coeffs(cont->dev, &default_downscale_filter);
+ free_filter_coeffs(cont->dev, &blur_filter);
+
+ cont->filters_initialized = 0;
+}
+
+struct b2r2_filter_spec *b2r2_filter_find(u16 scale_factor)
+{
+ int i;
+ struct b2r2_filter_spec *filter = NULL;
+
+ for (i = 0; i < filters_size; i++) {
+ if ((filters[i].min < scale_factor) &&
+ (scale_factor <= filters[i].max) &&
+ filters[i].h_coeffs_dma_addr &&
+ filters[i].v_coeffs_dma_addr) {
+ filter = &filters[i];
+ break;
+ }
+ }
+
+ if (filter == NULL) {
+ /*
+ * No suitable filter has been found. Use default filters,
+ * bilinear for any upscale.
+ */
+ if (scale_factor < (1 << 10))
+ filter = &bilinear_filter;
+ else
+ filter = &default_downscale_filter;
+ }
+
+ /*
+ * Check so that the coefficients were successfully allocated for this
+ * filter.
+ */
+ if (!filter->h_coeffs_dma_addr || !filter->v_coeffs_dma_addr)
+ return NULL;
+ else
+ return filter;
+}
+
+struct b2r2_filter_spec *b2r2_filter_blur()
+{
+ return &blur_filter;
+}
+
+/* Private functions */
+static int alloc_filter_coeffs(struct device *dev,
+ struct b2r2_filter_spec *filter)
+{
+ int ret;
+
+ filter->h_coeffs_dma_addr = dma_alloc_coherent(dev,
+ B2R2_HF_TABLE_SIZE, &(filter->h_coeffs_phys_addr),
+ GFP_DMA | GFP_KERNEL);
+ if (filter->h_coeffs_dma_addr == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ filter->v_coeffs_dma_addr = dma_alloc_coherent(dev,
+ B2R2_VF_TABLE_SIZE, &(filter->v_coeffs_phys_addr),
+ GFP_DMA | GFP_KERNEL);
+ if (filter->v_coeffs_dma_addr == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memcpy(filter->h_coeffs_dma_addr, filter->h_coeffs,
+ B2R2_HF_TABLE_SIZE);
+ memcpy(filter->v_coeffs_dma_addr, filter->v_coeffs,
+ B2R2_VF_TABLE_SIZE);
+
+ return 0;
+
+error:
+ free_filter_coeffs(dev, filter);
+ return ret;
+
+}
+
+static void free_filter_coeffs(struct device *dev,
+ struct b2r2_filter_spec *filter)
+{
+ if (filter->h_coeffs_dma_addr != NULL)
+ dma_free_coherent(dev, B2R2_HF_TABLE_SIZE,
+ filter->h_coeffs_dma_addr,
+ filter->h_coeffs_phys_addr);
+ if (filter->v_coeffs_dma_addr != NULL)
+ dma_free_coherent(dev, B2R2_VF_TABLE_SIZE,
+ filter->v_coeffs_dma_addr,
+ filter->v_coeffs_phys_addr);
+
+ filter->h_coeffs_dma_addr = NULL;
+ filter->h_coeffs_phys_addr = 0;
+ filter->v_coeffs_dma_addr = NULL;
+ filter->v_coeffs_phys_addr = 0;
+}
diff --git a/drivers/video/b2r2/b2r2_filters.h b/drivers/video/b2r2/b2r2_filters.h
new file mode 100644
index 00000000000..790c9ec8ee9
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_filters.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 filters.
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com> for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_VIDEO_B2R2_FILTERS_H
+#define _LINUX_VIDEO_B2R2_FILTERS_H
+
+#include <linux/kernel.h>
+
+#include "b2r2_internal.h"
+
+#define B2R2_HF_TABLE_SIZE 64
+#define B2R2_VF_TABLE_SIZE 40
+
+/**
+ * @struct b2r2_filter_spec - Filter specification structure
+ *
+ * @param min - Minimum scale factor for this filter (in 6.10 fixed point)
+ * @param max - Maximum scale factor for this filter (in 6.10 fixed point)
+ * @param h_coeffs - Horizontal filter coefficients
+ * @param v_coeffs - Vertical filter coefficients
+ * @param h_coeffs_dma_addr - Virtual DMA address for horizontal coefficients
+ * @param v_coeffs_dma_addr - Virtual DMA address for vertical coefficients
+ * @param h_coeffs_phys_addr - Physical address for horizontal coefficients
+ * @param v_coeffs_phys_addr - Physical address for vertical coefficients
+ */
+struct b2r2_filter_spec {
+ const u16 min;
+ const u16 max;
+
+ const u8 h_coeffs[B2R2_HF_TABLE_SIZE];
+ const u8 v_coeffs[B2R2_VF_TABLE_SIZE];
+
+ void *h_coeffs_dma_addr;
+ u32 h_coeffs_phys_addr;
+
+ void *v_coeffs_dma_addr;
+ u32 v_coeffs_phys_addr;
+};
+
+/**
+ * b2r2_filters_init() - Initilizes the B2R2 filters
+ */
+int b2r2_filters_init(struct b2r2_control *control);
+
+/**
+ * b2r2_filters_init() - De-initilizes the B2R2 filters
+ */
+void b2r2_filters_exit(struct b2r2_control *control);
+
+/**
+ * b2r2_filter_find() - Find a filter matching the given scale factor
+ *
+ * @param scale_factor - Scale factor to find a filter for
+ *
+ * Returns NULL if no filter could be found.
+ */
+struct b2r2_filter_spec *b2r2_filter_find(u16 scale_factor);
+
+/**
+ * b2r2_filter_blur() - Returns the blur filter
+ *
+ * Returns NULL if no blur filter is available.
+ */
+struct b2r2_filter_spec *b2r2_filter_blur(void);
+
+#endif /* _LINUX_VIDEO_B2R2_FILTERS_H */
diff --git a/drivers/video/b2r2/b2r2_generic.c b/drivers/video/b2r2/b2r2_generic.c
new file mode 100644
index 00000000000..4191e497e13
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_generic.c
@@ -0,0 +1,3206 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 generic. Full coverage of user interface but
+ * non optimized implementation. For Fallback purposes.
+ *
+ * Author: Maciej Socha <maciej.socha@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+
+#include "b2r2_generic.h"
+#include "b2r2_internal.h"
+#include "b2r2_global.h"
+#include "b2r2_debug.h"
+#include "b2r2_filters.h"
+#include "b2r2_hw_convert.h"
+
+/*
+ * Debug printing
+ */
+#define B2R2_GENERIC_DEBUG_AREAS 0
+#define B2R2_GENERIC_DEBUG
+
+#define B2R2_GENERIC_WORK_BUF_WIDTH 16
+#define B2R2_GENERIC_WORK_BUF_HEIGHT 16
+#define B2R2_GENERIC_WORK_BUF_PITCH (16 * 4)
+#define B2R2_GENERIC_WORK_BUF_FMT B2R2_NATIVE_ARGB8888
+
+/*
+ * Private functions
+ */
+
+/**
+ * reset_nodes() - clears the node list
+ */
+static void reset_nodes(struct b2r2_control *cont,
+ struct b2r2_node *node)
+{
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ while (node != NULL) {
+ memset(&(node->node), 0, sizeof(node->node));
+
+ /* TODO: Implement support for short linked lists */
+ node->node.GROUP0.B2R2_CIC = 0x7fffc;
+
+ if (node->next == NULL)
+ break;
+
+ node->node.GROUP0.B2R2_NIP = node->next->physical_address;
+
+ node = node->next;
+ }
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+/**
+ * dump_nodes() - prints the node list
+ */
+static void dump_nodes(struct b2r2_control *cont,
+ struct b2r2_node *first, bool dump_all)
+{
+ struct b2r2_node *node = first;
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+ do {
+ b2r2_log_debug(cont->dev, "\nNODE START:\n=============\n");
+ b2r2_log_debug(cont->dev, "B2R2_ACK: \t0x%.8x\n",
+ node->node.GROUP0.B2R2_ACK);
+ b2r2_log_debug(cont->dev, "B2R2_INS: \t0x%.8x\n",
+ node->node.GROUP0.B2R2_INS);
+ b2r2_log_debug(cont->dev, "B2R2_CIC: \t0x%.8x\n",
+ node->node.GROUP0.B2R2_CIC);
+ b2r2_log_debug(cont->dev, "B2R2_NIP: \t0x%.8x\n",
+ node->node.GROUP0.B2R2_NIP);
+
+ b2r2_log_debug(cont->dev, "B2R2_TSZ: \t0x%.8x\n",
+ node->node.GROUP1.B2R2_TSZ);
+ b2r2_log_debug(cont->dev, "B2R2_TXY: \t0x%.8x\n",
+ node->node.GROUP1.B2R2_TXY);
+ b2r2_log_debug(cont->dev, "B2R2_TTY: \t0x%.8x\n",
+ node->node.GROUP1.B2R2_TTY);
+ b2r2_log_debug(cont->dev, "B2R2_TBA: \t0x%.8x\n",
+ node->node.GROUP1.B2R2_TBA);
+
+ b2r2_log_debug(cont->dev, "B2R2_S2CF: \t0x%.8x\n",
+ node->node.GROUP2.B2R2_S2CF);
+ b2r2_log_debug(cont->dev, "B2R2_S1CF: \t0x%.8x\n",
+ node->node.GROUP2.B2R2_S1CF);
+
+ b2r2_log_debug(cont->dev, "B2R2_S1SZ: \t0x%.8x\n",
+ node->node.GROUP3.B2R2_SSZ);
+ b2r2_log_debug(cont->dev, "B2R2_S1XY: \t0x%.8x\n",
+ node->node.GROUP3.B2R2_SXY);
+ b2r2_log_debug(cont->dev, "B2R2_S1TY: \t0x%.8x\n",
+ node->node.GROUP3.B2R2_STY);
+ b2r2_log_debug(cont->dev, "B2R2_S1BA: \t0x%.8x\n",
+ node->node.GROUP3.B2R2_SBA);
+
+ b2r2_log_debug(cont->dev, "B2R2_S2SZ: \t0x%.8x\n",
+ node->node.GROUP4.B2R2_SSZ);
+ b2r2_log_debug(cont->dev, "B2R2_S2XY: \t0x%.8x\n",
+ node->node.GROUP4.B2R2_SXY);
+ b2r2_log_debug(cont->dev, "B2R2_S2TY: \t0x%.8x\n",
+ node->node.GROUP4.B2R2_STY);
+ b2r2_log_debug(cont->dev, "B2R2_S2BA: \t0x%.8x\n",
+ node->node.GROUP4.B2R2_SBA);
+
+ b2r2_log_debug(cont->dev, "B2R2_S3SZ: \t0x%.8x\n",
+ node->node.GROUP5.B2R2_SSZ);
+ b2r2_log_debug(cont->dev, "B2R2_S3XY: \t0x%.8x\n",
+ node->node.GROUP5.B2R2_SXY);
+ b2r2_log_debug(cont->dev, "B2R2_S3TY: \t0x%.8x\n",
+ node->node.GROUP5.B2R2_STY);
+ b2r2_log_debug(cont->dev, "B2R2_S3BA: \t0x%.8x\n",
+ node->node.GROUP5.B2R2_SBA);
+
+ b2r2_log_debug(cont->dev, "B2R2_CWS: \t0x%.8x\n",
+ node->node.GROUP6.B2R2_CWS);
+ b2r2_log_debug(cont->dev, "B2R2_CWO: \t0x%.8x\n",
+ node->node.GROUP6.B2R2_CWO);
+
+ b2r2_log_debug(cont->dev, "B2R2_FCTL: \t0x%.8x\n",
+ node->node.GROUP8.B2R2_FCTL);
+ b2r2_log_debug(cont->dev, "B2R2_RSF: \t0x%.8x\n",
+ node->node.GROUP9.B2R2_RSF);
+ b2r2_log_debug(cont->dev, "B2R2_RZI: \t0x%.8x\n",
+ node->node.GROUP9.B2R2_RZI);
+ b2r2_log_debug(cont->dev, "B2R2_HFP: \t0x%.8x\n",
+ node->node.GROUP9.B2R2_HFP);
+ b2r2_log_debug(cont->dev, "B2R2_VFP: \t0x%.8x\n",
+ node->node.GROUP9.B2R2_VFP);
+ b2r2_log_debug(cont->dev, "B2R2_LUMA_RSF: \t0x%.8x\n",
+ node->node.GROUP10.B2R2_RSF);
+ b2r2_log_debug(cont->dev, "B2R2_LUMA_RZI: \t0x%.8x\n",
+ node->node.GROUP10.B2R2_RZI);
+ b2r2_log_debug(cont->dev, "B2R2_LUMA_HFP: \t0x%.8x\n",
+ node->node.GROUP10.B2R2_HFP);
+ b2r2_log_debug(cont->dev, "B2R2_LUMA_VFP: \t0x%.8x\n",
+ node->node.GROUP10.B2R2_VFP);
+
+
+ b2r2_log_debug(cont->dev, "B2R2_IVMX0: \t0x%.8x\n",
+ node->node.GROUP15.B2R2_VMX0);
+ b2r2_log_debug(cont->dev, "B2R2_IVMX1: \t0x%.8x\n",
+ node->node.GROUP15.B2R2_VMX1);
+ b2r2_log_debug(cont->dev, "B2R2_IVMX2: \t0x%.8x\n",
+ node->node.GROUP15.B2R2_VMX2);
+ b2r2_log_debug(cont->dev, "B2R2_IVMX3: \t0x%.8x\n",
+ node->node.GROUP15.B2R2_VMX3);
+ b2r2_log_debug(cont->dev, "\n=============\nNODE END\n");
+
+ node = node->next;
+ } while (node != NULL && dump_all);
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+/**
+ * to_native_fmt() - returns the native B2R2 format
+ */
+static inline enum b2r2_native_fmt to_native_fmt(struct b2r2_control *cont,
+ enum b2r2_blt_fmt fmt)
+{
+
+ switch (fmt) {
+ case B2R2_BLT_FMT_UNUSED:
+ return B2R2_NATIVE_RGB565;
+ case B2R2_BLT_FMT_1_BIT_A1:
+ return B2R2_NATIVE_A1;
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return B2R2_NATIVE_A8;
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ return B2R2_NATIVE_RGB565;
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ return B2R2_NATIVE_ARGB4444;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ return B2R2_NATIVE_ARGB1555;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ return B2R2_NATIVE_ARGB8565;
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ return B2R2_NATIVE_RGB888;
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ return B2R2_NATIVE_YCBCR888;
+ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Not actually supported by HW */
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ return B2R2_NATIVE_ARGB8888;
+ case B2R2_BLT_FMT_32_BIT_VUYA8888: /* fall through */
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ return B2R2_NATIVE_AYCBCR8888;
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ return B2R2_NATIVE_YCBCR422R;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ return B2R2_NATIVE_YCBCR422R;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return B2R2_NATIVE_YCBCR42X_R2B;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return B2R2_NATIVE_YCBCR42X_MBN;
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return B2R2_NATIVE_YUV;
+ default:
+ /* Should never ever happen */
+ return B2R2_NATIVE_BYTE;
+ }
+}
+
+/**
+ * get_alpha_range() - returns the alpha range of the given format
+ */
+static inline enum b2r2_ty get_alpha_range(struct b2r2_control *cont,
+ enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ return B2R2_TY_ALPHA_RANGE_255; /* 0 - 255 */
+ break;
+ default:
+ break;
+ }
+
+ return B2R2_TY_ALPHA_RANGE_128; /* 0 - 128 */
+}
+
+static unsigned int get_pitch(struct b2r2_control *cont,
+ enum b2r2_blt_fmt format, u32 width)
+{
+ switch (format) {
+ case B2R2_BLT_FMT_1_BIT_A1: {
+ int pitch = width >> 3;
+ /* Check for remainder */
+ if (width & 7)
+ pitch++;
+ return pitch;
+ break;
+ }
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return width;
+ break;
+ case B2R2_BLT_FMT_16_BIT_RGB565: /* all 16 bits/pixel RGB formats */
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ return width * 2;
+ break;
+ case B2R2_BLT_FMT_24_BIT_RGB888: /* all 24 bits/pixel raster formats */
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ return width * 3;
+ break;
+ case B2R2_BLT_FMT_32_BIT_ARGB8888: /* all 32 bits/pixel formats */
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ return width * 4;
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ /* width of the buffer must be a multiple of 4 */
+ if (width & 3) {
+ b2r2_log_warn(cont->dev, "%s: Illegal width "
+ "for fmt=%#010x width=%d\n", __func__,
+ format, width);
+ return 0;
+ }
+ return width * 2;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return width;
+ break;
+ /* fall through, same pitch and pointers */
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ /* width of the buffer must be a multiple of 2 */
+ if (width & 1) {
+ b2r2_log_warn(cont->dev, "%s: Illegal width "
+ "for fmt=%#010x width=%d\n", __func__,
+ format, width);
+ return 0;
+ }
+ /*
+ * return pitch of the Y-buffer.
+ * U and V pitch can be derived from it.
+ */
+ return width;
+ break;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /* width of the buffer must be a multiple of 16. */
+ if (width & 15) {
+ b2r2_log_warn(cont->dev, "%s: Illegal width "
+ "for fmt=%#010x width=%d\n", __func__,
+ format, width);
+ return 0;
+ }
+ /*
+ * return pitch of the Y-buffer.
+ * U and V pitch can be derived from it.
+ */
+ return width;
+ break;
+ default:
+ b2r2_log_warn(cont->dev, "%s: Unable to determine pitch "
+ "for fmt=%#010x width=%d\n", __func__,
+ format, width);
+ return 0;
+ }
+}
+
+static s32 validate_buf(struct b2r2_control *cont,
+ const struct b2r2_blt_img *image,
+ const struct b2r2_resolved_buf *buf)
+{
+ u32 expect_buf_size;
+ u32 pitch;
+
+ if (image->width <= 0 || image->height <= 0) {
+ b2r2_log_warn(cont->dev, "%s: width=%d or height=%d negative"
+ ".\n", __func__, image->width, image->height);
+ return -EINVAL;
+ }
+
+ if (image->pitch == 0) {
+ /* autodetect pitch based on format and width */
+ pitch = get_pitch(cont, image->fmt, image->width);
+ } else
+ pitch = image->pitch;
+
+ expect_buf_size = pitch * image->height;
+
+ if (pitch == 0) {
+ b2r2_log_warn(cont->dev, "%s: Unable to detect pitch. "
+ "fmt=%#010x, width=%d\n",
+ __func__,
+ image->fmt, image->width);
+ return -EINVAL;
+ }
+
+ /* format specific adjustments */
+ switch (image->fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ /*
+ * Use ceil(height/2) in case buffer height
+ * is not divisible by 2.
+ */
+ expect_buf_size +=
+ (pitch >> 1) * ((image->height + 1) >> 1) * 2;
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ expect_buf_size += (pitch >> 1) * image->height * 2;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ expect_buf_size += pitch * image->height * 2;
+ break;
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ /*
+ * include space occupied by U and V data.
+ * U and V interleaved, half resolution, which makes
+ * the UV pitch equal to luma pitch.
+ * Use ceil(height/2) in case buffer height
+ * is not divisible by 2.
+ */
+ expect_buf_size += pitch * ((image->height + 1) >> 1);
+ break;
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ /*
+ * include space occupied by U and V data.
+ * U and V interleaved, half resolution, which makes
+ * the UV pitch equal to luma pitch.
+ */
+ expect_buf_size += pitch * image->height;
+ break;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ /* Height must be a multiple of 16 for macro-block format.*/
+ if (image->height & 15) {
+ b2r2_log_warn(cont->dev, "%s: Illegal height "
+ "for fmt=%#010x height=%d\n", __func__,
+ image->fmt, image->height);
+ return -EINVAL;
+ }
+ expect_buf_size += pitch * (image->height >> 1);
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /* Height must be a multiple of 16 for macro-block format.*/
+ if (image->height & 15) {
+ b2r2_log_warn(cont->dev, "%s: Illegal height "
+ "for fmt=%#010x height=%d\n", __func__,
+ image->fmt, image->height);
+ return -EINVAL;
+ }
+ expect_buf_size += pitch * image->height;
+ break;
+ default:
+ break;
+ }
+
+ if (buf->file_len < expect_buf_size) {
+ b2r2_log_warn(cont->dev, "%s: Invalid buffer size:\n"
+ "fmt=%#010x w=%d h=%d buf.len=%d expect_buf_size=%d\n",
+ __func__,
+ image->fmt, image->width, image->height, buf->file_len,
+ expect_buf_size);
+ return -EINVAL;
+ }
+
+ if (image->buf.type == B2R2_BLT_PTR_VIRTUAL) {
+ b2r2_log_warn(cont->dev, "%s: Virtual pointers not supported"
+ " yet.\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Bit-expand the color from fmt to RGB888 with blue at LSB.
+ * Copy MSBs into missing LSBs.
+ */
+static u32 to_RGB888(struct b2r2_control *cont, u32 color,
+ const enum b2r2_blt_fmt fmt)
+{
+ u32 out_color = 0;
+ u32 r = 0;
+ u32 g = 0;
+ u32 b = 0;
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ r = ((color & 0xf00) << 12) | ((color & 0xf00) << 8);
+ g = ((color & 0xf0) << 8) | ((color & 0xf0) << 4);
+ b = ((color & 0xf) << 4) | (color & 0xf);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ r = ((color & 0x7c00) << 9) | ((color & 0x7000) << 4);
+ g = ((color & 0x3e0) << 6) | ((color & 0x380) << 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ r = ((color & 0xf800) << 8) | ((color & 0xe000) << 3);
+ g = ((color & 0x7e0) << 5) | ((color & 0x600) >> 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ out_color = color & 0xffffff;
+ break;
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ r = (color & 0xff) << 16;
+ g = color & 0xff00;
+ b = (color & 0xff0000) >> 16;
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ r = ((color & 0xf800) << 8) | ((color & 0xe000) << 3);
+ g = ((color & 0x7e0) << 5) | ((color & 0x600) >> 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ default:
+ break;
+ }
+
+ return out_color;
+}
+
+
+static void setup_fill_input_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *out_buf)
+{
+ enum b2r2_native_fmt fill_fmt = 0;
+ u32 src_color = req->user_req.src_color;
+ const struct b2r2_blt_img *dst_img = &(req->user_req.dst_img);
+ struct b2r2_control *cont = req->instance->control;
+ bool fullrange = (req->user_req.flags &
+ B2R2_BLT_FLAG_FULL_RANGE_YUV) != 0;
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ /* Determine format in src_color */
+ switch (dst_img->fmt) {
+ /* ARGB formats */
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_FILL) != 0) {
+ fill_fmt = B2R2_NATIVE_ARGB8888;
+ } else {
+ /* SOURCE_FILL_RAW */
+ fill_fmt = to_native_fmt(cont, dst_img->fmt);
+ if (dst_img->fmt == B2R2_BLT_FMT_32_BIT_ABGR8888) {
+ /*
+ * Color is read from a register,
+ * where it is stored in ABGR format.
+ * Set up IVMX.
+ */
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_BGR);
+ }
+ }
+ break;
+ /* YUV formats */
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_FILL) != 0) {
+ fill_fmt = B2R2_NATIVE_AYCBCR8888;
+ /*
+ * Set up IVMX
+ * The destination format is in fact YUV,
+ * but the input stage stores the data in
+ * an intermediate buffer which is RGB.
+ * Hence the conversion from YUV to RGB.
+ * Format of the supplied src_color is
+ * B2R2_BLT_FMT_32_BIT_AYUV8888.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_TO_RGB);
+ } else {
+ /* SOURCE_FILL_RAW */
+ bool dst_yuv_planar =
+ B2R2_BLT_FMT_YUV420_PACKED_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YUV422_PACKED_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YVU420_PACKED_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YVU422_PACKED_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YUV444_PACKED_PLANAR ==
+ dst_img->fmt;
+
+ bool dst_yuv_semi_planar =
+ B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ==
+ dst_img->fmt ||
+ B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE ==
+ dst_img->fmt;
+
+ if (dst_yuv_planar || dst_yuv_semi_planar) {
+ /*
+ * SOURCE_FILL_RAW cannot be supported
+ * with multi-buffer formats.
+ * Force a legal format to prevent B2R2
+ * from misbehaving.
+ */
+ fill_fmt = B2R2_NATIVE_AYCBCR8888;
+ } else {
+ fill_fmt = to_native_fmt(cont, dst_img->fmt);
+ }
+
+ switch (dst_img->fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ if (fullrange)
+ b2r2_setup_ivmx(node,
+ B2R2_CC_BLT_YUV888_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node,
+ B2R2_CC_BLT_YUV888_TO_RGB);
+ /*
+ * Re-arrange the color components from
+ * VUY(A) to (A)YUV
+ */
+ if (dst_img->fmt ==
+ B2R2_BLT_FMT_24_BIT_VUY888) {
+ u32 Y = src_color & 0xff;
+ u32 U = src_color & 0xff00;
+ u32 V = src_color & 0xff0000;
+ src_color = (Y << 16) | U | (V >> 16);
+ } else if (dst_img->fmt ==
+ B2R2_BLT_FMT_32_BIT_VUYA8888) {
+ u32 A = src_color & 0xff;
+ u32 Y = src_color & 0xff00;
+ u32 U = src_color & 0xff0000;
+ u32 V = src_color & 0xff000000;
+ src_color = (A << 24) |
+ (Y << 8) |
+ (U >> 8) |
+ (V >> 24);
+ }
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ /*
+ * Setup input VMX to convert YVU to
+ * RGB 601 VIDEO
+ * Chroma components are swapped so
+ * it is YVU and not YUV.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node,
+ B2R2_CC_YVU_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_TO_RGB);
+ break;
+ default:
+ /*
+ * Set up IVMX
+ * The destination format is in fact YUV,
+ * but the input stage stores the data in
+ * an intermediate buffer which is RGB.
+ * Hence the conversion from YUV to RGB.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node,
+ B2R2_CC_YUV_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_TO_RGB);
+ break;
+ }
+ }
+ break;
+ default:
+ src_color = 0;
+ fill_fmt = B2R2_NATIVE_ARGB8888;
+ break;
+ }
+
+ node->node.GROUP1.B2R2_TBA = out_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+ /* Set color fill on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = 0;
+ node->node.GROUP4.B2R2_STY =
+ (0 << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ fill_fmt |
+ get_alpha_range(cont, dst_img->fmt) |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_COLOR_FILL_REGISTER;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_COLOR_FILL;
+ node->node.GROUP2.B2R2_S2CF = src_color;
+
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+static void setup_input_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *out_buf)
+{
+ /* Horizontal and vertical scaling factors in 6.10 fixed point format */
+ s32 h_scf = 1 << 10;
+ s32 v_scf = 1 << 10;
+ const struct b2r2_blt_rect *src_rect = &(req->user_req.src_rect);
+ const struct b2r2_blt_rect *dst_rect = &(req->user_req.dst_rect);
+ const struct b2r2_blt_img *src_img = &(req->user_req.src_img);
+ u32 src_pitch = 0;
+ /* horizontal and vertical scan order for out_buf */
+ enum b2r2_ty dst_hso = B2R2_TY_HSO_LEFT_TO_RIGHT;
+ enum b2r2_ty dst_vso = B2R2_TY_VSO_TOP_TO_BOTTOM;
+ u32 endianness = 0;
+ u32 fctl = 0;
+ u32 rsf = 0;
+ u32 rzi = 0;
+ bool yuv_semi_planar =
+ src_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ src_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+
+ bool yuv_planar =
+ src_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR;
+
+ struct b2r2_filter_spec *hf;
+ struct b2r2_filter_spec *vf;
+
+ bool use_h_filter = false;
+ bool use_v_filter = false;
+
+ struct b2r2_control *cont = req->instance->control;
+ bool fullrange = (req->user_req.flags &
+ B2R2_BLT_FLAG_FULL_RANGE_YUV) != 0;
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ if (((B2R2_BLT_FLAG_SOURCE_FILL | B2R2_BLT_FLAG_SOURCE_FILL_RAW) &
+ req->user_req.flags) != 0) {
+ setup_fill_input_stage(req, node, out_buf);
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+ return;
+ }
+
+ if (src_img->pitch == 0) {
+ /* Determine pitch based on format and width of the image. */
+ src_pitch = get_pitch(cont, src_img->fmt, src_img->width);
+ } else {
+ src_pitch = src_img->pitch;
+ }
+
+ b2r2_log_info(cont->dev, "%s transform=%#010x\n",
+ __func__, req->user_req.transform);
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ h_scf = (src_rect->width << 10) / dst_rect->height;
+ v_scf = (src_rect->height << 10) / dst_rect->width;
+ } else {
+ h_scf = (src_rect->width << 10) / dst_rect->width;
+ v_scf = (src_rect->height << 10) / dst_rect->height;
+ }
+
+ hf = b2r2_filter_find(h_scf);
+ vf = b2r2_filter_find(v_scf);
+
+ use_h_filter = h_scf != (1 << 10);
+ use_v_filter = v_scf != (1 << 10);
+
+ /* B2R2_BLT_FLAG_BLUR overrides any scaling filter. */
+ if (req->user_req.flags & B2R2_BLT_FLAG_BLUR) {
+ use_h_filter = true;
+ use_v_filter = true;
+ hf = b2r2_filter_blur();
+ vf = b2r2_filter_blur();
+ }
+
+ /* Configure horizontal rescale */
+ if (h_scf != (1 << 10)) {
+ b2r2_log_info(cont->dev, "%s: Scaling horizontally by 0x%.8x"
+ "\ns(%d, %d)->d(%d, %d)\n", __func__,
+ h_scf, src_rect->width, src_rect->height,
+ dst_rect->width, dst_rect->height);
+ }
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER;
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= h_scf << B2R2_RSF_HSRC_INC_SHIFT;
+ rzi |= B2R2_RZI_DEFAULT_HNB_REPEAT;
+
+ /* Configure vertical rescale */
+ if (v_scf != (1 << 10)) {
+ b2r2_log_info(cont->dev, "%s: Scaling vertically by 0x%.8x"
+ "\ns(%d, %d)->d(%d, %d)\n", __func__,
+ v_scf, src_rect->width, src_rect->height,
+ dst_rect->width, dst_rect->height);
+ }
+ fctl |= B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= v_scf << B2R2_RSF_VSRC_INC_SHIFT;
+ rzi |= 2 << B2R2_RZI_VNB_REPEAT_SHIFT;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_RESIZE_CHROMA;
+
+ /* Adjustments that depend on the source format */
+ switch (src_img->fmt) {
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_BGR);
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ /*
+ * Setup input VMX to convert YVU to RGB 601 VIDEO
+ * Chroma components are swapped so
+ * it is YVU and not YUV.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_TO_RGB);
+ break;
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_TO_RGB);
+ break;
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ /*
+ * Set up IVMX.
+ * For B2R2_BLT_FMT_32_BIT_YUV888 and
+ * B2R2_BLT_FMT_32_BIT_AYUV8888
+ * the color components are laid out in memory as V, U, Y, (A)
+ * with V at the first byte (due to little endian addressing).
+ * B2R2 expects them to be as U, Y, V, (A)
+ * with U at the first byte.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_TO_RGB);
+
+ /*
+ * Re-arrange color components from VUY(A) to (A)YUV
+ * for input VMX to work on them further.
+ */
+ if (src_img->fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ src_img->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+ break;
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE: {
+ /*
+ * Luma handled in the same way
+ * for all YUV multi-buffer formats.
+ * Set luma rescale registers.
+ */
+ u32 rsf_luma = 0;
+ u32 rzi_luma = 0;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_RESIZE_LUMA;
+
+ if (src_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ src_img->fmt ==
+ B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR) {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_TO_RGB);
+ } else {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_TO_RGB);
+ }
+
+ fctl |= B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_RESIZER;
+
+ if (use_h_filter && hf) {
+ fctl |= B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_FILTER;
+ node->node.GROUP10.B2R2_HFP = hf->h_coeffs_phys_addr;
+ }
+
+ if (use_v_filter && vf) {
+ fctl |= B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_FILTER;
+ node->node.GROUP10.B2R2_VFP = vf->v_coeffs_phys_addr;
+ }
+
+ rsf_luma |= h_scf << B2R2_RSF_HSRC_INC_SHIFT;
+ rzi_luma |= B2R2_RZI_DEFAULT_HNB_REPEAT;
+
+ rsf_luma |= v_scf << B2R2_RSF_VSRC_INC_SHIFT;
+ rzi_luma |= 2 << B2R2_RZI_VNB_REPEAT_SHIFT;
+
+ node->node.GROUP10.B2R2_RSF = rsf_luma;
+ node->node.GROUP10.B2R2_RZI = rzi_luma;
+
+ switch (src_img->fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chrominance is always half the luminance size
+ * so chrominance resizer is always active.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (h_scf >> 1) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (v_scf >> 1) << B2R2_RSF_VSRC_INC_SHIFT;
+ /* Select suitable filter for chroma */
+ hf = b2r2_filter_find(h_scf >> 1);
+ vf = b2r2_filter_find(v_scf >> 1);
+ use_h_filter = true;
+ use_v_filter = true;
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chrominance is always half the luminance size
+ * only in horizontal direction.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (h_scf >> 1) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= v_scf << B2R2_RSF_VSRC_INC_SHIFT;
+ /* Select suitable filter for chroma */
+ hf = b2r2_filter_find(h_scf >> 1);
+ use_h_filter = true;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ /* Chrominance is the same size as luminance.*/
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= h_scf << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= v_scf << B2R2_RSF_VSRC_INC_SHIFT;
+ /* Select suitable filter for chroma */
+ hf = b2r2_filter_find(h_scf);
+ vf = b2r2_filter_find(v_scf);
+ use_h_filter = true;
+ use_v_filter = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /*
+ * Set the filter control and rescale registers.
+ * GROUP9 registers are used for all single-buffer formats
+ * or for chroma in case of multi-buffer YUV formats.
+ * h/v_filter is now appropriately selected for chroma scaling,
+ * be it YUV multi-buffer, or single-buffer raster format.
+ * B2R2_BLT_FLAG_BLUR overrides any scaling filter.
+ */
+ if (req->user_req.flags & B2R2_BLT_FLAG_BLUR) {
+ use_h_filter = true;
+ use_v_filter = true;
+ hf = b2r2_filter_blur();
+ vf = b2r2_filter_blur();
+ }
+
+ if (use_h_filter && hf) {
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER;
+ node->node.GROUP9.B2R2_HFP = hf->h_coeffs_phys_addr;
+ }
+
+ if (use_v_filter && vf) {
+ fctl |= B2R2_FCTL_VF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER;
+ node->node.GROUP9.B2R2_VFP = vf->v_coeffs_phys_addr;
+ }
+
+ node->node.GROUP8.B2R2_FCTL |= fctl;
+ node->node.GROUP9.B2R2_RSF |= rsf;
+ node->node.GROUP9.B2R2_RZI |= rzi;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_FILTER_CONTROL;
+
+ /*
+ * Flip transform is done before potential rotation.
+ * This can be achieved with appropriate scan order.
+ * Transform stage will only do rotation.
+ */
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_H)
+ dst_hso = B2R2_TY_HSO_RIGHT_TO_LEFT;
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_V)
+ dst_vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+
+ /* Set target buffer */
+ node->node.GROUP1.B2R2_TBA = out_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ dst_hso | dst_vso;
+
+ if (yuv_planar) {
+ /*
+ * Set up chrominance buffers on source 1 and 2,
+ * luminance on source 3.
+ * src_pitch and physical_address apply to luminance,
+ * corresponding chrominance values have to be derived.
+ */
+ u32 cb_addr = 0;
+ u32 cr_addr = 0;
+ u32 chroma_pitch = 0;
+ bool swapped_chroma =
+ src_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ src_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR;
+ enum b2r2_native_fmt src_fmt =
+ to_native_fmt(cont, src_img->fmt);
+
+ if (swapped_chroma)
+ cr_addr = req->src_resolved.physical_address +
+ src_pitch * src_img->height;
+ else
+ cb_addr = req->src_resolved.physical_address +
+ src_pitch * src_img->height;
+
+ switch (src_img->fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ chroma_pitch = src_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ (src_img->height >> 1);
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ (src_img->height >> 1);
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ chroma_pitch = src_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ src_img->height;
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ src_img->height;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ /* Chrominance has full resolution, same as luminance.*/
+ chroma_pitch = src_pitch;
+ cr_addr =
+ cb_addr + chroma_pitch * src_img->height;
+ break;
+ default:
+ break;
+ }
+
+ node->node.GROUP3.B2R2_SBA = cr_addr;
+ node->node.GROUP3.B2R2_STY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ src_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP4.B2R2_SBA = cb_addr;
+ node->node.GROUP4.B2R2_STY = node->node.GROUP3.B2R2_STY;
+
+ node->node.GROUP5.B2R2_SBA = req->src_resolved.physical_address;
+ node->node.GROUP5.B2R2_STY =
+ (src_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ src_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_1_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_3_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_1 |
+ B2R2_CIC_SOURCE_2 |
+ B2R2_CIC_SOURCE_3;
+ } else if (yuv_semi_planar) {
+ /*
+ * Set up chrominance buffer on source 2, luminance on source 3.
+ * src_pitch and physical_address apply to luminance,
+ * corresponding chrominance values have to be derived.
+ * U and V are interleaved at half the luminance resolution,
+ * which makes the pitch of the UV plane equal
+ * to luminance pitch.
+ */
+ u32 chroma_addr = req->src_resolved.physical_address +
+ src_pitch * src_img->height;
+ u32 chroma_pitch = src_pitch;
+
+ enum b2r2_native_fmt src_fmt =
+ to_native_fmt(cont, src_img->fmt);
+
+ node->node.GROUP4.B2R2_SBA = chroma_addr;
+ node->node.GROUP4.B2R2_STY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ src_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP5.B2R2_SBA = req->src_resolved.physical_address;
+ node->node.GROUP5.B2R2_STY =
+ (src_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ src_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_3_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_2 | B2R2_CIC_SOURCE_3;
+ } else {
+ /* single buffer format */
+ node->node.GROUP4.B2R2_SBA = req->src_resolved.physical_address;
+ node->node.GROUP4.B2R2_STY =
+ (src_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ to_native_fmt(cont, src_img->fmt) |
+ get_alpha_range(cont, src_img->fmt) |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ endianness;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+ }
+
+ if ((req->user_req.flags &
+ B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) != 0) {
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_CLUTOP_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_CLUT;
+ node->node.GROUP7.B2R2_CCO = B2R2_CCO_CLUT_COLOR_CORRECTION |
+ B2R2_CCO_CLUT_UPDATE;
+ node->node.GROUP7.B2R2_CML = req->clut_phys_addr;
+ }
+
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+static void setup_transform_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *out_buf,
+ struct b2r2_work_buf *in_buf)
+{
+ /* vertical scan order for out_buf */
+ enum b2r2_ty dst_vso = B2R2_TY_VSO_TOP_TO_BOTTOM;
+ enum b2r2_blt_transform transform = req->user_req.transform;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_control *cont = req->instance->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ if (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ /*
+ * Scan order must be flipped otherwise contents will
+ * be mirrored vertically. Leftmost column of in_buf
+ * would become top instead of bottom row of out_buf.
+ */
+ dst_vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_ROTATION_ENABLED;
+ }
+
+ /* Set target buffer */
+ node->node.GROUP1.B2R2_TBA = out_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT | dst_vso;
+
+ /* Set source buffer on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+/*
+static void setup_mask_stage(const struct b2r2_blt_request req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *out_buf,
+ struct b2r2_work_buf *in_buf);
+*/
+
+static void setup_dst_read_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *out_buf)
+{
+ const struct b2r2_blt_img *dst_img = &(req->user_req.dst_img);
+ u32 fctl = 0;
+ u32 rsf = 0;
+ u32 endianness = 0;
+ bool yuv_semi_planar =
+ dst_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ dst_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+
+ bool yuv_planar =
+ dst_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR;
+
+ u32 dst_pitch = 0;
+ struct b2r2_control *cont = req->instance->control;
+ bool fullrange = (req->user_req.flags &
+ B2R2_BLT_FLAG_FULL_RANGE_YUV) != 0;
+
+ if (dst_img->pitch == 0) {
+ /* Determine pitch based on format and width of the image. */
+ dst_pitch = get_pitch(cont, dst_img->fmt, dst_img->width);
+ } else {
+ dst_pitch = dst_img->pitch;
+ }
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ /* Adjustments that depend on the destination format */
+ switch (dst_img->fmt) {
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_BGR);
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ /*
+ * Setup input VMX to convert YVU to RGB 601 VIDEO
+ * Chroma components are swapped
+ * so it is YVU and not YUV.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_TO_RGB);
+ break;
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_TO_RGB);
+ break;
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ /*
+ * Set up IVMX.
+ * For B2R2_BLT_FMT_32_BIT_YUV888 and
+ * B2R2_BLT_FMT_32_BIT_AYUV8888
+ * the color components are laid out in memory as V, U, Y, (A)
+ * with V at the first byte (due to little endian addressing).
+ * B2R2 expects them to be as U, Y, V, (A)
+ * with U at the first byte.
+ */
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_BLT_YUV888_TO_RGB);
+
+ /*
+ * Re-arrange color components from VUY(A) to (A)YUV
+ * for input VMX to work on them further.
+ */
+ if (dst_img->fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_img->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+ break;
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE: {
+ if (dst_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_img->fmt ==
+ B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR) {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YVU_TO_RGB);
+ } else {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_FULL_TO_RGB);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_YUV_TO_RGB);
+ }
+
+ switch (dst_img->fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chrominance is always half the luminance size
+ * so chrominance resizer is always active.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (1 << 9) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (1 << 9) << B2R2_RSF_VSRC_INC_SHIFT;
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chrominance is always half the luminance size
+ * only in horizontal direction.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (1 << 9) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (1 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ /* Chrominance is the same size as luminance.*/
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (1 << 10) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (1 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ break;
+ default:
+ break;
+ }
+ /* Set the filter control and rescale registers for chroma */
+ node->node.GROUP8.B2R2_FCTL |= fctl;
+ node->node.GROUP9.B2R2_RSF |= rsf;
+ node->node.GROUP9.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_FILTER_CONTROL | B2R2_CIC_RESIZE_CHROMA;
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Set target buffer */
+ node->node.GROUP1.B2R2_TBA = out_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ if (yuv_planar) {
+ /*
+ * Set up chrominance buffers on source 1 and 2,
+ * luminance on source 3.
+ * dst_pitch and physical_address apply to luminance,
+ * corresponding chrominance values have to be derived.
+ */
+ u32 cb_addr = 0;
+ u32 cr_addr = 0;
+ u32 chroma_pitch = 0;
+ bool swapped_chroma =
+ dst_img->fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_img->fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR;
+ enum b2r2_native_fmt dst_native_fmt =
+ to_native_fmt(cont, dst_img->fmt);
+
+ if (swapped_chroma)
+ cr_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+ else
+ cb_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+
+ switch (dst_img->fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ chroma_pitch = dst_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ (dst_img->height >> 1);
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ (dst_img->height >> 1);
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ chroma_pitch = dst_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ dst_img->height;
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ dst_img->height;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ chroma_pitch = dst_pitch;
+ cr_addr =
+ cb_addr + chroma_pitch * dst_img->height;
+ break;
+ default:
+ break;
+ }
+
+ node->node.GROUP3.B2R2_SBA = cr_addr;
+ node->node.GROUP3.B2R2_STY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP4.B2R2_SBA = cb_addr;
+ node->node.GROUP4.B2R2_STY = node->node.GROUP3.B2R2_STY;
+
+ node->node.GROUP5.B2R2_SBA = req->dst_resolved.physical_address;
+ node->node.GROUP5.B2R2_STY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_1_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_3_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_1 |
+ B2R2_CIC_SOURCE_2 |
+ B2R2_CIC_SOURCE_3;
+ } else if (yuv_semi_planar) {
+ /*
+ * Set up chrominance buffer on source 2, luminance on source 3.
+ * dst_pitch and physical_address apply to luminance,
+ * corresponding chrominance values have to be derived.
+ * U and V are interleaved at half the luminance resolution,
+ * which makes the pitch of the UV plane equal
+ * to luminance pitch.
+ */
+ u32 chroma_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+ u32 chroma_pitch = dst_pitch;
+
+ enum b2r2_native_fmt dst_native_fmt =
+ to_native_fmt(cont, dst_img->fmt);
+
+ node->node.GROUP4.B2R2_SBA = chroma_addr;
+ node->node.GROUP4.B2R2_STY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP5.B2R2_SBA = req->dst_resolved.physical_address;
+ node->node.GROUP5.B2R2_STY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_3_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_2 | B2R2_CIC_SOURCE_3;
+ } else {
+ /* single buffer format */
+ node->node.GROUP4.B2R2_SBA = req->dst_resolved.physical_address;
+ node->node.GROUP4.B2R2_STY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ to_native_fmt(cont, dst_img->fmt) |
+ get_alpha_range(cont, dst_img->fmt) |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ endianness;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+ }
+
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+static void setup_blend_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *bg_buf,
+ struct b2r2_work_buf *fg_buf)
+{
+ u32 global_alpha = req->user_req.global_alpha;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_control *cont = req->instance->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ node->node.GROUP0.B2R2_ACK = 0;
+
+ if (req->user_req.flags &
+ (B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND |
+ B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND)) {
+ /* Some kind of blending needs to be done. */
+ if (req->user_req.flags & B2R2_BLT_FLAG_SRC_IS_NOT_PREMULT)
+ node->node.GROUP0.B2R2_ACK |=
+ B2R2_ACK_MODE_BLEND_NOT_PREMULT;
+ else
+ node->node.GROUP0.B2R2_ACK |=
+ B2R2_ACK_MODE_BLEND_PREMULT;
+
+ /*
+ * global_alpha register accepts 0..128 range,
+ * global_alpha in the request is 0..255, remap needed.
+ */
+ if (req->user_req.flags & B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND) {
+ if (global_alpha == 255)
+ global_alpha = 128;
+ else
+ global_alpha >>= 1;
+ } else {
+ /*
+ * Use solid global_alpha
+ * if global alpha blending is not set.
+ */
+ global_alpha = 128;
+ }
+
+ node->node.GROUP0.B2R2_ACK |=
+ global_alpha << (B2R2_ACK_GALPHA_ROPID_SHIFT);
+
+ /* Set background on SRC1 channel */
+ node->node.GROUP3.B2R2_SBA = bg_buf->phys_addr;
+ node->node.GROUP3.B2R2_STY =
+ (B2R2_GENERIC_WORK_BUF_PITCH <<
+ B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ /* Set foreground on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = fg_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY =
+ (B2R2_GENERIC_WORK_BUF_PITCH <<
+ B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ /* Set target buffer */
+ node->node.GROUP1.B2R2_TBA = bg_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH <<
+ B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_1_FETCH_FROM_MEM |
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_1 |
+ B2R2_CIC_SOURCE_2;
+ } else {
+ /*
+ * No blending, foreground goes on SRC2. No global alpha.
+ * EMACSOC TODO: The blending stage should be skipped altogether
+ * if no blending is to be done. Probably could go directly from
+ * transform to writeback.
+ */
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+
+ node->node.GROUP4.B2R2_SBA = fg_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY =
+ (B2R2_GENERIC_WORK_BUF_PITCH <<
+ B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ node->node.GROUP1.B2R2_TBA = bg_buf->phys_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (B2R2_GENERIC_WORK_BUF_PITCH <<
+ B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+ }
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+static void setup_writeback_stage(const struct b2r2_blt_request *req,
+ struct b2r2_node *node,
+ struct b2r2_work_buf *in_buf)
+{
+ const struct b2r2_blt_img *dst_img = &(req->user_req.dst_img);
+ const enum b2r2_blt_fmt dst_fmt = dst_img->fmt;
+ const bool yuv_planar_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR;
+
+ const bool yuv_semi_planar_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+
+ const u32 group4_b2r2_sty =
+ (B2R2_GENERIC_WORK_BUF_PITCH << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ B2R2_GENERIC_WORK_BUF_FMT |
+ B2R2_TY_ALPHA_RANGE_255 |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ u32 dst_dither = 0;
+ u32 dst_pitch = 0;
+ u32 endianness = 0;
+
+ struct b2r2_control *cont = req->instance->control;
+ bool fullrange = (req->user_req.flags &
+ B2R2_BLT_FLAG_FULL_RANGE_YUV) != 0;
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ if (dst_img->pitch == 0) {
+ /* Determine pitch based on format and width of the image. */
+ dst_pitch = get_pitch(cont, dst_img->fmt, dst_img->width);
+ } else
+ dst_pitch = dst_img->pitch;
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_DITHER) != 0)
+ dst_dither = B2R2_TTY_RGB_ROUND_DITHER;
+
+ /* Set target buffer(s) */
+ if (yuv_planar_dst) {
+ /*
+ * three nodes required to write the output.
+ * Luma, blue chroma and red chroma.
+ */
+ u32 fctl = 0;
+ u32 rsf = 0;
+ const u32 group0_b2r2_ins =
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_RECT_CLIP_ENABLED;
+ const u32 group0_b2r2_cic =
+ B2R2_CIC_SOURCE_2 |
+ B2R2_CIC_CLIP_WINDOW;
+
+ u32 cb_addr = 0;
+ u32 cr_addr = 0;
+ u32 chroma_pitch = 0;
+ bool swapped_chroma =
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR;
+ enum b2r2_native_fmt dst_native_fmt =
+ to_native_fmt(cont, dst_img->fmt);
+ enum b2r2_ty alpha_range = get_alpha_range(cont, dst_img->fmt);
+
+ if (swapped_chroma)
+ cr_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+ else
+ cb_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+
+ switch (dst_fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ chroma_pitch = dst_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ (dst_img->height >> 1);
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ (dst_img->height >> 1);
+ /*
+ * Chrominance is always half the luminance size
+ * so chrominance resizer is always active.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ chroma_pitch = dst_pitch >> 1;
+ if (swapped_chroma)
+ cb_addr = cr_addr + chroma_pitch *
+ dst_img->height;
+ else
+ cr_addr = cb_addr + chroma_pitch *
+ dst_img->height;
+ /*
+ * YUV422 or YVU422
+ * Chrominance is always half the luminance size
+ * only in horizontal direction.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (1 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ chroma_pitch = dst_pitch;
+ cr_addr =
+ cb_addr + chroma_pitch * dst_img->height;
+ /*
+ * No scaling required since
+ * chrominance is not subsampled.
+ */
+ default:
+ break;
+ }
+
+ /* Luma (Y-component) */
+ node->node.GROUP1.B2R2_TBA = req->dst_resolved.physical_address;
+ node->node.GROUP1.B2R2_TTY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt | alpha_range |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither;
+
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV);
+
+ /* bypass ALU, no blending here. Handled in its own stage. */
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS = group0_b2r2_ins;
+ node->node.GROUP0.B2R2_CIC |= group0_b2r2_cic;
+
+ /* Set source buffer on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+
+ /* Blue chroma (U-component)*/
+ node = node->next;
+ node->node.GROUP1.B2R2_TBA = cb_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt | alpha_range |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither |
+ B2R2_TTY_CHROMA_NOT_LUMA;
+
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV);
+
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS = group0_b2r2_ins;
+ node->node.GROUP0.B2R2_CIC |= group0_b2r2_cic;
+ if (dst_fmt != B2R2_BLT_FMT_YUV444_PACKED_PLANAR) {
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_FILTER_CONTROL |
+ B2R2_CIC_RESIZE_CHROMA;
+ /* Set the filter control and rescale registers */
+ node->node.GROUP8.B2R2_FCTL = fctl;
+ node->node.GROUP9.B2R2_RSF = rsf;
+ node->node.GROUP9.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+ }
+
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+
+
+ /*
+ * Red chroma (V-component)
+ * The flag B2R2_TTY_CB_NOT_CR actually works
+ * the other way around, i.e. as if it was
+ * CR_NOT_CB.
+ */
+ node = node->next;
+ node->node.GROUP1.B2R2_TBA = cr_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt | alpha_range |
+ B2R2_TTY_CB_NOT_CR |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither |
+ B2R2_TTY_CHROMA_NOT_LUMA;
+
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV);
+
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS = group0_b2r2_ins;
+ node->node.GROUP0.B2R2_CIC |= group0_b2r2_cic;
+ if (dst_fmt != B2R2_BLT_FMT_YUV444_PACKED_PLANAR) {
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_FILTER_CONTROL |
+ B2R2_CIC_RESIZE_CHROMA;
+ /* Set the filter control and rescale registers */
+ node->node.GROUP8.B2R2_FCTL = fctl;
+ node->node.GROUP9.B2R2_RSF = rsf;
+ node->node.GROUP9.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+ }
+
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+ } else if (yuv_semi_planar_dst) {
+ /*
+ * two nodes required to write the output.
+ * One node for luma and one for interleaved chroma
+ * components.
+ */
+ u32 fctl = 0;
+ u32 rsf = 0;
+ const u32 group0_b2r2_ins =
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_RECT_CLIP_ENABLED;
+ const u32 group0_b2r2_cic =
+ B2R2_CIC_SOURCE_2 |
+ B2R2_CIC_CLIP_WINDOW;
+
+ u32 chroma_addr = req->dst_resolved.physical_address +
+ dst_pitch * dst_img->height;
+ u32 chroma_pitch = dst_pitch;
+ enum b2r2_native_fmt dst_native_fmt =
+ to_native_fmt(cont, dst_img->fmt);
+ enum b2r2_ty alpha_range = get_alpha_range(cont, dst_img->fmt);
+
+ if (dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_fmt ==
+ B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR) {
+ /*
+ * Chrominance is always half the luminance size
+ * so chrominance resizer is always active.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ } else {
+ /*
+ * YUV422
+ * Chrominance is always half the luminance size
+ * only in horizontal direction.
+ */
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER;
+
+ rsf &= ~(0xffff << B2R2_RSF_HSRC_INC_SHIFT);
+ rsf |= (2 << 10) << B2R2_RSF_HSRC_INC_SHIFT;
+ rsf &= ~(0xffff << B2R2_RSF_VSRC_INC_SHIFT);
+ rsf |= (1 << 10) << B2R2_RSF_VSRC_INC_SHIFT;
+ }
+
+ /* Luma (Y-component) */
+ node->node.GROUP1.B2R2_TBA = req->dst_resolved.physical_address;
+ node->node.GROUP1.B2R2_TTY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt | alpha_range |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither;
+
+ if (dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR) {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YVU_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YVU);
+ } else {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV);
+ }
+
+ /* bypass ALU, no blending here. Handled in its own stage. */
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS = group0_b2r2_ins;
+ node->node.GROUP0.B2R2_CIC |= group0_b2r2_cic;
+
+ /* Set source buffer on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+
+ /* Chroma (UV-components)*/
+ node = node->next;
+ node->node.GROUP1.B2R2_TBA = chroma_addr;
+ node->node.GROUP1.B2R2_TTY =
+ (chroma_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ dst_native_fmt | alpha_range |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither |
+ B2R2_TTY_CHROMA_NOT_LUMA;
+
+ if (dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR) {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YVU_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YVU);
+ } else {
+ if (fullrange)
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV_FULL);
+ else
+ b2r2_setup_ivmx(node, B2R2_CC_RGB_TO_YUV);
+ }
+
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS =
+ group0_b2r2_ins | B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= group0_b2r2_cic |
+ B2R2_CIC_FILTER_CONTROL |
+ B2R2_CIC_RESIZE_CHROMA;
+
+ /* Set the filter control and rescale registers */
+ node->node.GROUP8.B2R2_FCTL = fctl;
+ node->node.GROUP9.B2R2_RSF = rsf;
+ node->node.GROUP9.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+ } else {
+ /* single buffer target */
+
+ switch (dst_fmt) {
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ b2r2_setup_ovmx(node, B2R2_CC_RGB_TO_BGR);
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ if (fullrange)
+ b2r2_setup_ovmx(node, B2R2_CC_RGB_TO_YVU_FULL);
+ else
+ b2r2_setup_ovmx(node, B2R2_CC_RGB_TO_YVU);
+ break;
+ case B2R2_BLT_FMT_24_BIT_YUV888: /* fall through */
+ case B2R2_BLT_FMT_32_BIT_AYUV8888: /* fall through */
+ case B2R2_BLT_FMT_24_BIT_VUY888: /* fall through */
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ if (fullrange)
+ b2r2_setup_ovmx(node, B2R2_CC_RGB_TO_BLT_YUV888_FULL);
+ else
+ b2r2_setup_ovmx(node, B2R2_CC_RGB_TO_BLT_YUV888);
+ /*
+ * Re-arrange color components from (A)YUV to VUY(A)
+ * when bytes are stored in memory.
+ */
+ if (dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+ break;
+ default:
+ break;
+ }
+
+ node->node.GROUP1.B2R2_TBA = req->dst_resolved.physical_address;
+ node->node.GROUP1.B2R2_TTY =
+ (dst_pitch << B2R2_TY_BITMAP_PITCH_SHIFT) |
+ to_native_fmt(cont, dst_img->fmt) |
+ get_alpha_range(cont, dst_img->fmt) |
+ B2R2_TY_HSO_LEFT_TO_RIGHT |
+ B2R2_TY_VSO_TOP_TO_BOTTOM |
+ dst_dither |
+ endianness;
+
+ node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM |
+ B2R2_INS_RECT_CLIP_ENABLED;
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_SOURCE_2 | B2R2_CIC_CLIP_WINDOW;
+
+ if (req->user_req.flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY) {
+ u32 key_color = 0;
+
+ node->node.GROUP0.B2R2_ACK |=
+ B2R2_ACK_CKEY_SEL_SRC_AFTER_CLUT |
+ B2R2_ACK_CKEY_RED_MATCH_IF_BETWEEN |
+ B2R2_ACK_CKEY_GREEN_MATCH_IF_BETWEEN |
+ B2R2_ACK_CKEY_BLUE_MATCH_IF_BETWEEN;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_CKEY_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_COLOR_KEY;
+
+ key_color = to_RGB888(cont, req->user_req.src_color,
+ req->user_req.src_img.fmt);
+ node->node.GROUP12.B2R2_KEY1 = key_color;
+ node->node.GROUP12.B2R2_KEY2 = key_color;
+ }
+
+ /* Set source buffer on SRC2 channel */
+ node->node.GROUP4.B2R2_SBA = in_buf->phys_addr;
+ node->node.GROUP4.B2R2_STY = group4_b2r2_sty;
+ }
+ /*
+ * Writeback is the last stage. Terminate the program chain
+ * to prevent out-of-control B2R2 execution.
+ */
+ node->node.GROUP0.B2R2_NIP = 0;
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
+
+/*
+ * Public functions
+ */
+void b2r2_generic_init(struct b2r2_control *cont)
+{
+
+}
+
+void b2r2_generic_exit(struct b2r2_control *cont)
+{
+
+}
+
+int b2r2_generic_analyze(const struct b2r2_blt_request *req,
+ s32 *work_buf_width,
+ s32 *work_buf_height,
+ u32 *work_buf_count,
+ u32 *node_count)
+{
+ /*
+ * Need at least 4 nodes, read or fill input, read dst, blend
+ * and write back the result */
+ u32 n_nodes = 4;
+ /* Need at least 2 bufs, 1 for blend output and 1 for input */
+ u32 n_work_bufs = 2;
+ /* Horizontal and vertical scaling factors in 6.10 fixed point format */
+ s32 h_scf = 1 << 10;
+ s32 v_scf = 1 << 10;
+ enum b2r2_blt_fmt dst_fmt = 0;
+ bool is_src_fill = false;
+ bool yuv_planar_dst;
+ bool yuv_semi_planar_dst;
+ struct b2r2_blt_rect src_rect;
+ struct b2r2_blt_rect dst_rect;
+ struct b2r2_control *cont = req->instance->control;
+
+ if (req == NULL || work_buf_width == NULL || work_buf_height == NULL ||
+ work_buf_count == NULL || node_count == NULL) {
+ b2r2_log_warn(cont->dev, "%s: Invalid in or out pointers:\n"
+ "req=0x%p\n"
+ "work_buf_width=0x%p work_buf_height=0x%p "
+ "work_buf_count=0x%p\n"
+ "node_count=0x%p.\n",
+ __func__,
+ req,
+ work_buf_width, work_buf_height,
+ work_buf_count,
+ node_count);
+ return -EINVAL;
+ }
+
+ dst_fmt = req->user_req.dst_img.fmt;
+
+ is_src_fill = (req->user_req.flags &
+ (B2R2_BLT_FLAG_SOURCE_FILL |
+ B2R2_BLT_FLAG_SOURCE_FILL_RAW)) != 0;
+
+ yuv_planar_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR;
+ yuv_semi_planar_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+
+ *node_count = 0;
+ *work_buf_width = 0;
+ *work_buf_height = 0;
+ *work_buf_count = 0;
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ n_nodes++;
+ n_work_bufs++;
+ }
+
+ if ((yuv_planar_dst || yuv_semi_planar_dst) &&
+ (req->user_req.flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW)) {
+ b2r2_log_warn(cont->dev,
+ "%s: Invalid combination: source_fill_raw"
+ " and multi-buffer destination.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY) != 0 &&
+ (req->user_req.flags & B2R2_BLT_FLAG_DEST_COLOR_KEY)) {
+ b2r2_log_warn(cont->dev,
+ "%s: Invalid combination: source and "
+ "destination color keying.\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((req->user_req.flags &
+ (B2R2_BLT_FLAG_SOURCE_FILL |
+ B2R2_BLT_FLAG_SOURCE_FILL_RAW)) &&
+ (req->user_req.flags &
+ (B2R2_BLT_FLAG_SOURCE_COLOR_KEY |
+ B2R2_BLT_FLAG_DEST_COLOR_KEY))) {
+ b2r2_log_warn(cont->dev, "%s: Invalid combination: "
+ "source_fill and color keying.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((req->user_req.flags &
+ (B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND |
+ B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND)) &&
+ (req->user_req.flags &
+ (B2R2_BLT_FLAG_DEST_COLOR_KEY |
+ B2R2_BLT_FLAG_SOURCE_COLOR_KEY))) {
+ b2r2_log_warn(cont->dev, "%s: Invalid combination: "
+ "blending and color keying.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_MASK) &&
+ (req->user_req.flags &
+ (B2R2_BLT_FLAG_DEST_COLOR_KEY |
+ B2R2_BLT_FLAG_SOURCE_COLOR_KEY))) {
+ b2r2_log_warn(cont->dev, "%s: Invalid combination: source mask"
+ "and color keying.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (req->user_req.flags &
+ (B2R2_BLT_FLAG_DEST_COLOR_KEY |
+ B2R2_BLT_FLAG_SOURCE_MASK)) {
+ b2r2_log_warn(cont->dev, "%s: Unsupported: source mask, "
+ "destination color keying.\n",
+ __func__);
+ return -ENOSYS;
+ }
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_MASK)) {
+ enum b2r2_blt_fmt src_fmt = req->user_req.src_img.fmt;
+ bool yuv_src =
+ src_fmt == B2R2_BLT_FMT_Y_CB_Y_CR ||
+ src_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ src_fmt ==
+ B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+ if (yuv_src || src_fmt == B2R2_BLT_FMT_1_BIT_A1 ||
+ src_fmt == B2R2_BLT_FMT_8_BIT_A8) {
+ b2r2_log_warn(cont->dev, "%s: Unsupported: source "
+ "color keying with YUV or pure alpha "
+ "formats.\n", __func__);
+ return -ENOSYS;
+ }
+ }
+
+ /* Check for invalid dimensions that would hinder scale calculations */
+ src_rect = req->user_req.src_rect;
+ dst_rect = req->user_req.dst_rect;
+ /* Check for invalid src_rect unless src_fill is enabled */
+ if (!is_src_fill && (src_rect.x < 0 || src_rect.y < 0 ||
+ src_rect.x + src_rect.width > req->user_req.src_img.width ||
+ src_rect.y + src_rect.height > req->user_req.src_img.height)) {
+ b2r2_log_warn(cont->dev, "%s: src_rect outside src_img:\n"
+ "src(x,y,w,h)=(%d, %d, %d, %d) "
+ "src_img(w,h)=(%d, %d).\n",
+ __func__,
+ src_rect.x, src_rect.y, src_rect.width, src_rect.height,
+ req->user_req.src_img.width,
+ req->user_req.src_img.height);
+ return -EINVAL;
+ }
+
+ if (!is_src_fill && (src_rect.width <= 0 || src_rect.height <= 0)) {
+ b2r2_log_warn(cont->dev, "%s: Invalid source dimensions:\n"
+ "src(w,h)=(%d, %d).\n",
+ __func__,
+ src_rect.width, src_rect.height);
+ return -EINVAL;
+ }
+
+ if (dst_rect.width <= 0 || dst_rect.height <= 0) {
+ b2r2_log_warn(cont->dev, "%s: Invalid dest dimensions:\n"
+ "dst(w,h)=(%d, %d).\n",
+ __func__,
+ dst_rect.width, dst_rect.height);
+ return -EINVAL;
+ }
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) &&
+ req->user_req.clut == NULL) {
+ b2r2_log_warn(cont->dev, "%s: Invalid request: no table "
+ "specified for CLUT color correction.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Check for invalid image params */
+ if (!is_src_fill && validate_buf(cont, &(req->user_req.src_img),
+ &(req->src_resolved)))
+ return -EINVAL;
+
+ if (validate_buf(cont, &(req->user_req.dst_img), &(req->dst_resolved)))
+ return -EINVAL;
+
+ if (is_src_fill) {
+ /*
+ * Params correct for a source fill operation.
+ * No need for further checking.
+ */
+ if (yuv_planar_dst)
+ n_nodes += 2;
+ else if (yuv_semi_planar_dst)
+ n_nodes++;
+
+ *work_buf_width = B2R2_GENERIC_WORK_BUF_WIDTH;
+ *work_buf_height = B2R2_GENERIC_WORK_BUF_HEIGHT;
+ *work_buf_count = n_work_bufs;
+ *node_count = n_nodes;
+ b2r2_log_info(cont->dev, "%s DONE buf_w=%d buf_h=%d "
+ "buf_count=%d node_count=%d\n", __func__,
+ *work_buf_width, *work_buf_height,
+ *work_buf_count, *node_count);
+ return 0;
+ }
+
+ /*
+ * Calculate scaling factors, all transform enum values
+ * that include rotation have the CCW_ROT_90 bit set.
+ */
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ h_scf = (src_rect.width << 10) / dst_rect.height;
+ v_scf = (src_rect.height << 10) / dst_rect.width;
+ } else {
+ h_scf = (src_rect.width << 10) / dst_rect.width;
+ v_scf = (src_rect.height << 10) / dst_rect.height;
+ }
+
+ /* Check for degenerate/out_of_range scaling factors. */
+ if (h_scf <= 0 || v_scf <= 0 || h_scf > 0x7C00 || v_scf > 0x7C00) {
+ b2r2_log_warn(cont->dev,
+ "%s: Dimensions result in degenerate or "
+ "out of range scaling:\n"
+ "src(w,h)=(%d, %d) "
+ "dst(w,h)=(%d,%d).\n"
+ "h_scf=0x%.8x, v_scf=0x%.8x\n",
+ __func__,
+ src_rect.width, src_rect.height,
+ dst_rect.width, dst_rect.height,
+ h_scf, v_scf);
+ return -EINVAL;
+ }
+
+ if (yuv_planar_dst)
+ n_nodes += 2;
+ else if (yuv_semi_planar_dst)
+ n_nodes++;
+
+ *work_buf_width = B2R2_GENERIC_WORK_BUF_WIDTH;
+ *work_buf_height = B2R2_GENERIC_WORK_BUF_HEIGHT;
+ *work_buf_count = n_work_bufs;
+ *node_count = n_nodes;
+ b2r2_log_info(cont->dev, "%s DONE buf_w=%d buf_h=%d buf_count=%d "
+ "node_count=%d\n", __func__, *work_buf_width,
+ *work_buf_height, *work_buf_count, *node_count);
+ return 0;
+}
+
+/*
+ *
+ */
+int b2r2_generic_configure(const struct b2r2_blt_request *req,
+ struct b2r2_node *first,
+ struct b2r2_work_buf *tmp_bufs,
+ u32 buf_count)
+{
+ struct b2r2_node *node = NULL;
+ struct b2r2_work_buf *in_buf = NULL;
+ struct b2r2_work_buf *out_buf = NULL;
+ struct b2r2_work_buf *empty_buf = NULL;
+ struct b2r2_control *cont = req->instance->control;
+
+#ifdef B2R2_GENERIC_DEBUG
+ u32 needed_bufs = 0;
+ u32 needed_nodes = 0;
+ s32 work_buf_width = 0;
+ s32 work_buf_height = 0;
+ u32 n_nodes = 0;
+ int invalid_req = b2r2_generic_analyze(req, &work_buf_width,
+ &work_buf_height, &needed_bufs,
+ &needed_nodes);
+ if (invalid_req < 0) {
+ b2r2_log_warn(cont->dev,
+ "%s: Invalid request supplied, ec=%d\n",
+ __func__, invalid_req);
+ return -EINVAL;
+ }
+
+ node = first;
+
+ while (node != NULL) {
+ n_nodes++;
+ node = node->next;
+ }
+ if (n_nodes < needed_nodes) {
+ b2r2_log_warn(cont->dev, "%s: Not enough nodes %d < %d.\n",
+ __func__, n_nodes, needed_nodes);
+ return -EINVAL;
+ }
+
+ if (buf_count < needed_bufs) {
+ b2r2_log_warn(cont->dev, "%s: Not enough buffers %d < %d.\n",
+ __func__, buf_count, needed_bufs);
+ return -EINVAL;
+ }
+
+#endif
+
+ reset_nodes(cont, first);
+ node = first;
+ empty_buf = tmp_bufs;
+ out_buf = empty_buf;
+ empty_buf++;
+ /* Prepare input tile. Color_fill or read from src */
+ setup_input_stage(req, node, out_buf);
+ in_buf = out_buf;
+ out_buf = empty_buf;
+ empty_buf++;
+ node = node->next;
+
+ if ((req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) != 0) {
+ setup_transform_stage(req, node, out_buf, in_buf);
+ node = node->next;
+ in_buf = out_buf;
+ out_buf = empty_buf++;
+ }
+ /* EMACSOC TODO: mask */
+ /*
+ if (req->user_req.flags & B2R2_BLT_FLAG_SOURCE_MASK) {
+ setup_mask_stage(req, node, out_buf, in_buf);
+ node = node->next;
+ in_buf = out_buf;
+ out_buf = empty_buf++;
+ }
+ */
+ /* Read the part of destination that will be updated */
+ setup_dst_read_stage(req, node, out_buf);
+ node = node->next;
+ setup_blend_stage(req, node, out_buf, in_buf);
+ node = node->next;
+ in_buf = out_buf;
+ setup_writeback_stage(req, node, in_buf);
+ return 0;
+}
+
+void b2r2_generic_set_areas(const struct b2r2_blt_request *req,
+ struct b2r2_node *first,
+ struct b2r2_blt_rect *dst_rect_area)
+{
+ /*
+ * Nodes come in the following order: <input stage>, [transform],
+ * [src_mask], <dst_read>, <blend>, <writeback>
+ */
+ struct b2r2_node *node = first;
+ const struct b2r2_blt_rect *dst_rect = &(req->user_req.dst_rect);
+ const struct b2r2_blt_rect *src_rect = &(req->user_req.src_rect);
+ const enum b2r2_blt_fmt src_fmt = req->user_req.src_img.fmt;
+ bool yuv_multi_buffer_src =
+ src_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ src_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ src_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+ const enum b2r2_blt_fmt dst_fmt = req->user_req.dst_img.fmt;
+ const bool yuv_multi_buffer_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+ s32 h_scf = 1 << 10;
+ s32 v_scf = 1 << 10;
+ s32 src_x = 0;
+ s32 src_y = 0;
+ s32 src_w = 0;
+ s32 src_h = 0;
+ u32 b2r2_rzi = 0;
+ s32 clip_top = 0;
+ s32 clip_left = 0;
+ s32 clip_bottom = req->user_req.dst_img.height - 1;
+ s32 clip_right = req->user_req.dst_img.width - 1;
+ /* Dst coords inside the dst_rect, not the buffer */
+ s32 dst_x = dst_rect_area->x;
+ s32 dst_y = dst_rect_area->y;
+ struct b2r2_control *cont = req->instance->control;
+
+ b2r2_log_info(cont->dev, "%s ENTRY\n", __func__);
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ h_scf = (src_rect->width << 10) / dst_rect->height;
+ v_scf = (src_rect->height << 10) / dst_rect->width;
+ } else {
+ h_scf = (src_rect->width << 10) / dst_rect->width;
+ v_scf = (src_rect->height << 10) / dst_rect->height;
+ }
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ /*
+ * Normally the inverse transform for 90 degree rotation
+ * is given by:
+ * | 0 1| |x| | y|
+ * | | X | | = | |
+ * |-1 0| |y| |-x|
+ * but screen coordinates are flipped in y direction
+ * (compared to usual Cartesian coordinates), hence the offsets.
+ */
+ src_x = (dst_rect->height - dst_y - dst_rect_area->height) *
+ h_scf;
+ src_y = dst_x * v_scf;
+ src_w = dst_rect_area->height * h_scf;
+ src_h = dst_rect_area->width * v_scf;
+ } else {
+ src_x = dst_x * h_scf;
+ src_y = dst_y * v_scf;
+ src_w = dst_rect_area->width * h_scf;
+ src_h = dst_rect_area->height * v_scf;
+ }
+
+ b2r2_rzi |= ((src_x & 0x3ff) << B2R2_RZI_HSRC_INIT_SHIFT) |
+ ((src_y & 0x3ff) << B2R2_RZI_VSRC_INIT_SHIFT);
+
+ /*
+ * src_w must contain all the pixels that contribute
+ * to a particular tile.
+ * ((x + 0x3ff) >> 10) is equivalent to ceiling(x),
+ * expressed in 6.10 fixed point format.
+ * Every destination tile, maps to a certain area in the source
+ * rectangle. The area in source will most likely not be a rectangle
+ * with exact integer dimensions whenever arbitrary scaling is involved.
+ * Consider the following example.
+ * Suppose, that width of the current destination tile maps
+ * to 1.7 pixels in source, starting at x == 5.4, as calculated
+ * using the scaling factor.
+ * This means that while the destination tile is written,
+ * the source should be read from x == 5.4 up to x == 5.4 + 1.7 == 7.1
+ * Consequently, color from 3 pixels (x == 5, 6 and 7)
+ * needs to be read from source.
+ * The formula below the comment yields:
+ * ceil(0.4 + 1.7) == ceil(2.1) == 3
+ * (src_x & 0x3ff) is the fractional part of src_x,
+ * which is expressed in 6.10 fixed point format.
+ * Thus, width of the source area should be 3 pixels wide,
+ * starting at x == 5.
+ * However, the reading should not start at x == 5.0
+ * but a bit inside, namely x == 5.4
+ * The B2R2_RZI register is used to instruct the HW to do so.
+ * It contains the fractional part that will be added to
+ * the first pixel coordinate, before incrementing the current source
+ * coordinate with the step specified in B2R2_RSF register.
+ * The same applies to scaling in vertical direction.
+ */
+ src_w = ((src_x & 0x3ff) + src_w + 0x3ff) >> 10;
+ src_h = ((src_y & 0x3ff) + src_h + 0x3ff) >> 10;
+
+ /*
+ * EMACSOC TODO: Remove this debug clamp, once tile size
+ * is taken into account in generic_analyze()
+ */
+ if (src_w > 128)
+ src_w = 128;
+
+ src_x >>= 10;
+ src_y >>= 10;
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_H)
+ src_x = src_rect->width - src_x - src_w;
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_V)
+ src_y = src_rect->height - src_y - src_h;
+
+ /*
+ * Translate the src/dst_rect coordinates into true
+ * src/dst_buffer coordinates
+ */
+ src_x += src_rect->x;
+ src_y += src_rect->y;
+
+ dst_x += dst_rect->x;
+ dst_y += dst_rect->y;
+
+ /*
+ * Clamp the src coords to buffer dimensions
+ * to prevent illegal reads.
+ */
+ if (src_x < 0)
+ src_x = 0;
+
+ if (src_y < 0)
+ src_y = 0;
+
+ if ((src_x + src_w) > req->user_req.src_img.width)
+ src_w = req->user_req.src_img.width - src_x;
+
+ if ((src_y + src_h) > req->user_req.src_img.height)
+ src_h = req->user_req.src_img.height - src_y;
+
+
+ /* The input node */
+ if (yuv_multi_buffer_src) {
+ /* Luma on SRC3 */
+ node->node.GROUP5.B2R2_SXY =
+ ((src_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((src_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP5.B2R2_SSZ =
+ ((src_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((src_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ /* Clear and set only the SRC_INIT bits */
+ node->node.GROUP10.B2R2_RZI &=
+ ~((0x3ff << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (0x3ff << B2R2_RZI_VSRC_INIT_SHIFT));
+ node->node.GROUP10.B2R2_RZI |= b2r2_rzi;
+
+ node->node.GROUP9.B2R2_RZI &=
+ ~((0x3ff << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (0x3ff << B2R2_RZI_VSRC_INIT_SHIFT));
+ switch (src_fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chroma goes on SRC2 and potentially on SRC1.
+ * Chroma is half the size of luma. Must round up
+ * the chroma size to handle cases when luma size is not
+ * divisible by 2.
+ * E.g. luma width==7 requires chroma width==4.
+ * Chroma width==7/2==3 is only enough
+ * for luma width==6.
+ */
+ node->node.GROUP4.B2R2_SXY =
+ (((src_x & 0xffff) >> 1) << B2R2_XY_X_SHIFT) |
+ (((src_y & 0xffff) >> 1) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((((src_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((((src_h + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ if (src_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ src_fmt ==
+ B2R2_BLT_FMT_YVU420_PACKED_PLANAR) {
+ node->node.GROUP3.B2R2_SXY =
+ node->node.GROUP4.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ =
+ node->node.GROUP4.B2R2_SSZ;
+ }
+ node->node.GROUP9.B2R2_RZI |= (b2r2_rzi >> 1) &
+ ((0x3ff << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (0x3ff << B2R2_RZI_VSRC_INIT_SHIFT));
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chroma goes on SRC2 and potentially on SRC1.
+ * Now chroma is half the size of luma
+ * only in horizontal direction.
+ * Same rounding applies as for 420 formats above,
+ * except it is only done horizontally.
+ */
+ node->node.GROUP4.B2R2_SXY =
+ (((src_x & 0xffff) >> 1) << B2R2_XY_X_SHIFT) |
+ ((src_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((((src_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((src_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ if (src_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ src_fmt ==
+ B2R2_BLT_FMT_YVU422_PACKED_PLANAR) {
+ node->node.GROUP3.B2R2_SXY =
+ node->node.GROUP4.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ =
+ node->node.GROUP4.B2R2_SSZ;
+ }
+ node->node.GROUP9.B2R2_RZI |=
+ (((src_x & 0x3ff) >> 1) <<
+ B2R2_RZI_HSRC_INIT_SHIFT) |
+ ((src_y & 0x3ff) << B2R2_RZI_VSRC_INIT_SHIFT);
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ /*
+ * Chroma goes on SRC2 and SRC1.
+ * It is the same size as luma.
+ */
+ node->node.GROUP4.B2R2_SXY =
+ ((src_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((src_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((src_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((src_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ node->node.GROUP3.B2R2_SXY = node->node.GROUP4.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ = node->node.GROUP4.B2R2_SSZ;
+
+ /* Clear and set only the SRC_INIT bits */
+ node->node.GROUP9.B2R2_RZI &=
+ ~((0x3ff << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (0x3ff << B2R2_RZI_VSRC_INIT_SHIFT));
+ node->node.GROUP9.B2R2_RZI |= b2r2_rzi;
+ break;
+ default:
+ break;
+ }
+ } else {
+ node->node.GROUP4.B2R2_SXY =
+ ((src_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((src_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((src_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((src_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ /* Clear and set only the SRC_INIT bits */
+ node->node.GROUP9.B2R2_RZI &=
+ ~((0x3ff << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (0x3ff << B2R2_RZI_VSRC_INIT_SHIFT));
+ node->node.GROUP9.B2R2_RZI |= b2r2_rzi;
+ }
+
+ node->node.GROUP1.B2R2_TXY = 0;
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ /*
+ * dst_rect_area coordinates are specified
+ * after potential rotation.
+ * Input is read before rotation, hence the width and height
+ * need to be swapped.
+ * Horizontal and vertical flips are accomplished with
+ * suitable scanning order while writing
+ * to the temporary buffer.
+ */
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_H) {
+ node->node.GROUP1.B2R2_TXY |=
+ ((dst_rect_area->height - 1) & 0xffff) <<
+ B2R2_XY_X_SHIFT;
+ }
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_V) {
+ node->node.GROUP1.B2R2_TXY |=
+ ((dst_rect_area->width - 1) & 0xffff) <<
+ B2R2_XY_Y_SHIFT;
+ }
+
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ } else {
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_H) {
+ node->node.GROUP1.B2R2_TXY |=
+ ((dst_rect_area->width - 1) & 0xffff) <<
+ B2R2_XY_X_SHIFT;
+ }
+
+ if (req->user_req.transform & B2R2_BLT_TRANSFORM_FLIP_V) {
+ node->node.GROUP1.B2R2_TXY |=
+ ((dst_rect_area->height - 1) & 0xffff) <<
+ B2R2_XY_Y_SHIFT;
+ }
+
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ }
+
+ if (req->user_req.flags &
+ (B2R2_BLT_FLAG_SOURCE_FILL | B2R2_BLT_FLAG_SOURCE_FILL_RAW)) {
+ /*
+ * Scan order for source fill should always be left-to-right
+ * and top-to-bottom. Fill the input tile from top left.
+ */
+ node->node.GROUP1.B2R2_TXY = 0;
+ node->node.GROUP4.B2R2_SSZ = node->node.GROUP1.B2R2_TSZ;
+ }
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev, "%s Input node done.\n", __func__);
+ }
+
+ /* Transform */
+ if ((req->user_req.transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) != 0) {
+ /*
+ * Transform node operates on temporary buffers.
+ * Content always at top left, but scanning order
+ * has to be flipped during rotation.
+ * Width and height need to be considered as well, since
+ * a tile may not necessarily be filled completely.
+ * dst_rect_area dimensions are specified
+ * after potential rotation.
+ * Input is read before rotation, hence the width and height
+ * need to be swapped on src.
+ */
+ node = node->next;
+
+ node->node.GROUP4.B2R2_SXY = 0;
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ /* Bottom line written first */
+ node->node.GROUP1.B2R2_TXY =
+ ((dst_rect_area->height - 1) & 0xffff) <<
+ B2R2_XY_Y_SHIFT;
+
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev,
+ "%s Tranform node done.\n", __func__);
+ }
+ }
+
+ /* Source mask */
+ if (req->user_req.flags & B2R2_BLT_FLAG_SOURCE_MASK) {
+ node = node->next;
+ /*
+ * Same coords for mask as for the input stage.
+ * Should the mask be transformed together with source?
+ * EMACSOC TODO: Apply mask before any
+ * transform/scaling is done.
+ * Otherwise it will be dst_ not src_mask.
+ */
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev,
+ "%s Source mask node done.\n", __func__);
+ }
+ }
+
+ /* dst_read */
+ if (yuv_multi_buffer_dst) {
+ s32 dst_w = dst_rect_area->width;
+ s32 dst_h = dst_rect_area->height;
+ bool yuv420_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE;
+
+ bool yuv422_dst =
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE;
+ node = node->next;
+ /* Luma on SRC3 */
+ node->node.GROUP5.B2R2_SXY =
+ ((dst_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP5.B2R2_SSZ =
+ ((dst_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ if (yuv420_dst) {
+ /*
+ * Chroma goes on SRC2 and potentially on SRC1.
+ * Chroma is half the size of luma. Must round up
+ * the chroma size to handle cases when luma size is not
+ * divisible by 2.
+ * E.g. luma width==7 requires chroma width==4.
+ * Chroma width==7/2==3 is only enough
+ * for luma width==6.
+ */
+ node->node.GROUP4.B2R2_SXY =
+ (((dst_x & 0xffff) >> 1) << B2R2_XY_X_SHIFT) |
+ (((dst_y & 0xffff) >> 1) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((((dst_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((((dst_h + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+
+ if (dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt ==
+ B2R2_BLT_FMT_YVU420_PACKED_PLANAR) {
+ node->node.GROUP3.B2R2_SXY =
+ node->node.GROUP4.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ =
+ node->node.GROUP4.B2R2_SSZ;
+ }
+ } else if (yuv422_dst) {
+ /*
+ * Chroma goes on SRC2 and potentially on SRC1.
+ * Now chroma is half the size of luma
+ * only in horizontal direction.
+ * Same rounding applies as for 420 formats above,
+ * except it is only done horizontally.
+ */
+ node->node.GROUP4.B2R2_SXY =
+ (((dst_x & 0xffff) >> 1) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((((dst_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ if (dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt ==
+ B2R2_BLT_FMT_YVU422_PACKED_PLANAR) {
+ node->node.GROUP3.B2R2_SXY =
+ node->node.GROUP4.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ =
+ node->node.GROUP4.B2R2_SSZ;
+ }
+ } else if (dst_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR) {
+ /*
+ * Chroma goes on SRC2 and SRC1.
+ * It is the same size as luma.
+ */
+ node->node.GROUP4.B2R2_SXY = node->node.GROUP5.B2R2_SXY;
+ node->node.GROUP4.B2R2_SSZ = node->node.GROUP5.B2R2_SSZ;
+ node->node.GROUP3.B2R2_SXY = node->node.GROUP5.B2R2_SXY;
+ node->node.GROUP3.B2R2_SSZ = node->node.GROUP5.B2R2_SSZ;
+ }
+
+ node->node.GROUP1.B2R2_TXY = 0;
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ } else {
+ node = node->next;
+ node->node.GROUP4.B2R2_SXY =
+ ((dst_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ node->node.GROUP1.B2R2_TXY = 0;
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ }
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev, "%s dst_read node done.\n", __func__);
+ }
+
+ /* blend */
+ node = node->next;
+ node->node.GROUP3.B2R2_SXY = 0;
+ node->node.GROUP3.B2R2_SSZ =
+ ((dst_rect_area->width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ /* contents of the foreground temporary buffer always at top left */
+ node->node.GROUP4.B2R2_SXY = 0;
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_rect_area->width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ node->node.GROUP1.B2R2_TXY = 0;
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev, "%s Blend node done.\n", __func__);
+ }
+
+ /* writeback */
+ node = node->next;
+ if ((req->user_req.flags & B2R2_BLT_FLAG_DESTINATION_CLIP) != 0) {
+ clip_left = req->user_req.dst_clip_rect.x;
+ clip_top = req->user_req.dst_clip_rect.y;
+ clip_right = clip_left + req->user_req.dst_clip_rect.width - 1;
+ clip_bottom = clip_top + req->user_req.dst_clip_rect.height - 1;
+ }
+ /*
+ * Clamp the dst clip rectangle to buffer dimensions to prevent
+ * illegal writes. An illegal clip rectangle, e.g. outside the
+ * buffer will be ignored, resulting in nothing being clipped.
+ */
+ if (clip_left < 0 || req->user_req.dst_img.width <= clip_left)
+ clip_left = 0;
+
+ if (clip_top < 0 || req->user_req.dst_img.height <= clip_top)
+ clip_top = 0;
+
+ if (clip_right < 0 || req->user_req.dst_img.width <= clip_right)
+ clip_right = req->user_req.dst_img.width - 1;
+
+ if (clip_bottom < 0 || req->user_req.dst_img.height <= clip_bottom)
+ clip_bottom = req->user_req.dst_img.height - 1;
+
+ /*
+ * Only allow writing inside the clip rect.
+ * INTNL bit in B2R2_CWO should be zero.
+ */
+ node->node.GROUP6.B2R2_CWO =
+ ((clip_top & 0x7fff) << B2R2_CWO_Y_SHIFT) |
+ ((clip_left & 0x7fff) << B2R2_CWO_X_SHIFT);
+ node->node.GROUP6.B2R2_CWS =
+ ((clip_bottom & 0x7fff) << B2R2_CWS_Y_SHIFT) |
+ ((clip_right & 0x7fff) << B2R2_CWS_X_SHIFT);
+
+ if (yuv_multi_buffer_dst) {
+ const s32 dst_w = dst_rect_area->width;
+ const s32 dst_h = dst_rect_area->height;
+ int i = 0;
+ /* Number of nodes required to write chroma output */
+ int n_nodes = 1;
+ if (dst_fmt == B2R2_BLT_FMT_YUV420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU420_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YVU422_PACKED_PLANAR ||
+ dst_fmt == B2R2_BLT_FMT_YUV444_PACKED_PLANAR)
+ n_nodes = 2;
+
+ node->node.GROUP4.B2R2_SXY = 0;
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ /* Luma (Y-component) */
+ node->node.GROUP1.B2R2_TXY =
+ ((dst_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ node->node.GROUP6.B2R2_CWO =
+ ((clip_top & 0x7fff) << B2R2_CWO_Y_SHIFT) |
+ ((clip_left & 0x7fff) << B2R2_CWO_X_SHIFT);
+ node->node.GROUP6.B2R2_CWS =
+ ((clip_bottom & 0x7fff) << B2R2_CWS_Y_SHIFT) |
+ ((clip_right & 0x7fff) << B2R2_CWS_X_SHIFT);
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev,
+ "%s Writeback luma node done.\n", __func__);
+ }
+
+ node = node->next;
+
+ /*
+ * Chroma components. 1 or 2 nodes
+ * for semi-planar or planar buffer respectively.
+ */
+ for (i = 0; i < n_nodes && node != NULL; ++i) {
+
+ node->node.GROUP4.B2R2_SXY = 0;
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_w & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+
+ switch (dst_fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Chroma is half the size of luma.
+ * Must round up the chroma size to handle
+ * cases when luma size is not divisible by 2.
+ * E.g. luma_width==7 requires chroma_width==4.
+ * Chroma_width==7/2==3 is only enough
+ * for luma_width==6.
+ */
+ node->node.GROUP1.B2R2_TXY =
+ (((dst_x & 0xffff) >> 1) <<
+ B2R2_XY_X_SHIFT) |
+ (((dst_y & 0xffff) >> 1) <<
+ B2R2_XY_Y_SHIFT);
+ node->node.GROUP1.B2R2_TSZ =
+ ((((dst_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((((dst_h + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ break;
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ /*
+ * Now chroma is half the size of luma only
+ * in horizontal direction.
+ * Same rounding applies as
+ * for 420 formats above, except it is only
+ * done horizontally.
+ */
+ node->node.GROUP1.B2R2_TXY =
+ (((dst_x & 0xffff) >> 1) <<
+ B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP1.B2R2_TSZ =
+ ((((dst_w + 1) & 0xfff) >> 1) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ break;
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ /*
+ * Chroma has the same resolution as luma.
+ */
+ node->node.GROUP1.B2R2_TXY =
+ ((dst_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_w & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_h & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ break;
+ default:
+ break;
+ }
+
+ node->node.GROUP6.B2R2_CWO =
+ ((clip_top & 0x7fff) << B2R2_CWO_Y_SHIFT) |
+ ((clip_left & 0x7fff) << B2R2_CWO_X_SHIFT);
+ node->node.GROUP6.B2R2_CWS =
+ ((clip_bottom & 0x7fff) << B2R2_CWS_Y_SHIFT) |
+ ((clip_right & 0x7fff) << B2R2_CWS_X_SHIFT);
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev, "%s Writeback chroma "
+ "node %d of %d done.\n",
+ __func__, i + 1, n_nodes);
+ }
+
+ node = node->next;
+ }
+ } else {
+ node->node.GROUP4.B2R2_SXY = 0;
+ node->node.GROUP4.B2R2_SSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+ node->node.GROUP1.B2R2_TXY =
+ ((dst_x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((dst_y & 0xffff) << B2R2_XY_Y_SHIFT);
+ node->node.GROUP1.B2R2_TSZ =
+ ((dst_rect_area->width & 0xfff) <<
+ B2R2_SZ_WIDTH_SHIFT) |
+ ((dst_rect_area->height & 0xfff) <<
+ B2R2_SZ_HEIGHT_SHIFT);
+
+ if (B2R2_GENERIC_DEBUG_AREAS && dst_rect_area->x == 0 &&
+ dst_rect_area->y == 0) {
+ dump_nodes(cont, node, false);
+ b2r2_log_debug(cont->dev, "%s Writeback node done.\n",
+ __func__);
+ }
+ }
+
+ b2r2_log_info(cont->dev, "%s DONE\n", __func__);
+}
diff --git a/drivers/video/b2r2/b2r2_generic.h b/drivers/video/b2r2/b2r2_generic.h
new file mode 100644
index 00000000000..3b22f654deb
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_generic.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 generic. Full coverage of user interface but
+ * non optimized implementation. For Fallback purposes.
+ *
+ * Author: Maciej Socha <maciej.socha@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_VIDEO_B2R2_GENERIC_H
+#define _LINUX_VIDEO_B2R2_GENERIC_H
+
+#include <video/b2r2_blt.h>
+
+#include "b2r2_internal.h"
+
+/**
+ * b2r2_generic_init()
+ */
+void b2r2_generic_init(struct b2r2_control *cont);
+
+/**
+ * b2r2_generic_exit()
+ */
+void b2r2_generic_exit(struct b2r2_control *cont);
+
+/**
+ * b2r2_generic_analyze()
+ */
+int b2r2_generic_analyze(const struct b2r2_blt_request *req,
+ s32 *work_buf_width,
+ s32 *work_buf_height,
+ u32 *work_buf_count,
+ u32 *node_count);
+/**
+ * b2r2_generic_configure()
+ */
+int b2r2_generic_configure(const struct b2r2_blt_request *req,
+ struct b2r2_node *first,
+ struct b2r2_work_buf *tmp_bufs,
+ u32 buf_count);
+/**
+ * b2r2_generic_set_areas()
+ */
+void b2r2_generic_set_areas(const struct b2r2_blt_request *req,
+ struct b2r2_node *first,
+ struct b2r2_blt_rect *dst_rect_area);
+#endif
diff --git a/drivers/video/b2r2/b2r2_global.h b/drivers/video/b2r2/b2r2_global.h
new file mode 100644
index 00000000000..38cf74bb753
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_global.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 global definitions
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __B2R2_GLOBAL_H
+#define __B2R2_GLOBAL_H
+
+/** Sources involved */
+
+struct b2r2_system {
+ unsigned int B2R2_NIP;
+ unsigned int B2R2_CIC;
+ unsigned int B2R2_INS;
+ unsigned int B2R2_ACK;
+};
+
+struct b2r2_target {
+ unsigned int B2R2_TBA;
+ unsigned int B2R2_TTY;
+ unsigned int B2R2_TXY;
+ unsigned int B2R2_TSZ;
+};
+
+struct b2r2_color_fill {
+ unsigned int B2R2_S1CF;
+ unsigned int B2R2_S2CF;
+};
+
+struct b2r2_src_config {
+ unsigned int B2R2_SBA;
+ unsigned int B2R2_STY;
+ unsigned int B2R2_SXY;
+ unsigned int B2R2_SSZ;
+};
+
+struct b2r2_clip {
+ unsigned int B2R2_CWO;
+ unsigned int B2R2_CWS;
+};
+
+struct b2r2_color_key {
+ unsigned int B2R2_KEY1;
+ unsigned int B2R2_KEY2;
+};
+
+struct b2r2_clut {
+ unsigned int B2R2_CCO;
+ unsigned int B2R2_CML;
+};
+
+struct b2r2_rsz_pl_mask {
+ unsigned int B2R2_FCTL;
+ unsigned int B2R2_PMK;
+};
+
+struct b2r2_Cr_luma_rsz {
+ unsigned int B2R2_RSF;
+ unsigned int B2R2_RZI;
+ unsigned int B2R2_HFP;
+ unsigned int B2R2_VFP;
+};
+
+struct b2r2_flikr_filter {
+ unsigned int B2R2_FF0;
+ unsigned int B2R2_FF1;
+ unsigned int B2R2_FF2;
+ unsigned int B2R2_FF3;
+};
+
+struct b2r2_xyl {
+ unsigned int B2R2_XYL;
+ unsigned int B2R2_XYP;
+};
+
+struct b2r2_sau {
+ unsigned int B2R2_SAR;
+ unsigned int B2R2_USR;
+};
+
+struct b2r2_vm {
+ unsigned int B2R2_VMX0;
+ unsigned int B2R2_VMX1;
+ unsigned int B2R2_VMX2;
+ unsigned int B2R2_VMX3;
+};
+
+struct b2r2_link_list {
+
+ struct b2r2_system GROUP0;
+ struct b2r2_target GROUP1;
+ struct b2r2_color_fill GROUP2;
+ struct b2r2_src_config GROUP3;
+ struct b2r2_src_config GROUP4;
+ struct b2r2_src_config GROUP5;
+ struct b2r2_clip GROUP6;
+ struct b2r2_clut GROUP7;
+ struct b2r2_rsz_pl_mask GROUP8;
+ struct b2r2_Cr_luma_rsz GROUP9;
+ struct b2r2_Cr_luma_rsz GROUP10;
+ struct b2r2_flikr_filter GROUP11;
+ struct b2r2_color_key GROUP12;
+ struct b2r2_xyl GROUP13;
+ struct b2r2_sau GROUP14;
+ struct b2r2_vm GROUP15;
+ struct b2r2_vm GROUP16;
+
+ unsigned int B2R2_RESERVED[2];
+};
+
+
+#endif /* !defined(__B2R2_GLOBAL_H) */
diff --git a/drivers/video/b2r2/b2r2_hw.h b/drivers/video/b2r2/b2r2_hw.h
new file mode 100644
index 00000000000..9739912d78c
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_hw.h
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 hw definitions
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef B2R2_HW_H__
+#define B2R2_HW_H__
+
+#include <linux/bitops.h>
+
+/* Scaling works in strips 128 pixels wide */
+#define B2R2_RESCALE_MAX_WIDTH 128
+
+/* Rotation works in strips 16 pixels wide */
+#define B2R2_ROTATE_MAX_WIDTH 16
+
+/* B2R2 color formats */
+#define B2R2_COLOR_FORMAT_SHIFT 16
+enum b2r2_native_fmt {
+ /* RGB formats */
+ B2R2_NATIVE_RGB565 = 0x00 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_RGB888 = 0x01 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ARGB8565 = 0x04 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ARGB8888 = 0x05 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ARGB1555 = 0x06 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ARGB4444 = 0x07 << B2R2_COLOR_FORMAT_SHIFT,
+
+ /* YCbCr formats */
+ B2R2_NATIVE_YCBCR888 = 0x10 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_YCBCR422R = 0x12 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_AYCBCR8888 = 0x15 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_YCBCR42X_MB = 0x14 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_YCBCR42X_R2B = 0x16 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_YCBCR42X_MBN = 0x0e << B2R2_COLOR_FORMAT_SHIFT,
+
+ /* CLUT formats */
+ B2R2_NATIVE_CLUT2 = 0x09 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_CLUT8 = 0x0b << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ACLUT44 = 0x0c << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_ACLUT88 = 0x0d << B2R2_COLOR_FORMAT_SHIFT,
+
+ /* Misc. formats */
+ B2R2_NATIVE_A1 = 0x18 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_A8 = 0x19 << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_YUV = 0x1e << B2R2_COLOR_FORMAT_SHIFT,
+ B2R2_NATIVE_BYTE = 0x1f << B2R2_COLOR_FORMAT_SHIFT,
+};
+
+/* B2R2_CIC register values */
+enum b2r2_cic {
+ B2R2_CIC_COLOR_FILL = BIT(1),/*0x00000002*/
+ B2R2_CIC_SOURCE_1 = BIT(2),/*0x00000004*/
+ B2R2_CIC_SOURCE_2 = BIT(3),/*0x00000008*/
+ B2R2_CIC_SOURCE_3 = BIT(4),/*0x00000010*/
+ B2R2_CIC_CLIP_WINDOW = BIT(5),/*0x00000020*/
+ B2R2_CIC_CLUT = BIT(6),/*0x00000040*/
+ B2R2_CIC_FILTER_CONTROL = BIT(7),/*0x00000080*/
+ B2R2_CIC_RESIZE_CHROMA = BIT(8),/*0x00000100*/
+ B2R2_CIC_RESIZE_LUMA = BIT(9),/*0x00000200*/
+ B2R2_CIC_FLICKER_COEFF = BIT(10),/*0x00000400*/
+ B2R2_CIC_COLOR_KEY = BIT(11),/*0x00000800*/
+ B2R2_CIC_XYL = BIT(12),/*0x00001000*/
+ B2R2_CIC_SAU = BIT(13),/*0x00002000*/
+ B2R2_CIC_IVMX = BIT(14),/*0x00004000*/
+ B2R2_CIC_OVMX = BIT(15),/*0x00008000*/
+ B2R2_CIC_PACEDOT = BIT(16),/*0x00010000*/
+ B2R2_CIC_VC1 = BIT(17)/*0x00020000*/
+};
+
+/* B2R2_INS register values */
+#define B2R2_INS_SOURCE_1_SHIFT 0
+#define B2R2_INS_SOURCE_2_SHIFT 3
+#define B2R2_INS_SOURCE_3_SHIFT 5
+#define B2R2_INS_IVMX_SHIFT 6
+#define B2R2_INS_CLUTOP_SHIFT 7
+#define B2R2_INS_RESCALE2D_SHIFT 8
+#define B2R2_INS_FLICK_FILT_SHIFT 9
+#define B2R2_INS_RECT_CLIP_SHIFT 10
+#define B2R2_INS_CKEY_SHIFT 11
+#define B2R2_INS_OVMX_SHIFT 12
+#define B2R2_INS_DEI_SHIFT 13
+#define B2R2_INS_PLANE_MASK_SHIFT 14
+#define B2R2_INS_XYL_SHIFT 15
+#define B2R2_INS_DOT_SHIFT 16
+#define B2R2_INS_VC1R_SHIFT 17
+#define B2R2_INS_ROTATION_SHIFT 18
+#define B2R2_INS_PACE_DOWN_SHIFT 30
+#define B2R2_INS_BLITCOMPIRQ_SHIFT 31
+enum b2r2_ins {
+ /* Source 1 config */
+ B2R2_INS_SOURCE_1_FETCH_FROM_MEM = 0x1 << B2R2_INS_SOURCE_1_SHIFT,
+ B2R2_INS_SOURCE_1_COLOR_FILL_REGISTER = 0x3 << B2R2_INS_SOURCE_1_SHIFT,
+ B2R2_INS_SOURCE_1_DIRECT_COPY = 0x4 << B2R2_INS_SOURCE_1_SHIFT,
+ B2R2_INS_SOURCE_1_DIRECT_FILL = 0x7 << B2R2_INS_SOURCE_1_SHIFT,
+
+ /* Source 2 config */
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM = 0x1 << B2R2_INS_SOURCE_2_SHIFT,
+ B2R2_INS_SOURCE_2_COLOR_FILL_REGISTER = 0x3 << B2R2_INS_SOURCE_2_SHIFT,
+
+ /* Source 3 config */
+ B2R2_INS_SOURCE_3_FETCH_FROM_MEM = 0x1 << B2R2_INS_SOURCE_3_SHIFT,
+
+ /* Other configs */
+ B2R2_INS_IVMX_ENABLED = 0x1 << B2R2_INS_IVMX_SHIFT,
+ B2R2_INS_CLUTOP_ENABLED = 0x1 << B2R2_INS_CLUTOP_SHIFT,
+ B2R2_INS_RESCALE2D_ENABLED = 0x1 << B2R2_INS_RESCALE2D_SHIFT,
+ B2R2_INS_FLICK_FILT_ENABLED = 0x1 << B2R2_INS_FLICK_FILT_SHIFT,
+ B2R2_INS_RECT_CLIP_ENABLED = 0x1 << B2R2_INS_RECT_CLIP_SHIFT,
+ B2R2_INS_CKEY_ENABLED = 0x1 << B2R2_INS_CKEY_SHIFT,
+ B2R2_INS_OVMX_ENABLED = 0x1 << B2R2_INS_OVMX_SHIFT,
+ B2R2_INS_DEI_ENABLED = 0x1 << B2R2_INS_DEI_SHIFT,
+ B2R2_INS_PLANE_MASK_ENABLED = 0x1 << B2R2_INS_PLANE_MASK_SHIFT,
+ B2R2_INS_XYL_ENABLED = 0x1 << B2R2_INS_XYL_SHIFT,
+ B2R2_INS_DOT_ENABLED = 0x1 << B2R2_INS_DOT_SHIFT,
+ B2R2_INS_VC1R_ENABLED = 0x1 << B2R2_INS_VC1R_SHIFT,
+ B2R2_INS_ROTATION_ENABLED = 0x1 << B2R2_INS_ROTATION_SHIFT,
+ B2R2_INS_PACE_DOWN_ENABLED = 0x1 << B2R2_INS_PACE_DOWN_SHIFT,
+ B2R2_INS_BLITCOMPIRQ_ENABLED = 0x1 << B2R2_INS_BLITCOMPIRQ_SHIFT,
+
+};
+
+/* B2R2_ACK register values */
+#define B2R2_ACK_MODE_SHIFT 0
+#define B2R2_ACK_SWAP_FG_BG_SHIFT 4
+#define B2R2_ACK_GALPHA_ROPID_SHIFT 8
+#define B2R2_ACK_CKEY_BLUE_SHIFT 16
+#define B2R2_ACK_CKEY_GREEN_SHIFT 18
+#define B2R2_ACK_CKEY_RED_SHIFT 20
+#define B2R2_ACK_CKEY_SEL_SHIFT 22
+enum b2r2_ack {
+ /* ALU operation modes */
+ B2R2_ACK_MODE_LOGICAL_OPERATION = 0x1 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_BLEND_NOT_PREMULT = 0x2 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_BLEND_PREMULT = 0x3 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_LOGICAL_FIRST_PASS = 0x4 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_BLEND = 0x5 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_BYPASS_S2_S3 = 0x7 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_LOGICAL_SECOND_PASS = 0x8 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_XYL_LOGICAL = 0x9 << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_XYL_BLEND_NOT_PREMULT =
+ 0xa << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_XYL_BLEND_PREMULT = 0xb << B2R2_ACK_MODE_SHIFT,
+
+ /* ALU channel selection */
+ B2R2_ACK_SWAP_FG_BG = 0x1 << B2R2_ACK_SWAP_FG_BG_SHIFT,
+
+ /* Global alpha and ROP IDs */
+ B2R2_ACK_ROP_CLEAR = 0x0 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_AND = 0x1 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_AND_REV = 0x2 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_COPY = 0x3 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_AND_INV = 0x4 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_NOOP = 0x5 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_XOR = 0x6 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_OR = 0x7 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_NOR = 0x8 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_EQUIV = 0x9 << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_INVERT = 0xa << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_OR_REV = 0xb << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_COPY_INV = 0xc << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_OR_INV = 0xd << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_NAND = 0xe << B2R2_ACK_GALPHA_ROPID_SHIFT,
+ B2R2_ACK_ROP_SET = 0xf << B2R2_ACK_GALPHA_ROPID_SHIFT,
+
+ /* Color key configuration bits */
+ B2R2_ACK_CKEY_BLUE_MATCH_IF_BETWEEN = 0x1 << B2R2_ACK_CKEY_BLUE_SHIFT,
+ B2R2_ACK_CKEY_BLUE_MATCH_IF_LT_OR_GT = 0x2 << B2R2_ACK_CKEY_BLUE_SHIFT,
+ B2R2_ACK_CKEY_RED_MATCH_IF_BETWEEN = 0x1 << B2R2_ACK_CKEY_GREEN_SHIFT,
+ B2R2_ACK_CKEY_RED_MATCH_IF_LT_OR_GT = 0x2 << B2R2_ACK_CKEY_GREEN_SHIFT,
+ B2R2_ACK_CKEY_GREEN_MATCH_IF_BETWEEN = 0x1 << B2R2_ACK_CKEY_RED_SHIFT,
+ B2R2_ACK_CKEY_GREEN_MATCH_IF_LT_OR_GT = 0x2 << B2R2_ACK_CKEY_RED_SHIFT,
+
+ /* Color key input selection */
+ B2R2_ACK_CKEY_SEL_DEST = 0x0 << B2R2_ACK_CKEY_SEL_SHIFT,
+ B2R2_ACK_CKEY_SEL_SRC_BEFORE_CLUT = 0x1 << B2R2_ACK_CKEY_SEL_SHIFT,
+ B2R2_ACK_CKEY_SEL_SRC_AFTER_CLUT = 0x2 << B2R2_ACK_CKEY_SEL_SHIFT,
+ B2R2_ACK_CKEY_SEL_BLANKING_S2_ALPHA = 0x3 << B2R2_ACK_CKEY_SEL_SHIFT,
+};
+
+/* Common <S/T>TY defines */
+#define B2R2_TY_BITMAP_PITCH_SHIFT 0
+#define B2R2_TY_COLOR_FORM_SHIFT 16
+#define B2R2_TY_ALPHA_RANGE_SHIFT 21
+#define B2R2_TY_MB_ACCESS_MODE_SHIFT 23
+#define B2R2_TY_HSO_SHIFT 24
+#define B2R2_TY_VSO_SHIFT 25
+#define B2R2_TY_SUBBYTE_SHIFT 28
+#define B2R2_TY_ENDIAN_SHIFT 30
+#define B2R2_TY_SECURE_SHIFT 31
+
+/* Dummy enum for generalization of <S/T>TY registers */
+enum b2r2_ty {
+ /* Alpha range */
+ B2R2_TY_ALPHA_RANGE_128 = 0x0 << B2R2_TY_ALPHA_RANGE_SHIFT,
+ B2R2_TY_ALPHA_RANGE_255 = 0x1 << B2R2_TY_ALPHA_RANGE_SHIFT,
+
+ /* Access mode in macro-block organized frame buffers */
+ B2R2_TY_MB_ACCESS_MODE_FRAME = 0x0 << B2R2_TY_MB_ACCESS_MODE_SHIFT,
+ B2R2_TY_MB_ACCESS_MODE_FIELD = 0x1 << B2R2_TY_MB_ACCESS_MODE_SHIFT,
+
+ /* Horizontal scan order */
+ B2R2_TY_HSO_LEFT_TO_RIGHT = 0x0 << B2R2_TY_HSO_SHIFT,
+ B2R2_TY_HSO_RIGHT_TO_LEFT = 0x1 << B2R2_TY_HSO_SHIFT,
+
+ /* Vertical scan order */
+ B2R2_TY_VSO_TOP_TO_BOTTOM = 0x0 << B2R2_TY_VSO_SHIFT,
+ B2R2_TY_VSO_BOTTOM_TO_TOP = 0x1 << B2R2_TY_VSO_SHIFT,
+
+ /* Pixel ordering for sub-byte formats (position of right-most pixel) */
+ B2R2_TY_SUBBYTE_MSB = 0x0 << B2R2_TY_SUBBYTE_SHIFT,
+ B2R2_TY_SUBBYTE_LSB = 0x1 << B2R2_TY_SUBBYTE_SHIFT,
+
+ /* Bitmap endianess */
+ B2R2_TY_ENDIAN_BIG_NOT_LITTLE = 0x1 << B2R2_TY_ENDIAN_SHIFT,
+
+ /* Secureness of the target memory region */
+ B2R2_TY_SECURE_UNSECURE = 0x0 << B2R2_TY_SECURE_SHIFT,
+ B2R2_TY_SECURE_SECURE = 0x1 << B2R2_TY_SECURE_SHIFT,
+
+ /* Dummy to make sure the data type is large enough */
+ B2R2_TY_DUMMY = 0xffffffff,
+};
+
+/* B2R2_TTY register values */
+#define B2R2_TTY_CB_NOT_CR_SHIFT 22
+#define B2R2_TTY_RGB_ROUND_SHIFT 26
+#define B2R2_TTY_CHROMA_NOT_LUMA_SHIFT 27
+enum b2r2_tty {
+
+ /* Chroma component selection */
+ B2R2_TTY_CB_NOT_CR = 0x1 << B2R2_TTY_CB_NOT_CR_SHIFT,
+
+ /* RGB rounding mode */
+ B2R2_TTY_RGB_ROUND_NORMAL = 0x0 << B2R2_TTY_RGB_ROUND_SHIFT,
+ B2R2_TTY_RGB_ROUND_DITHER = 0x1 << B2R2_TTY_RGB_ROUND_SHIFT,
+
+ /* Component selection for splitted frame buffer formats */
+ B2R2_TTY_CHROMA_NOT_LUMA = 0x1 << B2R2_TTY_CHROMA_NOT_LUMA_SHIFT,
+};
+
+/* B2R2_S1TY register values */
+#define B2R2_S1TY_A1_SUBST_SHIFT 22
+#define B2R2_S1TY_ROTATION_SHIFT 27
+#define B2R2_S1TY_RGB_EXPANSION_SHIFT 29
+enum b2r2_s1ty {
+
+ /* Alpha bit substitution mode for ARGB1555 */
+ B2R2_S1TY_A1_SUBST_KEY_MODE = 0x1 << B2R2_S1TY_A1_SUBST_SHIFT,
+
+ /* Input rectangle rotation (NOT YET IMPLEMENTED) */
+ B2R2_S1TY_ENABLE_ROTATION = 0x1 << B2R2_S1TY_ROTATION_SHIFT,
+
+ /* RGB expansion mode */
+ B2R2_S1TY_RGB_EXPANSION_MSB_DUP = 0x0 << B2R2_S1TY_RGB_EXPANSION_SHIFT,
+ B2R2_S1TY_RGB_EXPANSION_LSP_ZERO = 0x1 << B2R2_S1TY_RGB_EXPANSION_SHIFT,
+};
+
+/* B2R2_S1TY register values */
+#define B2R2_S2TY_A1_SUBST_SHIFT 22
+#define B2R2_S2TY_CHROMA_LEFT_SHIFT 26
+#define B2R2_S2TY_RGB_EXPANSION_SHIFT 29
+enum b2r2_s2ty {
+
+ /* Alpha bit substitution mode for ARGB1555 */
+ B2R2_S2TY_A1_SUBST_KEY_MODE = 0x1 << B2R2_S2TY_A1_SUBST_SHIFT,
+
+ /* Chroma left extension */
+ B2R2_S2TY_CHROMA_LEFT_EXT_FOLLOWING_PIXEL = 0x0
+ << B2R2_S2TY_CHROMA_LEFT_SHIFT,
+ B2R2_S2TY_CHROMA_LEFT_EXT_AVERAGE = 0x1 << B2R2_S2TY_CHROMA_LEFT_SHIFT,
+
+ /* RGB expansion mode */
+ B2R2_S2TY_RGB_EXPANSION_MSB_DUP = 0x0 << B2R2_S2TY_RGB_EXPANSION_SHIFT,
+ B2R2_S2TY_RGB_EXPANSION_LSP_ZERO = 0x1 << B2R2_S2TY_RGB_EXPANSION_SHIFT,
+};
+
+/* B2R2_S1TY register values */
+#define B2R2_S3TY_BLANK_ACC_SHIFT 26
+enum b2r2_s3ty {
+ /* Enables "blank" access on this source (nothing will be fetched from
+ memory) */
+ B2R2_S3TY_ENABLE_BLANK_ACCESS = 0x1 << B2R2_S3TY_BLANK_ACC_SHIFT,
+};
+
+/* B2R2_<S or T>XY register values */
+#define B2R2_XY_X_SHIFT 0
+#define B2R2_XY_Y_SHIFT 16
+
+/* B2R2_<S or T>SZ register values */
+#define B2R2_SZ_WIDTH_SHIFT 0
+#define B2R2_SZ_HEIGHT_SHIFT 16
+
+/* Clip window offset (top left coordinates) */
+#define B2R2_CWO_X_SHIFT 0
+#define B2R2_CWO_Y_SHIFT 16
+
+/* Clip window stop (bottom right coordinates) */
+#define B2R2_CWS_X_SHIFT 0
+#define B2R2_CWS_Y_SHIFT 16
+
+/* Color look-up table */
+enum b2r2_cco {
+ B2R2_CCO_CLUT_COLOR_CORRECTION = (1 << 16),
+ B2R2_CCO_CLUT_UPDATE = (1 << 18),
+ B2R2_CCO_CLUT_ON_S1 = (1 << 15)
+};
+
+/* Filter control (2D resize control) */
+enum b2r2_fctl {
+ /* Horizontal 2D filter mode */
+ B2R2_FCTL_HF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER = BIT(0),
+ B2R2_FCTL_HF2D_MODE_ENABLE_ALPHA_CHANNEL_FILTER = BIT(1),
+ B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER = BIT(2),
+
+ /* Vertical 2D filter mode */
+ B2R2_FCTL_VF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER = BIT(4),
+ B2R2_FCTL_VF2D_MODE_ENABLE_ALPHA_CHANNEL_FILTER = BIT(5),
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER = BIT(6),
+
+ /* Alpha borders */
+ B2R2_FCTL_ENABLE_ALPHA_BORDER_RIGHT = BIT(12),
+ B2R2_FCTL_ENABLE_ALPHA_BORDER_LEFT = BIT(13),
+ B2R2_FCTL_ENABLE_ALPHA_BORDER_BOTTOM = BIT(14),
+ B2R2_FCTL_ENABLE_ALPHA_BORDER_TOP = BIT(15),
+
+ /* Luma path horizontal 2D filter mode */
+ B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_FILTER = BIT(24),
+ B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_RESIZER = BIT(25),
+
+ /* Luma path vertical 2D filter mode */
+ B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_FILTER = BIT(28),
+ B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_RESIZER = BIT(29),
+};
+
+/* Resize scaling factor */
+#define B2R2_RSF_HSRC_INC_SHIFT 0
+#define B2R2_RSF_VSRC_INC_SHIFT 16
+
+/* Resizer initialization */
+#define B2R2_RZI_HSRC_INIT_SHIFT 0
+#define B2R2_RZI_HNB_REPEAT_SHIFT 12
+#define B2R2_RZI_VSRC_INIT_SHIFT 16
+#define B2R2_RZI_VNB_REPEAT_SHIFT 28
+
+/* Default values for the resizer */
+#define B2R2_RZI_DEFAULT_HNB_REPEAT (3 << B2R2_RZI_HNB_REPEAT_SHIFT)
+#define B2R2_RZI_DEFAULT_VNB_REPEAT (3 << B2R2_RZI_VNB_REPEAT_SHIFT)
+
+
+/* Bus plug configuration registers */
+enum b2r2_plug_opcode_size {
+ B2R2_PLUG_OPCODE_SIZE_8 = 0x3,
+ B2R2_PLUG_OPCODE_SIZE_16 = 0x4,
+ B2R2_PLUG_OPCODE_SIZE_32 = 0x5,
+ B2R2_PLUG_OPCODE_SIZE_64 = 0x6,
+};
+
+enum b2r2_plug_chunk_size {
+ B2R2_PLUG_CHUNK_SIZE_1 = 0x0,
+ B2R2_PLUG_CHUNK_SIZE_2 = 0x1,
+ B2R2_PLUG_CHUNK_SIZE_4 = 0x2,
+ B2R2_PLUG_CHUNK_SIZE_8 = 0x3,
+ B2R2_PLUG_CHUNK_SIZE_16 = 0x4,
+ B2R2_PLUG_CHUNK_SIZE_32 = 0x5,
+ B2R2_PLUG_CHUNK_SIZE_64 = 0x6,
+ B2R2_PLUG_CHUNK_SIZE_128 = 0x7,
+};
+
+enum b2r2_plug_message_size {
+ B2R2_PLUG_MESSAGE_SIZE_1 = 0x0,
+ B2R2_PLUG_MESSAGE_SIZE_2 = 0x1,
+ B2R2_PLUG_MESSAGE_SIZE_4 = 0x2,
+ B2R2_PLUG_MESSAGE_SIZE_8 = 0x3,
+ B2R2_PLUG_MESSAGE_SIZE_16 = 0x4,
+ B2R2_PLUG_MESSAGE_SIZE_32 = 0x5,
+ B2R2_PLUG_MESSAGE_SIZE_64 = 0x6,
+ B2R2_PLUG_MESSAGE_SIZE_128 = 0x7,
+};
+
+enum b2r2_plug_page_size {
+ B2R2_PLUG_PAGE_SIZE_64 = 0x0,
+ B2R2_PLUG_PAGE_SIZE_128 = 0x1,
+ B2R2_PLUG_PAGE_SIZE_256 = 0x2,
+};
+
+/* Default opcode size */
+#if defined(CONFIG_B2R2_OPSIZE_8)
+# define B2R2_PLUG_OPCODE_SIZE_DEFAULT B2R2_PLUG_OPCODE_SIZE_8
+#elif defined(CONFIG_B2R2_OPSIZE_16)
+# define B2R2_PLUG_OPCODE_SIZE_DEFAULT B2R2_PLUG_OPCODE_SIZE_16
+#elif defined(CONFIG_B2R2_OPSIZE_32)
+# define B2R2_PLUG_OPCODE_SIZE_DEFAULT B2R2_PLUG_OPCODE_SIZE_32
+#elif defined(CONFIG_B2R2_OPSIZE_64)
+# define B2R2_PLUG_OPCODE_SIZE_DEFAULT B2R2_PLUG_OPCODE_SIZE_64
+#else
+# define B2R2_PLUG_OPCODE_SIZE_DEFAULT 0
+#endif
+
+/* Default chunk size */
+#if defined(CONFIG_B2R2_CHSIZE_1)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_1
+#elif defined(CONFIG_B2R2_CHSIZE_2)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_2
+#elif defined(CONFIG_B2R2_CHSIZE_4)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_4
+#elif defined(CONFIG_B2R2_CHSIZE_8)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_8
+#elif defined(CONFIG_B2R2_CHSIZE_16)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_16
+#elif defined(CONFIG_B2R2_CHSIZE_32)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_32
+#elif defined(CONFIG_B2R2_CHSIZE_64)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_64
+#elif defined(CONFIG_B2R2_CHSIZE_128)
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT B2R2_PLUG_CHUNK_SIZE_128
+#else
+# define B2R2_PLUG_CHUNK_SIZE_DEFAULT 0
+#endif
+
+/* Default message size */
+#if defined(CONFIG_B2R2_MGSIZE_1)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_1
+#elif defined(CONFIG_B2R2_MGSIZE_2)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_2
+#elif defined(CONFIG_B2R2_MGSIZE_4)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_4
+#elif defined(CONFIG_B2R2_MGSIZE_8)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_8
+#elif defined(CONFIG_B2R2_MGSIZE_16)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_16
+#elif defined(CONFIG_B2R2_MGSIZE_32)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_32
+#elif defined(CONFIG_B2R2_MGSIZE_64)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_64
+#elif defined(CONFIG_B2R2_MGSIZE_128)
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT B2R2_PLUG_MESSAGE_SIZE_128
+#else
+# define B2R2_PLUG_MESSAGE_SIZE_DEFAULT 0
+#endif
+
+/* Default page size */
+#if defined(CONFIG_B2R2_PGSIZE_64)
+# define B2R2_PLUG_PAGE_SIZE_DEFAULT B2R2_PLUG_PAGE_SIZE_64
+#elif defined(CONFIG_B2R2_PGSIZE_128)
+# define B2R2_PLUG_PAGE_SIZE_DEFAULT B2R2_PLUG_PAGE_SIZE_128
+#elif defined(CONFIG_B2R2_PGSIZE_256)
+# define B2R2_PLUG_PAGE_SIZE_DEFAULT B2R2_PLUG_PAGE_SIZE_256
+#else
+# define B2R2_PLUG_PAGE_SIZE_DEFAULT 0
+#endif
+
+#endif /* B2R2_HW_H__ */
diff --git a/drivers/video/b2r2/b2r2_hw_convert.c b/drivers/video/b2r2/b2r2_hw_convert.c
new file mode 100644
index 00000000000..d1b44db79c3
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_hw_convert.c
@@ -0,0 +1,747 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * ST-Ericsson B2R2 node splitter
+ *
+ * Author: Jorgen Nilsson <jorgen.nilsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include "b2r2_hw_convert.h"
+#include "b2r2_internal.h"
+#include "b2r2_utils.h"
+
+/*
+ * Macros and constants
+ */
+
+/* VMX register values for RGB to YUV color conversion */
+/* Magic numbers from 27.11 in DB8500_DesignSpecification_v2.5.pdf */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_RGB_TO_YUV_601_FULL_RANGE 0x107e4beb
+#define B2R2_VMX1_RGB_TO_YUV_601_FULL_RANGE 0x0982581d
+#define B2R2_VMX2_RGB_TO_YUV_601_FULL_RANGE 0xfa9ea483
+#define B2R2_VMX3_RGB_TO_YUV_601_FULL_RANGE 0x08000080
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_RGB_TO_YUV_601_STANDARD 0x0e1e8bee
+#define B2R2_VMX1_RGB_TO_YUV_601_STANDARD 0x08420419
+#define B2R2_VMX2_RGB_TO_YUV_601_STANDARD 0xfb5ed471
+#define B2R2_VMX3_RGB_TO_YUV_601_STANDARD 0x08004080
+
+/* 709 Full range conversion matrix */
+#define B2R2_VMX0_RGB_TO_YUV_709_FULL_RANGE 0x107e27f4
+#define B2R2_VMX1_RGB_TO_YUV_709_FULL_RANGE 0x06e2dc13
+#define B2R2_VMX2_RGB_TO_YUV_709_FULL_RANGE 0xfc5e6c83
+#define B2R2_VMX3_RGB_TO_YUV_709_FULL_RANGE 0x08000080
+
+/* 709 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_RGB_TO_YUV_709_STANDARD 0x0e3e6bf5
+#define B2R2_VMX1_RGB_TO_YUV_709_STANDARD 0x05e27410
+#define B2R2_VMX2_RGB_TO_YUV_709_STANDARD 0xfcdea471
+#define B2R2_VMX3_RGB_TO_YUV_709_STANDARD 0x08004080
+
+/* VMX register values for YUV to RGB color conversion */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_YUV_TO_RGB_601_FULL_RANGE 0x2c440000
+#define B2R2_VMX1_YUV_TO_RGB_601_FULL_RANGE 0xe9a403aa
+#define B2R2_VMX2_YUV_TO_RGB_601_FULL_RANGE 0x0004013f
+#define B2R2_VMX3_YUV_TO_RGB_601_FULL_RANGE 0x34f21322
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YUV_TO_RGB_601_STANDARD 0x3324a800
+#define B2R2_VMX1_YUV_TO_RGB_601_STANDARD 0xe604ab9c
+#define B2R2_VMX2_YUV_TO_RGB_601_STANDARD 0x0004a957
+#define B2R2_VMX3_YUV_TO_RGB_601_STANDARD 0x32121eeb
+
+/* 709 Full range conversion matrix */
+#define B2R2_VMX0_YUV_TO_RGB_709_FULL_RANGE 0x31440000
+#define B2R2_VMX1_YUV_TO_RGB_709_FULL_RANGE 0xf16403d1
+#define B2R2_VMX2_YUV_TO_RGB_709_FULL_RANGE 0x00040145
+#define B2R2_VMX3_YUV_TO_RGB_709_FULL_RANGE 0x33b14b18
+
+/* 709 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YUV_TO_RGB_709_STANDARD 0x3964a800
+#define B2R2_VMX1_YUV_TO_RGB_709_STANDARD 0xef04abc9
+#define B2R2_VMX2_YUV_TO_RGB_709_STANDARD 0x0004a95f
+#define B2R2_VMX3_YUV_TO_RGB_709_STANDARD 0x307132df
+
+/* VMX register values for RGB to BGR conversion */
+#define B2R2_VMX0_RGB_TO_BGR 0x00000100
+#define B2R2_VMX1_RGB_TO_BGR 0x00040000
+#define B2R2_VMX2_RGB_TO_BGR 0x20000000
+#define B2R2_VMX3_RGB_TO_BGR 0x00000000
+
+/* VMX register values for BGR to YUV color conversion */
+/* Note: All BGR -> YUV values are calculated by multiplying
+ * the RGB -> YUV matrices [A], with [S] to form [A]x[S] where
+ * |0 0 1|
+ * S = |0 1 0|
+ * |1 0 0|
+ * Essentially swapping first and third columns in
+ * the matrices (VMX0, VMX1 and VMX2 values).
+ * The offset vector VMX3 remains untouched.
+ * Put another way, the value of bits 0 through 9
+ * is swapped with the value of
+ * bits 20 through 31 in VMX0, VMX1 and VMX2,
+ * taking into consideration the compression
+ * that is used on bits 0 through 9. Bit 0 being LSB.
+ */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_BGR_TO_YUV_601_FULL_RANGE 0xfd7e4883
+#define B2R2_VMX1_BGR_TO_YUV_601_FULL_RANGE 0x03a2584c
+#define B2R2_VMX2_BGR_TO_YUV_601_FULL_RANGE 0x107ea7d4
+#define B2R2_VMX3_BGR_TO_YUV_601_FULL_RANGE 0x08000080
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_BGR_TO_YUV_601_STANDARD 0xfdde8870
+#define B2R2_VMX1_BGR_TO_YUV_601_STANDARD 0x03220442
+#define B2R2_VMX2_BGR_TO_YUV_601_STANDARD 0x0e3ed7da
+#define B2R2_VMX3_BGR_TO_YUV_601_STANDARD 0x08004080
+
+/* 709 Full range conversion matrix */
+#define B2R2_VMX0_BGR_TO_YUV_709_FULL_RANGE 0xfe9e2483
+#define B2R2_VMX1_BGR_TO_YUV_709_FULL_RANGE 0x0262dc37
+#define B2R2_VMX2_BGR_TO_YUV_709_FULL_RANGE 0x107e6fe2
+#define B2R2_VMX3_BGR_TO_YUV_709_FULL_RANGE 0x08000080
+
+/* 709 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_BGR_TO_YUV_709_STANDARD 0xfebe6871
+#define B2R2_VMX1_BGR_TO_YUV_709_STANDARD 0x0202742f
+#define B2R2_VMX2_BGR_TO_YUV_709_STANDARD 0x0e3ea7e6
+#define B2R2_VMX3_BGR_TO_YUV_709_STANDARD 0x08004080
+
+
+/* VMX register values for YUV to BGR conversion */
+/* Note: All YUV -> BGR values are constructed
+ * from the YUV -> RGB ones, by swapping
+ * first and third rows in the matrix
+ * (VMX0 and VMX2 values). Further, the first and
+ * third values in the offset vector need to be
+ * swapped as well, i.e. bits 0 through 9 are swapped
+ * with bits 20 through 29 in the VMX3 value.
+ * Bit 0 being LSB.
+ */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_YUV_TO_BGR_601_FULL_RANGE (B2R2_VMX2_YUV_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX1_YUV_TO_BGR_601_FULL_RANGE (B2R2_VMX1_YUV_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX2_YUV_TO_BGR_601_FULL_RANGE (B2R2_VMX0_YUV_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX3_YUV_TO_BGR_601_FULL_RANGE 0x3222134f
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YUV_TO_BGR_601_STANDARD (B2R2_VMX2_YUV_TO_RGB_601_STANDARD)
+#define B2R2_VMX1_YUV_TO_BGR_601_STANDARD (B2R2_VMX1_YUV_TO_RGB_601_STANDARD)
+#define B2R2_VMX2_YUV_TO_BGR_601_STANDARD (B2R2_VMX0_YUV_TO_RGB_601_STANDARD)
+#define B2R2_VMX3_YUV_TO_BGR_601_STANDARD 0x2eb21f21
+
+/* 709 Full range conversion matrix */
+#define B2R2_VMX0_YUV_TO_BGR_709_FULL_RANGE (B2R2_VMX2_YUV_TO_RGB_709_FULL_RANGE)
+#define B2R2_VMX1_YUV_TO_BGR_709_FULL_RANGE (B2R2_VMX1_YUV_TO_RGB_709_FULL_RANGE)
+#define B2R2_VMX2_YUV_TO_BGR_709_FULL_RANGE (B2R2_VMX0_YUV_TO_RGB_709_FULL_RANGE)
+#define B2R2_VMX3_YUV_TO_BGR_709_FULL_RANGE 0x31814b3b
+
+/* 709 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YUV_TO_BGR_709_STANDARD (B2R2_VMX2_YUV_TO_RGB_709_STANDARD)
+#define B2R2_VMX1_YUV_TO_BGR_709_STANDARD (B2R2_VMX1_YUV_TO_RGB_709_STANDARD)
+#define B2R2_VMX2_YUV_TO_BGR_709_STANDARD (B2R2_VMX0_YUV_TO_RGB_709_STANDARD)
+#define B2R2_VMX3_YUV_TO_BGR_709_STANDARD 0x2df13307
+
+
+/* VMX register values for YVU to RGB conversion */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_YVU_TO_RGB_601_FULL_RANGE 0x00040120
+#define B2R2_VMX1_YVU_TO_RGB_601_FULL_RANGE 0xF544034D
+#define B2R2_VMX2_YVU_TO_RGB_601_FULL_RANGE 0x37840000
+#define B2R2_VMX3_YVU_TO_RGB_601_FULL_RANGE (B2R2_VMX3_YUV_TO_RGB_601_FULL_RANGE)
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YVU_TO_RGB_601_STANDARD 0x0004A999
+#define B2R2_VMX1_YVU_TO_RGB_601_STANDARD 0xF384AB30
+#define B2R2_VMX2_YVU_TO_RGB_601_STANDARD 0x40A4A800
+#define B2R2_VMX3_YVU_TO_RGB_601_STANDARD (B2R2_VMX3_YUV_TO_RGB_601_STANDARD)
+
+/* VMX register values for RGB to YVU conversion */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_RGB_TO_YVU_601_FULL_RANGE (B2R2_VMX2_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX1_RGB_TO_YVU_601_FULL_RANGE (B2R2_VMX1_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX2_RGB_TO_YVU_601_FULL_RANGE (B2R2_VMX0_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX3_RGB_TO_YVU_601_FULL_RANGE (B2R2_VMX3_RGB_TO_YUV_601_FULL_RANGE)
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_RGB_TO_YVU_601_STANDARD (B2R2_VMX2_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX1_RGB_TO_YVU_601_STANDARD (B2R2_VMX1_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX2_RGB_TO_YVU_601_STANDARD (B2R2_VMX0_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX3_RGB_TO_YVU_601_STANDARD (B2R2_VMX3_RGB_TO_YUV_601_STANDARD)
+
+/* VMX register values for YVU to BGR conversion */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_YVU_TO_BGR_601_FULL_RANGE (B2R2_VMX2_YVU_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX1_YVU_TO_BGR_601_FULL_RANGE (B2R2_VMX1_YVU_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX2_YVU_TO_BGR_601_FULL_RANGE (B2R2_VMX0_YVU_TO_RGB_601_FULL_RANGE)
+#define B2R2_VMX3_YVU_TO_BGR_601_FULL_RANGE 0x3222134F
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_YVU_TO_BGR_601_STANDARD (B2R2_VMX2_YVU_TO_RGB_601_STANDARD)
+#define B2R2_VMX1_YVU_TO_BGR_601_STANDARD (B2R2_VMX1_YVU_TO_RGB_601_STANDARD)
+#define B2R2_VMX2_YVU_TO_BGR_601_STANDARD (B2R2_VMX0_YVU_TO_RGB_601_STANDARD)
+#define B2R2_VMX3_YVU_TO_BGR_601_STANDARD 0x3222134F
+
+/* VMX register values for BGR to YVU conversion */
+
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_BGR_TO_YVU_601_FULL_RANGE (B2R2_VMX2_BGR_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX1_BGR_TO_YVU_601_FULL_RANGE (B2R2_VMX1_BGR_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX2_BGR_TO_YVU_601_FULL_RANGE (B2R2_VMX0_BGR_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX3_BGR_TO_YVU_601_FULL_RANGE (B2R2_VMX3_BGR_TO_YUV_601_FULL_RANGE)
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_BGR_TO_YVU_601_STANDARD (B2R2_VMX2_BGR_TO_YUV_601_STANDARD)
+#define B2R2_VMX1_BGR_TO_YVU_601_STANDARD (B2R2_VMX1_BGR_TO_YUV_601_STANDARD)
+#define B2R2_VMX2_BGR_TO_YVU_601_STANDARD (B2R2_VMX0_BGR_TO_YUV_601_STANDARD)
+#define B2R2_VMX3_BGR_TO_YVU_601_STANDARD (B2R2_VMX3_BGR_TO_YUV_601_STANDARD)
+
+/* VMX register values for YVU to YUV conversion */
+
+/* 601 Video Matrix (standard 601 conversion) */
+/* Internally, the components are in fact stored
+ * with luma in the middle, i.e. UYV, which is why
+ * the values are just like for RGB->BGR conversion.
+ */
+#define B2R2_VMX0_YVU_TO_YUV 0x00000100
+#define B2R2_VMX1_YVU_TO_YUV 0x00040000
+#define B2R2_VMX2_YVU_TO_YUV 0x20000000
+#define B2R2_VMX3_YVU_TO_YUV 0x00000000
+
+/* VMX register values for RGB to BLT_YUV888 conversion */
+
+/*
+ * BLT_YUV888 has color components laid out in memory as V, U, Y, (Alpha)
+ * with V at the first byte (due to little endian addressing).
+ * B2R2 expects them to be as U, Y, V, (A)
+ * with U at the first byte.
+ * Note: RGB -> BLT_YUV888 values are calculated by multiplying
+ * the RGB -> YUV matrix [A], with [S] to form [S]x[A] where
+ * |0 1 0|
+ * S = |0 0 1|
+ * |1 0 0|
+ * Essentially changing the order of rows in the original
+ * matrix [A].
+ * row1 -> row3
+ * row2 -> row1
+ * row3 -> row2
+ * Values in the offset vector are swapped in the same manner.
+ */
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_RGB_TO_BLT_YUV888_601_FULL_RANGE (B2R2_VMX1_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX1_RGB_TO_BLT_YUV888_601_FULL_RANGE (B2R2_VMX2_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX2_RGB_TO_BLT_YUV888_601_FULL_RANGE (B2R2_VMX0_RGB_TO_YUV_601_FULL_RANGE)
+#define B2R2_VMX3_RGB_TO_BLT_YUV888_601_FULL_RANGE 0x00020080
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_RGB_TO_BLT_YUV888_601_STANDARD (B2R2_VMX1_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX1_RGB_TO_BLT_YUV888_601_STANDARD (B2R2_VMX2_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX2_RGB_TO_BLT_YUV888_601_STANDARD (B2R2_VMX0_RGB_TO_YUV_601_STANDARD)
+#define B2R2_VMX3_RGB_TO_BLT_YUV888_601_STANDARD 0x00020080
+
+/* VMX register values for BLT_YUV888 to RGB conversion */
+
+/*
+ * Note: BLT_YUV888 -> RGB values are calculated by multiplying
+ * the YUV -> RGB matrix [A], with [S] to form [A]x[S] where
+ * |0 0 1|
+ * S = |1 0 0|
+ * |0 1 0|
+ * Essentially changing the order of columns in the original
+ * matrix [A].
+ * col1 -> col3
+ * col2 -> col1
+ * col3 -> col2
+ * Values in the offset vector remain unchanged.
+ */
+/* 601 Full range conversion matrix */
+#define B2R2_VMX0_BLT_YUV888_TO_RGB_601_FULL_RANGE 0x20000121
+#define B2R2_VMX1_BLT_YUV888_TO_RGB_601_FULL_RANGE 0x201ea74c
+#define B2R2_VMX2_BLT_YUV888_TO_RGB_601_FULL_RANGE 0x2006f000
+#define B2R2_VMX3_BLT_YUV888_TO_RGB_601_FULL_RANGE (B2R2_VMX3_YUV_TO_RGB_601_FULL_RANGE)
+
+/* 601 Standard (clamped) conversion matrix */
+#define B2R2_VMX0_BLT_YUV888_TO_RGB_601_STANDARD 0x25400133
+#define B2R2_VMX1_BLT_YUV888_TO_RGB_601_STANDARD 0x255E7330
+#define B2R2_VMX2_BLT_YUV888_TO_RGB_601_STANDARD 0x25481400
+#define B2R2_VMX3_BLT_YUV888_TO_RGB_601_STANDARD (B2R2_VMX3_YUV_TO_RGB_601_FULL_RANGE)
+
+/* VMX register values for YUV to BLT_YUV888 conversion */
+#define B2R2_VMX0_YUV_TO_BLT_YUV888 0x00040000
+#define B2R2_VMX1_YUV_TO_BLT_YUV888 0x00000100
+#define B2R2_VMX2_YUV_TO_BLT_YUV888 0x20000000
+#define B2R2_VMX3_YUV_TO_BLT_YUV888 0x00000000
+
+/* VMX register values for BLT_YUV888 to YUV conversion */
+#define B2R2_VMX0_BLT_YUV888_TO_YUV 0x00000100
+#define B2R2_VMX1_BLT_YUV888_TO_YUV 0x20000000
+#define B2R2_VMX2_BLT_YUV888_TO_YUV 0x00040000
+#define B2R2_VMX3_BLT_YUV888_TO_YUV 0x00000000
+
+/* VMX register values for YVU to BLT_YUV888 conversion */
+#define B2R2_VMX0_YVU_TO_BLT_YUV888 0x00040000
+#define B2R2_VMX1_YVU_TO_BLT_YUV888 0x20000000
+#define B2R2_VMX2_YVU_TO_BLT_YUV888 0x00000100
+#define B2R2_VMX3_YVU_TO_BLT_YUV888 0x00000000
+
+/* VMX register values for BLT_YUV888 to YVU conversion */
+#define B2R2_VMX0_BLT_YUV888_TO_YVU 0x00040000
+#define B2R2_VMX1_BLT_YUV888_TO_YVU 0x20000000
+#define B2R2_VMX2_BLT_YUV888_TO_YVU 0x00000100
+#define B2R2_VMX3_BLT_YUV888_TO_YVU 0x00000000
+
+/*
+ * Internal types
+ */
+
+/*
+ * Global variables
+ */
+
+ /**
+ * VMx values for color space conversion
+ * (component swap)
+ */
+static const u32 vmx_yuv_to_blt_yuv888[] = {
+ B2R2_VMX0_YUV_TO_BLT_YUV888,
+ B2R2_VMX1_YUV_TO_BLT_YUV888,
+ B2R2_VMX2_YUV_TO_BLT_YUV888,
+ B2R2_VMX3_YUV_TO_BLT_YUV888,
+};
+
+static const u32 vmx_blt_yuv888_to_yuv[] = {
+ B2R2_VMX0_BLT_YUV888_TO_YUV,
+ B2R2_VMX1_BLT_YUV888_TO_YUV,
+ B2R2_VMX2_BLT_YUV888_TO_YUV,
+ B2R2_VMX3_BLT_YUV888_TO_YUV,
+};
+
+static const u32 vmx_yvu_to_blt_yuv888[] = {
+ B2R2_VMX0_YVU_TO_BLT_YUV888,
+ B2R2_VMX1_YVU_TO_BLT_YUV888,
+ B2R2_VMX2_YVU_TO_BLT_YUV888,
+ B2R2_VMX3_YVU_TO_BLT_YUV888,
+};
+
+static const u32 vmx_blt_yuv888_to_yvu[] = {
+ B2R2_VMX0_BLT_YUV888_TO_YVU,
+ B2R2_VMX1_BLT_YUV888_TO_YVU,
+ B2R2_VMX2_BLT_YUV888_TO_YVU,
+ B2R2_VMX3_BLT_YUV888_TO_YVU,
+};
+
+static const u32 vmx_rgb_to_bgr[] = {
+ B2R2_VMX0_RGB_TO_BGR,
+ B2R2_VMX1_RGB_TO_BGR,
+ B2R2_VMX2_RGB_TO_BGR,
+ B2R2_VMX3_RGB_TO_BGR,
+};
+
+static const u32 vmx_yvu_to_yuv[] = {
+ B2R2_VMX0_YVU_TO_YUV,
+ B2R2_VMX1_YVU_TO_YUV,
+ B2R2_VMX2_YVU_TO_YUV,
+ B2R2_VMX3_YVU_TO_YUV,
+};
+
+/**
+ * VMx values for color space conversions
+ * (standard 601 conversions)
+ */
+static const u32 vmx_rgb_to_yuv[] = {
+ B2R2_VMX0_RGB_TO_YUV_601_STANDARD,
+ B2R2_VMX1_RGB_TO_YUV_601_STANDARD,
+ B2R2_VMX2_RGB_TO_YUV_601_STANDARD,
+ B2R2_VMX3_RGB_TO_YUV_601_STANDARD,
+};
+
+static const u32 vmx_yuv_to_rgb[] = {
+ B2R2_VMX0_YUV_TO_RGB_601_STANDARD,
+ B2R2_VMX1_YUV_TO_RGB_601_STANDARD,
+ B2R2_VMX2_YUV_TO_RGB_601_STANDARD,
+ B2R2_VMX3_YUV_TO_RGB_601_STANDARD,
+};
+
+static const u32 vmx_rgb_to_blt_yuv888[] = {
+ B2R2_VMX0_RGB_TO_BLT_YUV888_601_STANDARD,
+ B2R2_VMX1_RGB_TO_BLT_YUV888_601_STANDARD,
+ B2R2_VMX2_RGB_TO_BLT_YUV888_601_STANDARD,
+ B2R2_VMX3_RGB_TO_BLT_YUV888_601_STANDARD,
+};
+
+static const u32 vmx_blt_yuv888_to_rgb[] = {
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_STANDARD,
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_STANDARD,
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_STANDARD,
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_STANDARD,
+};
+
+static const u32 vmx_rgb_to_yvu[] = {
+ B2R2_VMX0_RGB_TO_YVU_601_STANDARD,
+ B2R2_VMX1_RGB_TO_YVU_601_STANDARD,
+ B2R2_VMX2_RGB_TO_YVU_601_STANDARD,
+ B2R2_VMX3_RGB_TO_YVU_601_STANDARD,
+};
+
+static const u32 vmx_yvu_to_rgb[] = {
+ B2R2_VMX0_YVU_TO_RGB_601_STANDARD,
+ B2R2_VMX1_YVU_TO_RGB_601_STANDARD,
+ B2R2_VMX2_YVU_TO_RGB_601_STANDARD,
+ B2R2_VMX3_YVU_TO_RGB_601_STANDARD,
+};
+
+static const u32 vmx_bgr_to_yuv[] = {
+ B2R2_VMX0_BGR_TO_YUV_601_STANDARD,
+ B2R2_VMX1_BGR_TO_YUV_601_STANDARD,
+ B2R2_VMX2_BGR_TO_YUV_601_STANDARD,
+ B2R2_VMX3_BGR_TO_YUV_601_STANDARD,
+};
+
+static const u32 vmx_yuv_to_bgr[] = {
+ B2R2_VMX0_YUV_TO_BGR_601_STANDARD,
+ B2R2_VMX1_YUV_TO_BGR_601_STANDARD,
+ B2R2_VMX2_YUV_TO_BGR_601_STANDARD,
+ B2R2_VMX3_YUV_TO_BGR_601_STANDARD,
+};
+
+static const u32 vmx_bgr_to_yvu[] = {
+ B2R2_VMX0_BGR_TO_YVU_601_STANDARD,
+ B2R2_VMX1_BGR_TO_YVU_601_STANDARD,
+ B2R2_VMX2_BGR_TO_YVU_601_STANDARD,
+ B2R2_VMX3_BGR_TO_YVU_601_STANDARD,
+};
+
+static const u32 vmx_yvu_to_bgr[] = {
+ B2R2_VMX0_YVU_TO_BGR_601_STANDARD,
+ B2R2_VMX1_YVU_TO_BGR_601_STANDARD,
+ B2R2_VMX2_YVU_TO_BGR_601_STANDARD,
+ B2R2_VMX3_YVU_TO_BGR_601_STANDARD,
+};
+
+/**
+ * VMx values for color space conversions
+ * (full range conversions)
+ */
+
+static const u32 vmx_full_rgb_to_yuv[] = {
+ B2R2_VMX0_RGB_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX1_RGB_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX2_RGB_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX3_RGB_TO_YUV_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_yuv_to_rgb[] = {
+ B2R2_VMX0_YUV_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX1_YUV_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX2_YUV_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX3_YUV_TO_RGB_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_rgb_to_blt_yuv888[] = {
+ B2R2_VMX0_RGB_TO_BLT_YUV888_601_FULL_RANGE,
+ B2R2_VMX1_RGB_TO_BLT_YUV888_601_FULL_RANGE,
+ B2R2_VMX2_RGB_TO_BLT_YUV888_601_FULL_RANGE,
+ B2R2_VMX3_RGB_TO_BLT_YUV888_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_blt_yuv888_to_rgb[] = {
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_yvu_to_rgb[] = {
+ B2R2_VMX0_YVU_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX1_YVU_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX2_YVU_TO_RGB_601_FULL_RANGE,
+ B2R2_VMX3_YVU_TO_RGB_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_rgb_to_yvu[] = {
+ B2R2_VMX0_RGB_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX1_RGB_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX2_RGB_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX3_RGB_TO_YVU_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_bgr_to_yuv[] = {
+ B2R2_VMX0_BGR_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX1_BGR_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX2_BGR_TO_YUV_601_FULL_RANGE,
+ B2R2_VMX3_BGR_TO_YUV_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_yuv_to_bgr[] = {
+ B2R2_VMX0_YUV_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX1_YUV_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX2_YUV_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX3_YUV_TO_BGR_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_bgr_to_yvu[] = {
+ B2R2_VMX0_BGR_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX1_BGR_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX2_BGR_TO_YVU_601_FULL_RANGE,
+ B2R2_VMX3_BGR_TO_YVU_601_FULL_RANGE,
+};
+
+static const u32 vmx_full_yvu_to_bgr[] = {
+ B2R2_VMX0_YVU_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX1_YVU_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX2_YVU_TO_BGR_601_FULL_RANGE,
+ B2R2_VMX3_YVU_TO_BGR_601_FULL_RANGE,
+};
+
+/*
+ * Forward declaration of private functions
+ */
+
+/*
+ * Public functions
+ */
+
+/**
+ * Setup input versatile matrix for color space conversion
+ */
+int b2r2_setup_ivmx(struct b2r2_node *node, enum b2r2_color_conversion cc)
+{
+ const u32 *vmx = NULL;
+
+ if (b2r2_get_vmx(cc, &vmx) < 0 || vmx == NULL)
+ return -1;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+
+ node->node.GROUP15.B2R2_VMX0 = vmx[0];
+ node->node.GROUP15.B2R2_VMX1 = vmx[1];
+ node->node.GROUP15.B2R2_VMX2 = vmx[2];
+ node->node.GROUP15.B2R2_VMX3 = vmx[3];
+
+ return 0;
+}
+
+/**
+ * Setup output versatile matrix for color space conversion
+ */
+int b2r2_setup_ovmx(struct b2r2_node *node, enum b2r2_color_conversion cc)
+{
+ const u32 *vmx = NULL;
+
+ if (b2r2_get_vmx(cc, &vmx) < 0 || vmx == NULL)
+ return -1;
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_OVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_OVMX;
+
+ node->node.GROUP16.B2R2_VMX0 = vmx[0];
+ node->node.GROUP16.B2R2_VMX1 = vmx[1];
+ node->node.GROUP16.B2R2_VMX2 = vmx[2];
+ node->node.GROUP16.B2R2_VMX3 = vmx[3];
+
+ return 0;
+}
+
+enum b2r2_color_conversion b2r2_get_color_conversion(enum b2r2_blt_fmt src_fmt,
+ enum b2r2_blt_fmt dst_fmt, bool fullrange)
+{
+ if (b2r2_is_rgb_fmt(src_fmt)) {
+ if (b2r2_is_yvu_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_RGB_TO_YVU_FULL :
+ B2R2_CC_RGB_TO_YVU;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ /*
+ * (A)YUV/VUY(A) formats differ only in component
+ * order. This is handled by the endianness bit
+ * in B2R2_STY/TTY registers when src/target are set.
+ */
+ return fullrange ? B2R2_CC_RGB_TO_BLT_YUV888_FULL :
+ B2R2_CC_RGB_TO_BLT_YUV888;
+ else if (b2r2_is_yuv_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_RGB_TO_YUV_FULL :
+ B2R2_CC_RGB_TO_YUV;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return B2R2_CC_RGB_TO_BGR;
+ } else if (b2r2_is_yvu_fmt(src_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_YVU_FULL_TO_RGB :
+ B2R2_CC_YVU_TO_RGB;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_YVU_FULL_TO_BGR :
+ B2R2_CC_YVU_TO_BGR;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return B2R2_CC_YVU_TO_BLT_YUV888;
+ else if (b2r2_is_yuv_fmt(dst_fmt) &&
+ !b2r2_is_yvu_fmt(dst_fmt))
+ return B2R2_CC_YVU_TO_YUV;
+ } else if (src_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ src_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ src_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ src_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) {
+ /*
+ * (A)YUV/VUY(A) formats differ only in component
+ * order. This is handled by the endianness bit
+ * in B2R2_STY/TTY registers when src/target are set.
+ */
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_BLT_YUV888_FULL_TO_RGB :
+ B2R2_CC_BLT_YUV888_TO_RGB;
+ else if (b2r2_is_yvu_fmt(dst_fmt))
+ return B2R2_CC_BLT_YUV888_TO_YVU;
+ else if (b2r2_is_yuv_fmt(dst_fmt)) {
+ switch (dst_fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return B2R2_CC_NOTHING;
+ default:
+ return B2R2_CC_BLT_YUV888_TO_YUV;
+ }
+ }
+ } else if (b2r2_is_yuv_fmt(src_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_YUV_FULL_TO_RGB :
+ B2R2_CC_YUV_TO_RGB;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_YUV_FULL_TO_BGR :
+ B2R2_CC_YUV_TO_BGR;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return B2R2_CC_YUV_TO_BLT_YUV888;
+ else if (b2r2_is_yvu_fmt(dst_fmt))
+ return B2R2_CC_YVU_TO_YUV;
+ } else if (b2r2_is_bgr_fmt(src_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return B2R2_CC_RGB_TO_BGR;
+ else if (b2r2_is_yvu_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_BGR_TO_YVU_FULL :
+ B2R2_CC_BGR_TO_YVU;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ BUG_ON(1);
+ else if (b2r2_is_yuv_fmt(dst_fmt))
+ return fullrange ? B2R2_CC_BGR_TO_YUV_FULL :
+ B2R2_CC_BGR_TO_YUV;
+ }
+
+ return B2R2_CC_NOTHING;
+}
+
+int b2r2_get_vmx(enum b2r2_color_conversion cc, const u32 **vmx)
+{
+ if (vmx == NULL)
+ return -1;
+
+ switch (cc) {
+ case B2R2_CC_RGB_TO_BGR:
+ *vmx = &vmx_rgb_to_bgr[0];
+ break;
+ case B2R2_CC_BLT_YUV888_TO_YVU:
+ *vmx = &vmx_blt_yuv888_to_yvu[0];
+ break;
+ case B2R2_CC_BLT_YUV888_TO_YUV:
+ *vmx = &vmx_blt_yuv888_to_yuv[0];
+ break;
+ case B2R2_CC_YVU_TO_YUV:
+ *vmx = &vmx_yvu_to_yuv[0];
+ break;
+ case B2R2_CC_YVU_TO_BLT_YUV888:
+ *vmx = &vmx_yvu_to_blt_yuv888[0];
+ break;
+ case B2R2_CC_YUV_TO_BLT_YUV888:
+ *vmx = &vmx_yuv_to_blt_yuv888[0];
+ break;
+ case B2R2_CC_RGB_TO_YUV:
+ *vmx = &vmx_rgb_to_yuv[0];
+ break;
+ case B2R2_CC_RGB_TO_YUV_FULL:
+ *vmx = &vmx_full_rgb_to_yuv[0];
+ break;
+ case B2R2_CC_RGB_TO_YVU:
+ *vmx = &vmx_rgb_to_yvu[0];
+ break;
+ case B2R2_CC_RGB_TO_YVU_FULL:
+ *vmx = &vmx_full_rgb_to_yvu[0];
+ break;
+ case B2R2_CC_RGB_TO_BLT_YUV888:
+ *vmx = &vmx_rgb_to_blt_yuv888[0];
+ break;
+ case B2R2_CC_RGB_TO_BLT_YUV888_FULL:
+ *vmx = &vmx_full_rgb_to_blt_yuv888[0];
+ break;
+ case B2R2_CC_BGR_TO_YVU:
+ *vmx = &vmx_bgr_to_yvu[0];
+ break;
+ case B2R2_CC_BGR_TO_YVU_FULL:
+ *vmx = &vmx_full_bgr_to_yvu[0];
+ break;
+ case B2R2_CC_BGR_TO_YUV:
+ *vmx = &vmx_bgr_to_yuv[0];
+ break;
+ case B2R2_CC_BGR_TO_YUV_FULL:
+ *vmx = &vmx_full_bgr_to_yuv[0];
+ break;
+ case B2R2_CC_YUV_TO_RGB:
+ *vmx = &vmx_yuv_to_rgb[0];
+ break;
+ case B2R2_CC_YUV_FULL_TO_RGB:
+ *vmx = &vmx_full_yuv_to_rgb[0];
+ break;
+ case B2R2_CC_YUV_TO_BGR:
+ *vmx = &vmx_yuv_to_bgr[0];
+ break;
+ case B2R2_CC_YUV_FULL_TO_BGR:
+ *vmx = &vmx_full_yuv_to_bgr[0];
+ break;
+ case B2R2_CC_YVU_TO_RGB:
+ *vmx = &vmx_yvu_to_rgb[0];
+ break;
+ case B2R2_CC_YVU_FULL_TO_RGB:
+ *vmx = &vmx_full_yvu_to_rgb[0];
+ break;
+ case B2R2_CC_YVU_TO_BGR:
+ *vmx = &vmx_yvu_to_bgr[0];
+ break;
+ case B2R2_CC_YVU_FULL_TO_BGR:
+ *vmx = &vmx_full_yvu_to_bgr[0];
+ break;
+ case B2R2_CC_BLT_YUV888_TO_RGB:
+ *vmx = &vmx_blt_yuv888_to_rgb[0];
+ break;
+ case B2R2_CC_BLT_YUV888_FULL_TO_RGB:
+ *vmx = &vmx_full_blt_yuv888_to_rgb[0];
+ break;
+ case B2R2_CC_NOTHING:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
diff --git a/drivers/video/b2r2/b2r2_hw_convert.h b/drivers/video/b2r2/b2r2_hw_convert.h
new file mode 100644
index 00000000000..e173e898e44
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_hw_convert.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * ST-Ericsson B2R2 hw color conversion definitions
+ *
+ * Author: Jorgen Nilsson <jorgen.nilsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef B2R2_HW_CONVERT_H__
+#define B2R2_HW_CONVERT_H__
+
+#include "b2r2_internal.h"
+
+enum b2r2_color_conversion {
+ B2R2_CC_NOTHING = 0,
+ B2R2_CC_RGB_TO_BGR,
+ B2R2_CC_BLT_YUV888_TO_YVU,
+ B2R2_CC_BLT_YUV888_TO_YUV,
+ B2R2_CC_YUV_TO_BLT_YUV888,
+ B2R2_CC_YVU_TO_YUV,
+ B2R2_CC_YVU_TO_BLT_YUV888,
+ B2R2_CC_RGB_TO_YUV,
+ B2R2_CC_RGB_TO_YUV_FULL,
+ B2R2_CC_RGB_TO_YVU,
+ B2R2_CC_RGB_TO_YVU_FULL,
+ B2R2_CC_RGB_TO_BLT_YUV888,
+ B2R2_CC_RGB_TO_BLT_YUV888_FULL,
+ B2R2_CC_BGR_TO_YVU,
+ B2R2_CC_BGR_TO_YVU_FULL,
+ B2R2_CC_BGR_TO_YUV,
+ B2R2_CC_BGR_TO_YUV_FULL,
+ B2R2_CC_YUV_TO_RGB,
+ B2R2_CC_YUV_FULL_TO_RGB,
+ B2R2_CC_YUV_TO_BGR,
+ B2R2_CC_YUV_FULL_TO_BGR,
+ B2R2_CC_YVU_TO_RGB,
+ B2R2_CC_YVU_FULL_TO_RGB,
+ B2R2_CC_YVU_TO_BGR,
+ B2R2_CC_YVU_FULL_TO_BGR,
+ B2R2_CC_BLT_YUV888_TO_RGB,
+ B2R2_CC_BLT_YUV888_FULL_TO_RGB,
+};
+
+int b2r2_setup_ivmx(struct b2r2_node *node, enum b2r2_color_conversion cc);
+int b2r2_setup_ovmx(struct b2r2_node *node, enum b2r2_color_conversion cc);
+enum b2r2_color_conversion b2r2_get_color_conversion(enum b2r2_blt_fmt src_fmt,
+ enum b2r2_blt_fmt dst_fmt, bool fullrange);
+int b2r2_get_vmx(enum b2r2_color_conversion cc, const u32 **vmx);
+
+#endif /* B2R2_HW_CONVERT_H__ */
diff --git a/drivers/video/b2r2/b2r2_input_validation.c b/drivers/video/b2r2/b2r2_input_validation.c
new file mode 100644
index 00000000000..c8eb2f7b025
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_input_validation.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "b2r2_internal.h"
+#include "b2r2_input_validation.h"
+#include "b2r2_debug.h"
+#include "b2r2_utils.h"
+
+#include <video/b2r2_blt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+
+static bool is_valid_format(enum b2r2_blt_fmt fmt);
+static bool is_valid_bg_format(enum b2r2_blt_fmt fmt);
+
+static bool is_valid_pitch_for_fmt(struct device *dev,
+ u32 pitch, s32 width, enum b2r2_blt_fmt fmt);
+
+static bool is_aligned_width_for_fmt(s32 width, enum b2r2_blt_fmt fmt);
+static s32 width_2_complete_width(s32 width, enum b2r2_blt_fmt fmt);
+static bool is_complete_width_for_fmt(s32 width, enum b2r2_blt_fmt fmt);
+static bool is_valid_height_for_fmt(s32 height, enum b2r2_blt_fmt fmt);
+
+static bool validate_img(struct device *dev,
+ struct b2r2_blt_img *img);
+static bool validate_rect(struct device *dev,
+ struct b2r2_blt_rect *rect);
+
+
+static bool is_valid_format(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool is_valid_bg_format(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+
+static bool is_valid_pitch_for_fmt(struct device *dev,
+ u32 pitch, s32 width, enum b2r2_blt_fmt fmt)
+{
+ s32 complete_width;
+ u32 pitch_derived_from_width;
+
+ complete_width = width_2_complete_width(width, fmt);
+
+ pitch_derived_from_width = b2r2_calc_pitch_from_width(dev,
+ complete_width, fmt);
+
+ if (pitch < pitch_derived_from_width)
+ return false;
+
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ if (!b2r2_is_aligned(pitch, 2))
+ return false;
+
+ break;
+
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ if (!b2r2_is_aligned(pitch, 4))
+ return false;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+
+static bool is_aligned_width_for_fmt(s32 width, enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ if (!b2r2_is_aligned(width, 4))
+ return false;
+
+ break;
+
+ case B2R2_BLT_FMT_1_BIT_A1:
+ if (!b2r2_is_aligned(width, 8))
+ return false;
+
+ break;
+
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ if (!b2r2_is_aligned(width, 2))
+ return false;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static s32 width_2_complete_width(s32 width, enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return b2r2_align_up(width, 2);
+
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return b2r2_align_up(width, 16);
+
+ default:
+ return width;
+ }
+}
+
+static bool is_complete_width_for_fmt(s32 width, enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ if (!b2r2_is_aligned(width, 2))
+ return false;
+
+ break;
+
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ if (!b2r2_is_aligned(width, 16))
+ return false;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool is_valid_height_for_fmt(s32 height, enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ if (!b2r2_is_aligned(height, 2))
+ return false;
+
+ break;
+
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ if (!b2r2_is_aligned(height, 16))
+ return false;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool validate_img(struct device *dev,
+ struct b2r2_blt_img *img)
+{
+ /*
+ * So that we always can do width * height * bpp without overflowing a
+ * 32 bit signed integer. isqrt(s32_max / max_bpp) was used to
+ * calculate the value.
+ */
+ static const s32 max_img_width_height = 8191;
+
+ s32 img_size;
+
+ if (!is_valid_format(img->fmt)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!is_valid_format(img->fmt)\n");
+ return false;
+ }
+
+ if (img->width < 0 || img->width > max_img_width_height ||
+ img->height < 0 || img->height > max_img_width_height) {
+ b2r2_log_info(dev, "Validation Error: "
+ "img->width < 0 || "
+ "img->width > max_img_width_height || "
+ "img->height < 0 || "
+ "img->height > max_img_width_height\n");
+ return false;
+ }
+
+ if (b2r2_is_mb_fmt(img->fmt)) {
+ if (!is_complete_width_for_fmt(img->width, img->fmt)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!is_complete_width_for_fmt(img->width,"
+ " img->fmt)\n");
+ return false;
+ }
+ } else {
+ if (0 == img->pitch &&
+ (!is_aligned_width_for_fmt(img->width, img->fmt) ||
+ !is_complete_width_for_fmt(img->width, img->fmt))) {
+ b2r2_log_info(dev,
+ "Validation Error: "
+ "0 == img->pitch && "
+ "(!is_aligned_width_for_fmt(img->width,"
+ " img->fmt) || "
+ "!is_complete_width_for_fmt(img->width,"
+ " img->fmt))\n");
+ return false;
+ }
+
+ if (img->pitch != 0 &&
+ !is_valid_pitch_for_fmt(dev, img->pitch, img->width,
+ img->fmt)) {
+ b2r2_log_info(dev,
+ "Validation Error: "
+ "img->pitch != 0 && "
+ "!is_valid_pitch_for_fmt(dev, "
+ "img->pitch, img->width, img->fmt)\n");
+ return false;
+ }
+ }
+
+ if (!is_valid_height_for_fmt(img->width, img->fmt)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!is_valid_height_for_fmt(img->width, img->fmt)\n");
+ return false;
+ }
+
+ img_size = b2r2_get_img_size(dev, img);
+
+ /*
+ * To keep the entire image inside s32 range.
+ */
+ if ((B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET == img->buf.type ||
+ B2R2_BLT_PTR_FD_OFFSET == img->buf.type) &&
+ img->buf.offset > (u32)b2r2_s32_max - (u32)img_size) {
+ b2r2_log_info(dev, "Validation Error: "
+ "(B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET == "
+ "img->buf.type || B2R2_BLT_PTR_FD_OFFSET == "
+ "img->buf.type) && img->buf.offset > "
+ "(u32)B2R2_MAX_S32 - (u32)img_size\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool validate_rect(struct device *dev,
+ struct b2r2_blt_rect *rect)
+{
+ if (rect->width < 0 || rect->height < 0) {
+ b2r2_log_info(dev, "Validation Error: "
+ "rect->width < 0 || rect->height < 0\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool b2r2_validate_user_req(struct device *dev,
+ struct b2r2_blt_req *req)
+{
+ bool is_src_img_used;
+ bool is_bg_img_used;
+ bool is_src_mask_used;
+ bool is_dst_clip_rect_used;
+
+ if (req->size != sizeof(struct b2r2_blt_req)) {
+ b2r2_log_err(dev, "Validation Error: "
+ "req->size != sizeof(struct b2r2_blt_req)\n");
+ return false;
+ }
+
+ is_src_img_used = !(req->flags & B2R2_BLT_FLAG_SOURCE_FILL ||
+ req->flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW);
+ is_bg_img_used = (req->flags & B2R2_BLT_FLAG_BG_BLEND);
+ is_src_mask_used = req->flags & B2R2_BLT_FLAG_SOURCE_MASK;
+ is_dst_clip_rect_used = req->flags & B2R2_BLT_FLAG_DESTINATION_CLIP;
+
+ if (is_src_img_used || is_src_mask_used) {
+ if (!validate_rect(dev, &req->src_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_rect(dev, &req->src_rect)\n");
+ return false;
+ }
+ }
+
+ if (!validate_rect(dev, &req->dst_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_rect(dev, &req->dst_rect)\n");
+ return false;
+ }
+
+ if (is_bg_img_used) {
+ if (!validate_rect(dev, &req->bg_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_rect(dev, &req->bg_rect)\n");
+ return false;
+ }
+ }
+
+ if (is_dst_clip_rect_used) {
+ if (!validate_rect(dev, &req->dst_clip_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_rect(dev, &req->dst_clip_rect)\n");
+ return false;
+ }
+ }
+
+ if (is_src_img_used) {
+ struct b2r2_blt_rect src_img_bounding_rect;
+
+ if (!validate_img(dev, &req->src_img)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_img(dev, &req->src_img)\n");
+ return false;
+ }
+
+ b2r2_get_img_bounding_rect(&req->src_img,
+ &src_img_bounding_rect);
+ if (!b2r2_is_rect_inside_rect(&req->src_rect,
+ &src_img_bounding_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!b2r2_is_rect_inside_rect(&req->src_rect, "
+ "&src_img_bounding_rect)\n");
+ return false;
+ }
+ }
+
+ if (is_bg_img_used) {
+ struct b2r2_blt_rect bg_img_bounding_rect;
+
+ if (!validate_img(dev, &req->bg_img)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_img(dev, &req->bg_img)\n");
+ return false;
+ }
+
+ if (!is_valid_bg_format(req->bg_img.fmt)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!is_valid_bg_format(req->bg_img->fmt)\n");
+ return false;
+ }
+
+ b2r2_get_img_bounding_rect(&req->bg_img,
+ &bg_img_bounding_rect);
+ if (!b2r2_is_rect_inside_rect(&req->bg_rect,
+ &bg_img_bounding_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!b2r2_is_rect_inside_rect(&req->bg_rect, "
+ "&bg_img_bounding_rect)\n");
+ return false;
+ }
+ }
+
+ if (is_src_mask_used) {
+ struct b2r2_blt_rect src_mask_bounding_rect;
+
+ if (!validate_img(dev, &req->src_mask)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_img(dev, &req->src_mask)\n");
+ return false;
+ }
+
+ b2r2_get_img_bounding_rect(&req->src_mask,
+ &src_mask_bounding_rect);
+ if (!b2r2_is_rect_inside_rect(&req->src_rect,
+ &src_mask_bounding_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!b2r2_is_rect_inside_rect(&req->src_rect, "
+ "&src_mask_bounding_rect)\n");
+ return false;
+ }
+ }
+
+ if (!validate_img(dev, &req->dst_img)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!validate_img(dev, &req->dst_img)\n");
+ return false;
+ }
+
+ if (is_bg_img_used) {
+ if (!b2r2_is_rect_gte_rect(&req->bg_rect, &req->dst_rect)) {
+ b2r2_log_info(dev, "Validation Error: "
+ "!b2r2_is_rect_gte_rect(&req->bg_rect, "
+ "&req->dst_rect)\n");
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/drivers/video/b2r2/b2r2_input_validation.h b/drivers/video/b2r2/b2r2_input_validation.h
new file mode 100644
index 00000000000..25f022a45ab
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_input_validation.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_INPUT_VALIDATION_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_INPUT_VALIDATION_H_
+
+#include <video/b2r2_blt.h>
+
+#include "b2r2_internal.h"
+
+bool b2r2_validate_user_req(struct device *dev,
+ struct b2r2_blt_req *req);
+
+#endif
diff --git a/drivers/video/b2r2/b2r2_internal.h b/drivers/video/b2r2/b2r2_internal.h
new file mode 100644
index 00000000000..329d644e5e1
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_internal.h
@@ -0,0 +1,610 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 internal definitions
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_INTERNAL_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_INTERNAL_H_
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <video/b2r2_blt.h>
+
+#include "b2r2_global.h"
+#include "b2r2_hw.h"
+
+/**
+ * B2R2_MAX_NBR_DEVICES - The maximum number of B2R2s handled
+ */
+#define B2R2_MAX_NBR_DEVICES 2
+
+/* The maximum possible number of temporary buffers needed */
+#define MAX_TMP_BUFS_NEEDED 2
+
+/* Size of the color look-up table */
+#define CLUT_SIZE 1024
+
+/* The defined bits of the Interrupt Status Register */
+#define B2R2_ITS_MASK 0x0FFFF0FF
+
+/**
+ * b2r2_op_type - the type of B2R2 operation to configure
+ */
+enum b2r2_op_type {
+ B2R2_DIRECT_COPY,
+ B2R2_DIRECT_FILL,
+ B2R2_COPY,
+ B2R2_FILL,
+ B2R2_SCALE,
+ B2R2_ROTATE,
+ B2R2_SCALE_AND_ROTATE,
+ B2R2_FLIP,
+};
+
+/**
+ * b2r2_fmt_type - the type of buffer for a given format
+ */
+enum b2r2_fmt_type {
+ B2R2_FMT_TYPE_RASTER,
+ B2R2_FMT_TYPE_SEMI_PLANAR,
+ B2R2_FMT_TYPE_PLANAR,
+};
+
+/**
+ * b2r2_fmt_conv - the type of format conversion to do
+ */
+enum b2r2_fmt_conv {
+ B2R2_FMT_CONV_NONE,
+ B2R2_FMT_CONV_RGB_TO_YUV,
+ B2R2_FMT_CONV_YUV_TO_RGB,
+ B2R2_FMT_CONV_YUV_TO_YUV,
+ B2R2_FMT_CONV_RGB_TO_BGR,
+ B2R2_FMT_CONV_BGR_TO_RGB,
+ B2R2_FMT_CONV_YUV_TO_BGR,
+ B2R2_FMT_CONV_BGR_TO_YUV,
+};
+
+/**
+ * enum b2r2_core_queue - Indicates the B2R2 queue that the job belongs to
+ *
+ * @B2R2_CORE_QUEUE_AQ1: Application queue 1
+ * @B2R2_CORE_QUEUE_AQ2: Application queue 2
+ * @B2R2_CORE_QUEUE_AQ3: Application queue 3
+ * @B2R2_CORE_QUEUE_AQ4: Application queue 4
+ * @B2R2_CORE_QUEUE_CQ1: Composition queue 1
+ * @B2R2_CORE_QUEUE_CQ2: Composition queue 2
+ * @B2R2_CORE_QUEUE_NO_OF: Number of queues
+ */
+enum b2r2_core_queue {
+ B2R2_CORE_QUEUE_AQ1 = 0,
+ B2R2_CORE_QUEUE_AQ2,
+ B2R2_CORE_QUEUE_AQ3,
+ B2R2_CORE_QUEUE_AQ4,
+ B2R2_CORE_QUEUE_CQ1,
+ B2R2_CORE_QUEUE_CQ2,
+ B2R2_CORE_QUEUE_NO_OF,
+};
+
+#define B2R2_NUM_APPLICATIONS_QUEUES 4
+
+/**
+ * enum b2r2_core_job_state - Indicates the current state of the job
+ *
+ * @B2R2_CORE_JOB_IDLE: Never queued
+ * @B2R2_CORE_JOB_QUEUED: In queue but not started yet
+ * @B2R2_CORE_JOB_RUNNING: Running, executed by B2R2
+ * @B2R2_CORE_JOB_DONE: Completed
+ * @B2R2_CORE_JOB_CANCELED: Canceled
+ */
+enum b2r2_core_job_state {
+ B2R2_CORE_JOB_IDLE = 0,
+ B2R2_CORE_JOB_QUEUED,
+ B2R2_CORE_JOB_RUNNING,
+ B2R2_CORE_JOB_DONE,
+ B2R2_CORE_JOB_CANCELED,
+};
+
+/**
+ * b2r2_work_buf - specification for a temporary work buffer
+ *
+ * @size - the size of the buffer (set by b2r2_node_split)
+ * @phys_addr - the physical address of the buffer (set by b2r2_blt_main)
+ */
+struct b2r2_work_buf {
+ u32 size;
+ u32 phys_addr;
+ void *virt_addr;
+ u32 mem_handle;
+};
+
+struct tmp_buf {
+ struct b2r2_work_buf buf;
+ bool in_use;
+};
+
+/**
+ * struct b2r2_control_instance - Represents the B2R2 instance
+ * (one per open and blitter core)
+ *
+ * @lock: Lock to protect the instance
+ * @control_id: The b2r2 core core control identifier
+ * @control: The b2r2 core control entity
+ *
+ * @report_list: Ready requests that should be reported,
+ * @report_list_waitq: Wait queue for report list
+ * @no_of_active_requests: Number of requests added but not reported
+ * in callback.
+ * @synching: true if any client is waiting for b2r2_blt_synch(0)
+ * @synch_done_waitq: Wait queue to handle synching on request_id 0
+ */
+struct b2r2_control_instance {
+ struct mutex lock;
+ int control_id;
+ struct b2r2_control *control;
+
+ /* Requests to be reported */
+ struct list_head report_list;
+ wait_queue_head_t report_list_waitq;
+
+ /* Below for synching */
+ u32 no_of_active_requests;
+ bool synching;
+ wait_queue_head_t synch_done_waitq;
+};
+
+/**
+ * struct b2r2_node - Represents a B2R2 node with reqister values, executed
+ * by B2R2. Should be allocated non-cached.
+ *
+ * @next: Next node
+ * @physical_address: Physical address to be given to B2R2
+ * (physical address of "node" member below)
+ * @node: The B2R2 node with register settings. This is the data
+ * that B2R2 will use.
+ *
+ */
+struct b2r2_node {
+ struct b2r2_node *next;
+ u32 physical_address;
+
+ int src_tmp_index;
+ int dst_tmp_index;
+
+ int src_index;
+
+ /* B2R2 regs comes here */
+ struct b2r2_link_list node;
+};
+
+/**
+ * struct b2r2_resolved_buf - Contains calculated information about
+ * image buffers.
+ *
+ * @physical_address: Physical address of the buffer
+ * @virtual_address: Virtual address of the buffer
+ * @is_pmem: true if buffer is from pmem
+ * @hwmem_session: Hwmem session
+ * @hwmem_alloc: Hwmem alloc
+ * @filep: File pointer of mapped file (like pmem device, frame buffer device)
+ * @file_physical_start: Physical address of file start
+ * @file_virtual_start: Virtual address of file start
+ * @file_len: File len
+ *
+ */
+struct b2r2_resolved_buf {
+ u32 physical_address;
+ void *virtual_address;
+ bool is_pmem;
+ struct hwmem_alloc *hwmem_alloc;
+ /* Data for validation below */
+ struct file *filep;
+ u32 file_physical_start;
+ u32 file_virtual_start;
+ u32 file_len;
+};
+
+/**
+ * b2r2_node_split_buf - information about a source or destination buffer
+ *
+ * @addr - the physical base address
+ * @chroma_addr - the physical address of the chroma plane
+ * @chroma_cr_addr - the physical address of the Cr chroma plane
+ * @fmt - the buffer format
+ * @fmt_type - the buffer format type
+ * @rect - the rectangle of the buffer to use
+ * @color - the color value to use is case of a fill operation
+ * @pitch - the pixmap byte pitch
+ * @height - the pixmap height
+ * @alpha_range - the alpha range of the buffer (0-128 or 0-255)
+ * @hso - the horizontal scan order
+ * @vso - the vertical scan order
+ * @endian - the endianess of the buffer
+ * @plane_selection - the plane to write if buffer is planar or semi-planar
+ */
+struct b2r2_node_split_buf {
+ u32 addr;
+ u32 chroma_addr;
+ u32 chroma_cr_addr;
+
+ enum b2r2_blt_fmt fmt;
+ enum b2r2_fmt_type type;
+
+ struct b2r2_blt_rect rect;
+ struct b2r2_blt_rect win;
+
+ s32 dx;
+ s32 dy;
+
+ u32 color;
+ u16 pitch;
+ u16 width;
+ u16 height;
+
+ enum b2r2_ty alpha_range;
+ enum b2r2_ty hso;
+ enum b2r2_ty vso;
+ enum b2r2_ty endian;
+ enum b2r2_tty dither;
+
+ /* Plane selection (used when writing to a multibuffer format) */
+ enum b2r2_tty plane_selection;
+
+ /* Chroma plane selection (used when writing planar formats) */
+ enum b2r2_tty chroma_selection;
+
+ int tmp_buf_index;
+};
+
+/**
+ * b2r2_node_split_job - an instance of a node split job
+ *
+ * @type - the type of operation
+ * @ivmx - the ivmx matrix to use for color conversion
+ * @blend - determines if blending is enabled
+ * @clip - determines if destination clipping is enabled
+ * @rotation - determines if rotation is requested
+ * @fullrange - determines YUV<->RGB conversion matrix (iVMx)
+ * @swap_fg_bg - determines if FG and BG should be swapped when blending
+ * @flags - the flags passed in the blt request
+ * @flag_param - parameter required by certain flags,
+ * e.g. color for source color keying.
+ * @transform - the transforms passed in the blt request
+ * @global_alpha - the global alpha
+ * @clip_rect - the clipping rectangle to use
+ * @horiz_rescale - determmines if horizontal rescaling is enabled
+ * @horiz_sf - the horizontal scale factor
+ * @vert_rescale - determines if vertical rescale is enabled
+ * @vert_sf - the vertical scale factor
+ * @src - the incoming source buffer
+ * @bg - the incoming background buffer
+ * @dst - the outgoing destination buffer
+ * @work_bufs - work buffer specifications
+ * @tmp_bufs - temporary buffers
+ * @buf_count - the number of temporary buffers used for the job
+ * @node_count - the number of nodes used for the job
+ * @max_buf_size - the maximum size of temporary buffers
+ * @nbr_rows - the number of tile rows in the blit operation
+ * @nbr_cols - the number of time columns in the blit operation
+ */
+struct b2r2_node_split_job {
+ enum b2r2_op_type type;
+
+ const u32 *ivmx;
+
+ bool blend;
+ bool clip;
+ bool rotation;
+ bool fullrange;
+
+ bool swap_fg_bg;
+
+ u32 flags;
+ u32 flag_param;
+ u32 transform;
+ u32 global_alpha;
+
+ struct b2r2_blt_rect clip_rect;
+
+ bool h_rescale;
+ u16 h_rsf;
+
+ bool v_rescale;
+ u16 v_rsf;
+
+ struct b2r2_node_split_buf src;
+ struct b2r2_node_split_buf bg;
+ struct b2r2_node_split_buf dst;
+
+ struct b2r2_work_buf work_bufs[MAX_TMP_BUFS_NEEDED];
+ struct b2r2_node_split_buf tmp_bufs[MAX_TMP_BUFS_NEEDED];
+
+ u32 buf_count;
+ u32 node_count;
+ u32 max_buf_size;
+};
+
+/**
+ * struct b2r2_core_job - Represents a B2R2 core job
+ *
+ * @start_sentinel: Memory overwrite guard
+ *
+ * @tag: Client value. Used by b2r2_core_job_find_first_with_tag().
+ * @prio: Job priority, from -19 up to 20. Mapped to the
+ * B2R2 application queues. Filled in by the client.
+ * @first_node_address: Physical address of the first node. Filled
+ * in by the client.
+ * @last_node_address: Physical address of the last node. Filled
+ * in by the client.
+ *
+ * @callback: Function that will be called when the job is done.
+ * @acquire_resources: Function that allocates the resources needed
+ * to execute the job (i.e. SRAM alloc). Must not
+ * sleep if atomic, should fail with negative error code
+ * if resources not available.
+ * @release_resources: Function that releases the resources previously
+ * allocated by acquire_resources (i.e. SRAM alloc).
+ * @release: Function that will be called when the reference count reaches
+ * zero.
+ *
+ * @job_id: Unique id for this job, assigned by B2R2 core
+ * @job_state: The current state of the job
+ * @jiffies: Number of jiffies needed for this request
+ *
+ * @list: List entry element for internal list management
+ * @event: Wait queue event to wait for job done
+ * @work: Work queue structure, for callback implementation
+ *
+ * @queue: The queue that this job shall be submitted to
+ * @control: B2R2 Queue control
+ * @pace_control: For composition queue only
+ * @interrupt_context: Context for interrupt
+ * @hw_start_time: The point when the b2r2 HW queue is activated for this job
+ * @nsec_active_in_hw: Time spent on the b2r2 HW queue for this job
+ *
+ * @end_sentinel: Memory overwrite guard
+ */
+struct b2r2_core_job {
+ u32 start_sentinel;
+
+ /* Data to be filled in by client */
+ int tag;
+ int data;
+ int prio;
+ u32 first_node_address;
+ u32 last_node_address;
+ void (*callback)(struct b2r2_core_job *);
+ int (*acquire_resources)(struct b2r2_core_job *,
+ bool atomic);
+ void (*release_resources)(struct b2r2_core_job *,
+ bool atomic);
+ void (*release)(struct b2r2_core_job *);
+
+ /* Output data, do not modify */
+ int job_id;
+ enum b2r2_core_job_state job_state;
+ unsigned long jiffies;
+
+ /* Data below is internal to b2r2_core, do not modify */
+
+ /* Reference counting */
+ u32 ref_count;
+
+ /* Internal data */
+ struct list_head list;
+ wait_queue_head_t event;
+ struct work_struct work;
+
+ /* B2R2 HW data */
+ enum b2r2_core_queue queue;
+ u32 control;
+ u32 pace_control;
+ u32 interrupt_context;
+
+ /* Timing data */
+ u32 hw_start_time;
+ s32 nsec_active_in_hw;
+
+ u32 end_sentinel;
+};
+
+/**
+ * struct b2r2_blt_request - Represents one B2R2 blit request
+ *
+ * @instance: Back pointer to the instance structure
+ * @list: List item to keep track of requests per instance
+ * @user_req: The request received from userspace
+ * @job: The administration structure for the B2R2 job,
+ * consisting of one or more nodes
+ * @node_split_job: The administration structure for the B2R2 node split job
+ * @first_node: Pointer to the first B2R2 node
+ * @request_id: Request id for this job
+ * @core_mask: Bit mask with the cores doing part of the job
+ * @node_split_handle: Handle of the node split
+ * @src_resolved: Calculated info about the source buffer
+ * @src_mask_resolved: Calculated info about the source mask buffer
+ * @bg_resolved: Calculated info about the background buffer
+ * @dst_resolved: Calculated info about the destination buffer
+ * @profile: True if the blit shall be profiled, false otherwise
+ */
+struct b2r2_blt_request {
+ struct b2r2_control_instance *instance;
+ struct list_head list;
+ struct b2r2_blt_req user_req;
+ struct b2r2_core_job job;
+ struct b2r2_node_split_job node_split_job;
+ struct b2r2_node *first_node;
+ int request_id;
+ u32 core_mask;
+
+ /* Resolved buffer addresses */
+ struct b2r2_resolved_buf src_resolved;
+ struct b2r2_resolved_buf src_mask_resolved;
+ struct b2r2_resolved_buf bg_resolved;
+ struct b2r2_resolved_buf dst_resolved;
+
+ /* TBD: Info about SRAM usage & needs */
+ struct b2r2_work_buf *bufs;
+ u32 buf_count;
+
+ /* color look-up table */
+ void *clut;
+ u32 clut_phys_addr;
+
+ /* Profiling stuff */
+ bool profile;
+
+ s32 nsec_active_in_cpu;
+
+ u32 start_time_nsec;
+ s32 total_time_nsec;
+};
+
+/**
+ * struct b2r2_mem_heap - The memory heap
+ *
+ * @start_phys_addr: Physical memory start address
+ * @start_virt_ptr: Virtual pointer to start
+ * @size: Memory size
+ * @align: Alignment
+ * @blocks: List of all blocks
+ * @heap_lock: Protection for the heap
+ * @node_size: Size of each B2R2 node
+ * @node_heap: Heap for B2R2 node allocations
+ * @debugfs_root_dir: Debugfs B2R2 mem root dir
+ * @debugfs_heap_stats: Debugfs B2R2 memory status
+ * @debugfs_dir_blocks: Debugfs B2R2 free blocks dir
+ */
+struct b2r2_mem_heap {
+ dma_addr_t start_phys_addr;
+ void *start_virt_ptr;
+ u32 size;
+ u32 align;
+ struct list_head blocks;
+ spinlock_t heap_lock;
+ u32 node_size;
+ struct dma_pool *node_heap;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_root_dir;
+ struct dentry *debugfs_heap_stats;
+ struct dentry *debugfs_dir_blocks;
+#endif
+};
+
+/**
+ *
+ * @dev: The device handle of the b2r2 instance
+ * @id: The id of the b2r2 instance
+ * @name: The name of the b2r2 instance
+ * @data: Used to store a reference to b2r2_core
+ * @tmp_bufs: Temporary buffers needed in the node splitter
+ * @filters_initialized: Indicating of filters has been
+ * initialized for this b2r2 instance
+ * @mem_heap: The b2r2 heap, e.g. used to allocate nodes
+ * @debugfs_latest_request: Copy of the latest request issued
+ * @debugfs_root_dir: The debugfs root directory, e.g. /debugfs/b2r2
+ * @debugfs_debug_root_dir: The b2r2 debug root directory,
+ * e.g. /debugfs/b2r2/debug
+ * @stat_lock: Spin lock protecting the statistics
+ * @stat_n_jobs_added: Number of jobs added to b2r2_core
+ * @stat_n_jobs_released: Number of jobs released (job_release called)
+ * @stat_n_jobs_in_report_list: Number of jobs currently in the report list
+ * @stat_n_in_blt: Number of client threads currently exec inside b2r2_blt()
+ * @stat_n_in_blt_synch: Number of client threads currently waiting for synch
+ * @stat_n_in_blt_add: Number of client threads currenlty adding in b2r2_blt
+ * @stat_n_in_blt_wait: Number of client threads currently waiting in b2r2_blt
+ * @stat_n_in_synch_0: Number of client threads currently in b2r2_blt_sync
+ * waiting for all client jobs to finish
+ * @stat_n_in_synch_job: Number of client threads currently in b2r2_blt_sync
+ * waiting specific job to finish
+ * @stat_n_in_query_cap: Number of clients currently in query cap
+ * @stat_n_in_open: Number of clients currently in b2r2_blt_open
+ * @stat_n_in_release: Number of clients currently in b2r2_blt_release
+ * @last_job_lock: Mutex protecting last_job
+ * @last_job: The last running job on this b2r2 instance
+ * @last_job_chars: Temporary buffer used in printing last_job
+ * @prev_node_count: Node cound of last_job
+ */
+struct b2r2_control {
+ struct device *dev;
+ void *data;
+ int id;
+ struct kref ref;
+ bool enabled;
+ struct tmp_buf tmp_bufs[MAX_TMP_BUFS_NEEDED];
+ int filters_initialized;
+ struct b2r2_mem_heap mem_heap;
+#ifdef CONFIG_DEBUG_FS
+ struct b2r2_blt_request debugfs_latest_request;
+ struct dentry *debugfs_root_dir;
+ struct dentry *debugfs_debug_root_dir;
+#endif
+ struct mutex stat_lock;
+ unsigned long stat_n_jobs_added;
+ unsigned long stat_n_jobs_released;
+ unsigned long stat_n_jobs_in_report_list;
+ unsigned long stat_n_in_blt;
+ unsigned long stat_n_in_blt_synch;
+ unsigned long stat_n_in_blt_add;
+ unsigned long stat_n_in_blt_wait;
+ unsigned long stat_n_in_synch_0;
+ unsigned long stat_n_in_synch_job;
+ unsigned long stat_n_in_query_cap;
+ unsigned long stat_n_in_open;
+ unsigned long stat_n_in_release;
+ struct mutex last_job_lock;
+ struct b2r2_node *last_job;
+ char *last_job_chars;
+ int prev_node_count;
+};
+
+/* FIXME: The functions below should be removed when we are
+ switching to the new Robert Lind allocator */
+
+/**
+ * b2r2_blt_alloc_nodes() - Allocate nodes
+ *
+ * @node_count: Number of nodes to allocate
+ *
+ * Return:
+ * Returns a pointer to the first node in the node list.
+ */
+struct b2r2_node *b2r2_blt_alloc_nodes(struct b2r2_control *cont,
+ int node_count);
+
+/**
+ * b2r2_blt_free_nodes() - Release nodes previously allocated via
+ * b2r2_generate_nodes
+ *
+ * @first_node: First node in linked list of nodes
+ */
+void b2r2_blt_free_nodes(struct b2r2_control *cont,
+ struct b2r2_node *first_node);
+
+/**
+ * b2r2_blt_module_init() - Initialize the B2R2 blt module
+ */
+int b2r2_blt_module_init(struct b2r2_control *cont);
+
+/**
+ * b2r2_blt_module_exit() - Un-initialize the B2R2 blt module
+ */
+void b2r2_blt_module_exit(struct b2r2_control *cont);
+
+/**
+ * b2r2_blt_add_control() - Add the b2r2 core control
+ */
+void b2r2_blt_add_control(struct b2r2_control *cont);
+
+/**
+ * b2r2_blt_remove_control() - Remove the b2r2 core control
+ */
+void b2r2_blt_remove_control(struct b2r2_control *cont);
+
+#endif
diff --git a/drivers/video/b2r2/b2r2_kernel_if.c b/drivers/video/b2r2/b2r2_kernel_if.c
new file mode 100644
index 00000000000..373311ccca5
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_kernel_if.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 kernel interface for beeing a separate module
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <linux/fb.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+
+EXPORT_SYMBOL(fget_light);
+EXPORT_SYMBOL(fput_light);
+EXPORT_SYMBOL(flush_cache_range);
+EXPORT_SYMBOL(task_sched_runtime);
+#ifdef CONFIG_ANDROID_PMEM
+EXPORT_SYMBOL(get_pmem_file);
+EXPORT_SYMBOL(put_pmem_file);
+EXPORT_SYMBOL(flush_pmem_file);
+#endif
diff --git a/drivers/video/b2r2/b2r2_mem_alloc.c b/drivers/video/b2r2/b2r2_mem_alloc.c
new file mode 100644
index 00000000000..584b324b8fe
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_mem_alloc.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 internal Memory allocator
+ *
+ * Author: Robert Lind <robert.lind@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+
+#include "b2r2_internal.h"
+#include "b2r2_mem_alloc.h"
+
+/* Forward declarations */
+static struct b2r2_mem_block *b2r2_mem_block_alloc(
+ struct b2r2_control *cont, u32 offset, u32 size, bool free);
+static void b2r2_mem_block_free(struct b2r2_mem_block *mem_block);
+static int b2r2_mem_heap_status(struct b2r2_mem_heap *mem_heap,
+ struct b2r2_mem_heap_status *mem_heap_status);
+
+/* Align value down to specified alignment */
+static inline u32 align_down(u32 align, u32 value)
+{
+ return value & ~(align - 1);
+}
+
+/* Align value up to specified alignment */
+static inline u32 align_up(u32 align, u32 value)
+{
+ return (value + align - 1) & ~(align - 1);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+/* About debugfs:
+ * debugfs is a mountable debug file system.
+ *
+ * Mount like this:
+ * mkdir /debug
+ * mount -t debugfs none /debug
+ * ls /debug/b2r2/mem
+ *
+ * ls -al /debug/b2r2/mem/blocks
+ * cat /debug/b2r2/mem/stats
+ */
+
+
+/* Create string containing memory heap status */
+static char *get_b2r2_mem_stats(struct b2r2_mem_heap *mem_heap, char *buf)
+{
+ struct b2r2_mem_heap_status mem_heap_status;
+
+ if (b2r2_mem_heap_status(mem_heap, &mem_heap_status) != 0) {
+ strcpy(buf, "Error, failed to get status\n");
+ return buf;
+ }
+
+ sprintf(buf,
+ "Handle : 0x%lX\n"
+ "Physical start address : 0x%lX\n"
+ "Size : %lu\n"
+ "Align : %lu\n"
+ "No of blocks allocated : %lu\n"
+ "Allocated size : %lu\n"
+ "No of free blocks : %lu\n"
+ "Free size : %lu\n"
+ "No of locks : %lu\n"
+ "No of locked : %lu\n"
+ "No of nodes : %lu\n",
+ (unsigned long) mem_heap,
+ (unsigned long) mem_heap_status.start_phys_addr,
+ (unsigned long) mem_heap_status.size,
+ (unsigned long) mem_heap_status.align,
+ (unsigned long) mem_heap_status.num_alloc,
+ (unsigned long) mem_heap_status.allocated_size,
+ (unsigned long) mem_heap_status.num_free,
+ (unsigned long) mem_heap_status.free_size,
+ (unsigned long) mem_heap_status.num_locks,
+ (unsigned long) mem_heap_status.num_locked,
+ (unsigned long) mem_heap_status.num_nodes);
+
+ return buf;
+}
+
+/*
+ * Print memory heap status on file
+ * (Use like "cat /debug/b2r2/mem/stats")
+ */
+static int debugfs_b2r2_mem_stats_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct b2r2_mem_heap *mem_heap = filp->f_dentry->d_inode->i_private;
+ char Buf[400];
+ size_t dev_size;
+ int ret = 0;
+
+ get_b2r2_mem_stats(mem_heap, Buf);
+ dev_size = strlen(Buf);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, Buf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ return ret;
+}
+
+/* debugfs file operations for the "stats" file */
+static const struct file_operations debugfs_b2r2_mem_stats_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_mem_stats_read,
+};
+
+/* read function for file in the "blocks" sub directory */
+static int debugfs_b2r2_mem_block_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct b2r2_mem_block *mem_block = filp->f_dentry->d_inode->i_private;
+ char Buf[200];
+ size_t dev_size;
+ int ret = 0;
+
+ dev_size = sprintf(Buf, "offset: %08lX %s size: %8d "
+ "lock_count: %2d\n",
+ (unsigned long) mem_block->offset,
+ mem_block->free ? "free" : "allc",
+ mem_block->size,
+ mem_block->lock_count);
+
+ /* No more to read if offset != 0 */
+ if (*f_pos > dev_size)
+ goto out;
+
+ if (*f_pos + count > dev_size)
+ count = dev_size - *f_pos;
+
+ if (copy_to_user(buf, Buf, count))
+ ret = -EINVAL;
+ *f_pos += count;
+ ret = count;
+
+out:
+ return ret;
+}
+
+/* debugfs file operations for files in the "blocks" directory */
+static const struct file_operations debugfs_b2r2_mem_block_fops = {
+ .owner = THIS_MODULE,
+ .read = debugfs_b2r2_mem_block_read,
+};
+
+/*
+ * Create or update the debugfs directory entry for a file in the
+ * "blocks" directory (a memory allocation)
+ */
+void debugfs_create_mem_block_entry(struct b2r2_mem_block *mem_block,
+ struct dentry *parent)
+{
+ struct timespec tm = current_kernel_time();
+ struct timespec atime = tm;
+ struct timespec mtime = tm;
+ struct timespec ctime = tm;
+
+ if (!IS_ERR_OR_NULL(mem_block->debugfs_block)) {
+ atime = mem_block->debugfs_block->d_inode->i_atime;
+ ctime = mem_block->debugfs_block->d_inode->i_ctime;
+ debugfs_remove(mem_block->debugfs_block);
+ mem_block->debugfs_block = NULL;
+ }
+
+ /* Add the block in debugfs */
+ if (mem_block->free)
+ sprintf(mem_block->debugfs_fname, "%08lX free",
+ (unsigned long) mem_block->offset);
+ else {
+ sprintf(mem_block->debugfs_fname, "%08lX allc h:%08lX "
+ "lck:%d ",
+ (unsigned long) mem_block->offset,
+ (unsigned long) mem_block,
+ mem_block->lock_count);
+ }
+
+ mem_block->debugfs_block = debugfs_create_file(
+ mem_block->debugfs_fname,
+ 0444, parent, mem_block,
+ &debugfs_b2r2_mem_block_fops);
+ if (!IS_ERR_OR_NULL(mem_block->debugfs_block)) {
+ mem_block->debugfs_block->d_inode->i_size = mem_block->size;
+ mem_block->debugfs_block->d_inode->i_atime = atime;
+ mem_block->debugfs_block->d_inode->i_mtime = mtime;
+ mem_block->debugfs_block->d_inode->i_ctime = ctime;
+ }
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/* Module initialization function */
+int b2r2_mem_init(struct b2r2_control *cont,
+ u32 heap_size, u32 align, u32 node_size)
+{
+ struct b2r2_mem_block *mem_block;
+ u32 aligned_size;
+
+ dev_info(cont->dev, "%s: Creating heap for size %d bytes\n",
+ __func__, (int) heap_size);
+
+ /* Align size */
+ aligned_size = align_down(align, heap_size);
+ if (aligned_size == 0)
+ return -EINVAL;
+
+ cont->mem_heap.start_virt_ptr = dma_alloc_coherent(cont->dev,
+ aligned_size, &(cont->mem_heap.start_phys_addr), GFP_KERNEL);
+ if (!cont->mem_heap.start_phys_addr || !cont->mem_heap.start_virt_ptr) {
+ printk(KERN_ERR "B2R2_MEM: Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the heap */
+ cont->mem_heap.size = aligned_size;
+ cont->mem_heap.align = align;
+
+ INIT_LIST_HEAD(&cont->mem_heap.blocks);
+
+#ifdef CONFIG_DEBUG_FS
+ /* Register debugfs */
+ if (!IS_ERR_OR_NULL(cont->mem_heap.debugfs_root_dir)) {
+ cont->mem_heap.debugfs_heap_stats = debugfs_create_file(
+ "stats", 0444, cont->mem_heap.debugfs_root_dir,
+ &cont->mem_heap, &debugfs_b2r2_mem_stats_fops);
+ cont->mem_heap.debugfs_dir_blocks = debugfs_create_dir(
+ "blocks", cont->mem_heap.debugfs_root_dir);
+ }
+#endif
+
+ /* Create the first _free_ memory block */
+ mem_block = b2r2_mem_block_alloc(cont, 0, aligned_size, true);
+ if (!mem_block) {
+ dma_free_coherent(cont->dev, aligned_size,
+ cont->mem_heap.start_virt_ptr,
+ cont->mem_heap.start_phys_addr);
+ printk(KERN_ERR "B2R2_MEM: Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ /* Add the free block to the blocks list */
+ list_add(&mem_block->list, &cont->mem_heap.blocks);
+
+ /* Allocate separate heap for B2R2 nodes */
+ cont->mem_heap.node_size = node_size;
+ cont->mem_heap.node_heap = dma_pool_create("b2r2_node_cache",
+ cont->dev, node_size, align, 4096);
+ if (!cont->mem_heap.node_heap) {
+ b2r2_mem_block_free(mem_block);
+ dma_free_coherent(cont->dev, aligned_size,
+ cont->mem_heap.start_virt_ptr,
+ cont->mem_heap.start_phys_addr);
+ printk(KERN_ERR "B2R2_MEM: Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(b2r2_mem_init);
+
+/* Module exit function */
+void b2r2_mem_exit(struct b2r2_control *cont)
+{
+ struct list_head *ptr;
+
+ /* Free B2R2 node heap */
+ dma_pool_destroy(cont->mem_heap.node_heap);
+
+ list_for_each(ptr, &cont->mem_heap.blocks) {
+ struct b2r2_mem_block *mem_block =
+ list_entry(ptr, struct b2r2_mem_block, list);
+
+ b2r2_mem_block_free(mem_block);
+ }
+
+ dma_free_coherent(cont->dev, cont->mem_heap.size,
+ cont->mem_heap.start_virt_ptr,
+ cont->mem_heap.start_phys_addr);
+}
+EXPORT_SYMBOL(b2r2_mem_exit);
+
+/* Return status of the heap */
+static int b2r2_mem_heap_status(struct b2r2_mem_heap *mheap,
+ struct b2r2_mem_heap_status *mem_heap_status)
+{
+ struct list_head *ptr;
+
+ if (!mheap || !mem_heap_status)
+ return -EINVAL;
+ memset(mem_heap_status, 0, sizeof(*mem_heap_status));
+
+ /* Lock the heap */
+ spin_lock(&mheap->heap_lock);
+
+ /* Fill in static info */
+ mem_heap_status->start_phys_addr = mheap->start_phys_addr;
+ mem_heap_status->size = mheap->size;
+ mem_heap_status->align = mheap->align;
+
+ list_for_each(ptr, &mheap->blocks) {
+ struct b2r2_mem_block *mem_block =
+ list_entry(ptr, struct b2r2_mem_block, list);
+
+ if (mem_block->free) {
+ mem_heap_status->num_free++;
+ mem_heap_status->free_size += mem_block->size;
+ } else {
+ if (mem_block->lock_count) {
+ mem_heap_status->num_locked++;
+ mem_heap_status->num_locks +=
+ mem_block->lock_count;
+ }
+ mem_heap_status->num_alloc++;
+ mem_heap_status->allocated_size += mem_block->size;
+ }
+ }
+
+ spin_unlock(&mheap->heap_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(b2r2_mem_heap_status);
+
+/* Internal: Allocate a housekeeping structure
+ * for an allocated or free memory block
+ */
+static struct b2r2_mem_block *b2r2_mem_block_alloc(
+ struct b2r2_control *cont, u32 offset, u32 size, bool free)
+{
+ struct b2r2_mem_block *mem_block = kmalloc(
+ sizeof(struct b2r2_mem_block), GFP_KERNEL);
+
+ if (mem_block) {
+ mem_block->offset = offset;
+ mem_block->size = size;
+ mem_block->free = free;
+ mem_block->lock_count = 0;
+
+ INIT_LIST_HEAD(&mem_block->list);
+
+#ifdef CONFIG_DEBUG_FS
+ mem_block->debugfs_block = NULL;
+ /* Add the block in debugfs */
+ debugfs_create_mem_block_entry(mem_block,
+ cont->mem_heap.debugfs_dir_blocks);
+#endif
+ }
+
+ return mem_block;
+}
+
+/* Internal: Release housekeeping structure */
+static void b2r2_mem_block_free(struct b2r2_mem_block *mem_block)
+{
+ if (mem_block) {
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(mem_block->debugfs_block);
+#endif
+ kfree(mem_block);
+ }
+}
+
+/* Allocate a block from the heap */
+int b2r2_mem_alloc(struct b2r2_control *cont, u32 requested_size,
+ u32 *returned_size, u32 *mem_handle)
+{
+ int ret = 0;
+ struct list_head *ptr;
+ struct b2r2_mem_block *found_mem_block = NULL;
+ u32 aligned_size;
+
+ if (!mem_handle)
+ return -EINVAL;
+
+ printk(KERN_INFO "%s: size=%d\n", __func__, requested_size);
+
+ *mem_handle = 0;
+
+ /* Lock the heap */
+ spin_lock(&cont->mem_heap.heap_lock);
+
+ aligned_size = align_up(cont->mem_heap.align, requested_size);
+ /* Try to find the best matching free block of suitable size */
+ list_for_each(ptr, &cont->mem_heap.blocks) {
+ struct b2r2_mem_block *mem_block =
+ list_entry(ptr, struct b2r2_mem_block, list);
+
+ if (mem_block->free && mem_block->size >= aligned_size &&
+ (!found_mem_block ||
+ mem_block->size < found_mem_block->size)) {
+ found_mem_block = mem_block;
+ if (found_mem_block->size == aligned_size)
+ break;
+ }
+ }
+
+ if (found_mem_block) {
+ struct b2r2_mem_block *new_block
+ = b2r2_mem_block_alloc(cont,
+ found_mem_block->offset,
+ requested_size, false);
+
+ if (new_block) {
+ /* Insert the new block before the found block */
+ list_add_tail(&new_block->list,
+ &found_mem_block->list);
+
+ /* Split the free block */
+ found_mem_block->offset += aligned_size;
+ found_mem_block->size -= aligned_size;
+
+ if (found_mem_block->size == 0)
+ b2r2_mem_block_free(found_mem_block);
+ else {
+#ifdef CONFIG_DEBUG_FS
+ debugfs_create_mem_block_entry(
+ found_mem_block,
+ cont->mem_heap.debugfs_dir_blocks);
+#endif
+ }
+
+ *mem_handle = (u32) new_block;
+ *returned_size = aligned_size;
+ } else {
+ ret = -ENOMEM;
+ }
+ } else
+ ret = -ENOMEM;
+
+ if (ret != 0) {
+ *returned_size = 0;
+ *mem_handle = (u32) 0;
+ }
+
+ /* Unlock */
+ spin_unlock(&cont->mem_heap.heap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_mem_alloc);
+
+/* Free the allocated block */
+int b2r2_mem_free(struct b2r2_control *cont, u32 mem_handle)
+{
+ int ret = 0;
+ struct b2r2_mem_block *mem_block = (struct b2r2_mem_block *) mem_handle;
+
+ if (!mem_block)
+ return -EINVAL;
+
+ /* Lock the heap */
+ spin_lock(&cont->mem_heap.heap_lock);
+
+ if (!ret && mem_block->free)
+ ret = -EINVAL;
+
+ if (!ret) {
+ printk(KERN_INFO "%s: freeing block 0x%p\n", __func__, mem_block);
+ /* Release the block */
+
+ mem_block->free = true;
+ mem_block->size = align_up(cont->mem_heap.align,
+ mem_block->size);
+
+ /* Join with previous block if possible */
+ if (mem_block->list.prev != &cont->mem_heap.blocks) {
+ struct b2r2_mem_block *prev_block =
+ list_entry(mem_block->list.prev,
+ struct b2r2_mem_block, list);
+
+ if (prev_block->free &&
+ (prev_block->offset + prev_block->size) ==
+ mem_block->offset) {
+ mem_block->offset = prev_block->offset;
+ mem_block->size += prev_block->size;
+
+ b2r2_mem_block_free(prev_block);
+ }
+ }
+
+ /* Join with next block if possible */
+ if (mem_block->list.next != &cont->mem_heap.blocks) {
+ struct b2r2_mem_block *next_block
+ = list_entry(mem_block->list.next,
+ struct b2r2_mem_block,
+ list);
+
+ if (next_block->free &&
+ (mem_block->offset + mem_block->size) ==
+ next_block->offset) {
+ mem_block->size += next_block->size;
+
+ b2r2_mem_block_free(next_block);
+ }
+ }
+#ifdef CONFIG_DEBUG_FS
+ debugfs_create_mem_block_entry(mem_block,
+ cont->mem_heap.debugfs_dir_blocks);
+#endif
+ }
+
+ /* Unlock */
+ spin_unlock(&cont->mem_heap.heap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_mem_free);
+
+/* Lock the allocated block in memory */
+int b2r2_mem_lock(struct b2r2_control *cont, u32 mem_handle,
+ u32 *phys_addr, void **virt_ptr, u32 *size)
+{
+ struct b2r2_mem_block *mem_block =
+ (struct b2r2_mem_block *) mem_handle;
+
+ if (!mem_block)
+ return -EINVAL;
+
+ /* Lock the heap */
+ spin_lock(&cont->mem_heap.heap_lock);
+
+ mem_block->lock_count++;
+
+ if (phys_addr)
+ *phys_addr = cont->mem_heap.start_phys_addr + mem_block->offset;
+ if (virt_ptr)
+ *virt_ptr = (char *) cont->mem_heap.start_virt_ptr +
+ mem_block->offset;
+ if (size)
+ *size = align_up(cont->mem_heap.align, mem_block->size);
+#ifdef CONFIG_DEBUG_FS
+ debugfs_create_mem_block_entry(mem_block,
+ cont->mem_heap.debugfs_dir_blocks);
+#endif
+
+ spin_unlock(&cont->mem_heap.heap_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(b2r2_mem_lock);
+
+/* Unlock the allocated block in memory */
+int b2r2_mem_unlock(struct b2r2_control *cont, u32 mem_handle)
+{
+ struct b2r2_mem_block *mem_block =
+ (struct b2r2_mem_block *) mem_handle;
+
+ if (!mem_block)
+ return -EINVAL;
+
+ /* Lock the heap */
+ spin_lock(&cont->mem_heap.heap_lock);
+
+ mem_block->lock_count--;
+
+ spin_unlock(&cont->mem_heap.heap_lock);
+
+ /* debugfs will be updated in release */
+ return 0;
+/* return b2r2_mem_free(mem_handle);*/
+}
+EXPORT_SYMBOL(b2r2_mem_unlock);
+
+/* Allocate one or more b2r2 nodes from DMA pool */
+int b2r2_node_alloc(struct b2r2_control *cont, u32 num_nodes,
+ struct b2r2_node **first_node)
+{
+ int i;
+ int ret = 0;
+ u32 physical_address;
+ struct b2r2_node *first_node_ptr;
+ struct b2r2_node *node_ptr;
+
+ /* Check input parameters */
+ if ((num_nodes <= 0) || !first_node) {
+ dev_err(cont->dev,
+ "B2R2_MEM: Invalid parameter for b2r2_node_alloc, "
+ "num_nodes=%d, first_node=%ld\n",
+ (int) num_nodes, (long) first_node);
+ return -EINVAL;
+ }
+
+ /* Allocate the first node */
+ first_node_ptr = dma_pool_alloc(cont->mem_heap.node_heap,
+ GFP_DMA | GFP_KERNEL, &physical_address);
+ if (!first_node_ptr) {
+ dev_err(cont->dev,
+ "B2R2_MEM: Failed to allocate memory for node\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize first node */
+ first_node_ptr->next = NULL;
+ first_node_ptr->physical_address = physical_address +
+ offsetof(struct b2r2_node, node);
+
+ /* Allocate and initialize remaining nodes, */
+ /* and link them into a list */
+ for (i = 1, node_ptr = first_node_ptr; i < num_nodes; i++) {
+ node_ptr->next = dma_pool_alloc(cont->mem_heap.node_heap,
+ GFP_DMA | GFP_KERNEL, &physical_address);
+ if (node_ptr->next) {
+ node_ptr = node_ptr->next;
+ node_ptr->next = NULL;
+ node_ptr->physical_address = physical_address +
+ offsetof(struct b2r2_node, node);
+ } else {
+ printk(KERN_ERR "B2R2_MEM: Failed to allocate memory for node\n");
+ ret = -ENOMEM;
+ break;
+ }
+ }
+
+ /* If all nodes were allocated successfully, */
+ /* return the first node */
+ if (!ret)
+ *first_node = first_node_ptr;
+ else
+ b2r2_node_free(cont, first_node_ptr);
+
+ return ret;
+}
+EXPORT_SYMBOL(b2r2_node_alloc);
+
+/* Free a linked list of b2r2 nodes */
+void b2r2_node_free(struct b2r2_control *cont, struct b2r2_node *first_node)
+{
+ struct b2r2_node *current_node = first_node;
+ struct b2r2_node *next_node = NULL;
+
+ /* Traverse the linked list and free the nodes */
+ while (current_node != NULL) {
+ next_node = current_node->next;
+ dma_pool_free(cont->mem_heap.node_heap, current_node,
+ current_node->physical_address -
+ offsetof(struct b2r2_node, node));
+ current_node = next_node;
+ }
+}
+EXPORT_SYMBOL(b2r2_node_free);
+
+MODULE_AUTHOR("Robert Lind <robert.lind@ericsson.com");
+MODULE_DESCRIPTION("Ericsson AB B2R2 physical memory driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/b2r2/b2r2_mem_alloc.h b/drivers/video/b2r2/b2r2_mem_alloc.h
new file mode 100644
index 00000000000..4fd1e66abca
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_mem_alloc.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 internal Memory allocator
+ *
+ * Author: Robert Lind <robert.lind@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __B2R2_MEM_ALLOC_H
+#define __B2R2_MEM_ALLOC_H
+
+#include "b2r2_internal.h"
+
+
+/**
+ * struct b2r2_mem_heap_status - Information about current state of the heap
+ *
+ * @start_phys_addr: Physical address of the the memory area
+ * @size: Size of the memory area
+ * @align: Alignment of start and allocation sizes (in bytes).
+ * @num_alloc: Number of memory allocations
+ * @allocated_size: Size allocated (sum of requested sizes)
+ * @num_free: Number of free blocks (fragments)
+ * @free_size: Free size available for allocation
+ * @num_locks: Sum of number of number of locks on memory allocations
+ * @num_locked: Number of locked memory allocations
+ * @num_nodes: Number of node allocations
+ *
+ **/
+struct b2r2_mem_heap_status {
+ u32 start_phys_addr;
+ u32 size;
+ u32 align;
+ u32 num_alloc;
+ u32 allocated_size;
+ u32 num_free;
+ u32 free_size;
+ u32 num_locks;
+ u32 num_locked;
+ u32 num_nodes;
+};
+
+/**
+ * struct b2r2_mem_block - Represents one block of b2r2
+ * physical memory, free or allocated
+ *
+ * @list: For membership in list
+ * @offset: Offset in b2r2 physical memory area (aligned)
+ * @size: Size of the object (requested size if busy, else actual)
+ * @free: True if the block is free
+ * @lock_count: Lock count
+ * @debugfs_fname: Debugfs file name
+ * @debugfs_block: Debugfs dir entry for the block
+ */
+struct b2r2_mem_block {
+ struct list_head list;
+ u32 offset;
+ u32 size;
+ bool free;
+ u32 lock_count;
+#ifdef CONFIG_DEBUG_FS
+ char debugfs_fname[80];
+ struct dentry *debugfs_block;
+#endif
+};
+
+
+/* B2R2 memory API (kernel) */
+
+/**
+ * b2r2_mem_init() - Initializes the B2R2 memory manager
+ * @dev: Pointer to device to use for allocating the memory heap
+ * @heap_size: Size of the heap (in bytes)
+ * @align: Alignment to use for memory allocations on heap (in bytes)
+ * @node_size: Size of each B2R2 node (in bytes)
+ *
+ * Returns 0 if success, else negative error code
+ **/
+int b2r2_mem_init(struct b2r2_control *cont,
+ u32 heap_size, u32 align, u32 node_size);
+
+/**
+ * b2r2_mem_exit() - Cleans up the B2R2 memory manager
+ *
+ **/
+void b2r2_mem_exit(struct b2r2_control *cont);
+
+/**
+ * b2r2_mem_alloc() - Allocates memory block from physical memory heap
+ * @requested_size: Requested size
+ * @returned_size: Actual size of memory block. Might be adjusted due to
+ * alignment but is always >= requested size if function
+ * succeeds
+ * @mem_handle: Returned memory handle
+ *
+ * All memory allocations are movable when not locked.
+ * Returns 0 if OK else negative error value
+ **/
+int b2r2_mem_alloc(struct b2r2_control *cont, u32 requested_size,
+ u32 *returned_size, u32 *mem_handle);
+
+/**
+ * b2r2_mem_free() - Frees an allocation
+ * @mem_handle: Memory handle
+ *
+ * Returns 0 if OK else negative error value
+ **/
+int b2r2_mem_free(struct b2r2_control *cont, u32 mem_handle);
+
+/**
+ * b2r2_mem_lock() - Lock memory in memory and return physical address
+ * @mem_handle: Memory handle
+ * @phys_addr: Returned physical address to start of memory allocation.
+ * May be NULL.
+ * @virt_ptr: Returned virtual address pointer to start of memory allocation.
+ * May be NULL.
+ * @size: Returned size of memory allocation. May be NULL.
+ *
+ * The adress of the memory allocation is locked and the physical address
+ * is returned.
+ * The lock count is incremented by one.
+ * You need to call b2r2_mem_unlock once for each call to
+ * b2r2_mem_lock.
+ * Returns 0 if OK else negative error value
+ **/
+int b2r2_mem_lock(struct b2r2_control *cont, u32 mem_handle,
+ u32 *phys_addr, void **virt_ptr, u32 *size);
+
+/**
+ * b2r2_mem_unlock() - Unlock previously locked memory
+ * @mem_handle: Memory handle
+ *
+ * Decrements lock count. When lock count reaches 0 the
+ * memory area is movable again.
+ * Returns 0 if OK else negative error value
+ **/
+int b2r2_mem_unlock(struct b2r2_control *cont, u32 mem_handle);
+
+/**
+ * b2r2_node_alloc() - Allocates B2R2 node from physical memory heap
+ * @num_nodes: Number of linked nodes to allocate
+ * @first_node: Returned pointer to first node in linked list
+ *
+ * Returns 0 if OK else negative error value
+ **/
+int b2r2_node_alloc(struct b2r2_control *cont, u32 num_nodes,
+ struct b2r2_node **first_node);
+
+/**
+ * b2r2_node_free() - Frees a linked list of allocated B2R2 nodes
+ * @first_node: Pointer to first node in linked list
+ *
+ * Returns 0 if OK else negative error value
+ **/
+void b2r2_node_free(struct b2r2_control *cont, struct b2r2_node *first_node);
+
+
+#endif /* __B2R2_MEM_ALLOC_H */
diff --git a/drivers/video/b2r2/b2r2_node_gen.c b/drivers/video/b2r2/b2r2_node_gen.c
new file mode 100644
index 00000000000..1f48bac6fe7
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_node_gen.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 node generator
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+#include "b2r2_internal.h"
+
+static void free_nodes(struct b2r2_control *cont,
+ struct b2r2_node *first_node)
+{
+ struct b2r2_node *node = first_node;
+ int no_of_nodes = 0;
+
+ while (node) {
+ no_of_nodes++;
+ node = node->next;
+ }
+
+ dma_free_coherent(cont->dev,
+ no_of_nodes * sizeof(struct b2r2_node),
+ first_node,
+ first_node->physical_address -
+ offsetof(struct b2r2_node, node));
+}
+
+struct b2r2_node *b2r2_blt_alloc_nodes(struct b2r2_control *cont,
+ int no_of_nodes)
+{
+ u32 physical_address;
+ struct b2r2_node *nodes;
+ struct b2r2_node *tmpnode;
+
+ if (no_of_nodes <= 0) {
+ dev_err(cont->dev, "%s: Wrong number of nodes (%d)",
+ __func__, no_of_nodes);
+ return NULL;
+ }
+
+ /* Allocate the memory */
+ nodes = (struct b2r2_node *) dma_alloc_coherent(cont->dev,
+ no_of_nodes * sizeof(struct b2r2_node),
+ &physical_address, GFP_DMA | GFP_KERNEL);
+
+ if (nodes == NULL) {
+ dev_err(cont->dev,
+ "%s: Failed to alloc memory for nodes",
+ __func__);
+ return NULL;
+ }
+
+ /* Build the linked list */
+ tmpnode = nodes;
+ physical_address += offsetof(struct b2r2_node, node);
+ while (no_of_nodes--) {
+ tmpnode->physical_address = physical_address;
+ if (no_of_nodes)
+ tmpnode->next = tmpnode + 1;
+ else
+ tmpnode->next = NULL;
+
+ tmpnode++;
+ physical_address += sizeof(struct b2r2_node);
+ }
+
+ return nodes;
+}
+
+void b2r2_blt_free_nodes(struct b2r2_control *cont,
+ struct b2r2_node *first_node)
+{
+ free_nodes(cont, first_node);
+}
+
diff --git a/drivers/video/b2r2/b2r2_node_split.c b/drivers/video/b2r2/b2r2_node_split.c
new file mode 100644
index 00000000000..b2fb07580ca
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_node_split.c
@@ -0,0 +1,3033 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 node splitter
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include "b2r2_debug.h"
+#include "b2r2_node_split.h"
+#include "b2r2_internal.h"
+#include "b2r2_hw_convert.h"
+#include "b2r2_filters.h"
+#include "b2r2_utils.h"
+
+#include <linux/kernel.h>
+
+/*
+ * Macros and constants
+ */
+
+#define INSTANCES_DEFAULT_SIZE 10
+#define INSTANCES_GROW_SIZE 5
+
+/*
+ * Internal types
+ */
+
+
+/*
+ * Global variables
+ */
+
+
+/*
+ * Forward declaration of private functions
+ */
+static int analyze_fmt_conv(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ const u32 **vmx, u32 *node_count,
+ bool fullrange);
+static int analyze_color_fill(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count);
+static int analyze_copy(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count);
+static int analyze_scaling(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count);
+static int analyze_rotate(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count);
+static int analyze_transform(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count);
+static int analyze_rot_scale(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count);
+static int analyze_scale_factors(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this);
+
+static void configure_src(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_node_split_buf *src, const u32 *ivmx);
+static void configure_bg(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_node_split_buf *bg, bool swap_fg_bg);
+static int configure_dst(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_node_split_buf *dst, const u32 *ivmx,
+ struct b2r2_node **next);
+static void configure_blend(struct b2r2_control *cont, struct b2r2_node *node,
+ u32 flags, u32 global_alpha);
+static void configure_clip(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_blt_rect *clip_rect);
+
+static int configure_tile(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *node,
+ struct b2r2_node **next);
+static void configure_direct_fill(struct b2r2_control *cont,
+ struct b2r2_node *node, u32 color,
+ struct b2r2_node_split_buf *dst,
+ struct b2r2_node **next);
+static int configure_fill(struct b2r2_control *cont,
+ struct b2r2_node *node, u32 color, enum b2r2_blt_fmt fmt,
+ struct b2r2_node_split_buf *dst, const u32 *ivmx,
+ struct b2r2_node **next);
+static void configure_direct_copy(struct b2r2_control *cont,
+ struct b2r2_node *node, struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst, struct b2r2_node **next);
+static int configure_copy(struct b2r2_control *cont,
+ struct b2r2_node *node, struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst, const u32 *ivmx,
+ struct b2r2_node **next,
+ struct b2r2_node_split_job *this);
+static int configure_rotate(struct b2r2_control *cont,
+ struct b2r2_node *node, struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst, const u32 *ivmx,
+ struct b2r2_node **next,
+ struct b2r2_node_split_job *this);
+static int configure_scale(struct b2r2_control *cont,
+ struct b2r2_node *node, struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst, u16 h_rsf, u16 v_rsf,
+ const u32 *ivmx, struct b2r2_node **next,
+ struct b2r2_node_split_job *this);
+static int configure_rot_scale(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *node,
+ struct b2r2_node **next);
+
+static int check_rect(struct b2r2_control *cont,
+ const struct b2r2_blt_img *img,
+ const struct b2r2_blt_rect *rect,
+ const struct b2r2_blt_rect *clip);
+static void set_buf(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *buf,
+ u32 addr, const struct b2r2_blt_img *img,
+ const struct b2r2_blt_rect *rect, bool color_fill, u32 color);
+static int setup_tmp_buf(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *this, u32 max_size,
+ enum b2r2_blt_fmt pref_fmt, u32 pref_width, u32 pref_height);
+
+static bool is_transform(const struct b2r2_blt_request *req);
+static s32 rescale(struct b2r2_control *cont, s32 dim, u16 sf);
+static s32 inv_rescale(s32 dim, u16 sf);
+
+static void set_target(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf);
+static void set_src(struct b2r2_src_config *src, u32 addr,
+ struct b2r2_node_split_buf *buf);
+static void set_src_1(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf);
+static void set_src_2(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf);
+static void set_src_3(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf);
+static void set_ivmx(struct b2r2_node *node, const u32 *vmx_values);
+
+static void reset_nodes(struct b2r2_node *node);
+
+static bool bg_format_require_ivmx(enum b2r2_blt_fmt bg_fmt,
+ enum b2r2_blt_fmt dst_fmt);
+
+/*
+ * Public functions
+ */
+
+/**
+ * b2r2_node_split_analyze() - analyzes the request
+ */
+int b2r2_node_split_analyze(const struct b2r2_blt_request *req,
+ u32 max_buf_size, u32 *node_count, struct b2r2_work_buf **bufs,
+ u32 *buf_count, struct b2r2_node_split_job *this)
+{
+ int ret;
+ bool color_fill;
+ struct b2r2_control *cont = req->instance->control;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ memset(this, 0, sizeof(*this));
+
+ /* Copy parameters */
+ this->flags = req->user_req.flags;
+ this->transform = req->user_req.transform;
+ this->max_buf_size = max_buf_size;
+ this->global_alpha = req->user_req.global_alpha;
+ this->buf_count = 0;
+ this->node_count = 0;
+
+ if (this->flags & B2R2_BLT_FLAG_BLUR) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ /* Unsupported formats on src */
+ switch (req->user_req.src_img.fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ if (b2r2_is_bgr_fmt(req->user_req.dst_img.fmt)) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Unsupported formats on dst */
+ switch (req->user_req.dst_img.fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ if (b2r2_is_bgr_fmt(req->user_req.src_img.fmt)) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Unsupported formats on bg */
+ if (this->flags & B2R2_BLT_FLAG_BG_BLEND)
+ /*
+ * There are no ivmx on source 1, so check that there is no
+ * such requirement on the background to destination format
+ * conversion. This check is sufficient since the node splitter
+ * currently does not support destination ivmx. That fact also
+ * removes the source format as a parameter when checking the
+ * background format.
+ */
+ if (bg_format_require_ivmx(req->user_req.bg_img.fmt,
+ req->user_req.dst_img.fmt)) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ if ((this->flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY) &&
+ (b2r2_is_yuv_fmt(req->user_req.src_img.fmt) ||
+ req->user_req.src_img.fmt == B2R2_BLT_FMT_1_BIT_A1 ||
+ req->user_req.src_img.fmt == B2R2_BLT_FMT_8_BIT_A8)) {
+ b2r2_log_warn(cont->dev, "%s: Unsupported: source color keying "
+ "with YUV or pure alpha formats.\n", __func__);
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ if (this->flags & (B2R2_BLT_FLAG_DEST_COLOR_KEY |
+ B2R2_BLT_FLAG_SOURCE_MASK)) {
+ b2r2_log_warn(cont->dev, "%s: Unsupported: source mask, "
+ "destination color keying.\n", __func__);
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ if ((req->user_req.flags & B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) &&
+ req->user_req.clut == NULL) {
+ b2r2_log_warn(cont->dev, "%s: Invalid request: no table "
+ "specified for CLUT color correction.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Check for color fill */
+ color_fill = (this->flags & (B2R2_BLT_FLAG_SOURCE_FILL |
+ B2R2_BLT_FLAG_SOURCE_FILL_RAW)) != 0;
+
+ /* Configure the source and destination buffers */
+ set_buf(cont, &this->src, req->src_resolved.physical_address,
+ &req->user_req.src_img, &req->user_req.src_rect,
+ color_fill, req->user_req.src_color);
+
+ if (this->flags & B2R2_BLT_FLAG_BG_BLEND) {
+ set_buf(cont, &this->bg, req->bg_resolved.physical_address,
+ &req->user_req.bg_img, &req->user_req.bg_rect,
+ false, 0);
+ }
+
+ set_buf(cont, &this->dst, req->dst_resolved.physical_address,
+ &req->user_req.dst_img, &req->user_req.dst_rect, false,
+ 0);
+
+ b2r2_log_info(cont->dev, "%s:\n"
+ "\t\tsrc.rect=(%4d, %4d, %4d, %4d)\t"
+ "bg.rect=(%4d, %4d, %4d, %4d)\t"
+ "dst.rect=(%4d, %4d, %4d, %4d)\n", __func__, this->src.rect.x,
+ this->src.rect.y, this->src.rect.width, this->src.rect.height,
+ this->bg.rect.x, this->bg.rect.y, this->bg.rect.width,
+ this->bg.rect.height, this->dst.rect.x, this->dst.rect.y,
+ this->dst.rect.width, this->dst.rect.height);
+
+ if (this->flags & B2R2_BLT_FLAG_DITHER)
+ this->dst.dither = B2R2_TTY_RGB_ROUND_DITHER;
+
+ if (this->flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY)
+ this->flag_param = req->user_req.src_color;
+
+ /* Check for blending */
+ if ((this->flags & B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND) &&
+ (this->global_alpha != 255))
+ this->blend = true;
+ else if (this->flags & B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND)
+ this->blend = (color_fill && b2r2_fmt_has_alpha(this->dst.fmt)) ||
+ b2r2_fmt_has_alpha(this->src.fmt);
+ else if (this->flags & B2R2_BLT_FLAG_BG_BLEND)
+ this->blend = true;
+
+ /* Check for full range YUV conversion */
+ if (this->flags & B2R2_BLT_FLAG_FULL_RANGE_YUV)
+ this->fullrange = true;
+
+ if (this->blend && this->src.type == B2R2_FMT_TYPE_PLANAR) {
+ b2r2_log_warn(cont->dev, "%s: Unsupported: blend with planar"
+ " source\n", __func__);
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ /* Check for clipping */
+ this->clip = (this->flags & B2R2_BLT_FLAG_DESTINATION_CLIP) != 0;
+ if (this->clip) {
+ s32 l = req->user_req.dst_clip_rect.x;
+ s32 r = l + req->user_req.dst_clip_rect.width;
+ s32 t = req->user_req.dst_clip_rect.y;
+ s32 b = t + req->user_req.dst_clip_rect.height;
+
+ /* Intersect the clip and buffer rects */
+ if (l < 0)
+ l = 0;
+ if (r > req->user_req.dst_img.width)
+ r = req->user_req.dst_img.width;
+ if (t < 0)
+ t = 0;
+ if (b > req->user_req.dst_img.height)
+ b = req->user_req.dst_img.height;
+
+ this->clip_rect.x = l;
+ this->clip_rect.y = t;
+ this->clip_rect.width = r - l;
+ this->clip_rect.height = b - t;
+ } else {
+ /* Set the clip rectangle to the buffer bounds */
+ this->clip_rect.x = 0;
+ this->clip_rect.y = 0;
+ this->clip_rect.width = req->user_req.dst_img.width;
+ this->clip_rect.height = req->user_req.dst_img.height;
+ }
+
+ /* Validate the destination */
+ ret = check_rect(cont, &req->user_req.dst_img, &req->user_req.dst_rect,
+ &this->clip_rect);
+ if (ret < 0)
+ goto error;
+
+ /* Validate the source (if not color fill) */
+ if (!color_fill) {
+ ret = check_rect(cont, &req->user_req.src_img,
+ &req->user_req.src_rect, NULL);
+ if (ret < 0)
+ goto error;
+ }
+
+ /* Validate the background source */
+ if (this->flags & B2R2_BLT_FLAG_BG_BLEND) {
+ ret = check_rect(cont, &req->user_req.bg_img,
+ &req->user_req.bg_rect, NULL);
+ if (ret < 0)
+ goto error;
+ }
+
+ /* Do the analysis depending on the type of operation */
+ if (color_fill) {
+ ret = analyze_color_fill(this, req, &this->node_count);
+ } else {
+
+ bool upsample;
+ bool downsample;
+
+ /*
+ * YUV formats that are non-raster, non-yuv444 needs to be
+ * up (or down) sampled using the resizer.
+ *
+ * NOTE: The resizer needs to be enabled for YUV444 as well,
+ * even though there is no upsampling. This is most
+ * likely a bug in the hardware.
+ */
+ upsample = this->src.type != B2R2_FMT_TYPE_RASTER &&
+ b2r2_is_yuv_fmt(this->src.fmt);
+ downsample = this->dst.type != B2R2_FMT_TYPE_RASTER &&
+ b2r2_is_yuv_fmt(this->dst.fmt);
+
+ if (is_transform(req) || upsample || downsample)
+ ret = analyze_transform(this, req, &this->node_count,
+ &this->buf_count);
+ else
+ ret = analyze_copy(this, req, &this->node_count,
+ &this->buf_count);
+ }
+
+ if (ret == -ENOSYS) {
+ goto unsupported;
+ } else if (ret < 0) {
+ b2r2_log_warn(cont->dev, "%s: Analysis failed!\n", __func__);
+ goto error;
+ }
+
+ /* Setup the origin and movement of the destination window */
+ if (this->dst.hso == B2R2_TY_HSO_RIGHT_TO_LEFT) {
+ this->dst.dx = -this->dst.win.width;
+ this->dst.win.x = this->dst.rect.x + this->dst.rect.width - 1;
+ } else {
+ this->dst.dx = this->dst.win.width;
+ this->dst.win.x = this->dst.rect.x;
+ }
+ if (this->dst.vso == B2R2_TY_VSO_BOTTOM_TO_TOP) {
+ this->dst.dy = -this->dst.win.height;
+ this->dst.win.y = this->dst.rect.y + this->dst.rect.height - 1;
+ } else {
+ this->dst.dy = this->dst.win.height;
+ this->dst.win.y = this->dst.rect.y;
+ }
+
+ *buf_count = this->buf_count;
+ *node_count = this->node_count;
+
+ if (this->buf_count > 0)
+ *bufs = &this->work_bufs[0];
+
+ b2r2_log_info(cont->dev, "%s: dst.win=(%d, %d, %d, %d), "
+ "dst.dx=%d, dst.dy=%d\n", __func__, this->dst.win.x,
+ this->dst.win.y, this->dst.win.width, this->dst.win.height,
+ this->dst.dx, this->dst.dy);
+ if (this->buf_count > 0)
+ b2r2_log_info(cont->dev, "%s: buf_count=%d, buf_size=%d, "
+ "node_count=%d\n", __func__, *buf_count,
+ bufs[0]->size, *node_count);
+ else
+ b2r2_log_info(cont->dev, "%s: buf_count=%d, node_count=%d\n",
+ __func__, *buf_count, *node_count);
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+unsupported:
+ return ret;
+}
+
+/**
+ * b2r2_node_split_configure() - configures the node list
+ */
+int b2r2_node_split_configure(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *first)
+{
+ int ret;
+
+ struct b2r2_node_split_buf *dst = &this->dst;
+ struct b2r2_node *node = first;
+
+ u32 x_pixels = 0;
+ u32 y_pixels = 0;
+
+ reset_nodes(node);
+
+ while (y_pixels < dst->rect.height) {
+ s32 dst_x = dst->win.x;
+ s32 dst_w = dst->win.width;
+
+ /* Clamp window height */
+ if (dst->win.height > dst->rect.height - y_pixels)
+ dst->win.height = dst->rect.height - y_pixels;
+
+ while (x_pixels < dst->rect.width) {
+
+ /* Clamp window width */
+ if (dst_w > dst->rect.width - x_pixels)
+ dst->win.width = dst->rect.width - x_pixels;
+
+ ret = configure_tile(cont, this, node, &node);
+ if (ret < 0)
+ goto error;
+
+ dst->win.x += dst->dx;
+ x_pixels += max(dst->dx, -dst->dx);
+ b2r2_log_info(cont->dev, "%s: x_pixels=%d\n",
+ __func__, x_pixels);
+ }
+
+ dst->win.y += dst->dy;
+ y_pixels += max(dst->dy, -dst->dy);
+
+ dst->win.x = dst_x;
+ dst->win.width = dst_w;
+ x_pixels = 0;
+
+ b2r2_log_info(cont->dev, "%s: y_pixels=%d\n",
+ __func__, y_pixels);
+ }
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+/**
+ * b2r2_node_split_assign_buffers() - assigns temporary buffers to the node list
+ */
+int b2r2_node_split_assign_buffers(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *first,
+ struct b2r2_work_buf *bufs, u32 buf_count)
+{
+ struct b2r2_node *node = first;
+
+ while (node != NULL) {
+ /* The indices are offset by one */
+ if (node->dst_tmp_index) {
+ BUG_ON(node->dst_tmp_index > buf_count);
+
+ b2r2_log_info(cont->dev, "%s: assigning buf %d as "
+ "dst\n", __func__, node->dst_tmp_index);
+
+ node->node.GROUP1.B2R2_TBA =
+ bufs[node->dst_tmp_index - 1].phys_addr;
+ }
+ if (node->src_tmp_index) {
+ u32 addr = bufs[node->src_tmp_index - 1].phys_addr;
+
+ b2r2_log_info(cont->dev, "%s: assigning buf %d as src "
+ "%d ", __func__, node->src_tmp_index,
+ node->src_index);
+
+ BUG_ON(node->src_tmp_index > buf_count);
+
+ switch (node->src_index) {
+ case 1:
+ b2r2_log_info(cont->dev, "1\n");
+ node->node.GROUP3.B2R2_SBA = addr;
+ break;
+ case 2:
+ b2r2_log_info(cont->dev, "2\n");
+ node->node.GROUP4.B2R2_SBA = addr;
+ break;
+ case 3:
+ b2r2_log_info(cont->dev, "3\n");
+ node->node.GROUP5.B2R2_SBA = addr;
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+ }
+
+ b2r2_log_info(cont->dev, "%s: tba=%p\tsba=%p\n", __func__,
+ (void *)node->node.GROUP1.B2R2_TBA,
+ (void *)node->node.GROUP4.B2R2_SBA);
+
+ node = node->next;
+ }
+
+ return 0;
+}
+
+/**
+ * b2r2_node_split_unassign_buffers() - releases temporary buffers
+ */
+void b2r2_node_split_unassign_buffers(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *first)
+{
+ return;
+}
+
+/**
+ * b2r2_node_split_cancel() - cancels and releases a job instance
+ */
+void b2r2_node_split_cancel(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this)
+{
+ memset(this, 0, sizeof(*this));
+
+ return;
+}
+
+static int check_rect(struct b2r2_control *cont,
+ const struct b2r2_blt_img *img,
+ const struct b2r2_blt_rect *rect,
+ const struct b2r2_blt_rect *clip)
+{
+ int ret;
+
+ s32 l, r, b, t;
+
+ /* Check rectangle dimensions*/
+ if ((rect->width <= 0) || (rect->height <= 0)) {
+ b2r2_log_warn(cont->dev, "%s: Illegal rect (%d, %d, %d, %d)\n",
+ __func__, rect->x, rect->y, rect->width,
+ rect->height);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* If we are using clip we should only look at the intersection of the
+ rects */
+ if (clip) {
+ l = max(rect->x, clip->x);
+ t = max(rect->y, clip->y);
+ r = min(rect->x + rect->width, clip->x + clip->width);
+ b = min(rect->y + rect->height, clip->y + clip->height);
+ } else {
+ l = rect->x;
+ t = rect->y;
+ r = rect->x + rect->width;
+ b = rect->y + rect->height;
+ }
+
+ /* Check so that the rect isn't outside the buffer */
+ if ((l < 0) || (t < 0) || (l >= img->width) || (t >= img->height)) {
+ b2r2_log_warn(cont->dev, "%s: rect origin outside buffer\n",
+ __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if ((r > img->width) || (b > img->height)) {
+ b2r2_log_warn(cont->dev, "%s: rect ends outside buffer\n",
+ __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* Check so the intersected rectangle isn't empty */
+ if ((l == r) || (t == b)) {
+ b2r2_log_warn(cont->dev,
+ "%s: rect is empty (width or height zero)\n",
+ __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * bg_format_require_ivmx()
+ *
+ * Check if there are any color space conversion needed for the
+ * background to the destination format.
+ */
+static bool bg_format_require_ivmx(enum b2r2_blt_fmt bg_fmt,
+ enum b2r2_blt_fmt dst_fmt)
+{
+ if (b2r2_is_rgb_fmt(bg_fmt)) {
+ if (b2r2_is_yvu_fmt(dst_fmt))
+ return true;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return true;
+ else if (b2r2_is_yuv_fmt(dst_fmt))
+ return true;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return true;
+ } else if (b2r2_is_yvu_fmt(bg_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return true;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return true;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return true;
+ else if (b2r2_is_yuv_fmt(dst_fmt) &&
+ !b2r2_is_yvu_fmt(dst_fmt))
+ return true;
+ } else if (bg_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ bg_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ bg_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ bg_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) {
+ if (b2r2_is_rgb_fmt(dst_fmt)) {
+ return true;
+ } else if (b2r2_is_yvu_fmt(dst_fmt)) {
+ return true;
+ } else if (b2r2_is_yuv_fmt(dst_fmt)) {
+ switch (dst_fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ break;
+ default:
+ return true;
+ }
+ }
+ } else if (b2r2_is_yuv_fmt(bg_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return true;
+ else if (b2r2_is_bgr_fmt(dst_fmt))
+ return true;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return true;
+ else if (b2r2_is_yvu_fmt(dst_fmt))
+ return true;
+ } else if (b2r2_is_bgr_fmt(bg_fmt)) {
+ if (b2r2_is_rgb_fmt(dst_fmt))
+ return true;
+ else if (b2r2_is_yvu_fmt(dst_fmt))
+ return true;
+ else if (dst_fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 ||
+ dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ return true;
+ else if (b2r2_is_yuv_fmt(dst_fmt))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * analyze_fmt_conv() - analyze the format conversions needed for a job
+ */
+static int analyze_fmt_conv(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ const u32 **vmx, u32 *node_count, bool fullrange)
+{
+ enum b2r2_color_conversion cc =
+ b2r2_get_color_conversion(src->fmt, dst->fmt, fullrange);
+
+ b2r2_get_vmx(cc, vmx);
+
+ if (dst->type == B2R2_FMT_TYPE_RASTER) {
+ *node_count = 1;
+ } else if (dst->type == B2R2_FMT_TYPE_SEMI_PLANAR) {
+ *node_count = 2;
+ } else if (dst->type == B2R2_FMT_TYPE_PLANAR) {
+ *node_count = 3;
+ } else {
+ /* That's strange... */
+ BUG_ON(1);
+ }
+
+ return 0;
+}
+
+/**
+ * analyze_color_fill() - analyze a color fill operation
+ */
+static int analyze_color_fill(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count)
+{
+ int ret;
+ struct b2r2_control *cont = req->instance->control;
+
+ /* Destination must be raster for raw fill to work */
+ if (this->dst.type != B2R2_FMT_TYPE_RASTER) {
+ b2r2_log_warn(cont->dev,
+ "%s: fill requires raster destination\n",
+ __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* We will try to fill the entire rectangle in one go */
+ memcpy(&this->dst.win, &this->dst.rect, sizeof(this->dst.win));
+
+ /* Check if this is a direct fill */
+ if ((!this->blend) && ((this->flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW) ||
+ (this->dst.fmt == B2R2_BLT_FMT_32_BIT_ARGB8888) ||
+ (this->dst.fmt == B2R2_BLT_FMT_32_BIT_ABGR8888) ||
+ (this->dst.fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) ||
+ (this->dst.fmt == B2R2_BLT_FMT_32_BIT_VUYA8888))) {
+ this->type = B2R2_DIRECT_FILL;
+
+ /* The color format will be the same as the dst fmt */
+ this->src.fmt = this->dst.fmt;
+
+ /* The entire destination rectangle will be */
+ memcpy(&this->dst.win, &this->dst.rect,
+ sizeof(this->dst.win));
+ *node_count = 1;
+ } else {
+ this->type = B2R2_FILL;
+
+ /* Determine the fill color format */
+ if (this->flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW) {
+ /* The color format will be the same as the dst fmt */
+ this->src.fmt = this->dst.fmt;
+ } else {
+ /* If the dst fmt is YUV the fill fmt will be as well */
+ if (b2r2_is_yuv_fmt(this->dst.fmt)) {
+ this->src.fmt = B2R2_BLT_FMT_32_BIT_AYUV8888;
+ } else if (b2r2_is_rgb_fmt(this->dst.fmt)) {
+ this->src.fmt = B2R2_BLT_FMT_32_BIT_ARGB8888;
+ } else if (b2r2_is_bgr_fmt(this->dst.fmt)) {
+ /* Color will still be ARGB, we will translate
+ using IVMX (configured later) */
+ this->src.fmt = B2R2_BLT_FMT_32_BIT_ARGB8888;
+ } else {
+ /* Wait, what? */
+ b2r2_log_warn(cont->dev, "%s: "
+ "Illegal destination format for fill",
+ __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ /* Also, B2R2 seems to ignore the pixel alpha value */
+ if (((this->flags & B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND)
+ != 0) &&
+ ((this->flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW)
+ == 0) && b2r2_fmt_has_alpha(this->src.fmt)) {
+ u8 pixel_alpha = b2r2_get_alpha(this->src.fmt,
+ this->src.color);
+ u32 new_global = pixel_alpha * this->global_alpha / 255;
+
+ this->global_alpha = (u8)new_global;
+
+ /* Set the pixel alpha to full opaque so we don't get
+ any nasty surprises */
+ this->src.color = b2r2_set_alpha(this->src.fmt, 0xFF,
+ this->src.color);
+ }
+
+ ret = analyze_fmt_conv(
+ cont, &this->src, &this->dst, &this->ivmx,
+ node_count, this->fullrange);
+ if (ret < 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+
+}
+
+/**
+ * analyze_transform() - analyze a transform operation (rescale, rotate, etc.)
+ */
+static int analyze_transform(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ bool is_scaling;
+#ifdef CONFIG_B2R2_DEBUG
+ struct b2r2_control *cont = req->instance->control;
+#endif
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /*
+ * The transform enum is defined so that all rotation transforms are
+ * masked with the rotation flag
+ */
+ this->rotation = (this->transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) != 0;
+
+ /* B2R2 cannot do rotations if the destination is not raster, or 422R */
+ if (this->rotation && (this->dst.type != B2R2_FMT_TYPE_RASTER ||
+ this->dst.fmt == B2R2_BLT_FMT_Y_CB_Y_CR ||
+ this->dst.fmt == B2R2_BLT_FMT_CB_Y_CR_Y)) {
+ b2r2_log_warn(cont->dev,
+ "%s: Unsupported operation "
+ "(rot && (!dst_raster || dst==422R))",
+ __func__);
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ /* Flip the image by changing the scan order of the destination */
+ if (this->transform & B2R2_BLT_TRANSFORM_FLIP_H)
+ this->dst.hso = B2R2_TY_HSO_RIGHT_TO_LEFT;
+ if (this->transform & B2R2_BLT_TRANSFORM_FLIP_V)
+ this->dst.vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+
+ /* Check for scaling */
+ if (this->rotation) {
+ is_scaling = (this->src.rect.width != this->dst.rect.height) ||
+ (this->src.rect.height != this->dst.rect.width);
+ } else {
+ is_scaling = (this->src.rect.width != this->dst.rect.width) ||
+ (this->src.rect.height != this->dst.rect.height);
+ }
+
+ /* Plane separated formats must be treated as scaling */
+ is_scaling = is_scaling ||
+ (this->src.type == B2R2_FMT_TYPE_SEMI_PLANAR) ||
+ (this->src.type == B2R2_FMT_TYPE_PLANAR) ||
+ (this->dst.type == B2R2_FMT_TYPE_SEMI_PLANAR) ||
+ (this->dst.type == B2R2_FMT_TYPE_PLANAR);
+
+ if (is_scaling && this->rotation && this->blend) {
+ /* TODO: This is unsupported. Fix it! */
+ b2r2_log_info(cont->dev, "%s: Unsupported operation "
+ "(rot+rescale+blend)\n", __func__);
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+
+ /* Check which type of transform */
+ if (is_scaling && this->rotation) {
+ ret = analyze_rot_scale(this, req, node_count, buf_count);
+ if (ret < 0)
+ goto error;
+ } else if (is_scaling) {
+ ret = analyze_scaling(this, req, node_count, buf_count);
+ if (ret < 0)
+ goto error;
+ } else if (this->rotation) {
+ ret = analyze_rotate(this, req, node_count, buf_count);
+ if (ret < 0)
+ goto error;
+ } else {
+ /* No additional nodes needed for a flip */
+ ret = analyze_copy(this, req, node_count, buf_count);
+ if (ret < 0)
+ goto error;
+ this->type = B2R2_FLIP;
+ }
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+unsupported:
+ return ret;
+}
+
+/**
+ * analyze_copy() - analyze a copy operation
+ */
+static int analyze_copy(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ struct b2r2_control *cont = req->instance->control;
+
+ memcpy(&this->dst.win, &this->dst.rect, sizeof(this->dst.win));
+
+ if (!this->blend &&
+ !(this->flags & B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) &&
+ (this->src.fmt == this->dst.fmt) &&
+ (this->src.type == B2R2_FMT_TYPE_RASTER) &&
+ (this->dst.rect.x >= this->clip_rect.x) &&
+ (this->dst.rect.y >= this->clip_rect.y) &&
+ (this->dst.rect.x + this->dst.rect.width <=
+ this->clip_rect.x + this->clip_rect.width) &&
+ (this->dst.rect.y + this->dst.rect.height <=
+ this->clip_rect.y + this->clip_rect.height)) {
+ this->type = B2R2_DIRECT_COPY;
+ *node_count = 1;
+ } else {
+ u32 copy_count;
+
+ this->type = B2R2_COPY;
+
+ ret = analyze_fmt_conv(cont, &this->src, &this->dst,
+ &this->ivmx, &copy_count, this->fullrange);
+ if (ret < 0)
+ goto error;
+
+ *node_count = copy_count;
+ }
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+static int calc_rot_count(u32 width, u32 height)
+{
+ int count;
+
+ count = width / B2R2_ROTATE_MAX_WIDTH;
+ if (width % B2R2_ROTATE_MAX_WIDTH)
+ count++;
+ if (height > B2R2_ROTATE_MAX_WIDTH &&
+ height % B2R2_ROTATE_MAX_WIDTH)
+ count *= 2;
+
+ return count;
+}
+
+static int analyze_rot_scale_downscale(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ struct b2r2_control *cont = req->instance->control;
+ struct b2r2_node_split_buf *src = &this->src;
+ struct b2r2_node_split_buf *dst = &this->dst;
+ struct b2r2_node_split_buf *tmp = &this->tmp_bufs[0];
+
+ u32 num_rows;
+ u32 num_cols;
+ u32 rot_count;
+ u32 rescale_count;
+ u32 nodes_per_rot;
+ u32 nodes_per_rescale;
+ u32 right_width;
+ u32 bottom_height;
+ const u32 *dummy_vmx;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ /* Calculate the desired tmp buffer size */
+ tmp->win.width = rescale(cont, B2R2_RESCALE_MAX_WIDTH - 1, this->h_rsf);
+ tmp->win.width >>= 10;
+ tmp->win.width = min(tmp->win.width, dst->rect.height);
+ tmp->win.height = dst->rect.width;
+
+ setup_tmp_buf(cont, tmp, this->max_buf_size, dst->fmt, tmp->win.width,
+ tmp->win.height);
+ tmp->tmp_buf_index = 1;
+ this->work_bufs[0].size = tmp->pitch * tmp->height;
+
+ tmp->win.width = tmp->rect.width;
+ tmp->win.height = tmp->rect.height;
+
+ tmp->dither = dst->dither;
+ dst->dither = 0;
+
+ /* Update the dst window with the actual tmp buffer dimensions */
+ dst->win.width = tmp->win.height;
+ dst->win.height = tmp->win.width;
+
+ /* The rotated stripes are written to the destination bottom-up */
+ if (this->dst.vso == B2R2_TY_VSO_TOP_TO_BOTTOM)
+ this->dst.vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+ else
+ this->dst.vso = B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ /*
+ * Calculate how many nodes are required to copy to and from the tmp
+ * buffer
+ */
+ ret = analyze_fmt_conv(cont, src, tmp, &this->ivmx, &nodes_per_rescale,
+ this->fullrange);
+ if (ret < 0)
+ goto error;
+
+ /* We will not do any format conversion in the rotation stage */
+ ret = analyze_fmt_conv(cont, tmp, dst, &dummy_vmx, &nodes_per_rot,
+ this->fullrange);
+ if (ret < 0)
+ goto error;
+
+ /* Calculate node count for the inner tiles */
+ num_cols = dst->rect.width / dst->win.width;
+ num_rows = dst->rect.height / dst->win.height;
+
+ rescale_count = num_cols * num_rows;
+ rot_count = calc_rot_count(dst->win.height, dst->win.width) *
+ num_cols * num_rows;
+
+ right_width = dst->rect.width % dst->win.width;
+ bottom_height = dst->rect.height % dst->win.height;
+
+ /* Calculate node count for the rightmost tiles */
+ if (right_width) {
+ u32 count = calc_rot_count(dst->win.height, right_width);
+
+ rot_count += count * num_rows;
+ rescale_count += num_rows;
+ b2r2_log_info(cont->dev, "%s: rightmost: %d nodes\n", __func__,
+ count*num_rows);
+ }
+
+ /* Calculate node count for the bottom tiles */
+ if (bottom_height) {
+ u32 count = calc_rot_count(bottom_height, dst->win.width);
+
+ rot_count += count * num_cols;
+ rescale_count += num_cols;
+ b2r2_log_info(cont->dev, "%s: bottom: %d nodes\n", __func__,
+ count * num_cols);
+
+ }
+
+ /* And finally for the bottom right corner */
+ if (right_width && bottom_height) {
+ u32 count = calc_rot_count(bottom_height, right_width);
+
+ rot_count += count;
+ rescale_count++;
+ b2r2_log_info(cont->dev, "%s: bottom right: %d nodes\n",
+ __func__, count);
+
+ }
+
+ *node_count = rot_count * nodes_per_rot;
+ *node_count += rescale_count * nodes_per_rescale;
+ *buf_count = 1;
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+static int analyze_rot_scale_upscale(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ /* TODO: When upscaling we should optimally to the rotation first... */
+ return analyze_rot_scale_downscale(this, req, node_count, buf_count);
+}
+
+/**
+ * analyze_rot_scaling() - analyzes a combined rotation and scaling op
+ */
+static int analyze_rot_scale(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ bool upscale;
+ struct b2r2_control *cont = req->instance->control;
+
+ ret = analyze_scale_factors(cont, this);
+ if (ret < 0)
+ goto error;
+
+ upscale = (u32)this->h_rsf * (u32)this->v_rsf < (1 << 20);
+
+ if (upscale)
+ ret = analyze_rot_scale_upscale(this, req, node_count,
+ buf_count);
+ else
+ ret = analyze_rot_scale_downscale(this, req, node_count,
+ buf_count);
+
+ if (ret < 0)
+ goto error;
+
+ this->type = B2R2_SCALE_AND_ROTATE;
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/**
+ * analyze_scaling() - analyze a rescale operation
+ */
+static int analyze_scaling(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ u32 copy_count;
+ u32 nbr_cols;
+ s32 dst_w;
+ struct b2r2_control *cont = req->instance->control;
+
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ ret = analyze_scale_factors(cont, this);
+ if (ret < 0)
+ goto error;
+
+ /* Find out how many nodes a simple copy would require */
+ ret = analyze_fmt_conv(cont, &this->src, &this->dst, &this->ivmx,
+ &copy_count, this->fullrange);
+ if (ret < 0)
+ goto error;
+
+ memcpy(&this->dst.win, &this->dst.rect, sizeof(this->dst.win));
+
+ /*
+ * We need to subtract from the actual maximum rescale width since the
+ * start of the stripe will be floored and the end ceiled. This could in
+ * some cases cause the stripe to be one pixel more than the maximum
+ * width.
+ *
+ * Example:
+ * x = 127.8, w = 127.8
+ *
+ * The stripe will touch pixels 127.8 through 255.6, i.e. 129 pixels.
+ */
+ dst_w = rescale(cont, B2R2_RESCALE_MAX_WIDTH - 1, this->h_rsf);
+ if (dst_w < (1 << 10))
+ dst_w = 1;
+ else
+ dst_w >>= 10;
+
+ b2r2_log_info(cont->dev, "%s: dst_w=%d dst.rect.width=%d\n",
+ __func__, dst_w, this->dst.rect.width);
+
+ this->dst.win.width = min(dst_w, this->dst.rect.width);
+
+ b2r2_log_info(cont->dev, "%s: dst.win.width=%d\n",
+ __func__, this->dst.win.width);
+
+ nbr_cols = this->dst.rect.width / this->dst.win.width;
+ if (this->dst.rect.width % this->dst.win.width)
+ nbr_cols++;
+
+ *node_count = copy_count * nbr_cols;
+
+ this->type = B2R2_SCALE;
+
+ b2r2_log_info(cont->dev, "%s exit\n", __func__);
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+
+}
+
+/**
+ * analyze_rotate() - analyze a rotate operation
+ */
+static int analyze_rotate(struct b2r2_node_split_job *this,
+ const struct b2r2_blt_request *req, u32 *node_count,
+ u32 *buf_count)
+{
+ int ret;
+ u32 nodes_per_tile;
+ struct b2r2_control *cont = req->instance->control;
+
+ /* Find out how many nodes a simple copy would require */
+ ret = analyze_fmt_conv(cont, &this->src, &this->dst, &this->ivmx,
+ &nodes_per_tile, this->fullrange);
+ if (ret < 0)
+ goto error;
+
+ this->type = B2R2_ROTATE;
+
+ /* The rotated stripes are written to the destination bottom-up */
+ if (this->dst.vso == B2R2_TY_VSO_TOP_TO_BOTTOM)
+ this->dst.vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+ else
+ this->dst.vso = B2R2_TY_VSO_TOP_TO_BOTTOM;
+
+ memcpy(&this->dst.win, &this->dst.rect, sizeof(this->dst.win));
+
+ this->dst.win.height = min(this->dst.win.height, B2R2_ROTATE_MAX_WIDTH);
+
+ /*
+ * B2R2 cannot do rotations on stripes that are not a multiple of 16
+ * pixels high (if larger than 16 pixels).
+ */
+ if (this->dst.win.width > 16)
+ this->dst.win.width -= (this->dst.win.width % 16);
+
+ /* Blending cannot be combined with rotation */
+ if (this->blend) {
+ struct b2r2_node_split_buf *tmp = &this->tmp_bufs[0];
+ enum b2r2_blt_fmt tmp_fmt;
+
+ if (b2r2_is_yuv_fmt(this->dst.fmt))
+ tmp_fmt = B2R2_BLT_FMT_32_BIT_AYUV8888;
+ else if (b2r2_is_bgr_fmt(this->dst.fmt))
+ tmp_fmt = B2R2_BLT_FMT_32_BIT_ABGR8888;
+ else
+ tmp_fmt = B2R2_BLT_FMT_32_BIT_ARGB8888;
+
+ setup_tmp_buf(cont, tmp, this->max_buf_size, tmp_fmt,
+ this->dst.win.width, this->dst.win.height);
+
+ tmp->tmp_buf_index = 1;
+
+ tmp->vso = B2R2_TY_VSO_BOTTOM_TO_TOP;
+
+ this->dst.win.width = tmp->rect.width;
+ this->dst.win.height = tmp->rect.height;
+
+ memcpy(&tmp->win, &tmp->rect, sizeof(tmp->win));
+
+ *buf_count = 1;
+ this->work_bufs[0].size = tmp->pitch * tmp->height;
+
+ /*
+ * One more node per tile is required to rotate to the temp
+ * buffer.
+ */
+ nodes_per_tile++;
+ }
+
+ /* Finally, calculate the node count */
+ *node_count = nodes_per_tile *
+ calc_rot_count(this->src.rect.width, this->src.rect.height);
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * analyze_scale_factors() - determines the scale factors for the op
+ */
+static int analyze_scale_factors(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this)
+{
+ int ret;
+
+ u16 hsf;
+ u16 vsf;
+
+ if (this->rotation) {
+ ret = calculate_scale_factor(cont->dev, this->src.rect.width,
+ this->dst.rect.height, &hsf);
+ if (ret < 0)
+ goto error;
+
+ ret = calculate_scale_factor(cont->dev, this->src.rect.height,
+ this->dst.rect.width, &vsf);
+ if (ret < 0)
+ goto error;
+ } else {
+ ret = calculate_scale_factor(cont->dev, this->src.rect.width,
+ this->dst.rect.width, &hsf);
+ if (ret < 0)
+ goto error;
+
+ ret = calculate_scale_factor(cont->dev, this->src.rect.height,
+ this->dst.rect.height, &vsf);
+ if (ret < 0)
+ goto error;
+ }
+
+ this->h_rescale = hsf != (1 << 10);
+ this->v_rescale = vsf != (1 << 10);
+
+ this->h_rsf = hsf;
+ this->v_rsf = vsf;
+
+ b2r2_log_info(cont->dev, "%s: h_rsf=%.4x\n", __func__, this->h_rsf);
+ b2r2_log_info(cont->dev, "%s: v_rsf=%.4x\n", __func__, this->v_rsf);
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_tile() - configures one tile of a blit operation
+ */
+static int configure_tile(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *node,
+ struct b2r2_node **next)
+{
+ int ret = 0;
+
+ struct b2r2_node *last;
+ struct b2r2_node_split_buf *src = &this->src;
+ struct b2r2_node_split_buf *dst = &this->dst;
+ struct b2r2_node_split_buf *bg = &this->bg;
+
+ struct b2r2_blt_rect dst_norm;
+ struct b2r2_blt_rect src_norm;
+ struct b2r2_blt_rect bg_norm;
+
+ /* Normalize the dest coords to the dest rect coordinate space */
+ dst_norm.x = dst->win.x - dst->rect.x;
+ dst_norm.y = dst->win.y - dst->rect.y;
+ dst_norm.width = dst->win.width;
+ dst_norm.height = dst->win.height;
+
+ if (dst->vso == B2R2_TY_VSO_BOTTOM_TO_TOP) {
+ /* The y coord should be counted from the bottom */
+ dst_norm.y = dst->rect.height - (dst_norm.y + 1);
+ }
+ if (dst->hso == B2R2_TY_HSO_RIGHT_TO_LEFT) {
+ /* The x coord should be counted from the right */
+ dst_norm.x = dst->rect.width - (dst_norm.x + 1);
+ }
+
+ /* If the destination is rotated we should swap x, y */
+ if (this->rotation) {
+ src_norm.x = dst_norm.y;
+ src_norm.y = dst_norm.x;
+ src_norm.width = dst_norm.height;
+ src_norm.height = dst_norm.width;
+ } else {
+ src_norm.x = dst_norm.x;
+ src_norm.y = dst_norm.y;
+ src_norm.width = dst_norm.width;
+ src_norm.height = dst_norm.height;
+ }
+
+ /* Convert to src coordinate space */
+ src->win.x = src_norm.x + src->rect.x;
+ src->win.y = src_norm.y + src->rect.y;
+ src->win.width = src_norm.width;
+ src->win.height = src_norm.height;
+
+ /* Set bg norm */
+ bg_norm.x = dst->win.x - dst->rect.x;
+ bg_norm.y = dst->win.y - dst->rect.y;
+ bg_norm.width = dst->win.width;
+ bg_norm.height = dst->win.height;
+
+ /* Convert to bg coordinate space */
+ bg->win.x = bg_norm.x + bg->rect.x;
+ bg->win.y = bg_norm.y + bg->rect.y;
+ bg->win.width = bg_norm.width;
+ bg->win.height = bg_norm.height;
+ bg->vso = dst->vso;
+ bg->hso = dst->hso;
+
+ /* Do the configuration depending on operation type */
+ switch (this->type) {
+ case B2R2_DIRECT_FILL:
+ configure_direct_fill(cont, node, this->src.color, dst, &last);
+ break;
+
+ case B2R2_DIRECT_COPY:
+ configure_direct_copy(cont, node, src, dst, &last);
+ break;
+
+ case B2R2_FILL:
+ ret = configure_fill(cont, node, src->color, src->fmt,
+ dst, this->ivmx, &last);
+ break;
+
+ case B2R2_FLIP: /* FLIP is just a copy with different VSO/HSO */
+ case B2R2_COPY:
+ ret = configure_copy(
+ cont, node, src, dst, this->ivmx, &last, this);
+ break;
+
+ case B2R2_ROTATE:
+ {
+ struct b2r2_node_split_buf *tmp = &this->tmp_bufs[0];
+
+ if (this->blend) {
+ b2r2_log_info(cont->dev, "%s: rotation + "
+ "blend\n", __func__);
+
+ tmp->win.x = 0;
+ tmp->win.y = tmp->win.height - 1;
+ tmp->win.width = dst->win.width;
+ tmp->win.height = dst->win.height;
+
+ /* Rotate to the temp buf */
+ ret = configure_rotate(cont, node, src, tmp,
+ this->ivmx, &node, NULL);
+ if (ret < 0)
+ goto error;
+
+ /* Then do a copy to the destination */
+ ret = configure_copy(cont, node, tmp, dst, NULL,
+ &last, this);
+ } else {
+ /* Just do a rotation */
+ ret = configure_rotate(cont, node, src, dst,
+ this->ivmx, &last, this);
+ }
+ }
+ break;
+
+ case B2R2_SCALE:
+ ret = configure_scale(cont, node, src, dst, this->h_rsf,
+ this->v_rsf, this->ivmx, &last, this);
+ break;
+
+ case B2R2_SCALE_AND_ROTATE:
+ ret = configure_rot_scale(cont, this, node, &last);
+ break;
+
+ default:
+ b2r2_log_warn(cont->dev, "%s: Unsupported request\n", __func__);
+ ret = -ENOSYS;
+ goto error;
+ break;
+
+ }
+
+ if (ret < 0)
+ goto error;
+
+ /* Scale and rotate will configure its own blending and clipping */
+ if (this->type != B2R2_SCALE_AND_ROTATE) {
+
+ /* Configure blending and clipping */
+ do {
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: "
+ "Internal error! Out of nodes!\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (this->blend) {
+ if (this->flags & B2R2_BLT_FLAG_BG_BLEND)
+ configure_bg(cont, node, bg,
+ this->swap_fg_bg);
+ else
+ configure_bg(cont, node, dst,
+ this->swap_fg_bg);
+ configure_blend(cont, node, this->flags,
+ this->global_alpha);
+ }
+ if (this->clip)
+ configure_clip(cont, node, &this->clip_rect);
+
+ node = node->next;
+
+ } while (node != last);
+ }
+
+ /* Consume the nodes */
+ *next = last;
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: Error!\n", __func__);
+ return ret;
+}
+
+/*
+ * configure_sub_rot() - configure a sub-rotation
+ *
+ * This functions configures a set of nodes for rotation using the destination
+ * window instead of the rectangle for calculating tiles.
+ */
+static int configure_sub_rot(struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ const u32 *ivmx, struct b2r2_node **next,
+ struct b2r2_node_split_job *job)
+{
+ int ret;
+
+ struct b2r2_blt_rect src_win;
+ struct b2r2_blt_rect dst_win;
+
+ u32 y_pixels = 0;
+ u32 x_pixels = 0;
+
+ memcpy(&src_win, &src->win, sizeof(src_win));
+ memcpy(&dst_win, &dst->win, sizeof(dst_win));
+
+ b2r2_log_info(cont->dev, "%s: src_win=(%d, %d, %d, %d) "
+ "dst_win=(%d, %d, %d, %d)\n", __func__,
+ src_win.x, src_win.y, src_win.width, src_win.height,
+ dst_win.x, dst_win.y, dst_win.width, dst_win.height);
+
+ dst->win.height = B2R2_ROTATE_MAX_WIDTH;
+ if (dst->win.width % B2R2_ROTATE_MAX_WIDTH)
+ dst->win.width -= dst->win.width % B2R2_ROTATE_MAX_WIDTH;
+
+ while (x_pixels < dst_win.width) {
+ u32 src_x = src->win.x;
+ u32 src_w = src->win.width;
+ u32 dst_y = dst->win.y;
+ u32 dst_h = dst->win.height;
+
+ dst->win.width = min(dst->win.width, dst_win.width -
+ (int)x_pixels);
+ src->win.height = dst->win.width;
+
+ b2r2_log_info(cont->dev, "%s: x_pixels=%d\n",
+ __func__, x_pixels);
+
+ while (y_pixels < dst_win.height) {
+ dst->win.height = min(dst->win.height,
+ dst_win.height - (int)y_pixels);
+ src->win.width = dst->win.height;
+
+ b2r2_log_info(cont->dev, "%s: y_pixels=%d\n",
+ __func__, y_pixels);
+
+ ret = configure_rotate(cont, node, src, dst,
+ ivmx, &node, job);
+ if (ret < 0)
+ goto error;
+
+ src->win.x += (src->hso == B2R2_TY_HSO_LEFT_TO_RIGHT) ?
+ src->win.width : -src->win.width;
+ dst->win.y += (dst->vso == B2R2_TY_VSO_TOP_TO_BOTTOM) ?
+ dst->win.height : -dst->win.height;
+
+ y_pixels += dst->win.height;
+ }
+
+ src->win.x = src_x;
+ src->win.y += (src->vso == B2R2_TY_VSO_TOP_TO_BOTTOM) ?
+ src->win.height : -src->win.height;
+ src->win.width = src_w;
+
+ dst->win.x += (dst->hso == B2R2_TY_HSO_LEFT_TO_RIGHT) ?
+ dst->win.width : -dst->win.width;
+ dst->win.y = dst_y;
+ dst->win.height = dst_h;
+
+ x_pixels += dst->win.width;
+ y_pixels = 0;
+
+ }
+
+ memcpy(&src->win, &src_win, sizeof(src->win));
+ memcpy(&dst->win, &dst_win, sizeof(dst->win));
+
+ *next = node;
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_rot_downscale() - configures a combined rotate and downscale
+ *
+ * When doing a downscale it is better to do the rotation last.
+ */
+static int configure_rot_downscale(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this,
+ struct b2r2_node *node, struct b2r2_node **next)
+{
+ int ret;
+
+ struct b2r2_node_split_buf *src = &this->src;
+ struct b2r2_node_split_buf *dst = &this->dst;
+ struct b2r2_node_split_buf *tmp = &this->tmp_bufs[0];
+
+ tmp->win.x = 0;
+ tmp->win.y = 0;
+ tmp->win.width = dst->win.height;
+ tmp->win.height = dst->win.width;
+
+ ret = configure_scale(cont, node, src, tmp, this->h_rsf, this->v_rsf,
+ this->ivmx, &node, this);
+ if (ret < 0)
+ goto error;
+
+ ret = configure_sub_rot(cont, node, tmp, dst, NULL, &node, this);
+ if (ret < 0)
+ goto error;
+
+ *next = node;
+
+ return 0;
+
+error:
+ b2r2_log_info(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_rot_upscale() - configures a combined rotate and upscale
+ *
+ * When doing an upscale it is better to do the rotation first.
+ */
+static int configure_rot_upscale(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *node,
+ struct b2r2_node **next)
+{
+ /* TODO: Implement a optimal upscale (rotation first) */
+ return configure_rot_downscale(cont, this, node, next);
+}
+
+/**
+ * configure_rot_scale() - configures a combined rotation and scaling op
+ */
+static int configure_rot_scale(struct b2r2_control *cont,
+ struct b2r2_node_split_job *this, struct b2r2_node *node,
+ struct b2r2_node **next)
+{
+ int ret;
+
+ bool upscale = (u32)this->h_rsf * (u32)this->v_rsf < (1 << 10);
+
+ if (upscale)
+ ret = configure_rot_upscale(cont, this, node, next);
+ else
+ ret = configure_rot_downscale(cont, this, node, next);
+
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_direct_fill() - configures the given node for direct fill
+ *
+ * @node - the node to configure
+ * @color - the fill color
+ * @dst - the destination buffer
+ * @next - the next empty node in the node list
+ *
+ * This operation will always consume one node only.
+ */
+static void configure_direct_fill(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ u32 color,
+ struct b2r2_node_split_buf *dst,
+ struct b2r2_node **next)
+{
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_COLOR_FILL | B2R2_CIC_SOURCE_1;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_1_DIRECT_FILL;
+
+ /* Target setup */
+ set_target(node, dst->addr, dst);
+
+ /* Source setup */
+
+ /* It seems B2R2 checks so that source and dest has the same format */
+ node->node.GROUP3.B2R2_STY = b2r2_to_native_fmt(dst->fmt);
+ node->node.GROUP2.B2R2_S1CF = color;
+ node->node.GROUP2.B2R2_S2CF = 0;
+
+ /* Consume the node */
+ *next = node->next;
+}
+
+/**
+ * configure_direct_copy() - configures the node for direct copy
+ *
+ * @node - the node to configure
+ * @src - the source buffer
+ * @dst - the destination buffer
+ * @next - the next empty node in the node list
+ *
+ * This operation will always consume one node only.
+ */
+static void configure_direct_copy(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ struct b2r2_node **next)
+{
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_1;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_1_DIRECT_COPY;
+
+ /* Source setup, use the base function to avoid altering the INS */
+ set_src(&node->node.GROUP3, src->addr, src);
+
+ /* Target setup */
+ set_target(node, dst->addr, dst);
+
+ /* Consume the node */
+ *next = node->next;
+}
+
+/**
+ * configure_fill() - configures the given node for color fill
+ *
+ * @node - the node to configure
+ * @color - the fill color
+ * @fmt - the source color format
+ * @dst - the destination buffer
+ * @next - the next empty node in the node list
+ *
+ * A normal fill operation can be combined with any other per pixel operations
+ * such as blend.
+ *
+ * This operation will consume as many nodes as are required to write to the
+ * destination format.
+ */
+static int configure_fill(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ u32 color,
+ enum b2r2_blt_fmt fmt,
+ struct b2r2_node_split_buf *dst,
+ const u32 *ivmx,
+ struct b2r2_node **next)
+{
+ int ret;
+ struct b2r2_node *last;
+
+ /* Configure the destination */
+ ret = configure_dst(cont, node, dst, ivmx, &last);
+ if (ret < 0)
+ goto error;
+
+ do {
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: "
+ "Internal error! Out of nodes!\n", __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2 |
+ B2R2_CIC_COLOR_FILL;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_COLOR_FILL_REGISTER;
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+
+ /* B2R2 has a bug that disables color fill from S2. As a
+ workaround we use S1 for the color. */
+ node->node.GROUP2.B2R2_S1CF = 0;
+ node->node.GROUP2.B2R2_S2CF = color;
+
+ /* TO BE REMOVED: */
+ set_src_2(node, dst->addr, dst);
+ node->node.GROUP4.B2R2_STY = b2r2_to_native_fmt(fmt);
+
+ /* Setup the iVMX for color conversion */
+ if (ivmx != NULL)
+ set_ivmx(node, ivmx);
+
+ if ((dst->type == B2R2_FMT_TYPE_PLANAR) ||
+ (dst->type == B2R2_FMT_TYPE_SEMI_PLANAR)) {
+
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP8.B2R2_FCTL =
+ B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_RESIZER;
+ node->node.GROUP9.B2R2_RSF =
+ (1 << (B2R2_RSF_HSRC_INC_SHIFT + 10)) |
+ (1 << (B2R2_RSF_VSRC_INC_SHIFT + 10));
+ node->node.GROUP9.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+
+ node->node.GROUP10.B2R2_RSF =
+ (1 << (B2R2_RSF_HSRC_INC_SHIFT + 10)) |
+ (1 << (B2R2_RSF_VSRC_INC_SHIFT + 10));
+ node->node.GROUP10.B2R2_RZI =
+ B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT);
+ }
+
+ node = node->next;
+
+ } while (node != last);
+
+ /* Consume the nodes */
+ *next = node;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_copy() - configures the given node for a copy operation
+ *
+ * @node - the node to configure
+ * @src - the source buffer
+ * @dst - the destination buffer
+ * @ivmx - the iVMX to use for color conversion
+ * @next - the next empty node in the node list
+ *
+ * This operation will consume as many nodes as are required to write to the
+ * destination format.
+ */
+static int configure_copy(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ const u32 *ivmx,
+ struct b2r2_node **next,
+ struct b2r2_node_split_job *this)
+{
+ int ret;
+
+ struct b2r2_node *last;
+
+ ret = configure_dst(cont, node, dst, ivmx, &last);
+ if (ret < 0)
+ goto error;
+
+ /* Configure the source for each node */
+ do {
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: "
+ " Internal error! Out of nodes!\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BYPASS_S2_S3;
+ if (this != NULL &&
+ (this->flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY)
+ != 0) {
+ u32 key_color = 0;
+
+ node->node.GROUP0.B2R2_ACK |=
+ B2R2_ACK_CKEY_SEL_SRC_AFTER_CLUT |
+ B2R2_ACK_CKEY_RED_MATCH_IF_BETWEEN |
+ B2R2_ACK_CKEY_GREEN_MATCH_IF_BETWEEN |
+ B2R2_ACK_CKEY_BLUE_MATCH_IF_BETWEEN;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_CKEY_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_COLOR_KEY;
+
+ key_color = b2r2_to_RGB888(this->flag_param, src->fmt);
+ node->node.GROUP12.B2R2_KEY1 = key_color;
+ node->node.GROUP12.B2R2_KEY2 = key_color;
+ }
+
+ if (this != NULL &&
+ (this->flags &
+ B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) != 0) {
+ struct b2r2_blt_request *request =
+ container_of(this, struct b2r2_blt_request,
+ node_split_job);
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_CLUTOP_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_CLUT;
+ node->node.GROUP7.B2R2_CCO =
+ B2R2_CCO_CLUT_COLOR_CORRECTION |
+ B2R2_CCO_CLUT_UPDATE;
+ node->node.GROUP7.B2R2_CML = request->clut_phys_addr;
+ }
+ /* Configure the source(s) */
+ configure_src(cont, node, src, ivmx);
+
+ node = node->next;
+ } while (node != last);
+
+ /* Consume the nodes */
+ *next = node;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_rotate() - configures the given node for rotation
+ *
+ * @node - the node to configure
+ * @src - the source buffer
+ * @dst - the destination buffer
+ * @ivmx - the iVMX to use for color conversion
+ * @next - the next empty node in the node list
+ *
+ * This operation will consume as many nodes are are required by the combination
+ * of rotating and writing the destination format.
+ */
+static int configure_rotate(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ const u32 *ivmx,
+ struct b2r2_node **next,
+ struct b2r2_node_split_job *this)
+{
+ int ret;
+
+ struct b2r2_node *last;
+
+ ret = configure_copy(cont, node, src, dst, ivmx, &last, this);
+ if (ret < 0)
+ goto error;
+
+ do {
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: "
+ "Internal error! Out of nodes!\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_ROTATION_ENABLED;
+
+ b2r2_log_debug(cont->dev, "%s:\n"
+ "\tB2R2_TXY: %.8x\tB2R2_TSZ: %.8x\n"
+ "\tB2R2_S1XY: %.8x\tB2R2_S1SZ: %.8x\n"
+ "\tB2R2_S2XY: %.8x\tB2R2_S2SZ: %.8x\n"
+ "\tB2R2_S3XY: %.8x\tB2R2_S3SZ: %.8x\n"
+ "-----------------------------------\n",
+ __func__, node->node.GROUP1.B2R2_TXY,
+ node->node.GROUP1.B2R2_TSZ,
+ node->node.GROUP3.B2R2_SXY,
+ node->node.GROUP3.B2R2_SSZ,
+ node->node.GROUP4.B2R2_SXY,
+ node->node.GROUP4.B2R2_SSZ,
+ node->node.GROUP5.B2R2_SXY,
+ node->node.GROUP5.B2R2_SSZ);
+
+ node = node->next;
+
+ } while (node != last);
+
+ /* Consume the nodes */
+ *next = node;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: error!\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_scale() - configures the given node for scaling
+ *
+ * @node - the node to configure
+ * @src - the source buffer
+ * @dst - the destination buffer
+ * @h_rsf - the horizontal rescale factor
+ * @v_rsf - the vertical rescale factor
+ * @ivmx - the iVMX to use for color conversion
+ * @next - the next empty node in the node list
+ */
+static int configure_scale(
+ struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src,
+ struct b2r2_node_split_buf *dst,
+ u16 h_rsf, u16 v_rsf,
+ const u32 *ivmx, struct b2r2_node **next,
+ struct b2r2_node_split_job *this)
+{
+ int ret;
+
+ struct b2r2_node *last;
+
+ struct b2r2_filter_spec *hf = NULL;
+ struct b2r2_filter_spec *vf = NULL;
+
+ u32 fctl = 0;
+ u32 rsf = 0;
+ u32 rzi = 0;
+ u32 hsrc_init = 0;
+ u32 vsrc_init = 0;
+ u32 hfp = 0;
+ u32 vfp = 0;
+
+ u16 luma_h_rsf = h_rsf;
+ u16 luma_v_rsf = v_rsf;
+
+ struct b2r2_filter_spec *luma_hf = NULL;
+ struct b2r2_filter_spec *luma_vf = NULL;
+
+ u32 luma_fctl = 0;
+ u32 luma_rsf = 0;
+ u32 luma_rzi = 0;
+ u32 luma_hsrc_init = 0;
+ u32 luma_vsrc_init = 0;
+ u32 luma_hfp = 0;
+ u32 luma_vfp = 0;
+
+ s32 src_x;
+ s32 src_y;
+ s32 src_w;
+ s32 src_h;
+
+ bool upsample;
+ bool downsample;
+
+ struct b2r2_blt_rect tmp_win = src->win;
+ bool src_raster = src->type == B2R2_FMT_TYPE_RASTER;
+ bool dst_raster = dst->type == B2R2_FMT_TYPE_RASTER;
+
+ /* Rescale the normalized source window */
+ src_x = inv_rescale(src->win.x - src->rect.x, luma_h_rsf);
+ src_y = inv_rescale(src->win.y - src->rect.y, luma_v_rsf);
+ src_w = inv_rescale(src->win.width, luma_h_rsf);
+ src_h = inv_rescale(src->win.height, luma_v_rsf);
+
+ /* Convert to src coordinate space */
+ src->win.x = (src_x >> 10) + src->rect.x;
+ src->win.y = (src_y >> 10) + src->rect.y;
+
+ /*
+ * Since the stripe might start and end on a fractional pixel
+ * we need to count all the touched pixels in the width.
+ *
+ * Example:
+ * src_x = 1.8, src_w = 2.8
+ *
+ * The stripe touches pixels 1.8 through 4.6, i.e. 4 pixels
+ */
+ src->win.width = ((src_x & 0x3ff) + src_w + 0x3ff) >> 10;
+ src->win.height = ((src_y & 0x3ff) + src_h + 0x3ff) >> 10;
+
+ luma_hsrc_init = src_x & 0x3ff;
+ luma_vsrc_init = src_y & 0x3ff;
+
+ /* Check for upsampling of chroma */
+ upsample = !src_raster && !b2r2_is_yuv444_fmt(src->fmt);
+ if (upsample) {
+ h_rsf /= 2;
+
+ if (b2r2_is_yuv420_fmt(src->fmt))
+ v_rsf /= 2;
+ }
+
+ /* Check for downsampling of chroma */
+ downsample = !dst_raster && !b2r2_is_yuv444_fmt(dst->fmt);
+ if (downsample) {
+ h_rsf *= 2;
+
+ if (b2r2_is_yuv420_fmt(dst->fmt))
+ v_rsf *= 2;
+ }
+
+ src_x = inv_rescale(tmp_win.x - src->rect.x, h_rsf);
+ src_y = inv_rescale(tmp_win.y - src->rect.y, v_rsf);
+ hsrc_init = src_x & 0x3ff;
+ vsrc_init = src_y & 0x3ff;
+
+ /* Configure resize and filters */
+ fctl = B2R2_FCTL_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_VF2D_MODE_ENABLE_RESIZER;
+ luma_fctl = B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_RESIZER |
+ B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_RESIZER;
+
+ rsf = (h_rsf << B2R2_RSF_HSRC_INC_SHIFT) |
+ (v_rsf << B2R2_RSF_VSRC_INC_SHIFT);
+ luma_rsf = (luma_h_rsf << B2R2_RSF_HSRC_INC_SHIFT) |
+ (luma_v_rsf << B2R2_RSF_VSRC_INC_SHIFT);
+
+ rzi = B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT) |
+ (hsrc_init << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (vsrc_init << B2R2_RZI_VSRC_INIT_SHIFT);
+ luma_rzi = B2R2_RZI_DEFAULT_HNB_REPEAT |
+ (2 << B2R2_RZI_VNB_REPEAT_SHIFT) |
+ (luma_hsrc_init << B2R2_RZI_HSRC_INIT_SHIFT) |
+ (luma_vsrc_init << B2R2_RZI_VSRC_INIT_SHIFT);
+
+ /*
+ * We should only filter if there is an actual rescale (i.e. not when
+ * up or downsampling).
+ */
+ if (luma_h_rsf != (1 << 10)) {
+ hf = b2r2_filter_find(h_rsf);
+ luma_hf = b2r2_filter_find(luma_h_rsf);
+ }
+ if (luma_v_rsf != (1 << 10)) {
+ vf = b2r2_filter_find(v_rsf);
+ luma_vf = b2r2_filter_find(luma_v_rsf);
+ }
+
+ if (hf) {
+ fctl |= B2R2_FCTL_HF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER;
+ hfp = hf->h_coeffs_phys_addr;
+ }
+
+ if (vf) {
+ fctl |= B2R2_FCTL_VF2D_MODE_ENABLE_COLOR_CHANNEL_FILTER;
+ vfp = vf->v_coeffs_phys_addr;
+ }
+
+ if (luma_hf) {
+ luma_fctl |= B2R2_FCTL_LUMA_HF2D_MODE_ENABLE_FILTER;
+ luma_hfp = luma_hf->h_coeffs_phys_addr;
+ }
+
+ if (luma_vf) {
+ luma_fctl |= B2R2_FCTL_LUMA_VF2D_MODE_ENABLE_FILTER;
+ luma_vfp = luma_vf->v_coeffs_phys_addr;
+ }
+
+ ret = configure_copy(cont, node, src, dst, ivmx, &last, this);
+ if (ret < 0)
+ goto error;
+
+ do {
+ bool chroma_rescale =
+ (h_rsf != (1 << 10)) || (v_rsf != (1 << 10));
+ bool luma_rescale =
+ (luma_h_rsf != (1 << 10)) ||
+ (luma_v_rsf != (1 << 10));
+ bool dst_chroma = node->node.GROUP1.B2R2_TTY &
+ B2R2_TTY_CHROMA_NOT_LUMA;
+ bool dst_luma = !dst_chroma;
+
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: Internal error! Out "
+ "of nodes!\n", __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_FILTER_CONTROL;
+
+ /*
+ * If the source format is anything other than raster, we
+ * always have to enable both chroma and luma resizers. This
+ * could be a bug in the hardware, since it is not mentioned in
+ * the specification.
+ *
+ * Otherwise, we will only enable the chroma resizer when
+ * writing chroma and the luma resizer when writing luma
+ * (or both when writing raster). Also, if there is no rescale
+ * to be done there's no point in using the resizers.
+ */
+
+ if (!src_raster || (chroma_rescale &&
+ (dst_raster || dst_chroma))) {
+ /* Enable chroma resize */
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_RESIZE_CHROMA;
+ node->node.GROUP8.B2R2_FCTL |= fctl;
+
+ node->node.GROUP9.B2R2_RSF = rsf;
+ node->node.GROUP9.B2R2_RZI = rzi;
+ node->node.GROUP9.B2R2_HFP = hfp;
+ node->node.GROUP9.B2R2_VFP = vfp;
+ }
+
+ if (!src_raster || (luma_rescale &&
+ (dst_raster || dst_luma))) {
+ /* Enable luma resize */
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_RESCALE2D_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_RESIZE_LUMA;
+ node->node.GROUP8.B2R2_FCTL |= luma_fctl;
+
+ node->node.GROUP10.B2R2_RSF = luma_rsf;
+ node->node.GROUP10.B2R2_RZI = luma_rzi;
+ node->node.GROUP10.B2R2_HFP = luma_hfp;
+ node->node.GROUP10.B2R2_VFP = luma_vfp;
+ /*
+ * Scaling operation from raster to a multi-buffer
+ * format, requires the raster input to be scaled
+ * before luminance information can be extracted.
+ * Raster input is scaled by the chroma resizer.
+ * Luma resizer only handles luminance data which
+ * exists in a separate buffer in source image,
+ * as is the case with YUV planar/semi-planar formats.
+ */
+ if (src_raster) {
+ /* Activate chroma scaling */
+ node->node.GROUP0.B2R2_CIC |=
+ B2R2_CIC_RESIZE_CHROMA;
+ node->node.GROUP8.B2R2_FCTL |= fctl;
+ /*
+ * Color data must be scaled
+ * to the same size as luma.
+ * Use luma scaling parameters.
+ */
+ node->node.GROUP9.B2R2_RSF = luma_rsf;
+ node->node.GROUP9.B2R2_RZI = luma_rzi;
+ node->node.GROUP9.B2R2_HFP = luma_hfp;
+ node->node.GROUP9.B2R2_VFP = luma_vfp;
+ }
+ }
+
+ b2r2_log_info(cont->dev, "%s:\n"
+ "\tB2R2_TXY: %.8x\tB2R2_TSZ: %.8x\n"
+ "\tB2R2_S1XY: %.8x\tB2R2_S1SZ: %.8x\n"
+ "\tB2R2_S2XY: %.8x\tB2R2_S2SZ: %.8x\n"
+ "\tB2R2_S3XY: %.8x\tB2R2_S3SZ: %.8x\n"
+ "----------------------------------\n",
+ __func__, node->node.GROUP1.B2R2_TXY,
+ node->node.GROUP1.B2R2_TSZ,
+ node->node.GROUP3.B2R2_SXY,
+ node->node.GROUP3.B2R2_SSZ,
+ node->node.GROUP4.B2R2_SXY,
+ node->node.GROUP4.B2R2_SSZ,
+ node->node.GROUP5.B2R2_SXY,
+ node->node.GROUP5.B2R2_SSZ);
+
+ node = node->next;
+
+ } while (node != last);
+
+
+
+ /* Consume the nodes */
+ *next = node;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+/**
+ * configure_src() - configures the source registers and the iVMX
+ *
+ * @node - the node to configure
+ * @src - the source buffer
+ * @ivmx - the iVMX to use for color conversion
+ *
+ * This operation will not consume any nodes
+ */
+static void configure_src(struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *src, const u32 *ivmx)
+{
+ struct b2r2_node_split_buf tmp_buf;
+
+ b2r2_log_info(cont->dev,
+ "%s: src.win=(%d, %d, %d, %d)\n", __func__,
+ src->win.x, src->win.y, src->win.width,
+ src->win.height);
+
+ /* Configure S1 - S3 */
+ switch (src->type) {
+ case B2R2_FMT_TYPE_RASTER:
+ set_src_2(node, src->addr, src);
+ break;
+ case B2R2_FMT_TYPE_SEMI_PLANAR:
+ memcpy(&tmp_buf, src, sizeof(tmp_buf));
+
+ /*
+ * For 420 and 422 the chroma has lower resolution than the
+ * luma
+ */
+ if (!b2r2_is_yuv444_fmt(src->fmt)) {
+ tmp_buf.win.x >>= 1;
+ tmp_buf.win.width = (tmp_buf.win.width + 1) / 2;
+
+ if (b2r2_is_yuv420_fmt(src->fmt)) {
+ tmp_buf.win.height =
+ (tmp_buf.win.height + 1) / 2;
+ tmp_buf.win.y >>= 1;
+ }
+ }
+
+ set_src_3(node, src->addr, src);
+ set_src_2(node, tmp_buf.chroma_addr, &tmp_buf);
+ break;
+ case B2R2_FMT_TYPE_PLANAR:
+ memcpy(&tmp_buf, src, sizeof(tmp_buf));
+
+ if (!b2r2_is_yuv444_fmt(src->fmt)) {
+ /*
+ * Each chroma buffer will have half as many values
+ * per line as the luma buffer
+ */
+ tmp_buf.pitch = (tmp_buf.pitch + 1) / 2;
+
+ /* Horizontal resolution is half */
+ tmp_buf.win.x >>= 1;
+ tmp_buf.win.width = (tmp_buf.win.width + 1) / 2;
+
+ /*
+ * If the buffer is in YUV420 format, the vertical
+ * resolution is half as well
+ */
+ if (b2r2_is_yuv420_fmt(src->fmt)) {
+ tmp_buf.win.height =
+ (tmp_buf.win.height + 1) / 2;
+ tmp_buf.win.y >>= 1;
+ }
+ }
+
+ set_src_3(node, src->addr, src); /* Y */
+ set_src_2(node, tmp_buf.chroma_addr, &tmp_buf); /* U */
+ set_src_1(node, tmp_buf.chroma_cr_addr, &tmp_buf); /* V */
+
+ break;
+ default:
+ /* Should never, ever happen */
+ BUG_ON(1);
+ break;
+ }
+
+ /* Configure the iVMX for color space conversions */
+ if (ivmx != NULL)
+ set_ivmx(node, ivmx);
+}
+
+/**
+ * configure_bg() - configures a background for the given node
+ *
+ * @node - the node to configure
+ * @bg - the background buffer
+ * @swap_fg_bg - if true, fg will be on s1 instead of s2
+ *
+ * This operation will not consume any nodes.
+ *
+ * NOTE: This method should be called _AFTER_ the destination has been
+ * configured.
+ *
+ * WARNING: Take care when using this with semi-planar or planar sources since
+ * either S1 or S2 will be overwritten!
+ */
+static void configure_bg(struct b2r2_control *cont,
+ struct b2r2_node *node,
+ struct b2r2_node_split_buf *bg, bool swap_fg_bg)
+{
+ b2r2_log_info(cont->dev,
+ "%s: bg.win=(%d, %d, %d, %d)\n", __func__,
+ bg->win.x, bg->win.y, bg->win.width,
+ bg->win.height);
+
+ /* Configure S1 */
+ switch (bg->type) {
+ case B2R2_FMT_TYPE_RASTER:
+ if (swap_fg_bg) {
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_SWAP_FG_BG;
+
+ set_src(&node->node.GROUP4, bg->addr, bg);
+ } else {
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_1;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_1_FETCH_FROM_MEM;
+
+ set_src(&node->node.GROUP3, bg->addr, bg);
+ }
+ break;
+ default:
+ /* Should never, ever happen */
+ BUG_ON(1);
+ break;
+ }
+}
+
+/**
+ * configure_dst() - configures the destination registers of the given node
+ *
+ * @node - the node to configure
+ * @ivmx - the iVMX to use for color conversion
+ * @dst - the destination buffer
+ *
+ * This operation will consume as many nodes as are required to write the
+ * destination format.
+ */
+static int configure_dst(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_node_split_buf *dst, const u32 *ivmx,
+ struct b2r2_node **next)
+{
+ int ret;
+ int nbr_planes = 1;
+ int i;
+
+ struct b2r2_node_split_buf dst_planes[3];
+
+ b2r2_log_info(cont->dev,
+ "%s: dst.win=(%d, %d, %d, %d)\n", __func__,
+ dst->win.x, dst->win.y, dst->win.width,
+ dst->win.height);
+
+ memcpy(&dst_planes[0], dst, sizeof(dst_planes[0]));
+
+ if (dst->type != B2R2_FMT_TYPE_RASTER) {
+ /* There will be at least 2 planes */
+ nbr_planes = 2;
+
+ memcpy(&dst_planes[1], dst, sizeof(dst_planes[1]));
+
+ dst_planes[1].addr = dst->chroma_addr;
+ dst_planes[1].plane_selection = B2R2_TTY_CHROMA_NOT_LUMA;
+
+ if (!b2r2_is_yuv444_fmt(dst->fmt)) {
+ /* Horizontal resolution is half */
+ dst_planes[1].win.x /= 2;
+ /*
+ * Must round up the chroma size to handle cases when
+ * luma size is not divisible by 2. E.g. luma width==7 r
+ * equires chroma width==4. Chroma width==7/2==3 is only
+ * enough for luma width==6.
+ */
+ dst_planes[1].win.width =
+ (dst_planes[1].win.width + 1) / 2;
+
+ /*
+ * If the buffer is in YUV420 format, the vertical
+ * resolution is half as well. Height must be rounded in
+ * the same way as is done for width.
+ */
+ if (b2r2_is_yuv420_fmt(dst->fmt)) {
+ dst_planes[1].win.y /= 2;
+ dst_planes[1].win.height =
+ (dst_planes[1].win.height + 1) / 2;
+ }
+ }
+
+ if (dst->type == B2R2_FMT_TYPE_PLANAR) {
+ /* There will be a third plane as well */
+ nbr_planes = 3;
+
+ if (!b2r2_is_yuv444_fmt(dst->fmt)) {
+ /* The chroma planes have half the luma pitch */
+ dst_planes[1].pitch /= 2;
+ }
+
+ memcpy(&dst_planes[2], &dst_planes[1],
+ sizeof(dst_planes[2]));
+ dst_planes[2].addr = dst->chroma_cr_addr;
+
+ /*
+ * The third plane will be Cr.
+ * The flag B2R2_TTY_CB_NOT_CR actually works
+ * the other way around, i.e. as if it was
+ * B2R2_TTY_CR_NOT_CB.
+ */
+ dst_planes[2].chroma_selection = B2R2_TTY_CB_NOT_CR;
+ }
+
+ }
+
+ /* Configure one node for each plane */
+ for (i = 0; i < nbr_planes; i++) {
+
+ if (node == NULL) {
+ b2r2_log_warn(cont->dev, "%s: "
+ "Internal error! Out of nodes!\n", __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ /*
+ * When writing chroma, there's no need to read the luma and
+ * vice versa.
+ */
+ if ((node->node.GROUP3.B2R2_STY & B2R2_NATIVE_YUV) &&
+ (nbr_planes > 1)) {
+ if (i != 0) {
+ node->node.GROUP4.B2R2_STY |=
+ B2R2_S3TY_ENABLE_BLANK_ACCESS;
+ }
+ if (i != 1) {
+ node->node.GROUP0.B2R2_INS &=
+ ~B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_2_COLOR_FILL_REGISTER;
+ }
+ if (i != 2) {
+ node->node.GROUP0.B2R2_INS &=
+ ~B2R2_INS_SOURCE_1_FETCH_FROM_MEM;
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_SOURCE_1_COLOR_FILL_REGISTER;
+ }
+ } else if ((node->node.GROUP3.B2R2_STY &
+ (B2R2_NATIVE_YCBCR42X_MBN |
+ B2R2_NATIVE_YCBCR42X_R2B)) &&
+ (nbr_planes > 1)) {
+ if (i != 0) {
+ node->node.GROUP4.B2R2_STY |=
+ B2R2_S3TY_ENABLE_BLANK_ACCESS;
+ }
+ }
+
+ set_target(node, dst_planes[i].addr, &dst_planes[i]);
+
+ node = node->next;
+ }
+
+ /* Consume the nodes */
+ *next = node;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+
+}
+
+/**
+ * configure_blend() - configures the given node for alpha blending
+ *
+ * @node - the node to configure
+ * @flags - the flags passed in the blt_request
+ * @global_alpha - the global alpha to use (if enabled in flags)
+ *
+ * This operation will not consume any nodes.
+ *
+ * NOTE: This method should be called _AFTER_ the destination has been
+ * configured.
+ *
+ * WARNING: Take care when using this with semi-planar or planar sources since
+ * either S1 or S2 will be overwritten!
+ */
+static void configure_blend(struct b2r2_control *cont,
+ struct b2r2_node *node, u32 flags, u32 global_alpha)
+{
+ node->node.GROUP0.B2R2_ACK &= ~(B2R2_ACK_MODE_BYPASS_S2_S3);
+
+ /* Check if the foreground is premultiplied */
+ if ((flags & B2R2_BLT_FLAG_SRC_IS_NOT_PREMULT) != 0)
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BLEND_NOT_PREMULT;
+ else
+ node->node.GROUP0.B2R2_ACK |= B2R2_ACK_MODE_BLEND_PREMULT;
+
+ /* Check if global alpha blend should be enabled */
+ if (flags & B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND) {
+
+ /* B2R2 expects the global alpha to be in 0...128 range */
+ global_alpha = (global_alpha*128)/255;
+
+ node->node.GROUP0.B2R2_ACK |=
+ global_alpha << B2R2_ACK_GALPHA_ROPID_SHIFT;
+ } else {
+ node->node.GROUP0.B2R2_ACK |=
+ (128 << B2R2_ACK_GALPHA_ROPID_SHIFT);
+ }
+}
+
+/**
+ * configure_clip() - configures destination clipping for the given node
+ *
+ * @node - the node to configure
+ * @clip_rect - the clip rectangle
+ *
+ * This operation does not consume any nodes.
+ */
+static void configure_clip(struct b2r2_control *cont, struct b2r2_node *node,
+ struct b2r2_blt_rect *clip_rect)
+{
+ s32 l = clip_rect->x;
+ s32 r = clip_rect->x + clip_rect->width - 1;
+ s32 t = clip_rect->y;
+ s32 b = clip_rect->y + clip_rect->height - 1;
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_CLIP_WINDOW;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_RECT_CLIP_ENABLED;
+
+ /* Clip window setup */
+ node->node.GROUP6.B2R2_CWO =
+ ((t & 0x7FFF) << B2R2_CWO_Y_SHIFT) |
+ ((l & 0x7FFF) << B2R2_CWO_X_SHIFT);
+ node->node.GROUP6.B2R2_CWS =
+ ((b & 0x7FFF) << B2R2_CWO_Y_SHIFT) |
+ ((r & 0x7FFF) << B2R2_CWO_X_SHIFT);
+}
+
+/**
+ * set_buf() - configures the given buffer with the provided values
+ *
+ * @addr - the physical base address
+ * @img - the blt image to base the buffer on
+ * @rect - the rectangle to use
+ * @color_fill - determines whether the buffer should be used for color fill
+ * @color - the color to use in case of color fill
+ */
+static void set_buf(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *buf,
+ u32 addr,
+ const struct b2r2_blt_img *img,
+ const struct b2r2_blt_rect *rect,
+ bool color_fill,
+ u32 color)
+{
+ memset(buf, 0, sizeof(*buf));
+
+ buf->fmt = img->fmt;
+ buf->type = b2r2_get_fmt_type(img->fmt);
+
+ if (color_fill) {
+ buf->type = B2R2_FMT_TYPE_RASTER;
+ buf->color = color;
+ } else {
+ buf->addr = addr;
+
+ buf->alpha_range = b2r2_get_alpha_range(img->fmt);
+
+ if (img->pitch == 0)
+ buf->pitch = b2r2_fmt_byte_pitch(img->fmt, img->width);
+ else
+ buf->pitch = img->pitch;
+
+ buf->height = img->height;
+ buf->width = img->width;
+
+ switch (buf->type) {
+ case B2R2_FMT_TYPE_SEMI_PLANAR:
+ buf->chroma_addr = (u32)(((u8 *)addr) +
+ buf->pitch * buf->height);
+ break;
+ case B2R2_FMT_TYPE_PLANAR:
+ if (b2r2_is_yuv422_fmt(buf->fmt) ||
+ b2r2_is_yuv420_fmt(buf->fmt)) {
+ buf->chroma_addr = (u32)(((u8 *)addr) +
+ buf->pitch * buf->height);
+ } else {
+ buf->chroma_cr_addr = (u32)(((u8 *)addr) +
+ buf->pitch * buf->height);
+ }
+ if (b2r2_is_yuv420_fmt(buf->fmt)) {
+ /*
+ * Use ceil(height/2) in case
+ * buffer height is not divisible by 2.
+ */
+ buf->chroma_cr_addr =
+ (u32)(((u8 *)buf->chroma_addr) +
+ (buf->pitch >> 1) *
+ ((buf->height + 1) >> 1));
+ } else if (b2r2_is_yuv422_fmt(buf->fmt)) {
+ buf->chroma_cr_addr =
+ (u32)(((u8 *)buf->chroma_addr) +
+ (buf->pitch >> 1) * buf->height);
+ } else if (b2r2_is_yvu420_fmt(buf->fmt)) {
+ buf->chroma_addr =
+ (u32)(((u8 *)buf->chroma_cr_addr) +
+ (buf->pitch >> 1) *
+ ((buf->height + 1) >> 1));
+ } else if (b2r2_is_yvu422_fmt(buf->fmt)) {
+ buf->chroma_addr =
+ (u32)(((u8 *)buf->chroma_cr_addr) +
+ (buf->pitch >> 1) * buf->height);
+ }
+ break;
+ default:
+ break;
+ }
+
+ memcpy(&buf->rect, rect, sizeof(buf->rect));
+ }
+}
+
+/**
+ * setup_tmp_buf() - configure a temporary buffer
+ */
+static int setup_tmp_buf(struct b2r2_control *cont,
+ struct b2r2_node_split_buf *tmp,
+ u32 max_size,
+ enum b2r2_blt_fmt pref_fmt,
+ u32 pref_width,
+ u32 pref_height)
+{
+ int ret;
+
+ enum b2r2_blt_fmt fmt;
+
+ u32 width;
+ u32 height;
+ u32 pitch;
+ u32 size;
+
+ /* Determine what format we should use for the tmp buf */
+ if (b2r2_is_rgb_fmt(pref_fmt)) {
+ fmt = B2R2_BLT_FMT_32_BIT_ARGB8888;
+ } else if (b2r2_is_bgr_fmt(pref_fmt)) {
+ fmt = B2R2_BLT_FMT_32_BIT_ABGR8888;
+ } else if (b2r2_is_yvu_fmt(pref_fmt)) {
+ fmt = B2R2_BLT_FMT_CB_Y_CR_Y;
+ } else if (b2r2_is_yuv_fmt(pref_fmt)) {
+ fmt = B2R2_BLT_FMT_32_BIT_AYUV8888;
+ } else {
+ /* Wait, what? */
+ b2r2_log_warn(cont->dev, "%s: "
+ "Cannot create tmp buf from this fmt (%d)\n",
+ __func__, pref_fmt);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* See if we can fit the entire preferred rectangle */
+ width = pref_width;
+ height = pref_height;
+ pitch = b2r2_fmt_byte_pitch(fmt, width);
+ size = pitch * height;
+
+ if (size > max_size) {
+ /* We need to limit the size, so we choose a different width */
+ width = min(width, (u32) B2R2_RESCALE_MAX_WIDTH);
+ pitch = b2r2_fmt_byte_pitch(fmt, width);
+ height = min(height, max_size / pitch);
+ size = pitch * height;
+ }
+
+ /* We should at least have enough room for one scanline */
+ if (height == 0) {
+ b2r2_log_warn(cont->dev, "%s: Not enough tmp mem!\n",
+ __func__);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memset(tmp, 0, sizeof(*tmp));
+
+ tmp->fmt = fmt;
+ tmp->type = B2R2_FMT_TYPE_RASTER;
+ tmp->height = height;
+ tmp->width = width;
+ tmp->pitch = pitch;
+
+ tmp->rect.width = width;
+ tmp->rect.height = tmp->height;
+ tmp->alpha_range = B2R2_TY_ALPHA_RANGE_255;
+
+ return 0;
+error:
+ b2r2_log_warn(cont->dev, "%s: Exit...\n", __func__);
+ return ret;
+
+}
+
+/**
+ * is_transform() - returns whether the given request is a transform operation
+ */
+static bool is_transform(const struct b2r2_blt_request *req)
+{
+ return (req->user_req.transform != B2R2_BLT_TRANSFORM_NONE) ||
+ (req->user_req.src_rect.width !=
+ req->user_req.dst_rect.width) ||
+ (req->user_req.src_rect.height !=
+ req->user_req.dst_rect.height);
+}
+
+/**
+ * rescale() - rescales the given dimension
+ *
+ * Returns the rescaled dimension in 22.10 fixed point format.
+ */
+static s32 rescale(struct b2r2_control *cont, s32 dim, u16 sf)
+{
+ b2r2_log_info(cont->dev, "%s\n", __func__);
+
+ if (sf == 0) {
+ b2r2_log_err(cont->dev, "%s: Scale factor is 0!\n", __func__);
+ BUG_ON(1);
+ }
+
+ /*
+ * This is normally not safe to do, since it drastically decreases the
+ * precision of the integer part of the dimension. But since the B2R2
+ * hardware only has 12-bit registers for these values, we are safe.
+ */
+ return (dim << 20) / sf;
+}
+
+/**
+ * inv_rescale() - does an inverted rescale of the given dimension
+ *
+ * Returns the rescaled dimension in 22.10 fixed point format.
+ */
+static s32 inv_rescale(s32 dim, u16 sf)
+{
+ if (sf == 0)
+ return dim;
+
+ return dim * sf;
+}
+
+/**
+ * set_target() - sets the target registers of the given node
+ */
+static void set_target(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf)
+{
+ s32 l;
+ s32 r;
+ s32 t;
+ s32 b;
+
+ if (buf->tmp_buf_index)
+ node->dst_tmp_index = buf->tmp_buf_index;
+
+ node->node.GROUP1.B2R2_TBA = addr;
+ node->node.GROUP1.B2R2_TTY = buf->pitch | b2r2_to_native_fmt(buf->fmt) |
+ buf->alpha_range | buf->chroma_selection | buf->hso |
+ buf->vso | buf->dither | buf->plane_selection;
+
+ if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ node->node.GROUP1.B2R2_TTY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+
+ node->node.GROUP1.B2R2_TSZ =
+ ((buf->win.width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((buf->win.height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ node->node.GROUP1.B2R2_TXY =
+ ((buf->win.x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((buf->win.y & 0xffff) << B2R2_XY_Y_SHIFT);
+
+ /* Check if the rectangle is outside the buffer */
+ if (buf->vso == B2R2_TY_VSO_BOTTOM_TO_TOP)
+ t = buf->win.y - (buf->win.height - 1);
+ else
+ t = buf->win.y;
+
+ if (buf->hso == B2R2_TY_HSO_RIGHT_TO_LEFT)
+ l = buf->win.x - (buf->win.width - 1);
+ else
+ l = buf->win.x;
+
+ r = l + buf->win.width;
+ b = t + buf->win.height;
+
+ /* Clip to the destination buffer to prevent memory overwrites */
+ if ((l < 0) || (r > buf->width) || (t < 0) || (b > buf->height)) {
+ /* The clip rectangle is including the borders */
+ l = max(l, 0);
+ r = min(r, (s32) buf->width) - 1;
+ t = max(t, 0);
+ b = min(b, (s32) buf->height) - 1;
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_CLIP_WINDOW;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_RECT_CLIP_ENABLED;
+ node->node.GROUP6.B2R2_CWO =
+ ((l & 0x7FFF) << B2R2_CWS_X_SHIFT) |
+ ((t & 0x7FFF) << B2R2_CWS_Y_SHIFT);
+ node->node.GROUP6.B2R2_CWS =
+ ((r & 0x7FFF) << B2R2_CWO_X_SHIFT) |
+ ((b & 0x7FFF) << B2R2_CWO_Y_SHIFT);
+ }
+
+}
+
+/**
+ * set_src() - configures the given source register with the given values
+ */
+static void set_src(struct b2r2_src_config *src, u32 addr,
+ struct b2r2_node_split_buf *buf)
+{
+ src->B2R2_SBA = addr;
+ src->B2R2_STY = buf->pitch | b2r2_to_native_fmt(buf->fmt) |
+ buf->alpha_range | buf->hso | buf->vso;
+
+ if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ src->B2R2_STY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+
+ src->B2R2_SSZ = ((buf->win.width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) |
+ ((buf->win.height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT);
+ src->B2R2_SXY = ((buf->win.x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((buf->win.y & 0xffff) << B2R2_XY_Y_SHIFT);
+
+}
+
+/**
+ * set_src_1() - sets the source 1 registers of the given node
+ */
+static void set_src_1(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf)
+{
+ if (buf->tmp_buf_index)
+ node->src_tmp_index = buf->tmp_buf_index;
+
+ node->src_index = 1;
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_1;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_1_FETCH_FROM_MEM;
+
+ node->node.GROUP3.B2R2_SBA = addr;
+ node->node.GROUP3.B2R2_STY = buf->pitch | b2r2_to_native_fmt(buf->fmt) |
+ buf->alpha_range | buf->hso | buf->vso;
+
+ if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 ||
+ buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888)
+ node->node.GROUP3.B2R2_STY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE;
+
+ node->node.GROUP3.B2R2_SXY =
+ ((buf->win.x & 0xffff) << B2R2_XY_X_SHIFT) |
+ ((buf->win.y & 0xffff) << B2R2_XY_Y_SHIFT);
+
+ /* Source 1 has no size register */
+}
+
+/**
+ * set_src_2() - sets the source 2 registers of the given node
+ */
+static void set_src_2(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf)
+{
+ if (buf->tmp_buf_index)
+ node->src_tmp_index = buf->tmp_buf_index;
+
+ node->src_index = 2;
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_2_FETCH_FROM_MEM;
+
+ set_src(&node->node.GROUP4, addr, buf);
+}
+
+/**
+ * set_src_3() - sets the source 3 registers of the given node
+ */
+static void set_src_3(struct b2r2_node *node, u32 addr,
+ struct b2r2_node_split_buf *buf)
+{
+ if (buf->tmp_buf_index)
+ node->src_tmp_index = buf->tmp_buf_index;
+
+ node->src_index = 3;
+
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_3;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_3_FETCH_FROM_MEM;
+
+ set_src(&node->node.GROUP5, addr, buf);
+}
+
+/**
+ * set_ivmx() - configures the iVMX registers with the given values
+ */
+static void set_ivmx(struct b2r2_node *node, const u32 *vmx_values)
+{
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
+
+ node->node.GROUP15.B2R2_VMX0 = vmx_values[0];
+ node->node.GROUP15.B2R2_VMX1 = vmx_values[1];
+ node->node.GROUP15.B2R2_VMX2 = vmx_values[2];
+ node->node.GROUP15.B2R2_VMX3 = vmx_values[3];
+}
+
+/**
+ * reset_nodes() - clears the node list
+ */
+static void reset_nodes(struct b2r2_node *node)
+{
+ while (node != NULL) {
+ memset(&node->node, 0, sizeof(node->node));
+
+ node->src_tmp_index = 0;
+ node->dst_tmp_index = 0;
+
+ /* TODO: Implement support for short linked lists */
+ node->node.GROUP0.B2R2_CIC = 0x7ffff;
+
+ if (node->next != NULL)
+ node->node.GROUP0.B2R2_NIP =
+ node->next->physical_address;
+ node = node->next;
+ }
+}
+
+int b2r2_node_split_init(struct b2r2_control *cont)
+{
+ return 0;
+}
+
+void b2r2_node_split_exit(struct b2r2_control *cont)
+{
+
+}
diff --git a/drivers/video/b2r2/b2r2_node_split.h b/drivers/video/b2r2/b2r2_node_split.h
new file mode 100644
index 00000000000..a577241c31b
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_node_split.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 node splitter
+ *
+ * Author: Fredrik Allansson <fredrik.allansson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __B2R2_NODE_SPLIT_H_
+#define __B2R2_NODE_SPLIT_H_
+
+#include "b2r2_internal.h"
+#include "b2r2_hw.h"
+
+/**
+ * b2r2_node_split_analyze() - Analyzes a B2R2 request
+ *
+ * @req - The request to analyze
+ * @max_buf_size - The largest size allowed for intermediate buffers
+ * @node_count - Number of nodes required for the job
+ * @buf_count - Number of intermediate buffers required for the job
+ * @bufs - An array of buffers needed for intermediate buffers
+ *
+ * Analyzes the request and determines how many nodes and intermediate buffers
+ * are required.
+ *
+ * It is the responsibility of the caller to allocate memory and assign the
+ * physical addresses. After that b2r2_node_split_assign_buffers should be
+ * called to assign the buffers to the right nodes.
+ *
+ * Returns:
+ * A handle identifing the analyzed request if successful, a negative
+ * value otherwise.
+ */
+int b2r2_node_split_analyze(const struct b2r2_blt_request *req, u32 max_buf_size,
+ u32 *node_count, struct b2r2_work_buf **bufs, u32* buf_count,
+ struct b2r2_node_split_job *job);
+
+/**
+ * b2r2_node_split_configure() - Performs a node split
+ *
+ * @handle - A handle for the analyzed request
+ * @first - The first node in the list of nodes to use
+ *
+ * Fills the supplied list of nodes with the parameters acquired by analyzing
+ * the request.
+ *
+ * All pointers to intermediate buffers are represented by integers to be used
+ * in the array returned by b2r2_node_split_analyze.
+ *
+ * Returns:
+ * A negative value if an error occurred, 0 otherwise.
+ */
+int b2r2_node_split_configure(struct b2r2_control *cont,
+ struct b2r2_node_split_job *job, struct b2r2_node *first);
+
+/**
+ * b2r2_node_split_assign_buffers() - Assignes physical addresses
+ *
+ * @handle - The handle for the job
+ * @first - The first node in the node list
+ * @bufs - Buffers with assigned physical addresses
+ * @buf_count - Number of physical addresses
+ *
+ * Assigns the physical addresses where intermediate buffers are required in
+ * the node list.
+ *
+ * The order of the elements of 'bufs' must be maintained from the call to
+ * b2r2_node_split_analyze.
+ *
+ * Returns:
+ * A negative value if an error occurred, 0 otherwise.
+ */
+int b2r2_node_split_assign_buffers(struct b2r2_control *cont,
+ struct b2r2_node_split_job *job,
+ struct b2r2_node *first, struct b2r2_work_buf *bufs,
+ u32 buf_count);
+
+/**
+ * b2r2_node_split_unassign_buffers() - Removes all physical addresses
+ *
+ * @handle - The handle associated with the job
+ * @first - The first node in the node list
+ *
+ * Removes all references to intermediate buffers from the node list.
+ *
+ * This makes it possible to reuse the node list with new buffers by calling
+ * b2r2_node_split_assign_buffers again. Useful for caching node lists.
+ */
+void b2r2_node_split_unassign_buffers(struct b2r2_control *cont,
+ struct b2r2_node_split_job *job,
+ struct b2r2_node *first);
+
+/**
+ * b2r2_node_split_release() - Releases all resources for a job
+ *
+ * @handle - The handle identifying the job. This will be set to 0.
+ *
+ * Releases all resources associated with a job.
+ *
+ * This should always be called once b2r2_node_split_analyze has been called
+ * in order to release any resources allocated while analyzing.
+ */
+void b2r2_node_split_cancel(struct b2r2_control *cont,
+ struct b2r2_node_split_job *job);
+
+/**
+ * b2r2_node_split_init() - Initializes the node split module
+ *
+ * Initializes the node split module and creates debugfs files.
+ */
+int b2r2_node_split_init(struct b2r2_control *cont);
+
+/**
+ * b2r2_node_split_exit() - Deinitializes the node split module
+ *
+ * Releases all resources for the node split module.
+ */
+void b2r2_node_split_exit(struct b2r2_control *cont);
+
+#endif
diff --git a/drivers/video/b2r2/b2r2_profiler/Makefile b/drivers/video/b2r2/b2r2_profiler/Makefile
new file mode 100644
index 00000000000..69a85524fd7
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_profiler/Makefile
@@ -0,0 +1,3 @@
+# Make file for loadable module B2R2 Profiler
+
+obj-$(CONFIG_B2R2_PROFILER) += b2r2_profiler.o
diff --git a/drivers/video/b2r2/b2r2_profiler/b2r2_profiler.c b/drivers/video/b2r2/b2r2_profiler/b2r2_profiler.c
new file mode 100644
index 00000000000..e038941b4e8
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_profiler/b2r2_profiler.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson B2R2 profiler implementation
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/jiffies.h>
+
+#include <video/b2r2_blt.h>
+#include "../b2r2_profiler_api.h"
+
+
+#define S32_MAX 2147483647
+
+
+static int src_format_filter_on = false;
+module_param(src_format_filter_on, bool, S_IRUGO | S_IWUSR);
+static unsigned int src_format_filter;
+module_param(src_format_filter, uint, S_IRUGO | S_IWUSR);
+
+static int print_blts_on = 0;
+module_param(print_blts_on, bool, S_IRUGO | S_IWUSR);
+static int use_mpix_per_second_in_print_blts = 1;
+module_param(use_mpix_per_second_in_print_blts, bool, S_IRUGO | S_IWUSR);
+
+static int profiler_stats_on = 1;
+module_param(profiler_stats_on, bool, S_IRUGO | S_IWUSR);
+
+static const unsigned int profiler_stats_blts_used = 400;
+static struct {
+ unsigned long sampling_start_time_jiffies;
+
+ s32 min_mpix_per_second;
+ struct b2r2_blt_req min_blt_request;
+ struct b2r2_blt_profiling_info min_blt_profiling_info;
+
+ s32 max_mpix_per_second;
+ struct b2r2_blt_req max_blt_request;
+ struct b2r2_blt_profiling_info max_blt_profiling_info;
+
+ s32 accumulated_num_pixels;
+ s32 accumulated_num_usecs;
+
+ u32 num_blts_done;
+} profiler_stats;
+
+
+static s32 nsec_2_usec(const s32 nsec);
+
+static int is_scale_blt(const struct b2r2_blt_req * const request);
+static s32 get_blt_mpix_per_second(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info);
+static void print_blt(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info);
+
+static s32 get_num_pixels_in_blt(const struct b2r2_blt_req * const request);
+static s32 get_mpix_per_second(const s32 num_pixels, const s32 num_usecs);
+static void print_profiler_stats(void);
+static void reset_profiler_stats(void);
+static void do_profiler_stats(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info);
+
+static void blt_done(const struct b2r2_blt_req * const blt,
+ const s32 request_id,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info);
+
+
+static struct b2r2_profiler this = {
+ .blt_done = blt_done,
+};
+
+
+static s32 nsec_2_usec(const s32 nsec)
+{
+ return nsec / 1000;
+}
+
+
+static int is_scale_blt(const struct b2r2_blt_req * const request)
+{
+ if ((request->transform & B2R2_BLT_TRANSFORM_CCW_ROT_90 &&
+ (request->src_rect.width !=
+ request->dst_rect.height ||
+ request->src_rect.height !=
+ request->dst_rect.width)) ||
+ (!(request->transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) &&
+ (request->src_rect.width !=
+ request->dst_rect.width ||
+ request->src_rect.height !=
+ request->dst_rect.height)))
+ return 1;
+ else
+ return 0;
+}
+
+static s32 get_blt_mpix_per_second(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info)
+{
+ return get_mpix_per_second(get_num_pixels_in_blt(request),
+ nsec_2_usec(blt_profiling_info->nsec_active_in_cpu +
+ blt_profiling_info->nsec_active_in_b2r2));
+}
+
+static void print_blt(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info)
+{
+ char tmp_str[128];
+ sprintf(tmp_str, "SF: %#10x, DF: %#10x, F: %#10x, T: %#3x, S: %1i, P: %7i",
+ request->src_img.fmt,
+ request->dst_img.fmt,
+ request->flags,
+ request->transform,
+ is_scale_blt(request),
+ get_num_pixels_in_blt(request));
+ if (use_mpix_per_second_in_print_blts)
+ printk(KERN_ALERT "%s, MPix/s: %3i\n", tmp_str,
+ get_blt_mpix_per_second(request, blt_profiling_info));
+ else
+ printk(KERN_ALERT "%s, CPU: %10i, B2R2: %10i, Tot: %10i ns\n",
+ tmp_str, blt_profiling_info->nsec_active_in_cpu,
+ blt_profiling_info->nsec_active_in_b2r2,
+ blt_profiling_info->total_time_nsec);
+}
+
+
+static s32 get_num_pixels_in_blt(const struct b2r2_blt_req * const request)
+{
+ s32 num_pixels_in_src = request->src_rect.width * request->src_rect.height;
+ s32 num_pixels_in_dst = request->dst_rect.width * request->dst_rect.height;
+ if (request->flags & (B2R2_BLT_FLAG_SOURCE_FILL |
+ B2R2_BLT_FLAG_SOURCE_FILL_RAW))
+ return num_pixels_in_dst;
+ else
+ return (num_pixels_in_src + num_pixels_in_dst) / 2;
+}
+
+static s32 get_mpix_per_second(const s32 num_pixels, const s32 num_usecs)
+{
+ s32 num_pixels_scale_factor = num_pixels != 0 ?
+ S32_MAX / num_pixels : S32_MAX;
+ s32 num_usecs_scale_factor = num_usecs != 0 ?
+ S32_MAX / num_usecs : S32_MAX;
+ s32 scale_factor = min(num_pixels_scale_factor, num_usecs_scale_factor);
+
+ s32 num_pixels_scaled = num_pixels * scale_factor;
+ s32 num_usecs_scaled = num_usecs * scale_factor;
+
+ if (num_usecs_scaled < 1000000)
+ return 0;
+
+ return (num_pixels_scaled / 1000000) / (num_usecs_scaled / 1000000);
+}
+
+static void print_profiler_stats(void)
+{
+ printk(KERN_ALERT "Min: %3i, Avg: %3i, Max: %3i MPix/s\n",
+ profiler_stats.min_mpix_per_second,
+ get_mpix_per_second(
+ profiler_stats.accumulated_num_pixels,
+ profiler_stats.accumulated_num_usecs),
+ profiler_stats.max_mpix_per_second);
+ printk(KERN_ALERT "Min blit:\n");
+ print_blt(&profiler_stats.min_blt_request,
+ &profiler_stats.min_blt_profiling_info);
+ printk(KERN_ALERT "Max blit:\n");
+ print_blt(&profiler_stats.max_blt_request,
+ &profiler_stats.max_blt_profiling_info);
+}
+
+static void reset_profiler_stats(void)
+{
+ profiler_stats.sampling_start_time_jiffies = jiffies;
+ profiler_stats.min_mpix_per_second = S32_MAX;
+ profiler_stats.max_mpix_per_second = 0;
+ profiler_stats.accumulated_num_pixels = 0;
+ profiler_stats.accumulated_num_usecs = 0;
+ profiler_stats.num_blts_done = 0;
+}
+
+static void do_profiler_stats(const struct b2r2_blt_req * const request,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info)
+{
+ s32 num_pixels_in_blt;
+ s32 num_usec_blt_took;
+ s32 blt_mpix_per_second;
+
+ if (time_before(jiffies, profiler_stats.sampling_start_time_jiffies))
+ return;
+
+ num_pixels_in_blt = get_num_pixels_in_blt(request);
+ num_usec_blt_took = nsec_2_usec(blt_profiling_info->nsec_active_in_cpu +
+ blt_profiling_info->nsec_active_in_b2r2);
+ blt_mpix_per_second = get_mpix_per_second(num_pixels_in_blt,
+ num_usec_blt_took);
+
+ if (blt_mpix_per_second <=
+ profiler_stats.min_mpix_per_second) {
+ profiler_stats.min_mpix_per_second = blt_mpix_per_second;
+ memcpy(&profiler_stats.min_blt_request,
+ request, sizeof(struct b2r2_blt_req));
+ memcpy(&profiler_stats.min_blt_profiling_info,
+ blt_profiling_info,
+ sizeof(struct b2r2_blt_profiling_info));
+ }
+
+ if (blt_mpix_per_second >= profiler_stats.max_mpix_per_second) {
+ profiler_stats.max_mpix_per_second = blt_mpix_per_second;
+ memcpy(&profiler_stats.max_blt_request, request,
+ sizeof(struct b2r2_blt_req));
+ memcpy(&profiler_stats.max_blt_profiling_info,
+ blt_profiling_info, sizeof(struct b2r2_blt_profiling_info));
+ }
+
+ profiler_stats.accumulated_num_pixels += num_pixels_in_blt;
+ profiler_stats.accumulated_num_usecs += num_usec_blt_took;
+ profiler_stats.num_blts_done++;
+
+ if (profiler_stats.num_blts_done >= profiler_stats_blts_used) {
+ print_profiler_stats();
+ reset_profiler_stats();
+ /* The printouts initiated above can disturb the next measurement
+ so we delay it two seconds to give the printouts a chance to finish. */
+ profiler_stats.sampling_start_time_jiffies = jiffies + (2 * HZ);
+ }
+}
+
+static void blt_done(const struct b2r2_blt_req * const request,
+ const s32 request_id,
+ const struct b2r2_blt_profiling_info * const blt_profiling_info)
+{
+ /* Filters */
+ if (src_format_filter_on && request->src_img.fmt != src_format_filter)
+ return;
+
+ /* Processors */
+ if (print_blts_on)
+ print_blt(request, blt_profiling_info);
+
+ if (profiler_stats_on)
+ do_profiler_stats(request, blt_profiling_info);
+}
+
+
+static int __init b2r2_profiler_init(void)
+{
+ reset_profiler_stats();
+
+ return b2r2_register_profiler(&this);
+}
+module_init(b2r2_profiler_init);
+
+static void __exit b2r2_profiler_exit(void)
+{
+ b2r2_unregister_profiler(&this);
+}
+module_exit(b2r2_profiler_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Johan Mossberg (johan.xx.mossberg@stericsson.com)");
+MODULE_DESCRIPTION("B2R2 Profiler");
diff --git a/drivers/video/b2r2/b2r2_profiler_api.h b/drivers/video/b2r2/b2r2_profiler_api.h
new file mode 100644
index 00000000000..5f1f9abbe49
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_profiler_api.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 profiling API
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#ifndef _LINUX_VIDEO_B2R2_PROFILER_API_H
+#define _LINUX_VIDEO_B2R2_PROFILER_API_H
+
+#include <video/b2r2_blt.h>
+
+/**
+ * struct b2r2_blt_profiling_info - Profiling information for a blit
+ *
+ * @nsec_active_in_cpu: The number of nanoseconds the job was active in the CPU.
+ * This is an approximate value, check out the code for more
+ * info.
+ * @nsec_active_in_b2r2: The number of nanoseconds the job was active in B2R2. This
+ * is an approximate value, check out the code for more info.
+ * @total_time_nsec: The total time the job took in nano seconds. Includes ideling.
+ */
+struct b2r2_blt_profiling_info {
+ s32 nsec_active_in_cpu;
+ s32 nsec_active_in_b2r2;
+ s32 total_time_nsec;
+};
+
+/**
+ * struct b2r2_profiler - B2R2 profiler.
+ *
+ * The callbacks are never run concurrently. No heavy stuff must be done in the
+ * callbacks as this might adversely affect the B2R2 driver. The callbacks must
+ * not call the B2R2 profiler API as this will cause a deadlock. If the callbacks
+ * call into the B2R2 driver care must be taken as deadlock situations can arise.
+ *
+ * @blt_done: Called when a blit has finished, timed out or been canceled.
+ */
+struct b2r2_profiler {
+ void (*blt_done)(const struct b2r2_blt_req * const request, const s32 request_id, const struct b2r2_blt_profiling_info * const blt_profiling_info);
+};
+
+/**
+ * b2r2_register_profiler() - Registers a profiler.
+ *
+ * Currently only one profiler can be registered at any given time.
+ *
+ * @profiler: The profiler
+ *
+ * Returns 0 on success, negative error code on failure
+ */
+int b2r2_register_profiler(const struct b2r2_profiler * const profiler);
+
+/**
+ * b2r2_unregister_profiler() - Unregisters a profiler.
+ *
+ * @profiler: The profiler
+ */
+void b2r2_unregister_profiler(const struct b2r2_profiler * const profiler);
+
+#endif /* #ifdef _LINUX_VIDEO_B2R2_PROFILER_API_H */
diff --git a/drivers/video/b2r2/b2r2_profiler_socket.c b/drivers/video/b2r2/b2r2_profiler_socket.c
new file mode 100644
index 00000000000..cb95af9380e
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_profiler_socket.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 profiler socket communication
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/semaphore.h>
+#include <asm/errno.h>
+
+#include "b2r2_profiler_api.h"
+#include "b2r2_internal.h"
+#include "b2r2_core.h"
+
+/*
+ * TODO: Call the profiler in a seperate thread and have a circular buffer
+ * between the B2R2 driver and that thread. That way the profiler can not slow
+ * down or kill the B2R2 driver. Seems a bit overkill right now as there is
+ * only one B2R2 profiler and we have full control over it but the situation
+ * may be different in the future.
+ */
+
+
+static const struct b2r2_profiler *b2r2_profiler;
+static DEFINE_SEMAPHORE(b2r2_profiler_lock);
+
+
+int b2r2_register_profiler(const struct b2r2_profiler * const profiler)
+{
+ int return_value;
+
+ return_value = down_interruptible(&b2r2_profiler_lock);
+ if (return_value != 0)
+ return return_value;
+
+ if (b2r2_profiler != NULL) {
+ return_value = -EUSERS;
+
+ goto cleanup;
+ }
+
+ b2r2_profiler = profiler;
+
+ return_value = 0;
+
+cleanup:
+ up(&b2r2_profiler_lock);
+
+ return return_value;
+}
+EXPORT_SYMBOL(b2r2_register_profiler);
+
+void b2r2_unregister_profiler(const struct b2r2_profiler * const profiler)
+{
+ down(&b2r2_profiler_lock);
+
+ if (profiler == b2r2_profiler)
+ b2r2_profiler = NULL;
+
+ up(&b2r2_profiler_lock);
+}
+EXPORT_SYMBOL(b2r2_unregister_profiler);
+
+
+bool is_profiler_registered_approx(void)
+{
+ /* No locking by design, to make it fast, hence the approx */
+ if (b2r2_profiler != NULL)
+ return true;
+ else
+ return false;
+}
+
+void b2r2_call_profiler_blt_done(const struct b2r2_blt_request * const request)
+{
+ int return_value;
+ struct b2r2_blt_profiling_info blt_profiling_info;
+ struct b2r2_core *core = (struct b2r2_core *) request->job.data;
+ struct b2r2_control *cont = core->control;
+
+ return_value = down_interruptible(&b2r2_profiler_lock);
+ if (return_value != 0) {
+ dev_err(cont->dev,
+ "%s: Failed to acquire semaphore, ret=%i. "
+ "Lost profiler call!\n", __func__, return_value);
+
+ return;
+ }
+
+ if (NULL == b2r2_profiler)
+ goto cleanup;
+
+ blt_profiling_info.nsec_active_in_cpu = request->nsec_active_in_cpu;
+ blt_profiling_info.nsec_active_in_b2r2 = request->job.nsec_active_in_hw;
+ blt_profiling_info.total_time_nsec = request->total_time_nsec;
+
+ b2r2_profiler->blt_done(&request->user_req, request->request_id, &blt_profiling_info);
+
+cleanup:
+ up(&b2r2_profiler_lock);
+}
diff --git a/drivers/video/b2r2/b2r2_profiler_socket.h b/drivers/video/b2r2/b2r2_profiler_socket.h
new file mode 100644
index 00000000000..80b2c20293f
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_profiler_socket.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 profiler socket communication
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_VIDEO_B2R2_PROFILER_SOCKET_H
+#define _LINUX_VIDEO_B2R2_PROFILER_SOCKET_H
+
+#include "b2r2_internal.h"
+
+/* Will give a correct result most of the time but can be wrong */
+bool is_profiler_registered_approx(void);
+
+void b2r2_call_profiler_blt_done(const struct b2r2_blt_request * const request);
+
+#endif /* _LINUX_VIDEO_B2R2_PROFILER_SOCKET_H */
diff --git a/drivers/video/b2r2/b2r2_structures.h b/drivers/video/b2r2/b2r2_structures.h
new file mode 100644
index 00000000000..99fa7f047d3
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_structures.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 register struct
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#ifndef __B2R2_STRUCTURES_H
+#define __B2R2_STRUCTURES_H
+
+/* C struct view */
+struct b2r2_memory_map {
+ unsigned char fill0[2304];
+ unsigned int BLT_SSBA17; /* @2304 */
+ unsigned int BLT_SSBA18; /* @2308 */
+ unsigned int BLT_SSBA19; /* @2312 */
+ unsigned int BLT_SSBA20; /* @2316 */
+ unsigned int BLT_SSBA21; /* @2320 */
+ unsigned int BLT_SSBA22; /* @2324 */
+ unsigned int BLT_SSBA23; /* @2328 */
+ unsigned int BLT_SSBA24; /* @2332 */
+ unsigned char fill1[32];
+ unsigned int BLT_STBA5; /* @2368 */
+ unsigned int BLT_STBA6; /* @2372 */
+ unsigned int BLT_STBA7; /* @2376 */
+ unsigned int BLT_STBA8; /* @2380 */
+ unsigned char fill2[176];
+ unsigned int BLT_CTL; /* @2560 */
+ unsigned int BLT_ITS; /* @2564 */
+ unsigned int BLT_STA1; /* @2568 */
+ unsigned char fill3[4];
+ unsigned int BLT_SSBA1; /* @2576 */
+ unsigned int BLT_SSBA2; /* @2580 */
+ unsigned int BLT_SSBA3; /* @2584 */
+ unsigned int BLT_SSBA4; /* @2588 */
+ unsigned int BLT_SSBA5; /* @2592 */
+ unsigned int BLT_SSBA6; /* @2596 */
+ unsigned int BLT_SSBA7; /* @2600 */
+ unsigned int BLT_SSBA8; /* @2604 */
+ unsigned int BLT_STBA1; /* @2608 */
+ unsigned int BLT_STBA2; /* @2612 */
+ unsigned int BLT_STBA3; /* @2616 */
+ unsigned int BLT_STBA4; /* @2620 */
+ unsigned int BLT_CQ1_TRIG_IP; /* @2624 */
+ unsigned int BLT_CQ1_TRIG_CTL; /* @2628 */
+ unsigned int BLT_CQ1_PACE_CTL; /* @2632 */
+ unsigned int BLT_CQ1_IP; /* @2636 */
+ unsigned int BLT_CQ2_TRIG_IP; /* @2640 */
+ unsigned int BLT_CQ2_TRIG_CTL; /* @2644 */
+ unsigned int BLT_CQ2_PACE_CTL; /* @2648 */
+ unsigned int BLT_CQ2_IP; /* @2652 */
+ unsigned int BLT_AQ1_CTL; /* @2656 */
+ unsigned int BLT_AQ1_IP; /* @2660 */
+ unsigned int BLT_AQ1_LNA; /* @2664 */
+ unsigned int BLT_AQ1_STA; /* @2668 */
+ unsigned int BLT_AQ2_CTL; /* @2672 */
+ unsigned int BLT_AQ2_IP; /* @2676 */
+ unsigned int BLT_AQ2_LNA; /* @2680 */
+ unsigned int BLT_AQ2_STA; /* @2684 */
+ unsigned int BLT_AQ3_CTL; /* @2688 */
+ unsigned int BLT_AQ3_IP; /* @2692 */
+ unsigned int BLT_AQ3_LNA; /* @2696 */
+ unsigned int BLT_AQ3_STA; /* @2700 */
+ unsigned int BLT_AQ4_CTL; /* @2704 */
+ unsigned int BLT_AQ4_IP; /* @2708 */
+ unsigned int BLT_AQ4_LNA; /* @2712 */
+ unsigned int BLT_AQ4_STA; /* @2716 */
+ unsigned int BLT_SSBA9; /* @2720 */
+ unsigned int BLT_SSBA10; /* @2724 */
+ unsigned int BLT_SSBA11; /* @2728 */
+ unsigned int BLT_SSBA12; /* @2732 */
+ unsigned int BLT_SSBA13; /* @2736 */
+ unsigned int BLT_SSBA14; /* @2740 */
+ unsigned int BLT_SSBA15; /* @2744 */
+ unsigned int BLT_SSBA16; /* @2748 */
+ unsigned int BLT_SGA1; /* @2752 */
+ unsigned int BLT_SGA2; /* @2756 */
+ unsigned char fill4[8];
+ unsigned int BLT_ITM0; /* @2768 */
+ unsigned int BLT_ITM1; /* @2772 */
+ unsigned int BLT_ITM2; /* @2776 */
+ unsigned int BLT_ITM3; /* @2780 */
+ unsigned char fill5[16];
+ unsigned int BLT_DFV2; /* @2800 */
+ unsigned int BLT_DFV1; /* @2804 */
+ unsigned int BLT_PRI; /* @2808 */
+ unsigned char fill6[8];
+ unsigned int PLUGS1_OP2; /* @2820 */
+ unsigned int PLUGS1_CHZ; /* @2824 */
+ unsigned int PLUGS1_MSZ; /* @2828 */
+ unsigned int PLUGS1_PGZ; /* @2832 */
+ unsigned char fill7[16];
+ unsigned int PLUGS2_OP2; /* @2852 */
+ unsigned int PLUGS2_CHZ; /* @2856 */
+ unsigned int PLUGS2_MSZ; /* @2860 */
+ unsigned int PLUGS2_PGZ; /* @2864 */
+ unsigned char fill8[16];
+ unsigned int PLUGS3_OP2; /* @2884 */
+ unsigned int PLUGS3_CHZ; /* @2888 */
+ unsigned int PLUGS3_MSZ; /* @2892 */
+ unsigned int PLUGS3_PGZ; /* @2896 */
+ unsigned char fill9[48];
+ unsigned int PLUGT_OP2; /* @2948 */
+ unsigned int PLUGT_CHZ; /* @2952 */
+ unsigned int PLUGT_MSZ; /* @2956 */
+ unsigned int PLUGT_PGZ; /* @2960 */
+ unsigned char fill10[108];
+ unsigned int BLT_NIP; /* @3072 */
+ unsigned int BLT_CIC; /* @3076 */
+ unsigned int BLT_INS; /* @3080 */
+ unsigned int BLT_ACK; /* @3084 */
+ unsigned int BLT_TBA; /* @3088 */
+ unsigned int BLT_TTY; /* @3092 */
+ unsigned int BLT_TXY; /* @3096 */
+ unsigned int BLT_TSZ; /* @3100 */
+ unsigned int BLT_S1CF; /* @3104 */
+ unsigned int BLT_S2CF; /* @3108 */
+ unsigned int BLT_S1BA; /* @3112 */
+ unsigned int BLT_S1TY; /* @3116 */
+ unsigned int BLT_S1XY; /* @3120 */
+ unsigned char fill11[4];
+ unsigned int BLT_S2BA; /* @3128 */
+ unsigned int BLT_S2TY; /* @3132 */
+ unsigned int BLT_S2XY; /* @3136 */
+ unsigned int BLT_S2SZ; /* @3140 */
+ unsigned int BLT_S3BA; /* @3144 */
+ unsigned int BLT_S3TY; /* @3148 */
+ unsigned int BLT_S3XY; /* @3152 */
+ unsigned int BLT_S3SZ; /* @3156 */
+ unsigned int BLT_CWO; /* @3160 */
+ unsigned int BLT_CWS; /* @3164 */
+ unsigned int BLT_CCO; /* @3168 */
+ unsigned int BLT_CML; /* @3172 */
+ unsigned int BLT_FCTL; /* @3176 */
+ unsigned int BLT_PMK; /* @3180 */
+ unsigned int BLT_RSF; /* @3184 */
+ unsigned int BLT_RZI; /* @3188 */
+ unsigned int BLT_HFP; /* @3192 */
+ unsigned int BLT_VFP; /* @3196 */
+ unsigned int BLT_Y_RSF; /* @3200 */
+ unsigned int BLT_Y_RZI; /* @3204 */
+ unsigned int BLT_Y_HFP; /* @3208 */
+ unsigned int BLT_Y_VFP; /* @3212 */
+ unsigned char fill12[16];
+ unsigned int BLT_KEY1; /* @3232 */
+ unsigned int BLT_KEY2; /* @3236 */
+ unsigned char fill13[8];
+ unsigned int BLT_SAR; /* @3248 */
+ unsigned int BLT_USR; /* @3252 */
+ unsigned char fill14[8];
+ unsigned int BLT_IVMX0; /* @3264 */
+ unsigned int BLT_IVMX1; /* @3268 */
+ unsigned int BLT_IVMX2; /* @3272 */
+ unsigned int BLT_IVMX3; /* @3276 */
+ unsigned int BLT_OVMX0; /* @3280 */
+ unsigned int BLT_OVMX1; /* @3284 */
+ unsigned int BLT_OVMX2; /* @3288 */
+ unsigned int BLT_OVMX3; /* @3292 */
+ unsigned char fill15[8];
+ unsigned int BLT_VC1R; /* @3304 */
+ unsigned char fill16[20];
+ unsigned int BLT_Y_HFC0; /* @3328 */
+ unsigned int BLT_Y_HFC1; /* @3332 */
+ unsigned int BLT_Y_HFC2; /* @3336 */
+ unsigned int BLT_Y_HFC3; /* @3340 */
+ unsigned int BLT_Y_HFC4; /* @3344 */
+ unsigned int BLT_Y_HFC5; /* @3348 */
+ unsigned int BLT_Y_HFC6; /* @3352 */
+ unsigned int BLT_Y_HFC7; /* @3356 */
+ unsigned int BLT_Y_HFC8; /* @3360 */
+ unsigned int BLT_Y_HFC9; /* @3364 */
+ unsigned int BLT_Y_HFC10; /* @3368 */
+ unsigned int BLT_Y_HFC11; /* @3372 */
+ unsigned int BLT_Y_HFC12; /* @3376 */
+ unsigned int BLT_Y_HFC13; /* @3380 */
+ unsigned int BLT_Y_HFC14; /* @3384 */
+ unsigned int BLT_Y_HFC15; /* @3388 */
+ unsigned char fill17[80];
+ unsigned int BLT_Y_VFC0; /* @3472 */
+ unsigned int BLT_Y_VFC1; /* @3476 */
+ unsigned int BLT_Y_VFC2; /* @3480 */
+ unsigned int BLT_Y_VFC3; /* @3484 */
+ unsigned int BLT_Y_VFC4; /* @3488 */
+ unsigned int BLT_Y_VFC5; /* @3492 */
+ unsigned int BLT_Y_VFC6; /* @3496 */
+ unsigned int BLT_Y_VFC7; /* @3500 */
+ unsigned int BLT_Y_VFC8; /* @3504 */
+ unsigned int BLT_Y_VFC9; /* @3508 */
+ unsigned char fill18[72];
+ unsigned int BLT_HFC0; /* @3584 */
+ unsigned int BLT_HFC1; /* @3588 */
+ unsigned int BLT_HFC2; /* @3592 */
+ unsigned int BLT_HFC3; /* @3596 */
+ unsigned int BLT_HFC4; /* @3600 */
+ unsigned int BLT_HFC5; /* @3604 */
+ unsigned int BLT_HFC6; /* @3608 */
+ unsigned int BLT_HFC7; /* @3612 */
+ unsigned int BLT_HFC8; /* @3616 */
+ unsigned int BLT_HFC9; /* @3620 */
+ unsigned int BLT_HFC10; /* @3624 */
+ unsigned int BLT_HFC11; /* @3628 */
+ unsigned int BLT_HFC12; /* @3632 */
+ unsigned int BLT_HFC13; /* @3636 */
+ unsigned int BLT_HFC14; /* @3640 */
+ unsigned int BLT_HFC15; /* @3644 */
+ unsigned char fill19[80];
+ unsigned int BLT_VFC0; /* @3728 */
+ unsigned int BLT_VFC1; /* @3732 */
+ unsigned int BLT_VFC2; /* @3736 */
+ unsigned int BLT_VFC3; /* @3740 */
+ unsigned int BLT_VFC4; /* @3744 */
+ unsigned int BLT_VFC5; /* @3748 */
+ unsigned int BLT_VFC6; /* @3752 */
+ unsigned int BLT_VFC7; /* @3756 */
+ unsigned int BLT_VFC8; /* @3760 */
+ unsigned int BLT_VFC9; /* @3764 */
+};
+
+#endif /* !defined(__B2R2_STRUCTURES_H) */
+
diff --git a/drivers/video/b2r2/b2r2_timing.c b/drivers/video/b2r2/b2r2_timing.c
new file mode 100644
index 00000000000..4f3e2b8b042
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_timing.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 timing
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/time.h>
+
+
+u32 b2r2_get_curr_nsec(void)
+{
+ struct timespec ts;
+
+ getrawmonotonic(&ts);
+
+ return (u32)timespec_to_ns(&ts);
+}
diff --git a/drivers/video/b2r2/b2r2_timing.h b/drivers/video/b2r2/b2r2_timing.h
new file mode 100644
index 00000000000..e87113c0ec9
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_timing.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 timing
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_TIMING_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_TIMING_H_
+
+/**
+ * b2r2_get_curr_nsec() - Return the current nanosecond. Notice that the value
+ * wraps when the u32 limit is reached.
+ *
+ */
+u32 b2r2_get_curr_nsec(void);
+
+#endif /* _LINUX_DRIVERS_VIDEO_B2R2_TIMING_H_ */
diff --git a/drivers/video/b2r2/b2r2_utils.c b/drivers/video/b2r2/b2r2_utils.c
new file mode 100644
index 00000000000..44c738b5aab
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_utils.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 utils
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <video/b2r2_blt.h>
+
+#include "b2r2_utils.h"
+#include "b2r2_debug.h"
+#include "b2r2_internal.h"
+
+const s32 b2r2_s32_max = 2147483647;
+
+
+/**
+ * calculate_scale_factor() - calculates the scale factor between the given
+ * values
+ */
+int calculate_scale_factor(struct device *dev,
+ u32 from, u32 to, u16 *sf_out)
+{
+ int ret;
+ u32 sf;
+
+ b2r2_log_info(dev, "%s\n", __func__);
+
+ if (to == from) {
+ *sf_out = 1 << 10;
+ return 0;
+ } else if (to == 0) {
+ b2r2_log_err(dev, "%s: To is 0!\n", __func__);
+ BUG_ON(1);
+ }
+
+ sf = (from << 10) / to;
+
+ if ((sf & 0xffff0000) != 0) {
+ /* Overflow error */
+ b2r2_log_warn(dev, "%s: "
+ "Scale factor too large\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ } else if (sf == 0) {
+ b2r2_log_warn(dev, "%s: "
+ "Scale factor too small\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ *sf_out = (u16)sf;
+
+ b2r2_log_info(dev, "%s exit\n", __func__);
+
+ return 0;
+
+error:
+ b2r2_log_warn(dev, "%s: Exit...\n", __func__);
+ return ret;
+}
+
+void b2r2_get_img_bounding_rect(struct b2r2_blt_img *img,
+ struct b2r2_blt_rect *bounding_rect)
+{
+ bounding_rect->x = 0;
+ bounding_rect->y = 0;
+ bounding_rect->width = img->width;
+ bounding_rect->height = img->height;
+}
+
+
+bool b2r2_is_zero_area_rect(struct b2r2_blt_rect *rect)
+{
+ return rect->width == 0 || rect->height == 0;
+}
+
+bool b2r2_is_rect_inside_rect(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2)
+{
+ return rect1->x >= rect2->x &&
+ rect1->y >= rect2->y &&
+ rect1->x + rect1->width <= rect2->x + rect2->width &&
+ rect1->y + rect1->height <= rect2->y + rect2->height;
+}
+
+bool b2r2_is_rect_gte_rect(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2)
+{
+ return rect1->width >= rect2->width &&
+ rect1->height >= rect2->height;
+}
+
+void b2r2_intersect_rects(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2, struct b2r2_blt_rect *intersection)
+{
+ struct b2r2_blt_rect tmp_rect;
+
+ tmp_rect.x = max(rect1->x, rect2->x);
+ tmp_rect.y = max(rect1->y, rect2->y);
+ tmp_rect.width = min(rect1->x + rect1->width, rect2->x + rect2->width)
+ - tmp_rect.x;
+ if (tmp_rect.width < 0)
+ tmp_rect.width = 0;
+ tmp_rect.height =
+ min(rect1->y + rect1->height, rect2->y + rect2->height) -
+ tmp_rect.y;
+ if (tmp_rect.height < 0)
+ tmp_rect.height = 0;
+
+ *intersection = tmp_rect;
+}
+
+/*
+ * Calculate new rectangles for the supplied
+ * request, so that clipping to destination imaage
+ * can be avoided.
+ * Essentially, the new destination rectangle is
+ * defined inside the old one. Given the transform
+ * and scaling, one has to calculate which part of
+ * the old source rectangle corresponds to
+ * to the new part of old destination rectangle.
+ */
+void b2r2_trim_rects(struct device *dev,
+ const struct b2r2_blt_req *req,
+ struct b2r2_blt_rect *new_bg_rect,
+ struct b2r2_blt_rect *new_dst_rect,
+ struct b2r2_blt_rect *new_src_rect)
+{
+ enum b2r2_blt_transform transform = req->transform;
+ struct b2r2_blt_rect *old_src_rect =
+ (struct b2r2_blt_rect *) &req->src_rect;
+ struct b2r2_blt_rect *old_dst_rect =
+ (struct b2r2_blt_rect *) &req->dst_rect;
+ struct b2r2_blt_rect *old_bg_rect =
+ (struct b2r2_blt_rect *) &req->bg_rect;
+ struct b2r2_blt_rect dst_img_bounds;
+ s32 src_x = 0;
+ s32 src_y = 0;
+ s32 src_w = 0;
+ s32 src_h = 0;
+ s32 dx = 0;
+ s32 dy = 0;
+ s16 hsf;
+ s16 vsf;
+
+ b2r2_log_info(dev,
+ "%s\nold_dst_rect(x,y,w,h)=(%d, %d, %d, %d)\n", __func__,
+ old_dst_rect->x, old_dst_rect->y,
+ old_dst_rect->width, old_dst_rect->height);
+ b2r2_log_info(dev,
+ "%s\nold_src_rect(x,y,w,h)=(%d, %d, %d, %d)\n", __func__,
+ old_src_rect->x, old_src_rect->y,
+ old_src_rect->width, old_src_rect->height);
+
+ b2r2_get_img_bounding_rect((struct b2r2_blt_img *) &req->dst_img,
+ &dst_img_bounds);
+
+ /* dst_rect inside dst_img, no clipping necessary */
+ if (b2r2_is_rect_inside_rect(old_dst_rect, &dst_img_bounds))
+ goto keep_rects;
+
+ b2r2_intersect_rects(old_dst_rect, &dst_img_bounds, new_dst_rect);
+ b2r2_log_info(dev,
+ "%s\nnew_dst_rect(x,y,w,h)=(%d, %d, %d, %d)\n", __func__,
+ new_dst_rect->x, new_dst_rect->y,
+ new_dst_rect->width, new_dst_rect->height);
+
+ /* dst_rect completely outside, leave it to validation */
+ if (new_dst_rect->width == 0 || new_dst_rect->height == 0)
+ goto keep_rects;
+
+ dx = new_dst_rect->x - old_dst_rect->x;
+ dy = new_dst_rect->y - old_dst_rect->y;
+
+ if (transform & B2R2_BLT_TRANSFORM_CCW_ROT_90) {
+ int res = 0;
+ res = calculate_scale_factor(dev, old_src_rect->width,
+ old_dst_rect->height, &hsf);
+ /* invalid dimensions, leave them to validation */
+ if (res < 0)
+ goto keep_rects;
+
+ res = calculate_scale_factor(dev, old_src_rect->height,
+ old_dst_rect->width, &vsf);
+ if (res < 0)
+ goto keep_rects;
+
+ /*
+ * After applying the inverse transform
+ * for 90 degree rotation, the top-left corner
+ * becomes top-right.
+ * src_rect origin is defined as top-left,
+ * so a translation between dst and src
+ * coordinate spaces is necessary.
+ */
+ src_x = (old_src_rect->width << 10) -
+ hsf * (dy + new_dst_rect->height);
+ src_y = dx * vsf;
+ src_w = new_dst_rect->height * hsf;
+ src_h = new_dst_rect->width * vsf;
+ } else {
+ int res = 0;
+ res = calculate_scale_factor(dev, old_src_rect->width,
+ old_dst_rect->width, &hsf);
+ if (res < 0)
+ goto keep_rects;
+
+ res = calculate_scale_factor(dev, old_src_rect->height,
+ old_dst_rect->height, &vsf);
+ if (res < 0)
+ goto keep_rects;
+
+ src_x = dx * hsf;
+ src_y = dy * vsf;
+ src_w = new_dst_rect->width * hsf;
+ src_h = new_dst_rect->height * vsf;
+ }
+
+ /*
+ * src_w must contain all the pixels that contribute
+ * to a particular destination rectangle.
+ * ((x + 0x3ff) >> 10) is equivalent to ceiling(x),
+ * expressed in 6.10 fixed point format.
+ * Every destination rectangle, maps to a certain area in the source
+ * rectangle. The area in source will most likely not be a rectangle
+ * with exact integer dimensions whenever arbitrary scaling is involved.
+ * Consider the following example.
+ * Suppose, that width of the current destination rectangle maps
+ * to 1.7 pixels in source, starting at x == 5.4, as calculated
+ * using the scaling factor.
+ * This means that while the destination rectangle is written,
+ * the source should be read from x == 5.4 up to x == 5.4 + 1.7 == 7.1
+ * Consequently, color from 3 pixels (x == 5, 6 and 7)
+ * needs to be read from source.
+ * The formula below the comment yields:
+ * ceil(0.4 + 1.7) == ceil(2.1) == 3
+ * (src_x & 0x3ff) is the fractional part of src_x,
+ * which is expressed in 6.10 fixed point format.
+ * Thus, width of the source area should be 3 pixels wide,
+ * starting at x == 5.
+ */
+ src_w = ((src_x & 0x3ff) + src_w + 0x3ff) >> 10;
+ src_h = ((src_y & 0x3ff) + src_h + 0x3ff) >> 10;
+
+ src_x >>= 10;
+ src_y >>= 10;
+
+ if (transform & B2R2_BLT_TRANSFORM_FLIP_H)
+ src_x = old_src_rect->width - src_x - src_w;
+
+ if (transform & B2R2_BLT_TRANSFORM_FLIP_V)
+ src_y = old_src_rect->height - src_y - src_h;
+
+ /*
+ * Translate the src_rect coordinates into true
+ * src_buffer coordinates.
+ */
+ src_x += old_src_rect->x;
+ src_y += old_src_rect->y;
+
+ new_src_rect->x = src_x;
+ new_src_rect->y = src_y;
+ new_src_rect->width = src_w;
+ new_src_rect->height = src_h;
+
+ b2r2_log_info(dev,
+ "%s\nnew_src_rect(x,y,w,h)=(%d, %d, %d, %d)\n", __func__,
+ new_src_rect->x, new_src_rect->y,
+ new_src_rect->width, new_src_rect->height);
+
+ if (req->flags & B2R2_BLT_FLAG_BG_BLEND) {
+ /* Modify bg_rect in the same way as dst_rect */
+ s32 dw = new_dst_rect->width - old_dst_rect->width;
+ s32 dh = new_dst_rect->height - old_dst_rect->height;
+ b2r2_log_info(dev,
+ "%s\nold bg_rect(x,y,w,h)=(%d, %d, %d, %d)\n",
+ __func__, old_bg_rect->x, old_bg_rect->y,
+ old_bg_rect->width, old_bg_rect->height);
+ new_bg_rect->x = old_bg_rect->x + dx;
+ new_bg_rect->y = old_bg_rect->y + dy;
+ new_bg_rect->width = old_bg_rect->width + dw;
+ new_bg_rect->height = old_bg_rect->height + dh;
+ b2r2_log_info(dev,
+ "%s\nnew bg_rect(x,y,w,h)=(%d, %d, %d, %d)\n",
+ __func__, new_bg_rect->x, new_bg_rect->y,
+ new_bg_rect->width, new_bg_rect->height);
+ }
+ return;
+keep_rects:
+ /*
+ * Recalculation was not possible, or not necessary.
+ * Do not change anything, leave it to validation.
+ */
+ *new_src_rect = *old_src_rect;
+ *new_dst_rect = *old_dst_rect;
+ *new_bg_rect = *old_bg_rect;
+ b2r2_log_info(dev, "%s original rectangles preserved.\n", __func__);
+ return;
+}
+
+int b2r2_get_fmt_bpp(struct device *dev, enum b2r2_blt_fmt fmt)
+{
+ /*
+ * Currently this function is not used that often but if that changes a
+ * lookup table could make it a lot faster.
+ */
+ switch (fmt) {
+ case B2R2_BLT_FMT_1_BIT_A1:
+ return 1;
+
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return 8;
+
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ return 12;
+
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return 16;
+
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return 24;
+
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return 32;
+
+ default:
+ b2r2_log_err(dev,
+ "%s: Internal error! Format %#x not recognized.\n",
+ __func__, fmt);
+ return 32;
+ }
+}
+
+int b2r2_get_fmt_y_bpp(struct device *dev, enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return 8;
+
+ default:
+ b2r2_log_err(dev,
+ "%s: Internal error! Non YCbCr format supplied.\n",
+ __func__);
+ return 8;
+ }
+}
+
+
+bool b2r2_is_single_plane_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_independent_pixel_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcri_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcrsp_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcrp_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcr420_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcr422_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_ycbcr444_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_mb_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+u32 b2r2_calc_pitch_from_width(struct device *dev,
+ s32 width, enum b2r2_blt_fmt fmt)
+{
+ if (b2r2_is_single_plane_fmt(fmt)) {
+ return (u32)b2r2_div_round_up(width *
+ b2r2_get_fmt_bpp(dev, fmt), 8);
+ } else if (b2r2_is_ycbcrsp_fmt(fmt) || b2r2_is_ycbcrp_fmt(fmt)) {
+ return (u32)b2r2_div_round_up(width *
+ b2r2_get_fmt_y_bpp(dev, fmt), 8);
+ } else {
+ b2r2_log_err(dev, "%s: Internal error! "
+ "Pitchless format supplied.\n",
+ __func__);
+ return 0;
+ }
+}
+
+u32 b2r2_get_img_pitch(struct device *dev, struct b2r2_blt_img *img)
+{
+ if (img->pitch != 0)
+ return img->pitch;
+ else
+ return b2r2_calc_pitch_from_width(dev, img->width, img->fmt);
+}
+
+s32 b2r2_get_img_size(struct device *dev, struct b2r2_blt_img *img)
+{
+ if (b2r2_is_single_plane_fmt(img->fmt)) {
+ return (s32)b2r2_get_img_pitch(dev, img) * img->height;
+ } else if (b2r2_is_ycbcrsp_fmt(img->fmt) ||
+ b2r2_is_ycbcrp_fmt(img->fmt)) {
+ s32 y_plane_size;
+
+ y_plane_size = (s32)b2r2_get_img_pitch(dev, img) * img->height;
+
+ if (b2r2_is_ycbcr420_fmt(img->fmt)) {
+ return y_plane_size + y_plane_size / 2;
+ } else if (b2r2_is_ycbcr422_fmt(img->fmt)) {
+ return y_plane_size * 2;
+ } else if (b2r2_is_ycbcr444_fmt(img->fmt)) {
+ return y_plane_size * 3;
+ } else {
+ b2r2_log_err(dev, "%s: Internal error!"
+ " Format %#x not recognized.\n",
+ __func__, img->fmt);
+ return 0;
+ }
+ } else if (b2r2_is_mb_fmt(img->fmt)) {
+ return (img->width * img->height *
+ b2r2_get_fmt_bpp(dev, img->fmt)) / 8;
+ } else {
+ b2r2_log_err(dev, "%s: Internal error! "
+ "Format %#x not recognized.\n",
+ __func__, img->fmt);
+ return 0;
+ }
+}
+
+
+s32 b2r2_div_round_up(s32 dividend, s32 divisor)
+{
+ s32 quotient = dividend / divisor;
+ if (dividend % divisor != 0)
+ quotient++;
+
+ return quotient;
+}
+
+bool b2r2_is_aligned(s32 value, s32 alignment)
+{
+ return value % alignment == 0;
+}
+
+s32 b2r2_align_up(s32 value, s32 alignment)
+{
+ s32 remainder = abs(value) % abs(alignment);
+ s32 value_to_add;
+
+ if (remainder > 0) {
+ if (value >= 0)
+ value_to_add = alignment - remainder;
+ else
+ value_to_add = remainder;
+ } else {
+ value_to_add = 0;
+ }
+
+ return value + value_to_add;
+}
+
+/**
+ * b2r2_get_alpha_range() - returns the alpha range of the given format
+ */
+enum b2r2_ty b2r2_get_alpha_range(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ return B2R2_TY_ALPHA_RANGE_255; /* 0 - 255 */
+ default:
+ return B2R2_TY_ALPHA_RANGE_128; /* 0 - 128 */
+ }
+}
+
+/**
+ * b2r2_get_alpha() - returns the pixel alpha in 0...255 range
+ */
+u8 b2r2_get_alpha(enum b2r2_blt_fmt fmt, u32 pixel)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ return (pixel >> 24) & 0xff;
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return pixel & 0xff;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ return (pixel & 0xfff) >> 16;
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ return (((pixel >> 12) & 0xf) * 255) / 15;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ return (pixel >> 15) * 255;
+ case B2R2_BLT_FMT_1_BIT_A1:
+ return pixel * 255;
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return pixel;
+ default:
+ return 255;
+ }
+}
+
+/**
+ * b2r2_set_alpha() - returns a color value with the alpha component set
+ */
+u32 b2r2_set_alpha(enum b2r2_blt_fmt fmt, u8 alpha, u32 color)
+{
+ u32 alpha_mask;
+
+ switch (fmt) {
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ color &= 0x00ffffff;
+ alpha_mask = alpha << 24;
+ break;
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ color &= 0xffffff00;
+ alpha_mask = alpha;
+ break;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ color &= 0x00ffff;
+ alpha_mask = alpha << 16;
+ break;
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ color &= 0x0fff;
+ alpha_mask = (alpha << 8) & 0xF000;
+ break;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ color &= 0x7fff;
+ alpha_mask = (alpha / 255) << 15 ;
+ break;
+ case B2R2_BLT_FMT_1_BIT_A1:
+ color = 0;
+ alpha_mask = (alpha / 255);
+ break;
+ case B2R2_BLT_FMT_8_BIT_A8:
+ color = 0;
+ alpha_mask = alpha;
+ break;
+ default:
+ alpha_mask = 0;
+ }
+
+ return color | alpha_mask;
+}
+
+/**
+ * b2r2_fmt_has_alpha() - returns whether the given format carries an alpha value
+ */
+bool b2r2_fmt_has_alpha(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_is_rgb_fmt() - returns whether the given format is a rgb format
+ */
+bool b2r2_is_rgb_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_is_bgr_fmt() - returns whether the given format is a bgr format
+ */
+bool b2r2_is_bgr_fmt(enum b2r2_blt_fmt fmt)
+{
+ return (fmt == B2R2_BLT_FMT_32_BIT_ABGR8888);
+}
+
+/**
+ * b2r2_is_yuv_fmt() - returns whether the given format is a yuv format
+ */
+bool b2r2_is_yuv_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_is_yvu_fmt() - returns whether the given format is a yvu format
+ */
+bool b2r2_is_yvu_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_is_yuv420_fmt() - returns whether the given format is a yuv420 format
+ */
+bool b2r2_is_yuv420_fmt(enum b2r2_blt_fmt fmt)
+{
+
+ switch (fmt) {
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_yuv422_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_is_yvu420_fmt() - returns whether the given format is a yvu420 format
+ */
+bool b2r2_is_yvu420_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool b2r2_is_yvu422_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/**
+ * b2r2_is_yuv444_fmt() - returns whether the given format is a yuv444 format
+ */
+bool b2r2_is_yuv444_fmt(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * b2r2_fmt_byte_pitch() - returns the pitch of a pixmap with the given width
+ */
+int b2r2_fmt_byte_pitch(enum b2r2_blt_fmt fmt, u32 width)
+{
+ int pitch;
+
+ switch (fmt) {
+
+ case B2R2_BLT_FMT_1_BIT_A1:
+ pitch = width >> 3; /* Shift is faster than division */
+ if ((width & 0x3) != 0) /* Check for remainder */
+ pitch++;
+ return pitch;
+
+ case B2R2_BLT_FMT_8_BIT_A8: /* Fall through */
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE: /* Fall through */
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE: /* Fall through */
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR: /* Fall through */
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return width;
+
+ case B2R2_BLT_FMT_16_BIT_ARGB4444: /* Fall through */
+ case B2R2_BLT_FMT_16_BIT_ARGB1555: /* Fall through */
+ case B2R2_BLT_FMT_16_BIT_RGB565: /* Fall through */
+ case B2R2_BLT_FMT_Y_CB_Y_CR: /* Fall through */
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ return width << 1;
+
+ case B2R2_BLT_FMT_24_BIT_RGB888: /* Fall through */
+ case B2R2_BLT_FMT_24_BIT_ARGB8565: /* Fall through */
+ case B2R2_BLT_FMT_24_BIT_YUV888: /* Fall through */
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ return width * 3;
+
+ case B2R2_BLT_FMT_32_BIT_ARGB8888: /* Fall through */
+ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Fall through */
+ case B2R2_BLT_FMT_32_BIT_AYUV8888: /* Fall through */
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ return width << 2;
+
+ default:
+ /* Should never, ever happen */
+ BUG_ON(1);
+ return 0;
+ }
+}
+
+/**
+ * b2r2_to_native_fmt() - returns the native B2R2 format
+ */
+enum b2r2_native_fmt b2r2_to_native_fmt(enum b2r2_blt_fmt fmt)
+{
+
+ switch (fmt) {
+ case B2R2_BLT_FMT_UNUSED:
+ return B2R2_NATIVE_RGB565;
+ case B2R2_BLT_FMT_1_BIT_A1:
+ return B2R2_NATIVE_A1;
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return B2R2_NATIVE_A8;
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ return B2R2_NATIVE_RGB565;
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ return B2R2_NATIVE_ARGB4444;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ return B2R2_NATIVE_ARGB1555;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ return B2R2_NATIVE_ARGB8565;
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ return B2R2_NATIVE_RGB888;
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_24_BIT_VUY888: /* Not actually supported by HW */
+ return B2R2_NATIVE_YCBCR888;
+ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Not actually supported by HW */
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ return B2R2_NATIVE_ARGB8888;
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888: /* Not actually supported by HW */
+ return B2R2_NATIVE_AYCBCR8888;
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ return B2R2_NATIVE_YCBCR422R;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ return B2R2_NATIVE_YCBCR422R;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ return B2R2_NATIVE_YCBCR42X_R2B;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return B2R2_NATIVE_YCBCR42X_MBN;
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return B2R2_NATIVE_YUV;
+ default:
+ /* Should never ever happen */
+ return B2R2_NATIVE_BYTE;
+ }
+}
+
+/**
+ * Bit-expand the color from fmt to RGB888 with blue at LSB.
+ * Copy MSBs into missing LSBs.
+ */
+u32 b2r2_to_RGB888(u32 color, const enum b2r2_blt_fmt fmt)
+{
+ u32 out_color = 0;
+ u32 r = 0;
+ u32 g = 0;
+ u32 b = 0;
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ r = ((color & 0xf00) << 12) | ((color & 0xf00) << 8);
+ g = ((color & 0xf0) << 8) | ((color & 0xf0) << 4);
+ b = ((color & 0xf) << 4) | (color & 0xf);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ r = ((color & 0x7c00) << 9) | ((color & 0x7000) << 4);
+ g = ((color & 0x3e0) << 6) | ((color & 0x380) << 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ r = ((color & 0xf800) << 8) | ((color & 0xe000) << 3);
+ g = ((color & 0x7e0) << 5) | ((color & 0x600) >> 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ out_color = color & 0xffffff;
+ break;
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ r = (color & 0xff) << 16;
+ g = color & 0xff00;
+ b = (color & 0xff0000) >> 16;
+ out_color = r | g | b;
+ break;
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ r = ((color & 0xf800) << 8) | ((color & 0xe000) << 3);
+ g = ((color & 0x7e0) << 5) | ((color & 0x600) >> 1);
+ b = ((color & 0x1f) << 3) | ((color & 0x1c) >> 2);
+ out_color = r | g | b;
+ break;
+ default:
+ break;
+ }
+
+ return out_color;
+}
+
+/**
+ * b2r2_get_fmt_type() - returns the type of the given format (raster, planar, etc.)
+ */
+enum b2r2_fmt_type b2r2_get_fmt_type(enum b2r2_blt_fmt fmt)
+{
+ switch (fmt) {
+ case B2R2_BLT_FMT_16_BIT_ARGB4444:
+ case B2R2_BLT_FMT_16_BIT_ARGB1555:
+ case B2R2_BLT_FMT_16_BIT_RGB565:
+ case B2R2_BLT_FMT_24_BIT_RGB888:
+ case B2R2_BLT_FMT_32_BIT_ARGB8888:
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
+ case B2R2_BLT_FMT_CB_Y_CR_Y:
+ case B2R2_BLT_FMT_32_BIT_ABGR8888:
+ case B2R2_BLT_FMT_24_BIT_ARGB8565:
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ case B2R2_BLT_FMT_24_BIT_VUY888:
+ case B2R2_BLT_FMT_32_BIT_VUYA8888:
+ case B2R2_BLT_FMT_1_BIT_A1:
+ case B2R2_BLT_FMT_8_BIT_A8:
+ return B2R2_FMT_TYPE_RASTER;
+ case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_PLANAR:
+ case B2R2_BLT_FMT_YUV444_PACKED_PLANAR:
+ return B2R2_FMT_TYPE_PLANAR;
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
+ case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
+ case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
+ return B2R2_FMT_TYPE_SEMI_PLANAR;
+ default:
+ return B2R2_FMT_TYPE_RASTER;
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+/**
+ * sprintf_req() - Builds a string representing the request, for debug
+ *
+ * @request:Request that should be encoded into a string
+ * @buf: Receiving buffer
+ * @size: Size of receiving buffer
+ *
+ * Returns number of characters in string, excluding null terminator
+ */
+int sprintf_req(struct b2r2_blt_request *request, char *buf, int size)
+{
+ size_t dev_size = 0;
+
+ /* generic request info */
+ dev_size += sprintf(buf + dev_size,
+ "instance : 0x%08lX\n",
+ (unsigned long) request->instance);
+ dev_size += sprintf(buf + dev_size,
+ "size : %d bytes\n", request->user_req.size);
+ dev_size += sprintf(buf + dev_size,
+ "flags : 0x%08lX\n",
+ (unsigned long) request->user_req.flags);
+ dev_size += sprintf(buf + dev_size,
+ "transform : %d\n",
+ (int) request->user_req.transform);
+ dev_size += sprintf(buf + dev_size,
+ "prio : %d\n", request->user_req.transform);
+ dev_size += sprintf(buf + dev_size,
+ "global_alpha : %d\n",
+ (int) request->user_req.global_alpha);
+ dev_size += sprintf(buf + dev_size,
+ "report1 : 0x%08lX\n",
+ (unsigned long) request->user_req.report1);
+ dev_size += sprintf(buf + dev_size,
+ "report2 : 0x%08lX\n",
+ (unsigned long) request->user_req.report2);
+ dev_size += sprintf(buf + dev_size,
+ "request_id : 0x%08lX\n\n",
+ (unsigned long) request->request_id);
+
+ /* src info */
+ dev_size += sprintf(buf + dev_size,
+ "src_img.fmt : %#010x\n",
+ request->user_req.src_img.fmt);
+ dev_size += sprintf(buf + dev_size,
+ "src_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d, "
+ "offset=%d, len=%d}\n",
+ request->user_req.src_img.buf.type,
+ request->user_req.src_img.buf.hwmem_buf_name,
+ request->user_req.src_img.buf.fd,
+ request->user_req.src_img.buf.offset,
+ request->user_req.src_img.buf.len);
+ dev_size += sprintf(buf + dev_size,
+ "src_img : {width=%d, height=%d, pitch=%d}\n",
+ request->user_req.src_img.width,
+ request->user_req.src_img.height,
+ request->user_req.src_img.pitch);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask.fmt : %#010x\n",
+ request->user_req.src_mask.fmt);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
+ " offset=%d, len=%d}\n",
+ request->user_req.src_mask.buf.type,
+ request->user_req.src_mask.buf.hwmem_buf_name,
+ request->user_req.src_mask.buf.fd,
+ request->user_req.src_mask.buf.offset,
+ request->user_req.src_mask.buf.len);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask : {width=%d, height=%d, pitch=%d}\n",
+ request->user_req.src_mask.width,
+ request->user_req.src_mask.height,
+ request->user_req.src_mask.pitch);
+ dev_size += sprintf(buf + dev_size,
+ "src_rect : {x=%d, y=%d, width=%d, height=%d}\n",
+ request->user_req.src_rect.x,
+ request->user_req.src_rect.y,
+ request->user_req.src_rect.width,
+ request->user_req.src_rect.height);
+ dev_size += sprintf(buf + dev_size,
+ "src_color : 0x%08lX\n\n",
+ (unsigned long) request->user_req.src_color);
+
+ /* bg info */
+ dev_size += sprintf(buf + dev_size,
+ "bg_img.fmt : %#010x\n",
+ request->user_req.bg_img.fmt);
+ dev_size += sprintf(buf + dev_size,
+ "bg_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
+ " offset=%d, len=%d}\n",
+ request->user_req.bg_img.buf.type,
+ request->user_req.bg_img.buf.hwmem_buf_name,
+ request->user_req.bg_img.buf.fd,
+ request->user_req.bg_img.buf.offset,
+ request->user_req.bg_img.buf.len);
+ dev_size += sprintf(buf + dev_size,
+ "bg_img : {width=%d, height=%d, pitch=%d}\n",
+ request->user_req.bg_img.width,
+ request->user_req.bg_img.height,
+ request->user_req.bg_img.pitch);
+ dev_size += sprintf(buf + dev_size,
+ "bg_rect : {x=%d, y=%d, width=%d, height=%d}\n\n",
+ request->user_req.bg_rect.x,
+ request->user_req.bg_rect.y,
+ request->user_req.bg_rect.width,
+ request->user_req.bg_rect.height);
+
+ /* dst info */
+ dev_size += sprintf(buf + dev_size,
+ "dst_img.fmt : %#010x\n",
+ request->user_req.dst_img.fmt);
+ dev_size += sprintf(buf + dev_size,
+ "dst_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
+ " offset=%d, len=%d}\n",
+ request->user_req.dst_img.buf.type,
+ request->user_req.dst_img.buf.hwmem_buf_name,
+ request->user_req.dst_img.buf.fd,
+ request->user_req.dst_img.buf.offset,
+ request->user_req.dst_img.buf.len);
+ dev_size += sprintf(buf + dev_size,
+ "dst_img : {width=%d, height=%d, pitch=%d}\n",
+ request->user_req.dst_img.width,
+ request->user_req.dst_img.height,
+ request->user_req.dst_img.pitch);
+ dev_size += sprintf(buf + dev_size,
+ "dst_rect : {x=%d, y=%d, width=%d, height=%d}\n",
+ request->user_req.dst_rect.x,
+ request->user_req.dst_rect.y,
+ request->user_req.dst_rect.width,
+ request->user_req.dst_rect.height);
+ dev_size += sprintf(buf + dev_size,
+ "dst_clip_rect : {x=%d, y=%d, width=%d, height=%d}\n",
+ request->user_req.dst_clip_rect.x,
+ request->user_req.dst_clip_rect.y,
+ request->user_req.dst_clip_rect.width,
+ request->user_req.dst_clip_rect.height);
+ dev_size += sprintf(buf + dev_size,
+ "dst_color : 0x%08lX\n\n",
+ (unsigned long) request->user_req.dst_color);
+
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.physical : 0x%08lX\n",
+ (unsigned long) request->src_resolved.
+ physical_address);
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.virtual : 0x%08lX\n",
+ (unsigned long) request->src_resolved.virtual_address);
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.filep : 0x%08lX\n",
+ (unsigned long) request->src_resolved.filep);
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.filep_physical_start : 0x%08lX\n",
+ (unsigned long) request->src_resolved.
+ file_physical_start);
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.filep_virtual_start : 0x%08lX\n",
+ (unsigned long) request->src_resolved.file_virtual_start);
+ dev_size += sprintf(buf + dev_size,
+ "src_resolved.file_len : %d\n\n",
+ request->src_resolved.file_len);
+
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.physical : 0x%08lX\n",
+ (unsigned long) request->src_mask_resolved.
+ physical_address);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.virtual : 0x%08lX\n",
+ (unsigned long) request->src_mask_resolved.virtual_address);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.filep : 0x%08lX\n",
+ (unsigned long) request->src_mask_resolved.filep);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.filep_physical_start : 0x%08lX\n",
+ (unsigned long) request->src_mask_resolved.
+ file_physical_start);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.filep_virtual_start : 0x%08lX\n",
+ (unsigned long) request->src_mask_resolved.
+ file_virtual_start);
+ dev_size += sprintf(buf + dev_size,
+ "src_mask_resolved.file_len : %d\n\n",
+ request->src_mask_resolved.file_len);
+
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.physical : 0x%08lX\n",
+ (unsigned long) request->dst_resolved.
+ physical_address);
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.virtual : 0x%08lX\n",
+ (unsigned long) request->dst_resolved.virtual_address);
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.filep : 0x%08lX\n",
+ (unsigned long) request->dst_resolved.filep);
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.filep_physical_start : 0x%08lX\n",
+ (unsigned long) request->dst_resolved.
+ file_physical_start);
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.filep_virtual_start : 0x%08lX\n",
+ (unsigned long) request->dst_resolved.file_virtual_start);
+ dev_size += sprintf(buf + dev_size,
+ "dst_resolved.file_len : %d\n\n",
+ request->dst_resolved.file_len);
+
+ return dev_size;
+}
+#endif
+
+void b2r2_recalculate_rects(struct device *dev,
+ struct b2r2_blt_req *req)
+{
+ struct b2r2_blt_rect new_dst_rect;
+ struct b2r2_blt_rect new_src_rect;
+ struct b2r2_blt_rect new_bg_rect;
+
+ b2r2_trim_rects(dev,
+ req, &new_bg_rect, &new_dst_rect, &new_src_rect);
+
+ req->dst_rect = new_dst_rect;
+ req->src_rect = new_src_rect;
+ if (req->flags & B2R2_BLT_FLAG_BG_BLEND)
+ req->bg_rect = new_bg_rect;
+}
diff --git a/drivers/video/b2r2/b2r2_utils.h b/drivers/video/b2r2/b2r2_utils.h
new file mode 100644
index 00000000000..081ac1f4848
--- /dev/null
+++ b/drivers/video/b2r2/b2r2_utils.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 utils
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _LINUX_DRIVERS_VIDEO_B2R2_UTILS_H_
+#define _LINUX_DRIVERS_VIDEO_B2R2_UTILS_H_
+
+#include <video/b2r2_blt.h>
+
+#include "b2r2_internal.h"
+
+extern const s32 b2r2_s32_max;
+
+int calculate_scale_factor(struct device *dev,
+ u32 from, u32 to, u16 *sf_out);
+void b2r2_get_img_bounding_rect(struct b2r2_blt_img *img,
+ struct b2r2_blt_rect *bounding_rect);
+
+bool b2r2_is_zero_area_rect(struct b2r2_blt_rect *rect);
+bool b2r2_is_rect_inside_rect(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2);
+bool b2r2_is_rect_gte_rect(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2);
+void b2r2_intersect_rects(struct b2r2_blt_rect *rect1,
+ struct b2r2_blt_rect *rect2,
+ struct b2r2_blt_rect *intersection);
+void b2r2_trim_rects(struct device *dev,
+ const struct b2r2_blt_req *req,
+ struct b2r2_blt_rect *new_bg_rect,
+ struct b2r2_blt_rect *new_dst_rect,
+ struct b2r2_blt_rect *new_src_rect);
+
+int b2r2_get_fmt_bpp(struct device *dev, enum b2r2_blt_fmt fmt);
+int b2r2_get_fmt_y_bpp(struct device *dev, enum b2r2_blt_fmt fmt);
+
+bool b2r2_is_single_plane_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_independent_pixel_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcri_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcrsp_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcrp_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcr420_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcr422_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_ycbcr444_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_mb_fmt(enum b2r2_blt_fmt fmt);
+
+/*
+ * Rounds up if an invalid width causes the pitch to be non byte aligned.
+ */
+u32 b2r2_calc_pitch_from_width(struct device *dev,
+ s32 width, enum b2r2_blt_fmt fmt);
+u32 b2r2_get_img_pitch(struct device *dev,
+ struct b2r2_blt_img *img);
+s32 b2r2_get_img_size(struct device *dev,
+ struct b2r2_blt_img *img);
+
+s32 b2r2_div_round_up(s32 dividend, s32 divisor);
+bool b2r2_is_aligned(s32 value, s32 alignment);
+s32 b2r2_align_up(s32 value, s32 alignment);
+
+enum b2r2_ty b2r2_get_alpha_range(enum b2r2_blt_fmt fmt);
+u8 b2r2_get_alpha(enum b2r2_blt_fmt fmt, u32 pixel);
+u32 b2r2_set_alpha(enum b2r2_blt_fmt fmt, u8 alpha, u32 color);
+bool b2r2_fmt_has_alpha(enum b2r2_blt_fmt fmt);
+bool b2r2_is_rgb_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_bgr_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yuv_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yvu_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yuv420_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yuv422_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yvu420_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yvu422_fmt(enum b2r2_blt_fmt fmt);
+bool b2r2_is_yuv444_fmt(enum b2r2_blt_fmt fmt);
+int b2r2_fmt_byte_pitch(enum b2r2_blt_fmt fmt, u32 width);
+enum b2r2_native_fmt b2r2_to_native_fmt(enum b2r2_blt_fmt fmt);
+u32 b2r2_to_RGB888(u32 color, const enum b2r2_blt_fmt fmt);
+enum b2r2_fmt_type b2r2_get_fmt_type(enum b2r2_blt_fmt fmt);
+#ifdef CONFIG_DEBUG_FS
+int sprintf_req(struct b2r2_blt_request *request, char *buf, int size);
+#endif
+void b2r2_recalculate_rects(struct device *dev,
+ struct b2r2_blt_req *req);
+
+#endif
diff --git a/drivers/video/mcde/Kconfig b/drivers/video/mcde/Kconfig
new file mode 100644
index 00000000000..cb88a66d370
--- /dev/null
+++ b/drivers/video/mcde/Kconfig
@@ -0,0 +1,96 @@
+config FB_MCDE
+ tristate "MCDE support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select HWMEM
+ ---help---
+ This enables support for MCDE based frame buffer driver.
+
+ Please read the file <file:Documentation/fb/mcde.txt>
+
+config FB_MCDE_DEBUG
+ bool "MCDE debug messages"
+ depends on FB_MCDE
+ ---help---
+ Say Y here if you want the MCDE driver to output debug messages
+
+config FB_MCDE_VDEBUG
+ bool "MCDE verbose debug messages"
+ depends on FB_MCDE_DEBUG
+ ---help---
+ Say Y here if you want the MCDE driver to output more debug messages
+
+config MCDE_FB_AVOID_REALLOC
+ bool "MCDE early allocate framebuffer"
+ default n
+ depends on FB_MCDE
+ ---help---
+ If you say Y here maximum frame buffer size is allocated and
+ used for all resolutions. If you say N here, the frame buffer is
+ reallocated when resolution is changed. This reallocation might
+ fail because of fragmented memory. Note that this memory will
+ never be deallocated, while the MCDE framebuffer is used.
+
+config MCDE_DISPLAY_DSI
+ bool "Support for DSI displays within MCDE"
+ depends on FB_MCDE
+ default y
+
+menu "MCDE DSI displays"
+ depends on MCDE_DISPLAY_DSI
+
+config MCDE_DISPLAY_GENERIC_DSI
+ tristate "Generic DSI display driver"
+
+config MCDE_DISPLAY_SAMSUNG_S6D16D0
+ bool "Samsung S6D16D0 DSI display driver"
+ ---help---
+ Say Y if you have a TPO Taal or Blackpearl display panel.
+
+config MCDE_DISPLAY_SONY_ACX424AKP_DSI
+ tristate "Sony acx424akp DSI display driver"
+
+config MCDE_DISPLAY_AV8100
+ tristate "AV8100 HDMI/CVBS display driver"
+ select AV8100
+
+config MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ bool "HDMI_FB_AUTO_CREATE"
+ default y
+ depends on MCDE_DISPLAY_AV8100
+ ---help---
+ Say Y if you want the HDMI frame buffer to be created on start
+ Say N if you want the HDMI frame buffer to be created when HDMI
+ cable is plugged (needs user space HDMIservice)
+
+endmenu
+
+config MCDE_DISPLAY_DPI
+ bool "Support for DPI displays within MCDE"
+ depends on FB_MCDE
+ default n
+ ---help---
+ Add this option to choose which DPI display driver for MCDE to include
+
+ DPI (Display Pixel Interface) is a MIPI Alliance standard used for
+ active-matrix LCDs. The DPI uses parallel data lines.
+
+menu "MCDE DPI displays"
+ depends on MCDE_DISPLAY_DPI
+
+config MCDE_DISPLAY_VUIB500_DPI
+ tristate "DPI display driver for the VUIB500 board"
+ ---help---
+ The VUIB500 is an ST-Ericsson user interface board.
+
+endmenu
+
+config MCDE_DISPLAY_AB8500_DENC
+ tristate "AB8500 CVBS display driver"
+ depends on FB_MCDE
+ select AB8500_DENC
+
+
diff --git a/drivers/video/mcde/Makefile b/drivers/video/mcde/Makefile
new file mode 100644
index 00000000000..82a78c2542a
--- /dev/null
+++ b/drivers/video/mcde/Makefile
@@ -0,0 +1,23 @@
+mcde-objs += mcde_mod.o
+mcde-objs += mcde_hw.o
+mcde-objs += mcde_dss.o
+mcde-objs += mcde_display.o
+mcde-objs += mcde_bus.o
+mcde-objs += mcde_fb.o
+mcde-objs += mcde_debugfs.o
+obj-$(CONFIG_FB_MCDE) += mcde.o
+
+obj-$(CONFIG_MCDE_DISPLAY_GENERIC_DSI) += display-generic_dsi.o
+obj-$(CONFIG_MCDE_DISPLAY_SAMSUNG_S6D16D0) += display-samsung_s6d16d0.o
+obj-$(CONFIG_MCDE_DISPLAY_SONY_ACX424AKP_DSI) += display-sony_acx424akp_dsi.o
+obj-$(CONFIG_MCDE_DISPLAY_VUIB500_DPI) += display-vuib500-dpi.o
+obj-$(CONFIG_MCDE_DISPLAY_AB8500_DENC) += display-ab8500.o
+obj-$(CONFIG_MCDE_DISPLAY_AV8100) += display-av8100.o
+obj-$(CONFIG_DISPLAY_FICTIVE) += display-fictive.o
+
+ifdef CONFIG_FB_MCDE_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
+ifdef CONFIG_FB_MCDE_VDEBUG
+EXTRA_CFLAGS += -DVERBOSE_DEBUG
+endif
diff --git a/drivers/video/mcde/display-ab8500.c b/drivers/video/mcde/display-ab8500.c
new file mode 100644
index 00000000000..a761a5eec80
--- /dev/null
+++ b/drivers/video/mcde/display-ab8500.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * AB8500 display driver
+ *
+ * Author: Marcel Tunnissen <marcel.tuennissen@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-ab8500.h>
+
+#define AB8500_DISP_TRACE dev_dbg(&ddev->dev, "%s\n", __func__)
+
+#define SDTV_PIXCLOCK 37037
+
+/*
+ * PAL:
+ * Total nr of active lines: 576
+ * Total nr of blanking lines: 49
+ * total: 625
+ */
+#define PAL_HBP 132
+#define PAL_HFP 12
+#define PAL_VBP_FIELD_1 22
+#define PAL_VBP_FIELD_2 23
+#define PAL_VFP_FIELD_1 2
+#define PAL_VFP_FIELD_2 2
+
+/*
+ * NTSC (ITU-R BT.470-5):
+ * Total nr of active lines: 486
+ * Total nr of blanking lines: 39
+ * total: 525
+ */
+#define NTSC_ORG_HBP 122
+#define NTSC_ORG_HFP 16
+#define NTSC_ORG_VBP_FIELD_1 16
+#define NTSC_ORG_VBP_FIELD_2 17
+#define NTSC_ORG_VFP_FIELD_1 3
+#define NTSC_ORG_VFP_FIELD_2 3
+
+/*
+ * NTSC (DV variant):
+ * Total nr of active lines: 480
+ * Total nr of blanking lines: 45
+ * total: 525
+ */
+#define NTSC_HBP 122
+#define NTSC_HFP 16
+#define NTSC_VBP_FIELD_1 19
+#define NTSC_VBP_FIELD_2 20
+#define NTSC_VFP_FIELD_1 3
+#define NTSC_VFP_FIELD_2 3
+
+struct display_driver_data {
+ struct ab8500_denc_conf denc_conf;
+ struct platform_device *denc_dev;
+ int nr_regulators;
+ struct regulator **regulator;
+};
+
+static int try_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+static int set_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+static int set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode);
+static int on_first_update(struct mcde_display_device *ddev);
+static int display_update(struct mcde_display_device *ddev,
+ bool tripple_buffer);
+
+static int __devinit ab8500_probe(struct mcde_display_device *ddev)
+{
+ int ret = 0;
+ int i;
+ struct ab8500_display_platform_data *pdata = ddev->dev.platform_data;
+ struct display_driver_data *driver_data;
+
+ AB8500_DISP_TRACE;
+
+ if (pdata == NULL) {
+ dev_err(&ddev->dev, "%s:Platform data missing\n", __func__);
+ return -EINVAL;
+ }
+ if (ddev->port->type != MCDE_PORTTYPE_DPI) {
+ dev_err(&ddev->dev, "%s:Invalid port type %d\n", __func__,
+ ddev->port->type);
+ return -EINVAL;
+ }
+
+ driver_data = (struct display_driver_data *)
+ kzalloc(sizeof(struct display_driver_data), GFP_KERNEL);
+ if (!driver_data) {
+ dev_err(&ddev->dev, "Failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+ driver_data->denc_dev = ab8500_denc_get_device();
+ if (!driver_data->denc_dev) {
+ dev_err(&ddev->dev, "Failed to get DENC device\n");
+ ret = -ENODEV;
+ goto dev_get_failed;
+ }
+
+ driver_data->regulator = kzalloc(pdata->nr_regulators *
+ sizeof(struct regulator *), GFP_KERNEL);
+ if (!driver_data->regulator) {
+ dev_err(&ddev->dev, "Failed to allocate regulator list\n");
+ ret = -ENOMEM;
+ goto reg_alloc_failed;
+ }
+ for (i = 0; i < pdata->nr_regulators; i++) {
+ driver_data->regulator[i] = regulator_get(&ddev->dev,
+ pdata->regulator_id[i]);
+ if (IS_ERR(driver_data->regulator[i])) {
+ ret = PTR_ERR(driver_data->regulator[i]);
+ dev_warn(&ddev->dev, "%s:Failed to get regulator %s\n",
+ __func__, pdata->regulator_id[i]);
+ goto regulator_get_failed;
+ }
+ }
+ driver_data->nr_regulators = pdata->nr_regulators;
+
+ dev_set_drvdata(&ddev->dev, driver_data);
+
+ ddev->try_video_mode = try_video_mode;
+ ddev->set_video_mode = set_video_mode;
+ ddev->set_power_mode = set_power_mode;
+ ddev->on_first_update = on_first_update;
+ ddev->update = display_update;
+
+ return 0;
+
+regulator_get_failed:
+ for (i--; i >= 0; i--)
+ regulator_put(driver_data->regulator[i]);
+ kfree(driver_data->regulator);
+ driver_data->regulator = NULL;
+reg_alloc_failed:
+ ab8500_denc_put_device(driver_data->denc_dev);
+dev_get_failed:
+ kfree(driver_data);
+ return ret;
+}
+
+static int __devexit ab8500_remove(struct mcde_display_device *ddev)
+{
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+ AB8500_DISP_TRACE;
+
+ ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+
+ if (driver_data->regulator) {
+ int i;
+ for (i = driver_data->nr_regulators - 1; i >= 0; i--)
+ regulator_put(driver_data->regulator[i]);
+ kfree(driver_data->regulator);
+ driver_data->regulator = NULL;
+ driver_data->nr_regulators = 0;
+ }
+ ab8500_denc_put_device(driver_data->denc_dev);
+ kfree(driver_data);
+ return 0;
+}
+
+static int ab8500_resume(struct mcde_display_device *ddev)
+{
+ int ret = 0;
+ AB8500_DISP_TRACE;
+
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s: Failed to resume display\n",
+ __func__);
+
+ return ret;
+}
+
+static int ab8500_suspend(struct mcde_display_device *ddev, pm_message_t state)
+{
+ int ret = 0;
+ AB8500_DISP_TRACE;
+
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s: Failed to suspend display\n",
+ __func__);
+
+ return ret;
+}
+
+
+static struct mcde_display_driver ab8500_driver = {
+ .probe = ab8500_probe,
+ .remove = ab8500_remove,
+ .suspend = ab8500_suspend,
+ .resume = ab8500_resume,
+ .driver = {
+ .name = "mcde_tv_ab8500",
+ },
+};
+
+static void print_vmode(struct mcde_video_mode *vmode)
+{
+ pr_debug("resolution: %dx%d\n", vmode->xres, vmode->yres);
+ pr_debug(" pixclock: %d\n", vmode->pixclock);
+ pr_debug(" hbp: %d\n", vmode->hbp);
+ pr_debug(" hfp: %d\n", vmode->hfp);
+ pr_debug(" vbp: %d\n", vmode->vbp);
+ pr_debug(" vfp: %d\n", vmode->vfp);
+ pr_debug("interlaced: %s\n", vmode->interlaced ? "true" : "false");
+}
+
+static int try_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ AB8500_DISP_TRACE;
+
+ if (ddev == NULL || video_mode == NULL) {
+ dev_warn(&ddev->dev, "%s:ddev = NULL or video_mode = NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (video_mode->xres != 720) {
+ dev_warn(&ddev->dev,
+ "%s:Failed to find video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+ return -EINVAL;
+ }
+
+ /* TODO: move this part to MCDE: mcde_dss_try_video_mode? */
+ /* check for PAL */
+ switch (video_mode->yres) {
+ case 576:
+ /* set including SAV/EAV: */
+ video_mode->hbp = PAL_HBP;
+ video_mode->hfp = PAL_HFP;
+ video_mode->vbp = PAL_VBP_FIELD_1 + PAL_VBP_FIELD_2;
+ video_mode->vfp = PAL_VFP_FIELD_1 + PAL_VFP_FIELD_2;
+ video_mode->interlaced = true;
+ video_mode->pixclock = SDTV_PIXCLOCK;
+ break;
+ case 480:
+ /* set including SAV/EAV */
+ video_mode->hbp = NTSC_HBP;
+ video_mode->hfp = NTSC_HFP;
+ video_mode->vbp = NTSC_VBP_FIELD_1 + NTSC_VBP_FIELD_2;
+ video_mode->vfp = NTSC_VFP_FIELD_1 + NTSC_VFP_FIELD_2;
+ video_mode->interlaced = true;
+ video_mode->pixclock = SDTV_PIXCLOCK;
+ break;
+ case 486:
+ /* set including SAV/EAV */
+ video_mode->hbp = NTSC_ORG_HBP;
+ video_mode->hfp = NTSC_ORG_HFP;
+ video_mode->vbp = NTSC_ORG_VBP_FIELD_1 + NTSC_ORG_VBP_FIELD_2;
+ video_mode->vfp = NTSC_ORG_VFP_FIELD_1 + NTSC_ORG_VFP_FIELD_2;
+ video_mode->interlaced = true;
+ video_mode->pixclock = SDTV_PIXCLOCK;
+ break;
+ default:
+ dev_warn(&ddev->dev,
+ "%s:Failed to find video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+ return -EINVAL;
+ }
+
+ print_vmode(video_mode);
+
+ return 0;
+
+}
+
+static int set_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ int res;
+ struct ab8500_display_platform_data *pdata = ddev->dev.platform_data;
+ struct display_driver_data *driver_data =
+ (struct display_driver_data *)dev_get_drvdata(&ddev->dev);
+ AB8500_DISP_TRACE;
+
+ if (ddev == NULL || video_mode == NULL) {
+ dev_warn(&ddev->dev, "%s:ddev = NULL or video_mode = NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+ ddev->video_mode = *video_mode;
+
+ if (video_mode->xres != 720) {
+ dev_warn(&ddev->dev, "%s:Failed to set video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+ return -EINVAL;
+ }
+
+ /* check for PAL BDGHI and N */
+ switch (video_mode->yres) {
+ case 576:
+ driver_data->denc_conf.TV_std = TV_STD_PAL_BDGHI;
+ /* TODO: how to choose LOW DEF FILTER */
+ driver_data->denc_conf.cr_filter = TV_CR_PAL_HIGH_DEF_FILTER;
+ /* TODO: PAL N (e.g. uses a setup of 7.5 IRE) */
+ driver_data->denc_conf.black_level_setup = false;
+ break;
+ case 480: /* NTSC, PAL M DV variant */
+ case 486: /* NTSC, PAL M original */
+ /* TODO: PAL M */
+ driver_data->denc_conf.TV_std = TV_STD_NTSC_M;
+ /* TODO: how to choose LOW DEF FILTER */
+ driver_data->denc_conf.cr_filter = TV_CR_NTSC_HIGH_DEF_FILTER;
+ driver_data->denc_conf.black_level_setup = true;
+ break;
+ default:
+ dev_warn(&ddev->dev, "%s:Failed to set video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+ return -EINVAL;
+ }
+
+
+ driver_data->denc_conf.progressive = !video_mode->interlaced;
+ driver_data->denc_conf.act_output = true;
+ driver_data->denc_conf.test_pattern = false;
+ driver_data->denc_conf.partial_blanking = true;
+ driver_data->denc_conf.blank_all = false;
+ driver_data->denc_conf.suppress_col = false;
+ driver_data->denc_conf.phase_reset_mode = TV_PHASE_RST_MOD_DISABLE;
+ driver_data->denc_conf.dac_enable = false;
+ driver_data->denc_conf.act_dc_output = true;
+
+ set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (pdata->rgb_2_yCbCr_transform)
+ mcde_chnl_set_col_convert(ddev->chnl_state,
+ pdata->rgb_2_yCbCr_transform,
+ MCDE_CONVERT_RGB_2_YCBCR);
+ mcde_chnl_stop_flow(ddev->chnl_state);
+ res = mcde_chnl_set_video_mode(ddev->chnl_state, &ddev->video_mode);
+ if (res < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to set video mode on channel\n",
+ __func__);
+
+ return res;
+ }
+ ddev->update_flags |= UPDATE_FLAG_VIDEO_MODE;
+
+ return 0;
+}
+
+static int set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+ int i;
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+ AB8500_DISP_TRACE;
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+ dev_dbg(&ddev->dev, "off -> standby\n");
+ if (ddev->platform_enable) {
+ ret = ddev->platform_enable(ddev);
+ if (ret)
+ goto error;
+ }
+ if (driver_data->regulator) {
+ for (i = 0; i < driver_data->nr_regulators; i++) {
+ ret = regulator_enable(
+ driver_data->regulator[i]);
+ if (ret)
+ goto off_to_standby_failed;
+ dev_dbg(&ddev->dev, "regulator %d on\n", i);
+ }
+ }
+ ab8500_denc_power_up(driver_data->denc_dev);
+ ab8500_denc_reset(driver_data->denc_dev, true);
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+ dev_dbg(&ddev->dev, "standby -> on\n");
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ }
+ /* ON -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+ dev_dbg(&ddev->dev, "on -> standby\n");
+ ab8500_denc_reset(driver_data->denc_dev, false);
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+ /* STANDBY -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ bool error = false;
+ dev_dbg(&ddev->dev, "standby -> off\n");
+ if (driver_data->regulator) {
+ for (i = 0; i < driver_data->nr_regulators; i++) {
+ ret = regulator_disable(
+ driver_data->regulator[i]);
+ /* continue in case of an error */
+ error |= (ret != 0);
+ dev_dbg(&ddev->dev, "regulator %d off\n", i);
+ }
+ }
+ if (ddev->platform_disable) {
+ ret = ddev->platform_disable(ddev);
+ error |= (ret != 0);
+ }
+ if (error) {
+ /* the latest error code is returned */
+ goto error;
+ }
+ memset(&(ddev->video_mode), 0, sizeof(struct mcde_video_mode));
+ ab8500_denc_power_down(driver_data->denc_dev);
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+ return 0;
+
+ /* In case of an error, try to leave in off-state */
+off_to_standby_failed:
+ for (i--; i >= 0; i--)
+ regulator_disable(driver_data->regulator[i]);
+ ddev->platform_disable(ddev);
+
+error:
+ dev_err(&ddev->dev, "Failed to set power mode");
+ return ret;
+}
+
+static int on_first_update(struct mcde_display_device *ddev)
+{
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ ab8500_denc_conf(driver_data->denc_dev, &driver_data->denc_conf);
+ ab8500_denc_conf_plug_detect(driver_data->denc_dev, true, false,
+ TV_PLUG_TIME_2S);
+ ab8500_denc_mask_int_plug_det(driver_data->denc_dev, false, false);
+ ddev->first_update = false;
+ return 0;
+}
+
+static int display_update(struct mcde_display_device *ddev, bool tripple_buffer)
+{
+ int ret;
+
+ if (ddev->first_update)
+ on_first_update(ddev);
+ if (ddev->power_mode != MCDE_DISPLAY_PM_ON && ddev->set_power_mode) {
+ ret = set_power_mode(ddev, MCDE_DISPLAY_PM_ON);
+ if (ret < 0)
+ goto error;
+ }
+ ret = mcde_chnl_update(ddev->chnl_state, &ddev->update_area,
+ tripple_buffer);
+ if (ret < 0)
+ goto error;
+out:
+ return ret;
+error:
+ dev_warn(&ddev->dev, "%s:Failed to set power mode to on\n", __func__);
+ goto out;
+}
+
+/* Module init */
+static int __init mcde_display_tvout_ab8500_init(void)
+{
+ pr_debug("%s\n", __func__);
+
+ return mcde_display_driver_register(&ab8500_driver);
+}
+late_initcall(mcde_display_tvout_ab8500_init);
+
+static void __exit mcde_display_tvout_ab8500_exit(void)
+{
+ pr_debug("%s\n", __func__);
+
+ mcde_display_driver_unregister(&ab8500_driver);
+}
+module_exit(mcde_display_tvout_ab8500_exit);
+
+MODULE_AUTHOR("Marcel Tunnissen <marcel.tuennissen@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE TVout through AB8500 display driver");
diff --git a/drivers/video/mcde/display-av8100.c b/drivers/video/mcde/display-av8100.c
new file mode 100644
index 00000000000..70750998824
--- /dev/null
+++ b/drivers/video/mcde/display-av8100.c
@@ -0,0 +1,1656 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson HDMI display driver
+ *
+ * Author: Per Persson <per-xb-persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/compdev.h>
+#include <linux/clonedev.h>
+
+#include <video/mcde_fb.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-av8100.h>
+#include <video/av8100.h>
+#include <video/hdmi.h>
+
+#define SWITCH_HELPSTR ", 0=HDMI, 1=SDTV, 2=DVI\n"
+
+/* AVI Infoframe */
+#define AVI_INFOFRAME_DATA_SIZE 13
+#define AVI_INFOFRAME_TYPE 0x82
+#define AVI_INFOFRAME_VERSION 0x02
+#define AVI_INFOFRAME_DB1 0x10 /* Active Information present */
+#define AVI_INFOFRAME_DB2 0x08 /* Active Portion Aspect ratio */
+
+#ifdef CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER
+#define NUM_FB_BUFFERS 3
+#else
+#define NUM_FB_BUFFERS 2
+#endif
+
+#define DSI_HS_FREQ_HZ 840320000
+#define DSI_LP_FREQ_HZ 19200000
+
+struct cea_vesa_video_mode {
+ u32 cea;
+ u32 vesa_cea_nr;
+ struct mcde_video_mode *video_mode;
+};
+
+static int hdmi_try_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode);
+static int hdmi_set_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode);
+static int hdmi_set_pixel_format(
+ struct mcde_display_device *ddev, enum mcde_ovly_pix_fmt format);
+static struct mcde_video_mode *video_mode_get(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr);
+static int ceanr_convert(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr, u16 *w, u16 *h);
+
+static ssize_t show_hdmisdtvswitch(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_hdmisdtvswitch(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_input_pixel_format(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_input_pixel_format(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_disponoff(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_disponoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_vesacea(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t show_timing(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_timing(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_stayalive(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(disponoff, S_IRUGO | S_IWUSR, show_disponoff,
+ store_disponoff);
+static DEVICE_ATTR(vesacea, S_IRUGO, show_vesacea, NULL);
+static DEVICE_ATTR(timing, S_IRUGO | S_IWUSR, show_timing, store_timing);
+static DEVICE_ATTR(stayalive, S_IWUSR, NULL, store_stayalive);
+
+static DEVICE_ATTR(hdmisdtvswitch, S_IRUGO | S_IWUSR, show_hdmisdtvswitch,
+ store_hdmisdtvswitch);
+static DEVICE_ATTR(input_pixel_format, S_IRUGO | S_IWUSR,
+ show_input_pixel_format, store_input_pixel_format);
+
+static ssize_t show_hdmisdtvswitch(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *mdev = to_mcde_display_device(dev);
+ int index;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ sprintf(buf, "%1x%s", mdev->port->hdmi_sdtv_switch, SWITCH_HELPSTR);
+ index = 1 + strlen(SWITCH_HELPSTR) + 1;
+
+ return index;
+}
+
+static ssize_t store_hdmisdtvswitch(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *mdev = to_mcde_display_device(dev);
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (count > 0) {
+ if ((*buf == 0) || (*buf == '0')) {
+ dev_dbg(dev, "hdmi/sdtv switch = hdmi\n");
+ mdev->port->hdmi_sdtv_switch = HDMI_SWITCH;
+ mdev->native_x_res = NATIVE_XRES_HDMI;
+ mdev->native_y_res = NATIVE_YRES_HDMI;
+ } else if ((*buf == 1) || (*buf == '1')) {
+ dev_dbg(dev, "hdmi/sdtv switch = sdtv\n");
+ mdev->port->hdmi_sdtv_switch = SDTV_SWITCH;
+ mdev->native_x_res = NATIVE_XRES_SDTV;
+ mdev->native_y_res = NATIVE_YRES_SDTV;
+ } else if ((*buf == 2) || (*buf == '2')) {
+ dev_dbg(dev, "hdmi/sdtv switch = dvi\n");
+ mdev->port->hdmi_sdtv_switch = DVI_SWITCH;
+ mdev->native_x_res = NATIVE_XRES_HDMI;
+ mdev->native_y_res = NATIVE_YRES_HDMI;
+ }
+ /* implicitely read by a memcmp in dss */
+ mdev->video_mode.force_update = true;
+ }
+
+ return count;
+}
+
+static ssize_t show_input_pixel_format(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+
+ return sprintf(buf, "%d\n", ddev->port->pixel_format);
+}
+
+static ssize_t store_input_pixel_format(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (count > 0) {
+ unsigned long input;
+ if (strict_strtoul(buf, 10, &input) != 0)
+ return -EINVAL;
+ switch (input) {
+ /* intentional fall through */
+ case MCDE_PORTPIXFMT_DSI_16BPP:
+ case MCDE_PORTPIXFMT_DSI_18BPP:
+ case MCDE_PORTPIXFMT_DSI_18BPP_PACKED:
+ case MCDE_PORTPIXFMT_DSI_24BPP:
+ case MCDE_PORTPIXFMT_DSI_YCBCR422:
+ ddev->port->pixel_format = input;
+ break;
+ default:
+ dev_warn(&ddev->dev, "invalid format (%ld)\n",
+ input);
+ return -EINVAL;
+ break;
+ }
+ /* implicitely read by a memcmp in dss */
+ ddev->video_mode.force_update = true;
+ driver_data->update_port_pixel_format = true;
+ }
+
+ return count;
+}
+
+static ssize_t show_disponoff(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (ddev->fbi && driver_data->fbdevname) {
+ dev_dbg(dev, "name:%s\n", driver_data->fbdevname);
+ strcpy(buf, driver_data->fbdevname);
+ return strlen(driver_data->fbdevname) + 1;
+ }
+ return 0;
+}
+
+static ssize_t store_disponoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *mdev = to_mcde_display_device(dev);
+ bool enable = false;
+ u8 cea = 0;
+ u8 vesa_cea_nr = 0;
+#ifdef CONFIG_COMPDEV
+ struct mcde_fb *mfb;
+#endif
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if ((count != DISPONOFF_SIZE) && (count != DISPONOFF_SIZE + 1))
+ return -EINVAL;
+
+ if ((*buf == '0') && (*(buf + 1) == '1'))
+ enable = true;
+ cea = (hex_to_bin(buf[2]) << 4) + hex_to_bin(buf[3]);
+ vesa_cea_nr = (hex_to_bin(buf[4]) << 4) + hex_to_bin(buf[5]);
+ dev_dbg(dev, "enable:%d cea:%d nr:%d\n", enable, cea, vesa_cea_nr);
+
+ if (enable && !mdev->fbi) {
+ struct display_driver_data *driver_data = dev_get_drvdata(dev);
+ u16 w = mdev->native_x_res;
+ u16 h = mdev->native_y_res, vh;
+ int buffering = NUM_FB_BUFFERS;
+ struct fb_info *fbi;
+
+ ceanr_convert(mdev, cea, vesa_cea_nr, &w, &h);
+ vh = h * buffering;
+ fbi = mcde_fb_create(mdev, w, h, w, vh,
+ mdev->default_pixel_format, FB_ROTATE_UR);
+ if (IS_ERR(fbi))
+ dev_warn(dev, "fb create failed\n");
+ else
+ driver_data->fbdevname = dev_name(fbi->dev);
+
+#ifdef CONFIG_COMPDEV
+ /* TODO need another way for compdev to get actual size */
+ mdev->native_x_res = w;
+ mdev->native_y_res = h;
+
+ mfb = to_mcde_fb(fbi);
+ /* Create a compdev overlay for this display */
+ if (compdev_create(mdev, mfb->ovlys[0], false) < 0) {
+ dev_warn(&mdev->dev,
+ "Failed to create compdev for display %s\n",
+ mdev->name);
+ } else {
+ dev_dbg(&mdev->dev, "compdev created for (%s)\n",
+ mdev->name);
+ }
+#ifdef CONFIG_CLONEDEV
+ if (clonedev_create()) {
+ dev_warn(&mdev->dev,
+ "Failed to create clonedev for display %s\n",
+ mdev->name);
+ } else {
+ dev_dbg(&mdev->dev, "clonedev created for (%s)\n",
+ mdev->name);
+ }
+#endif
+#endif
+ } else if (!enable && mdev->fbi) {
+#ifdef CONFIG_CLONEDEV
+ clonedev_destroy();
+#endif
+#ifdef CONFIG_COMPDEV
+ compdev_destroy(mdev);
+#endif
+ mcde_fb_destroy(mdev);
+ }
+
+ return count;
+}
+
+static ssize_t show_timing(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+ struct mcde_video_mode *video_mode;
+ int index;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ index = 0;
+ if (driver_data->video_mode) {
+ video_mode = driver_data->video_mode;
+ memcpy(buf + index, &video_mode->xres, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->yres, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->pixclock, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->hbp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->hfp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->vbp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->vfp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->interlaced, sizeof(u32));
+ index += sizeof(u32);
+ }
+ return index;
+}
+
+static ssize_t store_timing(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (count != TIMING_SIZE)
+ return -EINVAL;
+
+ driver_data->video_mode = video_mode_get(ddev, *buf, *(buf + 1));
+
+ return count;
+}
+
+static ssize_t store_stayalive(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+
+ if (count != STAYALIVE_SIZE)
+ return -EINVAL;
+
+ if ((*buf == 1) || (*buf == '1'))
+ ddev->stay_alive = true;
+ else
+ ddev->stay_alive = false;
+
+ dev_dbg(dev, "%s %d\n", __func__, ddev->stay_alive);
+
+ return count;
+}
+
+static int ceanr_convert(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr, u16 *w, u16 *h)
+{
+ struct mcde_video_mode *video_mode;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ video_mode = video_mode_get(ddev, cea, vesa_cea_nr);
+ if (video_mode) {
+ *w = video_mode->xres;
+ *h = video_mode->yres;
+ dev_dbg(&ddev->dev, "cea:%d nr:%d found\n",
+ cea, vesa_cea_nr);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/* Supported HDMI modes */
+static struct mcde_video_mode video_modes_supp_hdmi[] = {
+ /* 0 CEA #1 640_480_60_P */
+ {
+ .xres = 640, .yres = 480,
+ .pixclock = 39682,
+ .hbp = 112, .hfp = 48,
+ .vbp = 33, .vfp = 12
+ },
+ /* 1 720_480_60_P */
+ {
+ .xres = 720, .yres = 480,
+ .pixclock = 37000,
+ .hbp = 104, .hfp = 34,
+ .vbp = 30, .vfp = 15
+ },
+ /* 2 720_576_50_P */
+ {
+ .xres = 720, .yres = 576,
+ .pixclock = 37037,
+ .hbp = 132, .hfp = 12,
+ .vbp = 44, .vfp = 5
+ },
+ /* 3 1280_720_60_P */
+ {
+ .xres = 1280, .yres = 720,
+ .pixclock = 13468,
+ .hbp = 256, .hfp = 114,
+ .vbp = 20, .vfp = 10
+ },
+ /* 4 1280_720_50_P */
+ {
+ .xres = 1280, .yres = 720,
+ .pixclock = 13468,
+ .hbp = 260, .hfp = 440,
+ .vbp = 25, .vfp = 5
+ },
+ /* 5 1280_720_30_P */
+ {
+ .xres = 1280, .yres = 720,
+ .pixclock = 13468,
+ .hbp = 260, .hfp = 1760,
+ .vbp = 20, .vfp = 10
+ },
+ /* 6 1280_720_24_P */
+ {
+ .xres = 1280, .yres = 720,
+ .pixclock = 16835,
+ .hbp = 260, .hfp = 1760,
+ .vbp = 20, .vfp = 10
+ },
+ /* 7 1280_720_25_P */
+ {
+ .xres = 1280, .yres = 720,
+ .pixclock = 13468,
+ .hbp = 260, .hfp = 2420,
+ .vbp = 20, .vfp = 10
+ },
+ /* 8 1920_1080_30_P */
+ {
+ .xres = 1920, .yres = 1080,
+ .pixclock = 13468,
+ .hbp = 189, .hfp = 91,
+ .vbp = 36, .vfp = 9
+ },
+ /* 9 1920_1080_24_P */
+ {
+ .xres = 1920, .yres = 1080,
+ .pixclock = 13468,
+ .hbp = 170, .hfp = 660,
+ .vbp = 36, .vfp = 9
+ },
+ /* 10 1920_1080_25_P */
+ {
+ .xres = 1920, .yres = 1080,
+ .pixclock = 13468,
+ .hbp = 192, .hfp = 528,
+ .vbp = 36, .vfp = 9
+ },
+ /* 11 720_480_60_I */
+ {
+ .xres = 720, .yres = 480,
+ .pixclock = 74074,
+ .hbp = 126, .hfp = 12,
+ .vbp = 44, .vfp = 1,
+ .interlaced = true,
+ },
+ /* 12 720_576_50_I */
+ {
+ .xres = 720, .yres = 576,
+ .pixclock = 74074,
+ .hbp = 132, .hfp = 12,
+ .vbp = 44, .vfp = 5,
+ .interlaced = true,
+ },
+ /* 13 1920_1080_50_I */
+ {
+ .xres = 1920, .yres = 1080,
+ .pixclock = 13468,
+ .hbp = 192, .hfp = 528,
+ .vbp = 20, .vfp = 25,
+ .interlaced = true,
+ },
+ /* 14 1920_1080_60_I */
+ {
+ .xres = 1920, .yres = 1080,
+ .pixclock = 13468,
+ .hbp = 192, .hfp = 88,
+ .vbp = 20, .vfp = 25,
+ .interlaced = true,
+ },
+ /* 15 VESA #9 800_600_60_P */
+ {
+ .xres = 800, .yres = 600,
+ .pixclock = 25000,
+ .hbp = 168, .hfp = 88,
+ .vbp = 23, .vfp = 5,
+ .interlaced = false,
+ },
+ /* 16 VESA #14 848_480_60_P */
+ {
+ .xres = 848, .yres = 480,
+ .pixclock = 29630,
+ .hbp = 128, .hfp = 112,
+ .vbp = 23, .vfp = 14,
+ .interlaced = false,
+ },
+ /* 17 VESA #16 1024_768_60_P */
+ {
+ .xres = 1024, .yres = 768,
+ .pixclock = 15385,
+ .hbp = 160, .hfp = 160,
+ .vbp = 29, .vfp = 9,
+ .interlaced = false,
+ },
+ /* 18 VESA #22 1280_768_60_P */
+ {
+ .xres = 1280, .yres = 768,
+ .pixclock = 14652,
+ .hbp = 80, .hfp = 80,
+ .vbp = 12, .vfp = 10,
+ .interlaced = false,
+ },
+ /* 19 VESA #23 1280_768_60_P */
+ {
+ .xres = 1280, .yres = 768,
+ .pixclock = 12579,
+ .hbp = 192, .hfp = 192,
+ .vbp = 20, .vfp = 10,
+ .interlaced = false,
+ },
+ /* 20 VESA #27 1280_800_60_P */
+ {
+ .xres = 1280, .yres = 800,
+ .pixclock = 14085,
+ .hbp = 80, .hfp = 80,
+ .vbp = 14, .vfp = 9,
+ .interlaced = false,
+ },
+ /* 21 VESA #28 1280_800_60_P */
+ {
+ .xres = 1280, .yres = 800,
+ .pixclock = 11976,
+ .hbp = 200, .hfp = 200,
+ .vbp = 22, .vfp = 9,
+ .interlaced = false,
+ },
+ /* 22 VESA #39 1360_768_60_P */
+ {
+ .xres = 1360, .yres = 768,
+ .pixclock = 11696,
+ .hbp = 176, .hfp = 256,
+ .vbp = 18, .vfp = 9,
+ .interlaced = false,
+ },
+ /* 23 VESA #81 1366_768_60_P */
+ {
+ .xres = 1366, .yres = 768,
+ .pixclock = 11662,
+ .hbp = 213, .hfp = 213,
+ .vbp = 24, .vfp = 6,
+ .interlaced = false,
+ },
+};
+
+/* Supported TVout modes */
+static struct mcde_video_mode video_modes_supp_sdtv[] = {
+ /* 720_480_60_I) */
+ {
+ .xres = 720, .yres = 480,
+ .pixclock = 74074,
+ .hbp = 126, .hfp = 12,
+ .vbp = 44, .vfp = 1,
+ .interlaced = true,
+ },
+ /* 720_576_50_I) */
+ {
+ .xres = 720, .yres = 576,
+ .pixclock = 74074,
+ .hbp = 132, .hfp = 12,
+ .vbp = 44, .vfp = 5,
+ .interlaced = true,
+ },
+};
+
+static struct cea_vesa_video_mode cea_vesa_video_mode[] = {
+ /* 640_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 1,
+ .video_mode = &video_modes_supp_hdmi[0],
+ },
+ /* 720_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 2,
+ .video_mode = &video_modes_supp_hdmi[1],
+ },
+ /* 720_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 3,
+ .video_mode = &video_modes_supp_hdmi[1],
+ },
+ /* 720_576_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 17,
+ .video_mode = &video_modes_supp_hdmi[2],
+ },
+ /* 720_576_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 18,
+ .video_mode = &video_modes_supp_hdmi[2],
+ },
+ /* 1280_720_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 4,
+ .video_mode = &video_modes_supp_hdmi[3],
+ },
+ /* 1280_720_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 19,
+ .video_mode = &video_modes_supp_hdmi[4],
+ },
+ /* 1280_720_30_P */
+ {
+ .cea = 1, .vesa_cea_nr = 62,
+ .video_mode = &video_modes_supp_hdmi[5],
+ },
+ /* 1280_720_24_P */
+ {
+ .cea = 1, .vesa_cea_nr = 60,
+ .video_mode = &video_modes_supp_hdmi[6],
+ },
+ /* 1280_720_25_P */
+ {
+ .cea = 1, .vesa_cea_nr = 61,
+ .video_mode = &video_modes_supp_hdmi[7],
+ },
+ /* 1920_1080_30_P */
+ {
+ .cea = 1, .vesa_cea_nr = 34,
+ .video_mode = &video_modes_supp_hdmi[8],
+ },
+ /* 1920_1080_24_P */
+ {
+ .cea = 1, .vesa_cea_nr = 32,
+ .video_mode = &video_modes_supp_hdmi[9],
+ },
+ /* 1920_1080_25_P */
+ {
+ .cea = 1, .vesa_cea_nr = 33,
+ .video_mode = &video_modes_supp_hdmi[10],
+ },
+ /* 720_480_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 6,
+ .video_mode = &video_modes_supp_hdmi[11],
+ },
+ /* 720_480_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 7,
+ .video_mode = &video_modes_supp_hdmi[11],
+ },
+ /* 720_576_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 21,
+ .video_mode = &video_modes_supp_hdmi[12],
+ },
+ /* 720_576_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 22,
+ .video_mode = &video_modes_supp_hdmi[12],
+ },
+ /* 1920_1080_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 20,
+ .video_mode = &video_modes_supp_hdmi[13],
+ },
+ /* 1920_1080_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 5,
+ .video_mode = &video_modes_supp_hdmi[14],
+ },
+ /* VESA #4 640_480_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 4,
+ .video_mode = &video_modes_supp_hdmi[0],
+ },
+ /* VESA #9 800_600_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 9,
+ .video_mode = &video_modes_supp_hdmi[15],
+ },
+ /* VESA #14 848_480_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 14,
+ .video_mode = &video_modes_supp_hdmi[16],
+ },
+ /* VESA #16 1024_768_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 16,
+ .video_mode = &video_modes_supp_hdmi[17],
+ },
+ /* VESA #22 1280_768_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 22,
+ .video_mode = &video_modes_supp_hdmi[18],
+ },
+ /* VESA #23 1280_768_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 23,
+ .video_mode = &video_modes_supp_hdmi[19],
+ },
+ /* VESA #27 1280_800_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 27,
+ .video_mode = &video_modes_supp_hdmi[20],
+ },
+ /* VESA #28 1280_800_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 28,
+ .video_mode = &video_modes_supp_hdmi[21],
+ },
+ /* VESA #39 1360_768_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 39,
+ .video_mode = &video_modes_supp_hdmi[22],
+ },
+ /* VESA #81 1366_768_60_P) */
+ {
+ .cea = 0, .vesa_cea_nr = 81,
+ .video_mode = &video_modes_supp_hdmi[23],
+ },
+};
+
+static ssize_t show_vesacea(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int findex;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ for (findex = 0; findex < ARRAY_SIZE(cea_vesa_video_mode); findex++) {
+ *(buf + findex * 2) = cea_vesa_video_mode[findex].cea;
+ *(buf + findex * 2 + 1) =
+ cea_vesa_video_mode[findex].vesa_cea_nr;
+ }
+ *(buf + findex * 2) = '\0';
+
+ return findex * 2 + 1;
+}
+
+static struct mcde_video_mode *video_mode_get(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr)
+{
+ int findex;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+
+ for (findex = 0; findex < ARRAY_SIZE(cea_vesa_video_mode); findex++)
+ if ((cea == cea_vesa_video_mode[findex].cea) &&
+ (vesa_cea_nr ==
+ cea_vesa_video_mode[findex].vesa_cea_nr)) {
+ dev_dbg(&ddev->dev, "cea:%d nr:%d\n", cea, vesa_cea_nr);
+ return cea_vesa_video_mode[findex].video_mode;
+ }
+
+ return NULL;
+}
+
+static u8 ceanr_get(struct mcde_display_device *ddev)
+{
+ int cnt;
+ int cea;
+ int vesa_cea_nr;
+ struct mcde_video_mode *vmode = &ddev->video_mode;
+ struct mcde_video_mode *vmode_try;
+
+ if (!vmode)
+ return 0;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+
+ for (cnt = 0; cnt < ARRAY_SIZE(cea_vesa_video_mode); cnt++) {
+ vmode_try = cea_vesa_video_mode[cnt].video_mode;
+ cea = cea_vesa_video_mode[cnt].cea;
+ vesa_cea_nr = cea_vesa_video_mode[cnt].vesa_cea_nr;
+
+ if (cea && vmode_try->xres == vmode->xres &&
+ vmode_try->yres == vmode->yres &&
+ vmode_try->pixclock == vmode->pixclock &&
+ vmode_try->hbp == vmode->hbp &&
+ vmode_try->hfp == vmode->hfp &&
+ vmode_try->vbp == vmode->vbp &&
+ vmode_try->vfp == vmode->vfp &&
+ vmode_try->interlaced == vmode->interlaced) {
+ dev_dbg(&ddev->dev, "ceanr:%d\n", vesa_cea_nr);
+ return vesa_cea_nr;
+ }
+ }
+
+ return 0;
+}
+
+#define AV8100_MAX_LEVEL 255
+
+static int hdmi_try_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ int index = 0;
+ int match_level = AV8100_MAX_LEVEL;
+ int found_index = -1;
+ struct mcde_video_mode *video_modes_supp;
+ int array_size;
+
+ if (ddev == NULL || video_mode == NULL) {
+ pr_warning("%s:ddev = NULL or video_mode = NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ dev_vdbg(&ddev->dev, "%s\n", __func__);
+
+ if (ddev->port->hdmi_sdtv_switch == SDTV_SWITCH) {
+ video_mode->interlaced = true;
+ video_modes_supp = video_modes_supp_sdtv;
+ array_size = ARRAY_SIZE(video_modes_supp_sdtv);
+ } else {
+ video_modes_supp = video_modes_supp_hdmi;
+ array_size = ARRAY_SIZE(video_modes_supp_hdmi);
+ }
+
+ while (index < array_size) {
+ /* 1. Check if all parameters match */
+ if ((video_mode->xres == video_modes_supp[index].xres) &&
+ (video_mode->yres == video_modes_supp[index].yres) &&
+ ((video_mode->xres + video_mode->hbp +
+ video_mode->hfp) ==
+ (video_modes_supp[index].xres +
+ video_modes_supp[index].hbp +
+ video_modes_supp[index].hfp)) &&
+ ((video_mode->yres + video_mode->vbp + video_mode->vfp)
+ ==
+ (video_modes_supp[index].yres +
+ video_modes_supp[index].vbp +
+ video_modes_supp[index].vfp)) &&
+ (video_mode->pixclock ==
+ video_modes_supp[index].pixclock) &&
+ (video_mode->interlaced ==
+ video_modes_supp[index].interlaced)) {
+ match_level = 1;
+ found_index = index;
+ break;
+ }
+
+ /* 2. Check if xres,yres,htot,vtot,interlaced match */
+ if ((match_level > 2) &&
+ (video_mode->xres == video_modes_supp[index].xres) &&
+ (video_mode->yres == video_modes_supp[index].yres) &&
+ ((video_mode->xres + video_mode->hbp +
+ video_mode->hfp) ==
+ (video_modes_supp[index].xres +
+ video_modes_supp[index].hbp +
+ video_modes_supp[index].hfp)) &&
+ ((video_mode->yres + video_mode->vbp + video_mode->vfp)
+ ==
+ (video_modes_supp[index].yres +
+ video_modes_supp[index].vbp +
+ video_modes_supp[index].vfp)) &&
+ (video_mode->interlaced ==
+ video_modes_supp[index].interlaced)) {
+ match_level = 2;
+ found_index = index;
+ }
+
+ /* 3. Check if xres,yres,pixelclock,interlaced match */
+ if ((match_level > 3) &&
+ (video_mode->xres == video_modes_supp[index].xres) &&
+ (video_mode->yres == video_modes_supp[index].yres) &&
+ (video_mode->interlaced ==
+ video_modes_supp[index].interlaced) &&
+ (video_mode->pixclock ==
+ video_modes_supp[index].pixclock)) {
+ match_level = 3;
+ found_index = index;
+ }
+
+ /* 4. Check if xres,yres,interlaced match */
+ if ((match_level > 4) &&
+ (video_mode->xres == video_modes_supp[index].xres) &&
+ (video_mode->yres == video_modes_supp[index].yres) &&
+ (video_mode->interlaced ==
+ video_modes_supp[index].interlaced)) {
+ match_level = 4;
+ found_index = index;
+ }
+
+ index++;
+ }
+
+ if (found_index == -1) {
+ dev_dbg(&ddev->dev, "video_mode not accepted\n");
+ dev_dbg(&ddev->dev, "xres:%d yres:%d pixclock:%d hbp:%d hfp:%d "
+ "vfp:%d vbp:%d intlcd:%d\n",
+ video_mode->xres, video_mode->yres,
+ video_mode->pixclock,
+ video_mode->hbp, video_mode->hfp,
+ video_mode->vfp, video_mode->vbp,
+ video_mode->interlaced);
+ return -EINVAL;
+ }
+
+ memset(video_mode, 0, sizeof(struct mcde_video_mode));
+ memcpy(video_mode, &video_modes_supp[found_index],
+ sizeof(struct mcde_video_mode));
+
+ dev_dbg(&ddev->dev, "%s:HDMI video_mode %d chosen. Level:%d\n",
+ __func__, found_index, match_level);
+
+ return 0;
+}
+
+static int hdmi_set_video_mode(
+ struct mcde_display_device *dev, struct mcde_video_mode *video_mode)
+{
+ int ret;
+ union av8100_configuration av8100_config;
+ struct mcde_display_hdmi_platform_data *pdata;
+ struct display_driver_data *driver_data;
+ struct av8100_status status;
+
+ /* TODO check video_mode_params */
+ if (dev == NULL || video_mode == NULL) {
+ pr_warning("%s:ddev = NULL or video_mode = NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ pdata = dev->dev.platform_data;
+ driver_data = dev_get_drvdata(&dev->dev);
+
+ dev_dbg(&dev->dev, "%s:\n", __func__);
+ dev_vdbg(&dev->dev, "%s:xres:%d yres:%d hbp:%d hfp:%d vbp:%d vfp:%d "
+ "interlaced:%d\n", __func__,
+ video_mode->xres,
+ video_mode->yres,
+ video_mode->hbp,
+ video_mode->hfp,
+ video_mode->vbp,
+ video_mode->vfp,
+ video_mode->interlaced);
+
+ if (driver_data->update_port_pixel_format) {
+ hdmi_set_pixel_format(dev, dev->pixel_format);
+ driver_data->update_port_pixel_format = false;
+ }
+
+ memset(&(dev->video_mode), 0, sizeof(struct mcde_video_mode));
+ memcpy(&(dev->video_mode), video_mode, sizeof(struct mcde_video_mode));
+
+ if (dev->port->pixel_format == MCDE_PORTPIXFMT_DSI_YCBCR422 &&
+ pdata->rgb_2_yCbCr_transform)
+ mcde_chnl_set_col_convert(dev->chnl_state,
+ pdata->rgb_2_yCbCr_transform,
+ MCDE_CONVERT_RGB_2_YCBCR);
+ mcde_chnl_stop_flow(dev->chnl_state);
+
+ ret = mcde_chnl_set_video_mode(dev->chnl_state, &dev->video_mode);
+ if (ret < 0) {
+ dev_warn(&dev->dev, "Failed to set video mode\n");
+ return ret;
+ }
+
+ status = av8100_status_get();
+ if (status.av8100_state == AV8100_OPMODE_UNDEFINED)
+ return -EINVAL;
+
+ if (av8100_ver_get() == AV8100_CHIPVER_1) {
+ if (status.av8100_state >= AV8100_OPMODE_STANDBY) {
+ /* Disable interrupts */
+ ret = av8100_disable_interrupt();
+ if (ret) {
+ dev_err(&dev->dev,
+ "%s:av8100_disable_interrupt failed\n",
+ __func__);
+ return ret;
+ }
+
+ ret = av8100_powerdown();
+ if (ret) {
+ dev_err(&dev->dev,
+ "av8100_powerdown failed\n");
+ return ret;
+ }
+
+ msleep(10);
+ }
+ }
+
+ /* Set to powerup with interrupts disabled */
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_STANDBY) {
+ ret = av8100_powerup();
+ if (ret) {
+ dev_err(&dev->dev, "av8100_powerup failed\n");
+ return ret;
+ }
+ }
+
+ if (status.av8100_state <= AV8100_OPMODE_IDLE) {
+ ret = av8100_download_firmware(I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "av8100_download_firmware failed\n");
+ return ret;
+ }
+ }
+
+ if (av8100_disable_interrupt())
+ return -EFAULT;
+
+ /*
+ * Don't look at dev->port->hdmi_sdtv_switch; it states only which
+ * one should be started, not which one is currently working
+ */
+ if (av8100_conf_get(AV8100_COMMAND_HDMI, &av8100_config))
+ return -EFAULT;
+ if (av8100_config.hdmi_format.hdmi_mode == AV8100_HDMI_ON) {
+ /* Set HDMI mode to OFF */
+ av8100_config.hdmi_format.hdmi_mode = AV8100_HDMI_OFF;
+ av8100_config.hdmi_format.dvi_format = AV8100_DVI_CTRL_CTL0;
+ av8100_config.hdmi_format.hdmi_format = AV8100_HDMI;
+ if (av8100_conf_prep(AV8100_COMMAND_HDMI, &av8100_config))
+ return -EFAULT;
+
+ if (av8100_conf_w(AV8100_COMMAND_HDMI, NULL, NULL,
+ I2C_INTERFACE))
+ return -EFAULT;
+ }
+ if (av8100_conf_get(AV8100_COMMAND_DENC, &av8100_config))
+ return -EFAULT;
+ if (av8100_config.denc_format.enable) {
+ /* Turn off DENC */
+ av8100_config.denc_format.enable = 0;
+ if (av8100_conf_prep(AV8100_COMMAND_DENC, &av8100_config))
+ return -EFAULT;
+ if (av8100_conf_w(AV8100_COMMAND_DENC, NULL, NULL,
+ I2C_INTERFACE))
+ return -EFAULT;
+ }
+
+ /* Get current av8100 video output format */
+ ret = av8100_conf_get(AV8100_COMMAND_VIDEO_OUTPUT_FORMAT,
+ &av8100_config);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_get "
+ "AV8100_COMMAND_VIDEO_OUTPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ if (dev->port->hdmi_sdtv_switch == SDTV_SWITCH)
+ av8100_config.video_output_format.video_output_cea_vesa =
+ dev->video_mode.yres == NATIVE_YRES_SDTV ?
+ AV8100_CEA21_22_576I_PAL_50HZ :
+ AV8100_CEA6_7_NTSC_60HZ;
+ else
+ av8100_config.video_output_format.video_output_cea_vesa =
+ av8100_video_output_format_get(
+ dev->video_mode.xres,
+ dev->video_mode.yres,
+ dev->video_mode.xres +
+ dev->video_mode.hbp + dev->video_mode.hfp,
+ dev->video_mode.yres +
+ dev->video_mode.vbp + dev->video_mode.vfp,
+ dev->video_mode.pixclock,
+ dev->video_mode.interlaced);
+
+ if (AV8100_VIDEO_OUTPUT_CEA_VESA_MAX ==
+ av8100_config.video_output_format.video_output_cea_vesa) {
+ dev_err(&dev->dev, "%s:video output format not found "
+ "\n", __func__);
+ return ret;
+ }
+
+ ret = av8100_conf_prep(AV8100_COMMAND_VIDEO_OUTPUT_FORMAT,
+ &av8100_config);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_prep "
+ "AV8100_COMMAND_VIDEO_OUTPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ /* Get current av8100 video input format */
+ ret = av8100_conf_get(AV8100_COMMAND_VIDEO_INPUT_FORMAT,
+ &av8100_config);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_get "
+ "AV8100_COMMAND_VIDEO_INPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ /* Set correct av8100 video input pixel format */
+ switch (dev->port->pixel_format) {
+ case MCDE_PORTPIXFMT_DSI_16BPP:
+ default:
+ av8100_config.video_input_format.input_pixel_format =
+ AV8100_INPUT_PIX_RGB565;
+ break;
+ case MCDE_PORTPIXFMT_DSI_18BPP:
+ av8100_config.video_input_format.input_pixel_format =
+ AV8100_INPUT_PIX_RGB666;
+ break;
+ case MCDE_PORTPIXFMT_DSI_18BPP_PACKED:
+ av8100_config.video_input_format.input_pixel_format =
+ AV8100_INPUT_PIX_RGB666P;
+ break;
+ case MCDE_PORTPIXFMT_DSI_24BPP:
+ av8100_config.video_input_format.input_pixel_format =
+ AV8100_INPUT_PIX_RGB888;
+ break;
+ case MCDE_PORTPIXFMT_DSI_YCBCR422:
+ av8100_config.video_input_format.input_pixel_format =
+ AV8100_INPUT_PIX_YCBCR422;
+ break;
+ }
+
+ /* Set ui_x4 */
+ av8100_config.video_input_format.ui_x4 = dev->port->phy.dsi.ui;
+
+ /* Set TE_config */
+ switch (dev->port->sync_src) {
+ case MCDE_SYNCSRC_TE0:
+ av8100_config.video_input_format.TE_config = AV8100_TE_IT_LINE;
+ break;
+ case MCDE_SYNCSRC_TE1:
+ av8100_config.video_input_format.TE_config = AV8100_TE_GPIO_IT;
+ break;
+ case MCDE_SYNCSRC_TE_POLLING:
+ av8100_config.video_input_format.TE_config =
+ AV8100_TE_DSI_LANE; /* Only on DSI, no interrupts */
+ break;
+ case MCDE_SYNCSRC_OFF:
+ default:
+ av8100_config.video_input_format.TE_config = AV8100_TE_OFF;
+ break;
+ }
+
+ ret = av8100_conf_prep(AV8100_COMMAND_VIDEO_INPUT_FORMAT,
+ &av8100_config);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_prep "
+ "AV8100_COMMAND_VIDEO_INPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ ret = av8100_conf_w(AV8100_COMMAND_VIDEO_INPUT_FORMAT,
+ NULL, NULL, I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_w "
+ "AV8100_COMMAND_VIDEO_INPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ if (dev->port->hdmi_sdtv_switch == SDTV_SWITCH) {
+ if (dev->port->pixel_format != MCDE_PORTPIXFMT_DSI_YCBCR422)
+ av8100_config.color_transform =
+ AV8100_COLOR_TRANSFORM_RGB_TO_DENC;
+ else
+ av8100_config.color_transform =
+ AV8100_COLOR_TRANSFORM_YUV_TO_DENC;
+ } else if (dev->port->pixel_format == MCDE_PORTPIXFMT_DSI_YCBCR422) {
+ av8100_config.color_transform =
+ AV8100_COLOR_TRANSFORM_YUV_TO_RGB;
+ } else {
+ av8100_config.color_transform =
+ AV8100_COLOR_TRANSFORM_INDENTITY;
+ }
+
+ ret = av8100_conf_prep(
+ AV8100_COMMAND_COLORSPACECONVERSION,
+ &av8100_config);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_configuration_prepare "
+ "AV8100_COMMAND_COLORSPACECONVERSION failed\n",
+ __func__);
+ return ret;
+ }
+
+ ret = av8100_conf_w(
+ AV8100_COMMAND_COLORSPACECONVERSION,
+ NULL, NULL, I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_w "
+ "AV8100_COMMAND_COLORSPACECONVERSION failed\n",
+ __func__);
+ return ret;
+ }
+
+ /* Set video output format */
+ ret = av8100_conf_w(AV8100_COMMAND_VIDEO_OUTPUT_FORMAT,
+ NULL, NULL, I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "av8100_conf_w failed\n");
+ return ret;
+ }
+
+ /* Set audio input format */
+ ret = av8100_conf_w(AV8100_COMMAND_AUDIO_INPUT_FORMAT,
+ NULL, NULL, I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_w "
+ "AV8100_COMMAND_AUDIO_INPUT_FORMAT failed\n",
+ __func__);
+ return ret;
+ }
+
+ dev->update_flags |= UPDATE_FLAG_VIDEO_MODE;
+ dev->first_update = true;
+
+ return 0;
+}
+
+static u16 rotate_byte_left(u8 c, int nr)
+{
+ return (0xff & (c << nr)) | (0xff & (c >> (8 - nr)));
+}
+
+static u16 map_yv(u8 in)
+{
+ return rotate_byte_left(in, 3) << 4;
+}
+
+static u16 map_u(u8 in)
+{
+ return rotate_byte_left(in, 5) << 4;
+}
+
+static int hdmi_set_pixel_format(
+ struct mcde_display_device *ddev, enum mcde_ovly_pix_fmt format)
+{
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ ddev->pixel_format = format;
+
+ return 0;
+}
+
+static int hdmi_set_port_pixel_format(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ mcde_chnl_stop_flow(ddev->chnl_state);
+ ret = mcde_chnl_set_pixel_format(ddev->chnl_state,
+ ddev->port->pixel_format);
+
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s: Failed to set pixel format = %d\n",
+ __func__, ddev->port->pixel_format);
+ return ret;
+ }
+
+ if (ddev->port->pixel_format == MCDE_PORTPIXFMT_DSI_YCBCR422 &&
+ av8100_ver_get() == 2) {
+ /* The V2 version has an error for unpacking YUV422 */
+ struct mcde_palette_table palette = {
+ .map_col_ch0 = *map_yv,
+ .map_col_ch1 = *map_u,
+ .map_col_ch2 = *map_yv,
+ };
+ ret = mcde_chnl_set_palette(ddev->chnl_state, &palette);
+ } else {
+ ret = mcde_chnl_set_palette(ddev->chnl_state, NULL);
+ }
+
+ return 0;
+}
+
+static int hdmi_apply_config(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ if (!ddev->update_flags)
+ return 0;
+
+ ret = mcde_chnl_apply(ddev->chnl_state);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to apply to channel\n",
+ __func__);
+ return ret;
+ }
+ ddev->update_flags = 0;
+
+ return 0;
+}
+
+static int hdmi_on_first_update(struct mcde_display_device *dev)
+{
+ int ret;
+ union av8100_configuration av8100_config;
+ u8 *infofr_data;
+ int infofr_crc;
+ int cnt;
+
+ dev->first_update = false;
+
+ /*
+ * Prepare HDMI configuration
+ * Avoid simultaneous output of DENC and HDMI/DVI.
+ * Only one of them should be enabled.
+ * Note HDMI/DVI and DENC are always turned off in set_video_mode.
+ */
+ switch (dev->port->hdmi_sdtv_switch) {
+ case SDTV_SWITCH:
+ if (av8100_conf_get(AV8100_COMMAND_DENC, &av8100_config))
+ return -EFAULT;
+ av8100_config.denc_format.enable = 1;
+ if (dev->video_mode.yres == NATIVE_YRES_SDTV) {
+ av8100_config.denc_format.standard_selection =
+ AV8100_PAL_BDGHI;
+ av8100_config.denc_format.cvbs_video_format =
+ AV8100_CVBS_625;
+ } else {
+ av8100_config.denc_format.standard_selection =
+ AV8100_NTSC_M;
+ av8100_config.denc_format.cvbs_video_format =
+ AV8100_CVBS_525;
+ }
+ ret = av8100_conf_prep(AV8100_COMMAND_DENC, &av8100_config);
+ break;
+ case DVI_SWITCH:
+ av8100_config.hdmi_format.hdmi_mode = AV8100_HDMI_ON;
+ av8100_config.hdmi_format.hdmi_format = AV8100_DVI;
+ av8100_config.hdmi_format.dvi_format = AV8100_DVI_CTRL_CTL0;
+ ret = av8100_conf_prep(AV8100_COMMAND_HDMI, &av8100_config);
+ break;
+ case HDMI_SWITCH:
+ default:
+ av8100_config.hdmi_format.hdmi_mode = AV8100_HDMI_ON;
+ av8100_config.hdmi_format.hdmi_format = AV8100_HDMI;
+ av8100_config.hdmi_format.dvi_format = AV8100_DVI_CTRL_CTL0;
+ ret = av8100_conf_prep(AV8100_COMMAND_HDMI, &av8100_config);
+ break;
+ }
+
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_prep "
+ "AV8100_COMMAND_HDMI/DENC failed\n", __func__);
+ return ret;
+ }
+
+ /* Enable interrupts */
+ ret = av8100_enable_interrupt();
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_enable_interrupt failed\n",
+ __func__);
+ return ret;
+ }
+
+ if (dev->port->hdmi_sdtv_switch == SDTV_SWITCH)
+ ret = av8100_conf_w(AV8100_COMMAND_DENC, NULL, NULL,
+ I2C_INTERFACE);
+ else
+ ret = av8100_conf_w(AV8100_COMMAND_HDMI, NULL, NULL,
+ I2C_INTERFACE);
+ if (ret) {
+ dev_err(&dev->dev, "%s:av8100_conf_w "
+ "AV8100_COMMAND_HDMI/DENC failed\n", __func__);
+ return ret;
+ }
+
+ /* AVI Infoframe only if HDMI */
+ if (dev->port->hdmi_sdtv_switch != HDMI_SWITCH)
+ goto hdmi_on_first_update_end;
+
+ /* Create AVI Infoframe */
+ av8100_config.infoframes_format.type = AVI_INFOFRAME_TYPE;
+ av8100_config.infoframes_format.version = AVI_INFOFRAME_VERSION;
+ av8100_config.infoframes_format.length = AVI_INFOFRAME_DATA_SIZE;
+
+ /* AVI Infoframe data */
+ infofr_data = &av8100_config.infoframes_format.data[0];
+ memset(infofr_data, 0, AVI_INFOFRAME_DATA_SIZE);
+ infofr_data[0] = AVI_INFOFRAME_DB1;
+ infofr_data[1] = AVI_INFOFRAME_DB2;
+ infofr_data[3] = ceanr_get(dev);
+
+ /* Calculate AVI Infoframe checksum */
+ infofr_crc = av8100_config.infoframes_format.type +
+ av8100_config.infoframes_format.version +
+ av8100_config.infoframes_format.length;
+ for (cnt = 0; cnt < AVI_INFOFRAME_DATA_SIZE; cnt++)
+ infofr_crc += infofr_data[cnt];
+ infofr_crc &= 0xFF;
+ av8100_config.infoframes_format.crc = 0x100 - infofr_crc;
+
+ /* Send AVI Infoframe */
+ if (av8100_conf_prep(AV8100_COMMAND_INFOFRAMES,
+ &av8100_config) != 0) {
+ dev_err(&dev->dev, "av8100_conf_prep FAIL\n");
+ return -EINVAL;
+ }
+
+ if (av8100_conf_w(AV8100_COMMAND_INFOFRAMES,
+ NULL, NULL, I2C_INTERFACE) != 0) {
+ dev_err(&dev->dev, "av8100_conf_w FAIL\n");
+ return -EINVAL;
+ }
+
+hdmi_on_first_update_end:
+ return ret;
+}
+
+static int hdmi_set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+ int ret = 0;
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+ if (ddev->platform_enable) {
+ ret = ddev->platform_enable(ddev);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * the regulator for analog TV out is only enabled here,
+ * this means that one needs to switch to the OFF state
+ * to be able to switch from HDMI to CVBS.
+ */
+ if (ddev->port->hdmi_sdtv_switch == SDTV_SWITCH) {
+ ret = regulator_enable(driver_data->cvbs_regulator);
+ if (ret)
+ return ret;
+ driver_data->cvbs_regulator_enabled = true;
+ }
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+
+ hdmi_set_port_pixel_format(ddev);
+ }
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ goto set_power_and_exit;
+ }
+ /* ON -> STANDBY */
+ else if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ memset(&(ddev->video_mode), 0, sizeof(struct mcde_video_mode));
+ ret = av8100_powerscan();
+ if (ret)
+ dev_err(&ddev->dev, "%s:av8100_powerscan failed\n"
+ , __func__);
+ if (ddev->platform_disable) {
+ ret = ddev->platform_disable(ddev);
+ if (ret)
+ return ret;
+ }
+ if (driver_data->cvbs_regulator_enabled) {
+ ret = regulator_disable(driver_data->cvbs_regulator);
+ if (ret)
+ return ret;
+ driver_data->cvbs_regulator_enabled = false;
+ }
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+set_power_and_exit:
+ mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode);
+
+ return ret;
+}
+
+static int hdmi_set_rotation(struct mcde_display_device *ddev,
+ enum mcde_display_rotation rotation)
+{
+ /* Not possible to rotate HDMI */
+ return 0;
+}
+
+static int __devinit hdmi_probe(struct mcde_display_device *dev)
+{
+ int ret = 0;
+ struct mcde_port *port;
+ struct display_driver_data *driver_data;
+ struct mcde_display_hdmi_platform_data *pdata =
+ dev->dev.platform_data;
+
+ if (pdata == NULL) {
+ dev_err(&dev->dev, "%s:Platform data missing\n", __func__);
+ return -EINVAL;
+ }
+
+ if (dev->port->type != MCDE_PORTTYPE_DSI) {
+ dev_err(&dev->dev, "%s:Invalid port type %d\n",
+ __func__, dev->port->type);
+ return -EINVAL;
+ }
+
+ driver_data = (struct display_driver_data *)
+ kzalloc(sizeof(struct display_driver_data), GFP_KERNEL);
+ if (!driver_data) {
+ dev_err(&dev->dev, "Failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ /* DSI use clock continous mode if AV8100_CHIPVER_1 > 1 */
+ if (av8100_ver_get() > AV8100_CHIPVER_1)
+ dev->port->phy.dsi.clk_cont = true;
+
+ dev->on_first_update = hdmi_on_first_update;
+ dev->try_video_mode = hdmi_try_video_mode;
+ dev->set_video_mode = hdmi_set_video_mode;
+ dev->apply_config = hdmi_apply_config;
+ dev->set_pixel_format = hdmi_set_pixel_format;
+ dev->set_power_mode = hdmi_set_power_mode;
+ dev->set_rotation = hdmi_set_rotation;
+
+ port = dev->port;
+
+ port->phy.dsi.host_eot_gen = true;
+ port->phy.dsi.num_data_lanes = 2;
+ port->phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ port->phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
+
+ /* Create sysfs files */
+ if (device_create_file(&dev->dev, &dev_attr_hdmisdtvswitch))
+ dev_info(&dev->dev,
+ "Unable to create hdmisdtvswitch attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_input_pixel_format))
+ dev_info(&dev->dev,
+ "Unable to create input_pixel_format attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_disponoff))
+ dev_info(&dev->dev,
+ "Unable to create disponoff attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_vesacea))
+ dev_info(&dev->dev,
+ "Unable to create ceavesa attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_timing))
+ dev_info(&dev->dev,
+ "Unable to create timing attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_stayalive))
+ dev_info(&dev->dev,
+ "Unable to create stayalive attr\n");
+
+ if (pdata->cvbs_regulator_id) {
+ driver_data->cvbs_regulator = regulator_get(&dev->dev,
+ pdata->cvbs_regulator_id);
+ if (IS_ERR(driver_data->cvbs_regulator)) {
+ ret = PTR_ERR(driver_data->cvbs_regulator);
+ dev_warn(&dev->dev, "%s:Failed to get regulator %s\n",
+ __func__, pdata->cvbs_regulator_id);
+ driver_data->cvbs_regulator = NULL;
+ goto av_regulator_get_failed;
+ }
+ }
+
+ dev_set_drvdata(&dev->dev, driver_data);
+ dev_info(&dev->dev, "HDMI display probed\n");
+
+ return 0;
+
+av_regulator_get_failed:
+ kfree(driver_data);
+ return ret;
+}
+
+static int __devexit hdmi_remove(struct mcde_display_device *dev)
+{
+ struct display_driver_data *driver_data = dev_get_drvdata(&dev->dev);
+ struct mcde_display_hdmi_platform_data *pdata =
+ dev->dev.platform_data;
+
+ /* Remove sysfs files */
+ device_remove_file(&dev->dev, &dev_attr_input_pixel_format);
+ device_remove_file(&dev->dev, &dev_attr_hdmisdtvswitch);
+ device_remove_file(&dev->dev, &dev_attr_disponoff);
+ device_remove_file(&dev->dev, &dev_attr_vesacea);
+ device_remove_file(&dev->dev, &dev_attr_timing);
+ device_remove_file(&dev->dev, &dev_attr_stayalive);
+
+ dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF);
+
+ if (driver_data->cvbs_regulator)
+ regulator_put(driver_data->cvbs_regulator);
+ kfree(driver_data);
+ if (pdata->hdmi_platform_enable) {
+ if (pdata->regulator)
+ regulator_put(pdata->regulator);
+ if (pdata->reset_gpio) {
+ gpio_direction_input(pdata->reset_gpio);
+ gpio_free(pdata->reset_gpio);
+ }
+ }
+
+ return 0;
+}
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+static int hdmi_resume(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ if (ddev->chnl_state == NULL)
+ return 0;
+
+ /* set_power_mode will handle call platform_enable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to resume display\n"
+ , __func__);
+
+ return ret;
+}
+
+static int hdmi_suspend(struct mcde_display_device *ddev, pm_message_t state)
+{
+ int ret;
+
+ if (ddev->chnl_state == NULL)
+ return 0;
+
+ /* set_power_mode will handle call platform_disable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to suspend display\n"
+ , __func__);
+
+ return ret;
+}
+#endif
+
+static struct mcde_display_driver hdmi_driver = {
+ .probe = hdmi_probe,
+ .remove = hdmi_remove,
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ .suspend = hdmi_suspend,
+ .resume = hdmi_resume,
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+ .driver = {
+ .name = "av8100_hdmi",
+ },
+};
+
+/* Module init */
+static int __init mcde_display_hdmi_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ return mcde_display_driver_register(&hdmi_driver);
+
+}
+late_initcall(mcde_display_hdmi_init);
+
+static void __exit mcde_display_hdmi_exit(void)
+{
+ pr_info("%s\n", __func__);
+
+ mcde_display_driver_unregister(&hdmi_driver);
+}
+module_exit(mcde_display_hdmi_exit);
+
+MODULE_AUTHOR("Per Persson <per.xb.persson@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson hdmi display driver");
diff --git a/drivers/video/mcde/display-fictive.c b/drivers/video/mcde/display-fictive.c
new file mode 100644
index 00000000000..c7ea1429b9f
--- /dev/null
+++ b/drivers/video/mcde/display-fictive.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * ST-Ericsson MCDE fictive display driver
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+
+#include <video/mcde_display.h>
+
+static int __devinit fictive_probe(struct mcde_display_device *dev)
+{
+ dev->platform_enable = NULL,
+ dev->platform_disable = NULL,
+ dev->set_power_mode = NULL;
+
+ dev_info(&dev->dev, "Fictive display probed\n");
+
+ return 0;
+}
+
+static int __devexit fictive_remove(struct mcde_display_device *dev)
+{
+ return 0;
+}
+
+static struct mcde_display_driver fictive_driver = {
+ .probe = fictive_probe,
+ .remove = fictive_remove,
+ .driver = {
+ .name = "mcde_disp_fictive",
+ },
+};
+
+/* Module init */
+static int __init mcde_display_fictive_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ return mcde_display_driver_register(&fictive_driver);
+}
+module_init(mcde_display_fictive_init);
+
+static void __exit mcde_display_fictive_exit(void)
+{
+ pr_info("%s\n", __func__);
+
+ mcde_display_driver_unregister(&fictive_driver);
+}
+module_exit(mcde_display_fictive_exit);
+
+MODULE_AUTHOR("Per Persson <per.xb.persson@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE fictive display driver");
diff --git a/drivers/video/mcde/display-generic_dsi.c b/drivers/video/mcde/display-generic_dsi.c
new file mode 100644
index 00000000000..dfbaa4a8765
--- /dev/null
+++ b/drivers/video/mcde/display-generic_dsi.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE generic DCS display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+
+#include <video/mcde_display.h>
+#include <video/mcde_display-generic_dsi.h>
+
+static int generic_platform_enable(struct mcde_display_device *dev)
+{
+ struct mcde_display_generic_platform_data *pdata =
+ dev->dev.platform_data;
+
+ dev_dbg(&dev->dev, "%s: Reset & power on generic display\n", __func__);
+
+ if (pdata->regulator) {
+ if (regulator_enable(pdata->regulator) < 0) {
+ dev_err(&dev->dev, "%s:Failed to enable regulator\n"
+ , __func__);
+ return -EINVAL;
+ }
+ }
+ if (pdata->reset_gpio)
+ gpio_set_value_cansleep(pdata->reset_gpio, pdata->reset_high);
+ mdelay(pdata->reset_delay);
+ if (pdata->reset_gpio)
+ gpio_set_value_cansleep(pdata->reset_gpio, !pdata->reset_high);
+
+ return 0;
+}
+
+static int generic_platform_disable(struct mcde_display_device *dev)
+{
+ struct mcde_display_generic_platform_data *pdata =
+ dev->dev.platform_data;
+
+ dev_dbg(&dev->dev, "%s:Reset & power off generic display\n", __func__);
+
+ if (pdata->regulator) {
+ if (regulator_disable(pdata->regulator) < 0) {
+ dev_err(&dev->dev, "%s:Failed to disable regulator\n"
+ , __func__);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int generic_set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+ struct mcde_display_generic_platform_data *pdata =
+ ddev->dev.platform_data;
+
+ dev_dbg(&ddev->dev, "%s:Set Power mode\n", __func__);
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+
+ if (ddev->platform_enable) {
+ ret = ddev->platform_enable(ddev);
+ if (ret)
+ return ret;
+ }
+
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_EXIT_SLEEP_MODE, NULL, 0);
+ if (ret)
+ return ret;
+
+ msleep(pdata->sleep_out_delay);
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_DISPLAY_ON, NULL, 0);
+ if (ret)
+ return ret;
+
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ goto set_power_and_exit;
+ }
+ /* ON -> STANDBY */
+ else if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_DISPLAY_OFF, NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_ENTER_SLEEP_MODE, NULL, 0);
+ if (ret)
+ return ret;
+
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* SLEEP -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ if (ddev->platform_disable) {
+ ret = ddev->platform_disable(ddev);
+ if (ret)
+ return ret;
+ }
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+set_power_and_exit:
+ mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode);
+
+ return ret;
+}
+
+static int __devinit generic_probe(struct mcde_display_device *dev)
+{
+ int ret = 0;
+ struct mcde_display_generic_platform_data *pdata =
+ dev->dev.platform_data;
+
+ if (pdata == NULL) {
+ dev_err(&dev->dev, "%s:Platform data missing\n", __func__);
+ return -EINVAL;
+ }
+
+ if (dev->port->type != MCDE_PORTTYPE_DSI) {
+ dev_err(&dev->dev,
+ "%s:Invalid port type %d\n",
+ __func__, dev->port->type);
+ return -EINVAL;
+ }
+
+ if (!dev->platform_enable && !dev->platform_disable) {
+ pdata->generic_platform_enable = true;
+ if (pdata->reset_gpio) {
+ ret = gpio_request(pdata->reset_gpio, NULL);
+ if (ret) {
+ dev_warn(&dev->dev,
+ "%s:Failed to request gpio %d\n",
+ __func__, pdata->reset_gpio);
+ goto gpio_request_failed;
+ }
+ gpio_direction_output(pdata->reset_gpio,
+ !pdata->reset_high);
+ }
+ if (pdata->regulator_id) {
+ pdata->regulator = regulator_get(&dev->dev,
+ pdata->regulator_id);
+ if (IS_ERR(pdata->regulator)) {
+ ret = PTR_ERR(pdata->regulator);
+ dev_warn(&dev->dev,
+ "%s:Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_id);
+ pdata->regulator = NULL;
+ goto regulator_get_failed;
+ }
+
+ if (regulator_set_voltage(pdata->regulator,
+ pdata->min_supply_voltage,
+ pdata->max_supply_voltage) < 0) {
+ int volt;
+
+ dev_warn(&dev->dev,
+ "%s:Failed to set voltage '%s'\n",
+ __func__, pdata->regulator_id);
+ volt = regulator_get_voltage(pdata->regulator);
+ dev_warn(&dev->dev,
+ "Voltage:%d\n", volt);
+ }
+
+ /*
+ * When u-boot has display a startup screen.
+ * U-boot has turned on display power however the
+ * regulator framework does not know about that
+ * This is the case here, the display driver has to
+ * enable the regulator for the display.
+ */
+ if (dev->power_mode == MCDE_DISPLAY_PM_STANDBY) {
+ ret = regulator_enable(pdata->regulator);
+ if (ret < 0) {
+ dev_err(&dev->dev,
+ "%s:Failed to enable regulator\n"
+ , __func__);
+ goto regulator_enable_failed;
+ }
+ }
+ }
+ }
+
+ dev->platform_enable = generic_platform_enable,
+ dev->platform_disable = generic_platform_disable,
+ dev->set_power_mode = generic_set_power_mode;
+
+ dev_info(&dev->dev, "Generic display probed\n");
+
+ goto out;
+regulator_enable_failed:
+regulator_get_failed:
+ if (pdata->generic_platform_enable && pdata->reset_gpio)
+ gpio_free(pdata->reset_gpio);
+gpio_request_failed:
+out:
+ return ret;
+}
+
+static int __devexit generic_remove(struct mcde_display_device *dev)
+{
+ struct mcde_display_generic_platform_data *pdata =
+ dev->dev.platform_data;
+
+ dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF);
+
+ if (!pdata->generic_platform_enable)
+ return 0;
+
+ if (pdata->regulator)
+ regulator_put(pdata->regulator);
+ if (pdata->reset_gpio) {
+ gpio_direction_input(pdata->reset_gpio);
+ gpio_free(pdata->reset_gpio);
+ }
+
+ return 0;
+}
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+static int generic_resume(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ /* set_power_mode will handle call platform_enable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to resume display\n"
+ , __func__);
+ return ret;
+}
+
+static int generic_suspend(struct mcde_display_device *ddev, pm_message_t state)
+{
+ int ret;
+
+ /* set_power_mode will handle call platform_disable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to suspend display\n"
+ , __func__);
+ return ret;
+}
+#endif
+
+static struct mcde_display_driver generic_driver = {
+ .probe = generic_probe,
+ .remove = generic_remove,
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ .suspend = generic_suspend,
+ .resume = generic_resume,
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+ .driver = {
+ .name = "mcde_disp_generic",
+ },
+};
+
+/* Module init */
+static int __init mcde_display_generic_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ return mcde_display_driver_register(&generic_driver);
+}
+module_init(mcde_display_generic_init);
+
+static void __exit mcde_display_generic_exit(void)
+{
+ pr_info("%s\n", __func__);
+
+ mcde_display_driver_unregister(&generic_driver);
+}
+module_exit(mcde_display_generic_exit);
+
+MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE generic DCS display driver");
diff --git a/drivers/video/mcde/display-samsung_s6d16d0.c b/drivers/video/mcde/display-samsung_s6d16d0.c
new file mode 100644
index 00000000000..900c3f70aa6
--- /dev/null
+++ b/drivers/video/mcde/display-samsung_s6d16d0.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE Samsung S6D16D0 display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+
+#include <video/mcde_display.h>
+
+#define RESET_DURATION_US 10
+#define RESET_DELAY_MS 120
+#define SLEEP_OUT_DELAY_MS 120
+#define IO_REGU "vdd1"
+#define IO_REGU_MIN 1650000
+#define IO_REGU_MAX 3300000
+
+#define DSI_HS_FREQ_HZ 420160000
+#define DSI_LP_FREQ_HZ 19200000
+
+struct device_info {
+ int reset_gpio;
+ struct mcde_port port;
+ struct regulator *regulator;
+};
+
+static inline struct device_info *get_drvdata(struct mcde_display_device *ddev)
+{
+ return (struct device_info *)dev_get_drvdata(&ddev->dev);
+}
+
+static int power_on(struct mcde_display_device *ddev)
+{
+ struct device_info *di = get_drvdata(ddev);
+
+ dev_dbg(&ddev->dev, "Reset & power on s6d16d0 display\n");
+
+ regulator_enable(di->regulator);
+ gpio_set_value_cansleep(di->reset_gpio, 0);
+ udelay(RESET_DURATION_US);
+ gpio_set_value_cansleep(di->reset_gpio, 1);
+ msleep(RESET_DELAY_MS);
+
+ return 0;
+}
+
+static int power_off(struct mcde_display_device *ddev)
+{
+ struct device_info *di = get_drvdata(ddev);
+
+ dev_dbg(&ddev->dev, "Power off s6d16d0 display\n");
+
+ regulator_disable(di->regulator);
+
+ return 0;
+}
+
+static int display_on(struct mcde_display_device *ddev)
+{
+ int ret;
+ u8 val = 0;
+
+ dev_dbg(&ddev->dev, "Display on s6d16d0\n");
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_TEAR_ON, &val, 1);
+ if (ret)
+ dev_warn(&ddev->dev,
+ "%s:Failed to enable synchronized update\n", __func__);
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_EXIT_SLEEP_MODE,
+ NULL, 0);
+ if (ret)
+ return ret;
+ msleep(SLEEP_OUT_DELAY_MS);
+ return mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_SET_DISPLAY_ON,
+ NULL, 0);
+}
+
+static int display_off(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ dev_dbg(&ddev->dev, "Display off s6d16d0\n");
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_SET_DISPLAY_OFF,
+ NULL, 0);
+ if (ret)
+ return ret;
+
+ return mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_ENTER_SLEEP_MODE,
+ NULL, 0);
+}
+
+static int set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+
+ dev_dbg(&ddev->dev, "Set power mode %d\n", power_mode);
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+ ret = power_on(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+
+ ret = display_on(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ }
+ /* ON -> STANDBY */
+ else if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+
+ ret = display_off(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ ret = power_off(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+ return mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode);
+}
+
+static int __devinit samsung_s6d16d0_probe(struct mcde_display_device *ddev)
+{
+ int ret = 0;
+ struct mcde_display_dsi_platform_data *pdata = ddev->dev.platform_data;
+ struct device_info *di;
+
+ if (pdata == NULL || !pdata->reset_gpio) {
+ dev_err(&ddev->dev, "Invalid platform data\n");
+ return -EINVAL;
+ }
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+ di->reset_gpio = pdata->reset_gpio;
+ di->port.link = pdata->link;
+ di->port.type = MCDE_PORTTYPE_DSI;
+ di->port.mode = MCDE_PORTMODE_CMD;
+ di->port.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP;
+ di->port.sync_src = ddev->port->sync_src;
+ di->port.frame_trig = ddev->port->frame_trig;
+ di->port.phy.dsi.num_data_lanes = 2;
+ di->port.phy.dsi.host_eot_gen = true;
+ /* TODO: Move UI to mcde_hw.c when clk_get_rate(dsi) is done */
+ di->port.phy.dsi.ui = 9;
+ di->port.phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ di->port.phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
+
+ ret = gpio_request(di->reset_gpio, NULL);
+ if (ret)
+ goto gpio_request_failed;
+ gpio_direction_output(di->reset_gpio, 1);
+ di->regulator = regulator_get(&ddev->dev, IO_REGU);
+ if (IS_ERR(di->regulator)) {
+ di->regulator = NULL;
+ goto regulator_get_failed;
+ }
+ ret = regulator_set_voltage(di->regulator, IO_REGU_MIN, IO_REGU_MAX);
+ if (WARN_ON(ret))
+ goto regulator_voltage_failed;
+
+ /* Get in sync with u-boot */
+ if (ddev->power_mode != MCDE_DISPLAY_PM_OFF)
+ (void)regulator_enable(di->regulator);
+
+ ddev->set_power_mode = set_power_mode;
+ ddev->port = &di->port;
+ ddev->native_x_res = 864;
+ ddev->native_y_res = 480;
+ dev_set_drvdata(&ddev->dev, di);
+
+ dev_info(&ddev->dev, "Samsung s6d16d0 display probed\n");
+
+ return 0;
+regulator_voltage_failed:
+ regulator_put(di->regulator);
+regulator_get_failed:
+ gpio_free(di->reset_gpio);
+gpio_request_failed:
+ kfree(di);
+ return ret;
+}
+
+static struct mcde_display_driver samsung_s6d16d0_driver = {
+ .probe = samsung_s6d16d0_probe,
+ .driver = {
+ .name = "samsung_s6d16d0",
+ },
+};
+
+static int __init samsung_s6d16d0_init(void)
+{
+ return mcde_display_driver_register(&samsung_s6d16d0_driver);
+}
+module_init(samsung_s6d16d0_init);
+
+MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE Samsung S6D16D0 display driver");
diff --git a/drivers/video/mcde/display-sony_acx424akp_dsi.c b/drivers/video/mcde/display-sony_acx424akp_dsi.c
new file mode 100644
index 00000000000..867bbb37375
--- /dev/null
+++ b/drivers/video/mcde/display-sony_acx424akp_dsi.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE Sony acx424akp DCS display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <linux/regulator/consumer.h>
+
+#include <video/mcde_display.h>
+#include <video/mcde_display-sony_acx424akp_dsi.h>
+
+#define RESET_DELAY_MS 11
+#define RESET_LOW_DELAY_US 20
+#define SLEEP_OUT_DELAY_MS 140
+#define SLEEP_IN_DELAY_MS 85 /* Assume 60 Hz 5 frames */
+#define IO_REGU "vddi"
+#define IO_REGU_MIN 1600000
+#define IO_REGU_MAX 3300000
+
+#define DSI_HS_FREQ_HZ 420160000
+#define DSI_LP_FREQ_HZ 19200000
+
+struct device_info {
+ int reset_gpio;
+ struct mcde_port port;
+ struct regulator *regulator;
+};
+
+static inline struct device_info *get_drvdata(struct mcde_display_device *ddev)
+{
+ return (struct device_info *)dev_get_drvdata(&ddev->dev);
+}
+
+static int display_read_deviceid(struct mcde_display_device *dev, u16 *id)
+{
+ struct mcde_chnl_state *chnl;
+
+ u8 id1, id2, id3;
+ int len = 1;
+ int ret = 0;
+ int readret = 0;
+
+ dev_dbg(&dev->dev, "%s: Read device id of the display\n", __func__);
+
+ /* Acquire MCDE resources */
+ chnl = mcde_chnl_get(dev->chnl_id, dev->fifo, dev->port);
+ if (IS_ERR(chnl)) {
+ ret = PTR_ERR(chnl);
+ dev_warn(&dev->dev, "Failed to acquire MCDE channel\n");
+ goto out;
+ }
+
+ /* plugnplay: use registers DA, DBh and DCh to detect display */
+ readret = mcde_dsi_dcs_read(chnl, 0xDA, (u32 *)&id1, &len);
+ if (!readret)
+ readret = mcde_dsi_dcs_read(chnl, 0xDB, (u32 *)&id2, &len);
+ if (!readret)
+ readret = mcde_dsi_dcs_read(chnl, 0xDC, (u32 *)&id3, &len);
+
+ if (readret) {
+ dev_info(&dev->dev,
+ "mcde_dsi_dcs_read failed to read display ID\n");
+ goto read_fail;
+ }
+
+ *id = (id3 << 8) | id2;
+read_fail:
+ /* close MCDE channel */
+ mcde_chnl_put(chnl);
+out:
+ return 0;
+}
+
+static int power_on(struct mcde_display_device *dev)
+{
+ struct device_info *di = get_drvdata(dev);
+
+ dev_dbg(&dev->dev, "%s: Reset & power on sony display\n", __func__);
+
+ regulator_enable(di->regulator);
+ gpio_set_value_cansleep(di->reset_gpio, 1);
+ msleep(RESET_DELAY_MS);
+ gpio_set_value_cansleep(di->reset_gpio, 0);
+ udelay(RESET_LOW_DELAY_US);
+ gpio_set_value_cansleep(di->reset_gpio, 1);
+ msleep(RESET_DELAY_MS);
+
+ return 0;
+}
+
+static int power_off(struct mcde_display_device *dev)
+{
+ struct device_info *di = get_drvdata(dev);
+
+ dev_dbg(&dev->dev, "%s:Reset & power off sony display\n", __func__);
+
+ gpio_set_value_cansleep(di->reset_gpio, 0);
+ msleep(RESET_DELAY_MS);
+ regulator_disable(di->regulator);
+
+ return 0;
+}
+
+static int display_on(struct mcde_display_device *ddev)
+{
+ int ret;
+ u8 val = 0;
+
+ dev_dbg(&ddev->dev, "Display on sony display\n");
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_TEAR_ON, &val, 1);
+ if (ret)
+ dev_warn(&ddev->dev,
+ "%s:Failed to enable synchronized update\n", __func__);
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_EXIT_SLEEP_MODE,
+ NULL, 0);
+ if (ret)
+ return ret;
+ msleep(SLEEP_OUT_DELAY_MS);
+ return mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_SET_DISPLAY_ON,
+ NULL, 0);
+}
+
+static int display_off(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ dev_dbg(&ddev->dev, "Display off sony display\n");
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_SET_DISPLAY_OFF,
+ NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_ENTER_SLEEP_MODE,
+ NULL, 0);
+ /* Wait for 4 frames or more */
+ msleep(SLEEP_IN_DELAY_MS);
+
+ return ret;
+}
+
+static int sony_acx424akp_set_scan_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+ u8 param[MCDE_MAX_DSI_DIRECT_CMD_WRITE];
+
+ dev_dbg(&ddev->dev, "%s:Set Power mode\n", __func__);
+
+ /* 180 rotation for SONY ACX424AKP display */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY) {
+ param[0] = 0xAA;
+ ret = mcde_dsi_dcs_write(ddev->chnl_state, 0xf3, param, 1);
+ if (ret)
+ return ret;
+
+ param[0] = 0x00;
+ param[1] = 0x00;
+ ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3);
+ if (ret)
+ return ret;
+
+ param[0] = 0xC9;
+ param[1] = 0x01;
+ ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3);
+ if (ret)
+ return ret;
+
+ param[0] = 0xA2;
+ param[1] = 0x00;
+ ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3);
+ if (ret)
+ return ret;
+
+ param[0] = 0xFF;
+ param[1] = 0xAA;
+ ret = mcde_dsi_generic_write(ddev->chnl_state, param, 3);
+ if (ret)
+ return ret;
+ }
+ return ret;
+}
+
+static int sony_acx424akp_set_power_mode(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+
+ dev_dbg(&ddev->dev, "%s:Set Power mode\n", __func__);
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+ ret = power_on(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+
+ ret = display_on(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ }
+ /* ON -> STANDBY */
+ else if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+
+ ret = display_off(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ /* STANDBY -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ ret = power_off(ddev);
+ if (ret)
+ return ret;
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+ return mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode);
+}
+
+static int __devinit sony_acx424akp_probe(struct mcde_display_device *dev)
+{
+ int ret = 0;
+ u16 id = 0;
+ struct device_info *di;
+ struct mcde_port *port;
+ struct mcde_display_sony_acx424akp_platform_data *pdata =
+ dev->dev.platform_data;
+
+ if (pdata == NULL || !pdata->reset_gpio) {
+ dev_err(&dev->dev, "Invalid platform data\n");
+ return -EINVAL;
+ }
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ port = dev->port;
+ di->reset_gpio = pdata->reset_gpio;
+ di->port.type = MCDE_PORTTYPE_DSI;
+ di->port.mode = MCDE_PORTMODE_CMD;
+ di->port.pixel_format = MCDE_PORTPIXFMT_DSI_24BPP;
+ di->port.sync_src = dev->port->sync_src;
+ di->port.frame_trig = dev->port->frame_trig;
+ di->port.phy.dsi.num_data_lanes = 2;
+ di->port.link = port->link;
+ di->port.phy.dsi.host_eot_gen = true;
+ /* TODO: Move UI to mcde_hw.c when clk_get_rate(dsi) is done */
+ di->port.phy.dsi.ui = 9;
+ di->port.phy.dsi.hs_freq = DSI_HS_FREQ_HZ;
+ di->port.phy.dsi.lp_freq = DSI_LP_FREQ_HZ;
+
+ ret = gpio_request(di->reset_gpio, NULL);
+ if (WARN_ON(ret))
+ goto gpio_request_failed;
+
+ gpio_direction_output(di->reset_gpio, 1);
+ di->regulator = regulator_get(&dev->dev, IO_REGU);
+ if (IS_ERR(di->regulator)) {
+ ret = PTR_ERR(di->regulator);
+ di->regulator = NULL;
+ goto regulator_get_failed;
+ }
+ ret = regulator_set_voltage(di->regulator, IO_REGU_MIN, IO_REGU_MAX);
+ if (WARN_ON(ret))
+ goto regulator_voltage_failed;
+
+ dev->set_power_mode = sony_acx424akp_set_power_mode;
+
+ dev->port = &di->port;
+ dev->native_x_res = 480;
+ dev->native_y_res = 854;
+ dev_set_drvdata(&dev->dev, di);
+
+ /*
+ * When u-boot has display a startup screen.
+ * U-boot has turned on display power however the
+ * regulator framework does not know about that
+ * This is the case here, the display driver has to
+ * enable the regulator for the display.
+ */
+ if (dev->power_mode != MCDE_DISPLAY_PM_OFF) {
+ (void) regulator_enable(di->regulator);
+ } else {
+ power_on(dev);
+ dev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+
+ ret = display_read_deviceid(dev, &id);
+ if (ret)
+ goto read_id_failed;
+
+ switch (id) {
+ case DISPLAY_SONY_ACX424AKP:
+ case DISPLAY_SONY_ACX424AKP_ID2:
+ pdata->disp_panel = id;
+ dev_info(&dev->dev,
+ "Sony ACX424AKP display (ID 0x%.4X) probed\n", id);
+ break;
+ default:
+ pdata->disp_panel = DISPLAY_NONE;
+ dev_info(&dev->dev,
+ "Display not recognized (ID 0x%.4X) probed\n", id);
+ goto read_id_failed;
+ }
+
+ return 0;
+
+read_id_failed:
+regulator_voltage_failed:
+ regulator_put(di->regulator);
+regulator_get_failed:
+ gpio_free(di->reset_gpio);
+gpio_request_failed:
+ kfree(di);
+ return ret;
+}
+
+static int __devexit sony_acx424akp_remove(struct mcde_display_device *dev)
+{
+ struct device_info *di = get_drvdata(dev);
+
+ dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF);
+
+ regulator_put(di->regulator);
+ gpio_direction_input(di->reset_gpio);
+ gpio_free(di->reset_gpio);
+
+ kfree(di);
+
+ return 0;
+}
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+static int sony_acx424akp_resume(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ /* set_power_mode will handle call platform_enable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to resume display\n"
+ , __func__);
+ return ret;
+}
+
+static int sony_acx424akp_suspend(struct mcde_display_device *ddev, \
+ pm_message_t state)
+{
+ int ret;
+
+ /* set_power_mode will handle call platform_disable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to suspend display\n"
+ , __func__);
+ return ret;
+}
+#endif
+
+static struct mcde_display_driver sony_acx424akp_driver = {
+ .probe = sony_acx424akp_probe,
+ .remove = sony_acx424akp_remove,
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ .suspend = sony_acx424akp_suspend,
+ .resume = sony_acx424akp_resume,
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+ .driver = {
+ .name = "mcde_disp_sony_acx424akp",
+ },
+};
+
+/* Module init */
+static int __init mcde_display_sony_acx424akp_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ return mcde_display_driver_register(&sony_acx424akp_driver);
+}
+module_init(mcde_display_sony_acx424akp_init);
+
+static void __exit mcde_display_sony_acx424akp_exit(void)
+{
+ pr_info("%s\n", __func__);
+
+ mcde_display_driver_unregister(&sony_acx424akp_driver);
+}
+module_exit(mcde_display_sony_acx424akp_exit);
+
+MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE Sony ACX424AKP DCS display driver");
diff --git a/drivers/video/mcde/display-vuib500-dpi.c b/drivers/video/mcde/display-vuib500-dpi.c
new file mode 100644
index 00000000000..2bd5b990608
--- /dev/null
+++ b/drivers/video/mcde/display-vuib500-dpi.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE DPI display driver
+ * The VUIB500 is an user interface board the can be attached to an HREF. It
+ * supports the DPI pixel interface and converts this to an analog VGA signal,
+ * which can be connected to a monitor using a DSUB connector. The VUIB board
+ * uses an external power supply of 5V.
+ *
+ * Author: Marcel Tunnissen <marcel.tuennissen@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <video/mcde_display.h>
+#include <video/mcde_display-vuib500-dpi.h>
+
+#define DPI_DISP_TRACE dev_dbg(&ddev->dev, "%s\n", __func__)
+
+static int try_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+static int set_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+
+static int __devinit dpi_display_probe(struct mcde_display_device *ddev)
+{
+ int ret = 0;
+ struct mcde_display_dpi_platform_data *pdata = ddev->dev.platform_data;
+ DPI_DISP_TRACE;
+
+ if (pdata == NULL) {
+ dev_err(&ddev->dev, "%s:Platform data missing\n", __func__);
+ ret = -EINVAL;
+ goto no_pdata;
+ }
+
+ if (ddev->port->type != MCDE_PORTTYPE_DPI) {
+ dev_err(&ddev->dev,
+ "%s:Invalid port type %d\n",
+ __func__, ddev->port->type);
+ ret = -EINVAL;
+ goto invalid_port_type;
+ }
+
+ ddev->try_video_mode = try_video_mode;
+ ddev->set_video_mode = set_video_mode;
+ dev_info(&ddev->dev, "DPI display probed\n");
+
+ goto out;
+invalid_port_type:
+no_pdata:
+out:
+ return ret;
+}
+
+static int __devexit dpi_display_remove(struct mcde_display_device *ddev)
+{
+ DPI_DISP_TRACE;
+
+ ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+
+ return 0;
+}
+
+static int dpi_display_resume(struct mcde_display_device *ddev)
+{
+ int ret;
+ DPI_DISP_TRACE;
+
+ /* set_power_mode will handle call platform_enable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to resume display\n"
+ , __func__);
+ return ret;
+}
+
+static int dpi_display_suspend(struct mcde_display_device *ddev,
+ pm_message_t state)
+{
+ int ret;
+ DPI_DISP_TRACE;
+
+ /* set_power_mode will handle call platform_disable */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+ if (ret < 0)
+ dev_warn(&ddev->dev, "%s:Failed to suspend display\n"
+ , __func__);
+ return ret;
+}
+
+static void print_vmode(struct mcde_video_mode *vmode)
+{
+ pr_debug("resolution: %dx%d\n", vmode->xres, vmode->yres);
+ pr_debug(" pixclock: %d\n", vmode->pixclock);
+ pr_debug(" hbp: %d\n", vmode->hbp);
+ pr_debug(" hfp: %d\n", vmode->hfp);
+ pr_debug(" hsw: %d\n", vmode->hsw);
+ pr_debug(" vbp: %d\n", vmode->vbp);
+ pr_debug(" vfp: %d\n", vmode->vfp);
+ pr_debug(" vsw: %d\n", vmode->vsw);
+ pr_debug("interlaced: %s\n", vmode->interlaced ? "true" : "false");
+}
+
+/* Taken from the programmed value of the LCD clock in PRCMU */
+#define PIX_CLK_FREQ 25000000
+#define VMODE_XRES 640
+#define VMODE_YRES 480
+
+static int try_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ int res = -EINVAL;
+ DPI_DISP_TRACE;
+
+ if (ddev == NULL || video_mode == NULL) {
+ dev_warn(&ddev->dev, "%s:ddev = NULL or video_mode = NULL\n",
+ __func__);
+ return res;
+ }
+
+ if (video_mode->xres == VMODE_XRES && video_mode->yres == VMODE_YRES) {
+ video_mode->hbp = 40;
+ video_mode->hfp = 8;
+ video_mode->hsw = 96;
+ video_mode->vbp = 25;
+ video_mode->vfp = 2;
+ video_mode->vsw = 2;
+ /*
+ * The pixclock setting is not used within MCDE. The clock is
+ * setup elsewhere. But the pixclock value is visible in user
+ * space.
+ */
+ video_mode->pixclock = (int) (1e+12 * (1.0 / PIX_CLK_FREQ));
+ res = 0;
+ } /* TODO: add more supported resolutions here */
+ video_mode->interlaced = false;
+
+ if (res == 0)
+ print_vmode(video_mode);
+ else
+ dev_warn(&ddev->dev,
+ "%s:Failed to find video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+
+ return res;
+
+}
+
+static int set_video_mode(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ int res;
+ DPI_DISP_TRACE;
+
+ if (ddev == NULL || video_mode == NULL) {
+ dev_warn(&ddev->dev, "%s:ddev = NULL or video_mode = NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (video_mode->xres != VMODE_XRES || video_mode->yres != VMODE_YRES) {
+ dev_warn(&ddev->dev, "%s:Failed to set video mode x=%d, y=%d\n",
+ __func__, video_mode->xres, video_mode->yres);
+ return -EINVAL;
+ }
+ ddev->video_mode = *video_mode;
+ print_vmode(video_mode);
+
+ res = mcde_chnl_set_video_mode(ddev->chnl_state, &ddev->video_mode);
+ if (res < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to set video mode on channel\n",
+ __func__);
+
+ }
+ /* notify mcde display driver about updated video mode */
+ ddev->update_flags |= UPDATE_FLAG_VIDEO_MODE;
+ return res;
+}
+
+static struct mcde_display_driver dpi_display_driver = {
+ .probe = dpi_display_probe,
+ .remove = dpi_display_remove,
+ .suspend = dpi_display_suspend,
+ .resume = dpi_display_resume,
+ .driver = {
+ .name = "mcde_display_dpi",
+ },
+};
+
+/* Module init */
+static int __init mcde_dpi_display_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ return mcde_display_driver_register(&dpi_display_driver);
+}
+module_init(mcde_dpi_display_init);
+
+static void __exit mcde_dpi_display_exit(void)
+{
+ pr_info("%s\n", __func__);
+
+ mcde_display_driver_unregister(&dpi_display_driver);
+}
+module_exit(mcde_dpi_display_exit);
+
+MODULE_AUTHOR("Marcel Tunnissen <marcel.tuennissen@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE DPI display driver fro VUIB500 display");
diff --git a/drivers/video/mcde/dsilink_regs.h b/drivers/video/mcde/dsilink_regs.h
new file mode 100644
index 00000000000..29fa75a1752
--- /dev/null
+++ b/drivers/video/mcde/dsilink_regs.h
@@ -0,0 +1,2037 @@
+
+#define DSI_VAL2REG(__reg, __fld, __val) \
+ (((__val) << __reg##_##__fld##_SHIFT) & __reg##_##__fld##_MASK)
+#define DSI_REG2VAL(__reg, __fld, __val) \
+ (((__val) & __reg##_##__fld##_MASK) >> __reg##_##__fld##_SHIFT)
+
+#define DSI_MCTL_INTEGRATION_MODE 0x00000000
+#define DSI_MCTL_INTEGRATION_MODE_INT_MODE_EN_SHIFT 0
+#define DSI_MCTL_INTEGRATION_MODE_INT_MODE_EN_MASK 0x00000001
+#define DSI_MCTL_INTEGRATION_MODE_INT_MODE_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_INTEGRATION_MODE, INT_MODE_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL 0x00000004
+#define DSI_MCTL_MAIN_DATA_CTL_LINK_EN_SHIFT 0
+#define DSI_MCTL_MAIN_DATA_CTL_LINK_EN_MASK 0x00000001
+#define DSI_MCTL_MAIN_DATA_CTL_LINK_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, LINK_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_SHIFT 1
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_MASK 0x00000002
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_CMD 0
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_VID 1
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_ENUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, IF1_MODE, \
+ DSI_MCTL_MAIN_DATA_CTL_IF1_MODE_##__x)
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_MODE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, IF1_MODE, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_VID_EN_SHIFT 2
+#define DSI_MCTL_MAIN_DATA_CTL_VID_EN_MASK 0x00000004
+#define DSI_MCTL_MAIN_DATA_CTL_VID_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, VID_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_TVG_SEL_SHIFT 3
+#define DSI_MCTL_MAIN_DATA_CTL_TVG_SEL_MASK 0x00000008
+#define DSI_MCTL_MAIN_DATA_CTL_TVG_SEL(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, TVG_SEL, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_TBG_SEL_SHIFT 4
+#define DSI_MCTL_MAIN_DATA_CTL_TBG_SEL_MASK 0x00000010
+#define DSI_MCTL_MAIN_DATA_CTL_TBG_SEL(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, TBG_SEL, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_TE_EN_SHIFT 5
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_TE_EN_MASK 0x00000020
+#define DSI_MCTL_MAIN_DATA_CTL_IF1_TE_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, IF1_TE_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_IF2_TE_EN_SHIFT 6
+#define DSI_MCTL_MAIN_DATA_CTL_IF2_TE_EN_MASK 0x00000040
+#define DSI_MCTL_MAIN_DATA_CTL_IF2_TE_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, IF2_TE_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN_SHIFT 7
+#define DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN_MASK 0x00000080
+#define DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, REG_TE_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_READ_EN_SHIFT 8
+#define DSI_MCTL_MAIN_DATA_CTL_READ_EN_MASK 0x00000100
+#define DSI_MCTL_MAIN_DATA_CTL_READ_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, READ_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_BTA_EN_SHIFT 9
+#define DSI_MCTL_MAIN_DATA_CTL_BTA_EN_MASK 0x00000200
+#define DSI_MCTL_MAIN_DATA_CTL_BTA_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, BTA_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_ECC_SHIFT 10
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_ECC_MASK 0x00000400
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_ECC(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, DISP_GEN_ECC, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_CHECKSUM_SHIFT 11
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_CHECKSUM_MASK 0x00000800
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_GEN_CHECKSUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, DISP_GEN_CHECKSUM, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN_SHIFT 12
+#define DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN_MASK 0x00001000
+#define DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, HOST_EOT_GEN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_EOT_GEN_SHIFT 13
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_EOT_GEN_MASK 0x00002000
+#define DSI_MCTL_MAIN_DATA_CTL_DISP_EOT_GEN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, DISP_EOT_GEN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_DLX_REMAP_EN_SHIFT 14
+#define DSI_MCTL_MAIN_DATA_CTL_DLX_REMAP_EN_MASK 0x00004000
+#define DSI_MCTL_MAIN_DATA_CTL_DLX_REMAP_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, DLX_REMAP_EN, __x)
+#define DSI_MCTL_MAIN_DATA_CTL_TE_POLLING_EN_SHIFT 15
+#define DSI_MCTL_MAIN_DATA_CTL_TE_POLLING_EN_MASK 0x00008000
+#define DSI_MCTL_MAIN_DATA_CTL_TE_POLLING_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_DATA_CTL, TE_POLLING_EN, __x)
+#define DSI_MCTL_MAIN_PHY_CTL 0x00000008
+#define DSI_MCTL_MAIN_PHY_CTL_LANE2_EN_SHIFT 0
+#define DSI_MCTL_MAIN_PHY_CTL_LANE2_EN_MASK 0x00000001
+#define DSI_MCTL_MAIN_PHY_CTL_LANE2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, LANE2_EN, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_FORCE_STOP_MODE_SHIFT 1
+#define DSI_MCTL_MAIN_PHY_CTL_FORCE_STOP_MODE_MASK 0x00000002
+#define DSI_MCTL_MAIN_PHY_CTL_FORCE_STOP_MODE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, FORCE_STOP_MODE, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS_SHIFT 2
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS_MASK 0x00000004
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, CLK_CONTINUOUS, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN_SHIFT 3
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN_MASK 0x00000008
+#define DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, CLK_ULPM_EN, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN_SHIFT 4
+#define DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN_MASK 0x00000010
+#define DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, DAT1_ULPM_EN, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN_SHIFT 5
+#define DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN_MASK 0x00000020
+#define DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, DAT2_ULPM_EN, __x)
+#define DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_SHIFT 6
+#define DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_MASK 0x000003C0
+#define DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_PHY_CTL, WAIT_BURST_TIME, __x)
+#define DSI_MCTL_PLL_CTL 0x0000000C
+#define DSI_MCTL_PLL_CTL_PLL_MULT_SHIFT 0
+#define DSI_MCTL_PLL_CTL_PLL_MULT_MASK 0x000000FF
+#define DSI_MCTL_PLL_CTL_PLL_MULT(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_MULT, __x)
+#define DSI_MCTL_PLL_CTL_PLL_OUT_DIV_SHIFT 8
+#define DSI_MCTL_PLL_CTL_PLL_OUT_DIV_MASK 0x00003F00
+#define DSI_MCTL_PLL_CTL_PLL_OUT_DIV(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_OUT_DIV, __x)
+#define DSI_MCTL_PLL_CTL_PLL_IN_DIV_SHIFT 14
+#define DSI_MCTL_PLL_CTL_PLL_IN_DIV_MASK 0x0001C000
+#define DSI_MCTL_PLL_CTL_PLL_IN_DIV(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_IN_DIV, __x)
+#define DSI_MCTL_PLL_CTL_PLL_SEL_DIV2_SHIFT 17
+#define DSI_MCTL_PLL_CTL_PLL_SEL_DIV2_MASK 0x00020000
+#define DSI_MCTL_PLL_CTL_PLL_SEL_DIV2(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_SEL_DIV2, __x)
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL_SHIFT 18
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL_MASK 0x00040000
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL_INT_PLL 0
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL_SYS_PLL 1
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL_ENUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_OUT_SEL, \
+ DSI_MCTL_PLL_CTL_PLL_OUT_SEL_##__x)
+#define DSI_MCTL_PLL_CTL_PLL_OUT_SEL(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_OUT_SEL, __x)
+#define DSI_MCTL_PLL_CTL_PLL_MASTER_SHIFT 31
+#define DSI_MCTL_PLL_CTL_PLL_MASTER_MASK 0x80000000
+#define DSI_MCTL_PLL_CTL_PLL_MASTER(__x) \
+ DSI_VAL2REG(DSI_MCTL_PLL_CTL, PLL_MASTER, __x)
+#define DSI_MCTL_LANE_STS 0x00000010
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_SHIFT 0
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_MASK 0x00000003
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_START 0
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_IDLE 1
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_HS 2
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_ULPM 3
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE_ENUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, CLKLANE_STATE, \
+ DSI_MCTL_LANE_STS_CLKLANE_STATE_##__x)
+#define DSI_MCTL_LANE_STS_CLKLANE_STATE(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, CLKLANE_STATE, __x)
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_SHIFT 2
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_MASK 0x0000001C
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_START 0
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_IDLE 1
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_WRITE 2
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_ULPM 3
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_READ 4
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE_ENUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, DATLANE1_STATE, \
+ DSI_MCTL_LANE_STS_DATLANE1_STATE_##__x)
+#define DSI_MCTL_LANE_STS_DATLANE1_STATE(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, DATLANE1_STATE, __x)
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_SHIFT 5
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_MASK 0x00000060
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_START 0
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_IDLE 1
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_WRITE 2
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_ULPM 3
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE_ENUM(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, DATLANE2_STATE, \
+ DSI_MCTL_LANE_STS_DATLANE2_STATE_##__x)
+#define DSI_MCTL_LANE_STS_DATLANE2_STATE(__x) \
+ DSI_VAL2REG(DSI_MCTL_LANE_STS, DATLANE2_STATE, __x)
+#define DSI_MCTL_DPHY_TIMEOUT 0x00000014
+#define DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_SHIFT 0
+#define DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_MASK 0x0000000F
+#define DSI_MCTL_DPHY_TIMEOUT_CLK_DIV(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_TIMEOUT, CLK_DIV, __x)
+#define DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_SHIFT 4
+#define DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_MASK 0x0003FFF0
+#define DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_TIMEOUT, HSTX_TO_VAL, __x)
+#define DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_SHIFT 18
+#define DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_MASK 0xFFFC0000
+#define DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_TIMEOUT, LPRX_TO_VAL, __x)
+#define DSI_MCTL_ULPOUT_TIME 0x00000018
+#define DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_SHIFT 0
+#define DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_MASK 0x000001FF
+#define DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME(__x) \
+ DSI_VAL2REG(DSI_MCTL_ULPOUT_TIME, CKLANE_ULPOUT_TIME, __x)
+#define DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_SHIFT 9
+#define DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_MASK 0x0003FE00
+#define DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME(__x) \
+ DSI_VAL2REG(DSI_MCTL_ULPOUT_TIME, DATA_ULPOUT_TIME, __x)
+#define DSI_MCTL_DPHY_STATIC 0x0000001C
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_CLK_SHIFT 0
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_CLK_MASK 0x00000001
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_CLK(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, SWAP_PINS_CLK, __x)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_CLK_SHIFT 1
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_CLK_MASK 0x00000002
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_CLK(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, HS_INVERT_CLK, __x)
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT1_SHIFT 2
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT1_MASK 0x00000004
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, SWAP_PINS_DAT1, __x)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT1_SHIFT 3
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT1_MASK 0x00000008
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, HS_INVERT_DAT1, __x)
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT2_SHIFT 4
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT2_MASK 0x00000010
+#define DSI_MCTL_DPHY_STATIC_SWAP_PINS_DAT2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, SWAP_PINS_DAT2, __x)
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT2_SHIFT 5
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT2_MASK 0x00000020
+#define DSI_MCTL_DPHY_STATIC_HS_INVERT_DAT2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, HS_INVERT_DAT2, __x)
+#define DSI_MCTL_DPHY_STATIC_UI_X4_SHIFT 6
+#define DSI_MCTL_DPHY_STATIC_UI_X4_MASK 0x00000FC0
+#define DSI_MCTL_DPHY_STATIC_UI_X4(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_STATIC, UI_X4, __x)
+#define DSI_MCTL_MAIN_EN 0x00000020
+#define DSI_MCTL_MAIN_EN_PLL_START_SHIFT 0
+#define DSI_MCTL_MAIN_EN_PLL_START_MASK 0x00000001
+#define DSI_MCTL_MAIN_EN_PLL_START(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, PLL_START, __x)
+#define DSI_MCTL_MAIN_EN_CKLANE_EN_SHIFT 3
+#define DSI_MCTL_MAIN_EN_CKLANE_EN_MASK 0x00000008
+#define DSI_MCTL_MAIN_EN_CKLANE_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, CKLANE_EN, __x)
+#define DSI_MCTL_MAIN_EN_DAT1_EN_SHIFT 4
+#define DSI_MCTL_MAIN_EN_DAT1_EN_MASK 0x00000010
+#define DSI_MCTL_MAIN_EN_DAT1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, DAT1_EN, __x)
+#define DSI_MCTL_MAIN_EN_DAT2_EN_SHIFT 5
+#define DSI_MCTL_MAIN_EN_DAT2_EN_MASK 0x00000020
+#define DSI_MCTL_MAIN_EN_DAT2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, DAT2_EN, __x)
+#define DSI_MCTL_MAIN_EN_CLKLANE_ULPM_REQ_SHIFT 6
+#define DSI_MCTL_MAIN_EN_CLKLANE_ULPM_REQ_MASK 0x00000040
+#define DSI_MCTL_MAIN_EN_CLKLANE_ULPM_REQ(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, CLKLANE_ULPM_REQ, __x)
+#define DSI_MCTL_MAIN_EN_DAT1_ULPM_REQ_SHIFT 7
+#define DSI_MCTL_MAIN_EN_DAT1_ULPM_REQ_MASK 0x00000080
+#define DSI_MCTL_MAIN_EN_DAT1_ULPM_REQ(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, DAT1_ULPM_REQ, __x)
+#define DSI_MCTL_MAIN_EN_DAT2_ULPM_REQ_SHIFT 8
+#define DSI_MCTL_MAIN_EN_DAT2_ULPM_REQ_MASK 0x00000100
+#define DSI_MCTL_MAIN_EN_DAT2_ULPM_REQ(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, DAT2_ULPM_REQ, __x)
+#define DSI_MCTL_MAIN_EN_IF1_EN_SHIFT 9
+#define DSI_MCTL_MAIN_EN_IF1_EN_MASK 0x00000200
+#define DSI_MCTL_MAIN_EN_IF1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, IF1_EN, __x)
+#define DSI_MCTL_MAIN_EN_IF2_EN_SHIFT 10
+#define DSI_MCTL_MAIN_EN_IF2_EN_MASK 0x00000400
+#define DSI_MCTL_MAIN_EN_IF2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_EN, IF2_EN, __x)
+#define DSI_MCTL_MAIN_STS 0x00000024
+#define DSI_MCTL_MAIN_STS_PLL_LOCK_SHIFT 0
+#define DSI_MCTL_MAIN_STS_PLL_LOCK_MASK 0x00000001
+#define DSI_MCTL_MAIN_STS_PLL_LOCK(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, PLL_LOCK, __x)
+#define DSI_MCTL_MAIN_STS_CLKLANE_READY_SHIFT 1
+#define DSI_MCTL_MAIN_STS_CLKLANE_READY_MASK 0x00000002
+#define DSI_MCTL_MAIN_STS_CLKLANE_READY(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, CLKLANE_READY, __x)
+#define DSI_MCTL_MAIN_STS_DAT1_READY_SHIFT 2
+#define DSI_MCTL_MAIN_STS_DAT1_READY_MASK 0x00000004
+#define DSI_MCTL_MAIN_STS_DAT1_READY(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, DAT1_READY, __x)
+#define DSI_MCTL_MAIN_STS_DAT2_READY_SHIFT 3
+#define DSI_MCTL_MAIN_STS_DAT2_READY_MASK 0x00000008
+#define DSI_MCTL_MAIN_STS_DAT2_READY(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, DAT2_READY, __x)
+#define DSI_MCTL_MAIN_STS_HSTX_TO_ERR_SHIFT 4
+#define DSI_MCTL_MAIN_STS_HSTX_TO_ERR_MASK 0x00000010
+#define DSI_MCTL_MAIN_STS_HSTX_TO_ERR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, HSTX_TO_ERR, __x)
+#define DSI_MCTL_MAIN_STS_LPRX_TO_ERR_SHIFT 5
+#define DSI_MCTL_MAIN_STS_LPRX_TO_ERR_MASK 0x00000020
+#define DSI_MCTL_MAIN_STS_LPRX_TO_ERR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, LPRX_TO_ERR, __x)
+#define DSI_MCTL_MAIN_STS_CRS_UNTERM_PCK_SHIFT 6
+#define DSI_MCTL_MAIN_STS_CRS_UNTERM_PCK_MASK 0x00000040
+#define DSI_MCTL_MAIN_STS_CRS_UNTERM_PCK(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, CRS_UNTERM_PCK, __x)
+#define DSI_MCTL_MAIN_STS_VRS_UNTERM_PCK_SHIFT 7
+#define DSI_MCTL_MAIN_STS_VRS_UNTERM_PCK_MASK 0x00000080
+#define DSI_MCTL_MAIN_STS_VRS_UNTERM_PCK(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS, VRS_UNTERM_PCK, __x)
+#define DSI_MCTL_DPHY_ERR 0x00000028
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_1_SHIFT 6
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_1_MASK 0x00000040
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_ESC_1, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_2_SHIFT 7
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_2_MASK 0x00000080
+#define DSI_MCTL_DPHY_ERR_ERR_ESC_2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_ESC_2, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_1_SHIFT 8
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_1_MASK 0x00000100
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_SYNCESC_1, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_2_SHIFT 9
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_2_MASK 0x00000200
+#define DSI_MCTL_DPHY_ERR_ERR_SYNCESC_2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_SYNCESC_2, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_1_SHIFT 10
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_1_MASK 0x00000400
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONTROL_1, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_2_SHIFT 11
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_2_MASK 0x00000800
+#define DSI_MCTL_DPHY_ERR_ERR_CONTROL_2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONTROL_2, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_1_SHIFT 12
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_1_MASK 0x00001000
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONT_LP0_1, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_2_SHIFT 13
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_2_MASK 0x00002000
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP0_2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONT_LP0_2, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_1_SHIFT 14
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_1_MASK 0x00004000
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_1(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONT_LP1_1, __x)
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_2_SHIFT 15
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_2_MASK 0x00008000
+#define DSI_MCTL_DPHY_ERR_ERR_CONT_LP1_2(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR, ERR_CONT_LP1_2, __x)
+#define DSI_INT_VID_RDDATA 0x00000030
+#define DSI_INT_VID_RDDATA_IF_DATA_SHIFT 0
+#define DSI_INT_VID_RDDATA_IF_DATA_MASK 0x0000FFFF
+#define DSI_INT_VID_RDDATA_IF_DATA(__x) \
+ DSI_VAL2REG(DSI_INT_VID_RDDATA, IF_DATA, __x)
+#define DSI_INT_VID_RDDATA_IF_VALID_SHIFT 16
+#define DSI_INT_VID_RDDATA_IF_VALID_MASK 0x00010000
+#define DSI_INT_VID_RDDATA_IF_VALID(__x) \
+ DSI_VAL2REG(DSI_INT_VID_RDDATA, IF_VALID, __x)
+#define DSI_INT_VID_RDDATA_IF_START_SHIFT 17
+#define DSI_INT_VID_RDDATA_IF_START_MASK 0x00020000
+#define DSI_INT_VID_RDDATA_IF_START(__x) \
+ DSI_VAL2REG(DSI_INT_VID_RDDATA, IF_START, __x)
+#define DSI_INT_VID_RDDATA_IF_FRAME_SYNC_SHIFT 18
+#define DSI_INT_VID_RDDATA_IF_FRAME_SYNC_MASK 0x00040000
+#define DSI_INT_VID_RDDATA_IF_FRAME_SYNC(__x) \
+ DSI_VAL2REG(DSI_INT_VID_RDDATA, IF_FRAME_SYNC, __x)
+#define DSI_INT_VID_GNT 0x00000034
+#define DSI_INT_VID_GNT_IF_STALL_SHIFT 0
+#define DSI_INT_VID_GNT_IF_STALL_MASK 0x00000001
+#define DSI_INT_VID_GNT_IF_STALL(__x) \
+ DSI_VAL2REG(DSI_INT_VID_GNT, IF_STALL, __x)
+#define DSI_INT_CMD_RDDATA 0x00000038
+#define DSI_INT_CMD_RDDATA_IF_DATA_SHIFT 0
+#define DSI_INT_CMD_RDDATA_IF_DATA_MASK 0x0000FFFF
+#define DSI_INT_CMD_RDDATA_IF_DATA(__x) \
+ DSI_VAL2REG(DSI_INT_CMD_RDDATA, IF_DATA, __x)
+#define DSI_INT_CMD_RDDATA_IF_VALID_SHIFT 16
+#define DSI_INT_CMD_RDDATA_IF_VALID_MASK 0x00010000
+#define DSI_INT_CMD_RDDATA_IF_VALID(__x) \
+ DSI_VAL2REG(DSI_INT_CMD_RDDATA, IF_VALID, __x)
+#define DSI_INT_CMD_RDDATA_IF_START_SHIFT 17
+#define DSI_INT_CMD_RDDATA_IF_START_MASK 0x00020000
+#define DSI_INT_CMD_RDDATA_IF_START(__x) \
+ DSI_VAL2REG(DSI_INT_CMD_RDDATA, IF_START, __x)
+#define DSI_INT_CMD_RDDATA_IF_FRAME_SYNC_SHIFT 18
+#define DSI_INT_CMD_RDDATA_IF_FRAME_SYNC_MASK 0x00040000
+#define DSI_INT_CMD_RDDATA_IF_FRAME_SYNC(__x) \
+ DSI_VAL2REG(DSI_INT_CMD_RDDATA, IF_FRAME_SYNC, __x)
+#define DSI_INT_CMD_GNT 0x0000003C
+#define DSI_INT_CMD_GNT_IF_STALL_SHIFT 0
+#define DSI_INT_CMD_GNT_IF_STALL_MASK 0x00000001
+#define DSI_INT_CMD_GNT_IF_STALL(__x) \
+ DSI_VAL2REG(DSI_INT_CMD_GNT, IF_STALL, __x)
+#define DSI_INT_INTERRUPT_CTL 0x00000040
+#define DSI_INT_INTERRUPT_CTL_INT_VAL_SHIFT 0
+#define DSI_INT_INTERRUPT_CTL_INT_VAL_MASK 0x00000001
+#define DSI_INT_INTERRUPT_CTL_INT_VAL(__x) \
+ DSI_VAL2REG(DSI_INT_INTERRUPT_CTL, INT_VAL, __x)
+#define DSI_CMD_MODE_CTL 0x00000050
+#define DSI_CMD_MODE_CTL_IF1_ID_SHIFT 0
+#define DSI_CMD_MODE_CTL_IF1_ID_MASK 0x00000003
+#define DSI_CMD_MODE_CTL_IF1_ID(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, IF1_ID, __x)
+#define DSI_CMD_MODE_CTL_IF2_ID_SHIFT 2
+#define DSI_CMD_MODE_CTL_IF2_ID_MASK 0x0000000C
+#define DSI_CMD_MODE_CTL_IF2_ID(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, IF2_ID, __x)
+#define DSI_CMD_MODE_CTL_IF1_LP_EN_SHIFT 4
+#define DSI_CMD_MODE_CTL_IF1_LP_EN_MASK 0x00000010
+#define DSI_CMD_MODE_CTL_IF1_LP_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, IF1_LP_EN, __x)
+#define DSI_CMD_MODE_CTL_IF2_LP_EN_SHIFT 5
+#define DSI_CMD_MODE_CTL_IF2_LP_EN_MASK 0x00000020
+#define DSI_CMD_MODE_CTL_IF2_LP_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, IF2_LP_EN, __x)
+#define DSI_CMD_MODE_CTL_ARB_MODE_SHIFT 6
+#define DSI_CMD_MODE_CTL_ARB_MODE_MASK 0x00000040
+#define DSI_CMD_MODE_CTL_ARB_MODE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, ARB_MODE, __x)
+#define DSI_CMD_MODE_CTL_ARB_PRI_SHIFT 7
+#define DSI_CMD_MODE_CTL_ARB_PRI_MASK 0x00000080
+#define DSI_CMD_MODE_CTL_ARB_PRI(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, ARB_PRI, __x)
+#define DSI_CMD_MODE_CTL_FIL_VALUE_SHIFT 8
+#define DSI_CMD_MODE_CTL_FIL_VALUE_MASK 0x0000FF00
+#define DSI_CMD_MODE_CTL_FIL_VALUE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, FIL_VALUE, __x)
+#define DSI_CMD_MODE_CTL_TE_TIMEOUT_SHIFT 16
+#define DSI_CMD_MODE_CTL_TE_TIMEOUT_MASK 0x03FF0000
+#define DSI_CMD_MODE_CTL_TE_TIMEOUT(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_CTL, TE_TIMEOUT, __x)
+#define DSI_CMD_MODE_STS 0x00000054
+#define DSI_CMD_MODE_STS_ERR_NO_TE_SHIFT 0
+#define DSI_CMD_MODE_STS_ERR_NO_TE_MASK 0x00000001
+#define DSI_CMD_MODE_STS_ERR_NO_TE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, ERR_NO_TE, __x)
+#define DSI_CMD_MODE_STS_ERR_TE_MISS_SHIFT 1
+#define DSI_CMD_MODE_STS_ERR_TE_MISS_MASK 0x00000002
+#define DSI_CMD_MODE_STS_ERR_TE_MISS(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, ERR_TE_MISS, __x)
+#define DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN_SHIFT 2
+#define DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN_MASK 0x00000004
+#define DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, ERR_SDI1_UNDERRUN, __x)
+#define DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN_SHIFT 3
+#define DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN_MASK 0x00000008
+#define DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, ERR_SDI2_UNDERRUN, __x)
+#define DSI_CMD_MODE_STS_ERR_UNWANTED_RD_SHIFT 4
+#define DSI_CMD_MODE_STS_ERR_UNWANTED_RD_MASK 0x00000010
+#define DSI_CMD_MODE_STS_ERR_UNWANTED_RD(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, ERR_UNWANTED_RD, __x)
+#define DSI_CMD_MODE_STS_CSM_RUNNING_SHIFT 5
+#define DSI_CMD_MODE_STS_CSM_RUNNING_MASK 0x00000020
+#define DSI_CMD_MODE_STS_CSM_RUNNING(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS, CSM_RUNNING, __x)
+#define DSI_DIRECT_CMD_SEND 0x00000060
+#define DSI_DIRECT_CMD_SEND_START_SHIFT 0
+#define DSI_DIRECT_CMD_SEND_START_MASK 0xFFFFFFFF
+#define DSI_DIRECT_CMD_SEND_START(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_SEND, START, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS 0x00000064
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_SHIFT 0
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_MASK 0x00000007
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE 0
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ 1
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TE_REQ 4
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TRIG_REQ 5
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_BTA_REQ 6
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_NAT, \
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_##__x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_NAT, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT_SHIFT 3
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT_MASK 0x00000008
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_LONGNOTSHORT, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT 8
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_MASK 0x00003F00
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_0 3
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_1 19
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_SHORT_WRITE_2 35
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_GENERIC_LONG_WRITE 41
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_0 5
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_SHORT_WRITE_1 21
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_LONG_WRITE 57
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_DCS_READ 6
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SET_MAX_PKT_SIZE 55
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_HEAD, \
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_##__x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_HEAD, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT 14
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_MASK 0x0000C000
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_ID, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT 16
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_MASK 0x001F0000
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_SIZE, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN_SHIFT 21
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN_MASK 0x00200000
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, CMD_LP_EN, __x)
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_TRIGGER_VAL_SHIFT 24
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_TRIGGER_VAL_MASK 0x0F000000
+#define DSI_DIRECT_CMD_MAIN_SETTINGS_TRIGGER_VAL(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_MAIN_SETTINGS, TRIGGER_VAL, __x)
+#define DSI_DIRECT_CMD_STS 0x00000068
+#define DSI_DIRECT_CMD_STS_CMD_TRANSMISSION_SHIFT 0
+#define DSI_DIRECT_CMD_STS_CMD_TRANSMISSION_MASK 0x00000001
+#define DSI_DIRECT_CMD_STS_CMD_TRANSMISSION(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, CMD_TRANSMISSION, __x)
+#define DSI_DIRECT_CMD_STS_WRITE_COMPLETED_SHIFT 1
+#define DSI_DIRECT_CMD_STS_WRITE_COMPLETED_MASK 0x00000002
+#define DSI_DIRECT_CMD_STS_WRITE_COMPLETED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, WRITE_COMPLETED, __x)
+#define DSI_DIRECT_CMD_STS_TRIGGER_COMPLETED_SHIFT 2
+#define DSI_DIRECT_CMD_STS_TRIGGER_COMPLETED_MASK 0x00000004
+#define DSI_DIRECT_CMD_STS_TRIGGER_COMPLETED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, TRIGGER_COMPLETED, __x)
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_SHIFT 3
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_MASK 0x00000008
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, READ_COMPLETED, __x)
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_RECEIVED_SHIFT 4
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_RECEIVED_MASK 0x00000010
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_RECEIVED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, ACKNOWLEDGE_RECEIVED, __x)
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED_SHIFT 5
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED_MASK 0x00000020
+#define DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, ACKNOWLEDGE_WITH_ERR_RECEIVED, __x)
+#define DSI_DIRECT_CMD_STS_TRIGGER_RECEIVED_SHIFT 6
+#define DSI_DIRECT_CMD_STS_TRIGGER_RECEIVED_MASK 0x00000040
+#define DSI_DIRECT_CMD_STS_TRIGGER_RECEIVED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, TRIGGER_RECEIVED, __x)
+#define DSI_DIRECT_CMD_STS_TE_RECEIVED_SHIFT 7
+#define DSI_DIRECT_CMD_STS_TE_RECEIVED_MASK 0x00000080
+#define DSI_DIRECT_CMD_STS_TE_RECEIVED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, TE_RECEIVED, __x)
+#define DSI_DIRECT_CMD_STS_BTA_COMPLETED_SHIFT 8
+#define DSI_DIRECT_CMD_STS_BTA_COMPLETED_MASK 0x00000100
+#define DSI_DIRECT_CMD_STS_BTA_COMPLETED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, BTA_COMPLETED, __x)
+#define DSI_DIRECT_CMD_STS_BTA_FINISHED_SHIFT 9
+#define DSI_DIRECT_CMD_STS_BTA_FINISHED_MASK 0x00000200
+#define DSI_DIRECT_CMD_STS_BTA_FINISHED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, BTA_FINISHED, __x)
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR_SHIFT 10
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR_MASK 0x00000400
+#define DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, READ_COMPLETED_WITH_ERR, __x)
+#define DSI_DIRECT_CMD_STS_TRIGGER_VAL_SHIFT 11
+#define DSI_DIRECT_CMD_STS_TRIGGER_VAL_MASK 0x00007800
+#define DSI_DIRECT_CMD_STS_TRIGGER_VAL(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, TRIGGER_VAL, __x)
+#define DSI_DIRECT_CMD_STS_ACK_VAL_SHIFT 16
+#define DSI_DIRECT_CMD_STS_ACK_VAL_MASK 0xFFFF0000
+#define DSI_DIRECT_CMD_STS_ACK_VAL(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS, ACK_VAL, __x)
+#define DSI_DIRECT_CMD_RD_INIT 0x0000006C
+#define DSI_DIRECT_CMD_RD_INIT_RESET_SHIFT 0
+#define DSI_DIRECT_CMD_RD_INIT_RESET_MASK 0xFFFFFFFF
+#define DSI_DIRECT_CMD_RD_INIT_RESET(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_INIT, RESET, __x)
+#define DSI_DIRECT_CMD_WRDAT0 0x00000070
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT0_SHIFT 0
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT0_MASK 0x000000FF
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT0(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT0, WRDAT0, __x)
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT1_SHIFT 8
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT1_MASK 0x0000FF00
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT1(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT0, WRDAT1, __x)
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT2_SHIFT 16
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT2_MASK 0x00FF0000
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT2(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT0, WRDAT2, __x)
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT3_SHIFT 24
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT3_MASK 0xFF000000
+#define DSI_DIRECT_CMD_WRDAT0_WRDAT3(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT0, WRDAT3, __x)
+#define DSI_DIRECT_CMD_WRDAT1 0x00000074
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT4_SHIFT 0
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT4_MASK 0x000000FF
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT4(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT1, WRDAT4, __x)
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT5_SHIFT 8
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT5_MASK 0x0000FF00
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT5(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT1, WRDAT5, __x)
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT6_SHIFT 16
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT6_MASK 0x00FF0000
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT6(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT1, WRDAT6, __x)
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT7_SHIFT 24
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT7_MASK 0xFF000000
+#define DSI_DIRECT_CMD_WRDAT1_WRDAT7(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT1, WRDAT7, __x)
+#define DSI_DIRECT_CMD_WRDAT2 0x00000078
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT8_SHIFT 0
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT8_MASK 0x000000FF
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT8(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT2, WRDAT8, __x)
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT9_SHIFT 8
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT9_MASK 0x0000FF00
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT9(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT2, WRDAT9, __x)
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT10_SHIFT 16
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT10_MASK 0x00FF0000
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT10(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT2, WRDAT10, __x)
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT11_SHIFT 24
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT11_MASK 0xFF000000
+#define DSI_DIRECT_CMD_WRDAT2_WRDAT11(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT2, WRDAT11, __x)
+#define DSI_DIRECT_CMD_WRDAT3 0x0000007C
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT12_SHIFT 0
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT12_MASK 0x000000FF
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT12(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT3, WRDAT12, __x)
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT13_SHIFT 8
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT13_MASK 0x0000FF00
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT13(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT3, WRDAT13, __x)
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT14_SHIFT 16
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT14_MASK 0x00FF0000
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT14(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT3, WRDAT14, __x)
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT15_SHIFT 24
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT15_MASK 0xFF000000
+#define DSI_DIRECT_CMD_WRDAT3_WRDAT15(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_WRDAT3, WRDAT15, __x)
+#define DSI_DIRECT_CMD_RDDAT 0x00000080
+#define DSI_DIRECT_CMD_RDDAT_RDDAT0_SHIFT 0
+#define DSI_DIRECT_CMD_RDDAT_RDDAT0_MASK 0x000000FF
+#define DSI_DIRECT_CMD_RDDAT_RDDAT0(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RDDAT, RDDAT0, __x)
+#define DSI_DIRECT_CMD_RDDAT_RDDAT1_SHIFT 8
+#define DSI_DIRECT_CMD_RDDAT_RDDAT1_MASK 0x0000FF00
+#define DSI_DIRECT_CMD_RDDAT_RDDAT1(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RDDAT, RDDAT1, __x)
+#define DSI_DIRECT_CMD_RDDAT_RDDAT2_SHIFT 16
+#define DSI_DIRECT_CMD_RDDAT_RDDAT2_MASK 0x00FF0000
+#define DSI_DIRECT_CMD_RDDAT_RDDAT2(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RDDAT, RDDAT2, __x)
+#define DSI_DIRECT_CMD_RDDAT_RDDAT3_SHIFT 24
+#define DSI_DIRECT_CMD_RDDAT_RDDAT3_MASK 0xFF000000
+#define DSI_DIRECT_CMD_RDDAT_RDDAT3(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RDDAT, RDDAT3, __x)
+#define DSI_DIRECT_CMD_RD_PROPERTY 0x00000084
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_SHIFT 0
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_MASK 0x0000FFFF
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_PROPERTY, RD_SIZE, __x)
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_ID_SHIFT 16
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_ID_MASK 0x00030000
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_ID(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_PROPERTY, RD_ID, __x)
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_DCSNOTGENERIC_SHIFT 18
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_DCSNOTGENERIC_MASK 0x00040000
+#define DSI_DIRECT_CMD_RD_PROPERTY_RD_DCSNOTGENERIC(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_PROPERTY, RD_DCSNOTGENERIC, __x)
+#define DSI_DIRECT_CMD_RD_STS 0x00000088
+#define DSI_DIRECT_CMD_RD_STS_ERR_FIXED_SHIFT 0
+#define DSI_DIRECT_CMD_RD_STS_ERR_FIXED_MASK 0x00000001
+#define DSI_DIRECT_CMD_RD_STS_ERR_FIXED(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_FIXED, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNCORRECTABLE_SHIFT 1
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNCORRECTABLE_MASK 0x00000002
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNCORRECTABLE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_UNCORRECTABLE, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_CHECKSUM_SHIFT 2
+#define DSI_DIRECT_CMD_RD_STS_ERR_CHECKSUM_MASK 0x00000004
+#define DSI_DIRECT_CMD_RD_STS_ERR_CHECKSUM(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_CHECKSUM, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNDECODABLE_SHIFT 3
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNDECODABLE_MASK 0x00000008
+#define DSI_DIRECT_CMD_RD_STS_ERR_UNDECODABLE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_UNDECODABLE, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_RECEIVE_SHIFT 4
+#define DSI_DIRECT_CMD_RD_STS_ERR_RECEIVE_MASK 0x00000010
+#define DSI_DIRECT_CMD_RD_STS_ERR_RECEIVE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_RECEIVE, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_OVERSIZE_SHIFT 5
+#define DSI_DIRECT_CMD_RD_STS_ERR_OVERSIZE_MASK 0x00000020
+#define DSI_DIRECT_CMD_RD_STS_ERR_OVERSIZE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_OVERSIZE, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_WRONG_LENGTH_SHIFT 6
+#define DSI_DIRECT_CMD_RD_STS_ERR_WRONG_LENGTH_MASK 0x00000040
+#define DSI_DIRECT_CMD_RD_STS_ERR_WRONG_LENGTH(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_WRONG_LENGTH, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_MISSING_EOT_SHIFT 7
+#define DSI_DIRECT_CMD_RD_STS_ERR_MISSING_EOT_MASK 0x00000080
+#define DSI_DIRECT_CMD_RD_STS_ERR_MISSING_EOT(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_MISSING_EOT, __x)
+#define DSI_DIRECT_CMD_RD_STS_ERR_EOT_WITH_ERR_SHIFT 8
+#define DSI_DIRECT_CMD_RD_STS_ERR_EOT_WITH_ERR_MASK 0x00000100
+#define DSI_DIRECT_CMD_RD_STS_ERR_EOT_WITH_ERR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS, ERR_EOT_WITH_ERR, __x)
+#define DSI_VID_MAIN_CTL 0x00000090
+#define DSI_VID_MAIN_CTL_START_MODE_SHIFT 0
+#define DSI_VID_MAIN_CTL_START_MODE_MASK 0x00000003
+#define DSI_VID_MAIN_CTL_START_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, START_MODE, __x)
+#define DSI_VID_MAIN_CTL_STOP_MODE_SHIFT 2
+#define DSI_VID_MAIN_CTL_STOP_MODE_MASK 0x0000000C
+#define DSI_VID_MAIN_CTL_STOP_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, STOP_MODE, __x)
+#define DSI_VID_MAIN_CTL_VID_ID_SHIFT 4
+#define DSI_VID_MAIN_CTL_VID_ID_MASK 0x00000030
+#define DSI_VID_MAIN_CTL_VID_ID(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, VID_ID, __x)
+#define DSI_VID_MAIN_CTL_HEADER_SHIFT 6
+#define DSI_VID_MAIN_CTL_HEADER_MASK 0x00000FC0
+#define DSI_VID_MAIN_CTL_HEADER(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, HEADER, __x)
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_SHIFT 12
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_MASK 0x00003000
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_16BITS 0
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS 1
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS_LOOSE 2
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_24BITS 3
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE_ENUM(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, VID_PIXEL_MODE, \
+ DSI_VID_MAIN_CTL_VID_PIXEL_MODE_##__x)
+#define DSI_VID_MAIN_CTL_VID_PIXEL_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, VID_PIXEL_MODE, __x)
+#define DSI_VID_MAIN_CTL_BURST_MODE_SHIFT 14
+#define DSI_VID_MAIN_CTL_BURST_MODE_MASK 0x00004000
+#define DSI_VID_MAIN_CTL_BURST_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, BURST_MODE, __x)
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE_SHIFT 15
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE_MASK 0x00008000
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, SYNC_PULSE_ACTIVE, __x)
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL_SHIFT 16
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL_MASK 0x00010000
+#define DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, SYNC_PULSE_HORIZONTAL, __x)
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_SHIFT 17
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_MASK 0x00060000
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_NULL 0
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING 1
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0 2
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_1 3
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_ENUM(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, REG_BLKLINE_MODE, \
+ DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_##__x)
+#define DSI_VID_MAIN_CTL_REG_BLKLINE_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, REG_BLKLINE_MODE, __x)
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_SHIFT 19
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_MASK 0x00180000
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_NULL 0
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_BLANKING 1
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 2
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_1 3
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_ENUM(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, REG_BLKEOL_MODE, \
+ DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_##__x)
+#define DSI_VID_MAIN_CTL_REG_BLKEOL_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, REG_BLKEOL_MODE, __x)
+#define DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT 21
+#define DSI_VID_MAIN_CTL_RECOVERY_MODE_MASK 0x00600000
+#define DSI_VID_MAIN_CTL_RECOVERY_MODE(__x) \
+ DSI_VAL2REG(DSI_VID_MAIN_CTL, RECOVERY_MODE, __x)
+#define DSI_VID_VSIZE 0x00000094
+#define DSI_VID_VSIZE_VSA_LENGTH_SHIFT 0
+#define DSI_VID_VSIZE_VSA_LENGTH_MASK 0x0000003F
+#define DSI_VID_VSIZE_VSA_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_VSIZE, VSA_LENGTH, __x)
+#define DSI_VID_VSIZE_VBP_LENGTH_SHIFT 6
+#define DSI_VID_VSIZE_VBP_LENGTH_MASK 0x00000FC0
+#define DSI_VID_VSIZE_VBP_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_VSIZE, VBP_LENGTH, __x)
+#define DSI_VID_VSIZE_VFP_LENGTH_SHIFT 12
+#define DSI_VID_VSIZE_VFP_LENGTH_MASK 0x000FF000
+#define DSI_VID_VSIZE_VFP_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_VSIZE, VFP_LENGTH, __x)
+#define DSI_VID_VSIZE_VACT_LENGTH_SHIFT 20
+#define DSI_VID_VSIZE_VACT_LENGTH_MASK 0x7FF00000
+#define DSI_VID_VSIZE_VACT_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_VSIZE, VACT_LENGTH, __x)
+#define DSI_VID_HSIZE1 0x00000098
+#define DSI_VID_HSIZE1_HSA_LENGTH_SHIFT 0
+#define DSI_VID_HSIZE1_HSA_LENGTH_MASK 0x000003FF
+#define DSI_VID_HSIZE1_HSA_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_HSIZE1, HSA_LENGTH, __x)
+#define DSI_VID_HSIZE1_HBP_LENGTH_SHIFT 10
+#define DSI_VID_HSIZE1_HBP_LENGTH_MASK 0x000FFC00
+#define DSI_VID_HSIZE1_HBP_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_HSIZE1, HBP_LENGTH, __x)
+#define DSI_VID_HSIZE1_HFP_LENGTH_SHIFT 20
+#define DSI_VID_HSIZE1_HFP_LENGTH_MASK 0x7FF00000
+#define DSI_VID_HSIZE1_HFP_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_HSIZE1, HFP_LENGTH, __x)
+#define DSI_VID_HSIZE2 0x0000009C
+#define DSI_VID_HSIZE2_RGB_SIZE_SHIFT 0
+#define DSI_VID_HSIZE2_RGB_SIZE_MASK 0x00001FFF
+#define DSI_VID_HSIZE2_RGB_SIZE(__x) \
+ DSI_VAL2REG(DSI_VID_HSIZE2, RGB_SIZE, __x)
+#define DSI_VID_BLKSIZE1 0x000000A0
+#define DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT 0
+#define DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK 0x00001FFF
+#define DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK(__x) \
+ DSI_VAL2REG(DSI_VID_BLKSIZE1, BLKLINE_EVENT_PCK, __x)
+#define DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT 13
+#define DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK 0x03FFE000
+#define DSI_VID_BLKSIZE1_BLKEOL_PCK(__x) \
+ DSI_VAL2REG(DSI_VID_BLKSIZE1, BLKEOL_PCK, __x)
+#define DSI_VID_BLKSIZE2 0x000000A4
+#define DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT 0
+#define DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_MASK 0x00001FFF
+#define DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK(__x) \
+ DSI_VAL2REG(DSI_VID_BLKSIZE2, BLKLINE_PULSE_PCK, __x)
+#define DSI_VID_PCK_TIME 0x000000A8
+#define DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT 0
+#define DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK 0x00001FFF
+#define DSI_VID_PCK_TIME_BLKEOL_DURATION(__x) \
+ DSI_VAL2REG(DSI_VID_PCK_TIME, BLKEOL_DURATION, __x)
+#define DSI_VID_DPHY_TIME 0x000000AC
+#define DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT 0
+#define DSI_VID_DPHY_TIME_REG_LINE_DURATION_MASK 0x00001FFF
+#define DSI_VID_DPHY_TIME_REG_LINE_DURATION(__x) \
+ DSI_VAL2REG(DSI_VID_DPHY_TIME, REG_LINE_DURATION, __x)
+#define DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT 13
+#define DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_MASK 0x00FFE000
+#define DSI_VID_DPHY_TIME_REG_WAKEUP_TIME(__x) \
+ DSI_VAL2REG(DSI_VID_DPHY_TIME, REG_WAKEUP_TIME, __x)
+#define DSI_VID_ERR_COLOR 0x000000B0
+#define DSI_VID_ERR_COLOR_COL_RED_SHIFT 0
+#define DSI_VID_ERR_COLOR_COL_RED_MASK 0x000000FF
+#define DSI_VID_ERR_COLOR_COL_RED(__x) \
+ DSI_VAL2REG(DSI_VID_ERR_COLOR, COL_RED, __x)
+#define DSI_VID_ERR_COLOR_COL_GREEN_SHIFT 8
+#define DSI_VID_ERR_COLOR_COL_GREEN_MASK 0x0000FF00
+#define DSI_VID_ERR_COLOR_COL_GREEN(__x) \
+ DSI_VAL2REG(DSI_VID_ERR_COLOR, COL_GREEN, __x)
+#define DSI_VID_ERR_COLOR_COL_BLUE_SHIFT 16
+#define DSI_VID_ERR_COLOR_COL_BLUE_MASK 0x00FF0000
+#define DSI_VID_ERR_COLOR_COL_BLUE(__x) \
+ DSI_VAL2REG(DSI_VID_ERR_COLOR, COL_BLUE, __x)
+#define DSI_VID_ERR_COLOR_PAD_VAL_SHIFT 24
+#define DSI_VID_ERR_COLOR_PAD_VAL_MASK 0xFF000000
+#define DSI_VID_ERR_COLOR_PAD_VAL(__x) \
+ DSI_VAL2REG(DSI_VID_ERR_COLOR, PAD_VAL, __x)
+#define DSI_VID_VPOS 0x000000B4
+#define DSI_VID_VPOS_LINE_POS_SHIFT 0
+#define DSI_VID_VPOS_LINE_POS_MASK 0x00000003
+#define DSI_VID_VPOS_LINE_POS(__x) \
+ DSI_VAL2REG(DSI_VID_VPOS, LINE_POS, __x)
+#define DSI_VID_VPOS_LINE_VAL_SHIFT 2
+#define DSI_VID_VPOS_LINE_VAL_MASK 0x00001FFC
+#define DSI_VID_VPOS_LINE_VAL(__x) \
+ DSI_VAL2REG(DSI_VID_VPOS, LINE_VAL, __x)
+#define DSI_VID_HPOS 0x000000B8
+#define DSI_VID_HPOS_HORIZONTAL_POS_SHIFT 0
+#define DSI_VID_HPOS_HORIZONTAL_POS_MASK 0x00000007
+#define DSI_VID_HPOS_HORIZONTAL_POS(__x) \
+ DSI_VAL2REG(DSI_VID_HPOS, HORIZONTAL_POS, __x)
+#define DSI_VID_HPOS_HORIZONTAL_VAL_SHIFT 3
+#define DSI_VID_HPOS_HORIZONTAL_VAL_MASK 0x0000FFF8
+#define DSI_VID_HPOS_HORIZONTAL_VAL(__x) \
+ DSI_VAL2REG(DSI_VID_HPOS, HORIZONTAL_VAL, __x)
+#define DSI_VID_MODE_STS 0x000000BC
+#define DSI_VID_MODE_STS_VSG_RUNNING_SHIFT 0
+#define DSI_VID_MODE_STS_VSG_RUNNING_MASK 0x00000001
+#define DSI_VID_MODE_STS_VSG_RUNNING(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, VSG_RUNNING, __x)
+#define DSI_VID_MODE_STS_ERR_MISSING_DATA_SHIFT 1
+#define DSI_VID_MODE_STS_ERR_MISSING_DATA_MASK 0x00000002
+#define DSI_VID_MODE_STS_ERR_MISSING_DATA(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_MISSING_DATA, __x)
+#define DSI_VID_MODE_STS_ERR_MISSING_HSYNC_SHIFT 2
+#define DSI_VID_MODE_STS_ERR_MISSING_HSYNC_MASK 0x00000004
+#define DSI_VID_MODE_STS_ERR_MISSING_HSYNC(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_MISSING_HSYNC, __x)
+#define DSI_VID_MODE_STS_ERR_MISSING_VSYNC_SHIFT 3
+#define DSI_VID_MODE_STS_ERR_MISSING_VSYNC_MASK 0x00000008
+#define DSI_VID_MODE_STS_ERR_MISSING_VSYNC(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_MISSING_VSYNC, __x)
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH_SHIFT 4
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH_MASK 0x00000010
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, REG_ERR_SMALL_LENGTH, __x)
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT_SHIFT 5
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT_MASK 0x00000020
+#define DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, REG_ERR_SMALL_HEIGHT, __x)
+#define DSI_VID_MODE_STS_ERR_BURSTWRITE_SHIFT 6
+#define DSI_VID_MODE_STS_ERR_BURSTWRITE_MASK 0x00000040
+#define DSI_VID_MODE_STS_ERR_BURSTWRITE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_BURSTWRITE, __x)
+#define DSI_VID_MODE_STS_ERR_LONGWRITE_SHIFT 7
+#define DSI_VID_MODE_STS_ERR_LONGWRITE_MASK 0x00000080
+#define DSI_VID_MODE_STS_ERR_LONGWRITE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_LONGWRITE, __x)
+#define DSI_VID_MODE_STS_ERR_LONGREAD_SHIFT 8
+#define DSI_VID_MODE_STS_ERR_LONGREAD_MASK 0x00000100
+#define DSI_VID_MODE_STS_ERR_LONGREAD(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_LONGREAD, __x)
+#define DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH_SHIFT 9
+#define DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH_MASK 0x00000200
+#define DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, ERR_VRS_WRONG_LENGTH, __x)
+#define DSI_VID_MODE_STS_VSG_RECOVERY_SHIFT 10
+#define DSI_VID_MODE_STS_VSG_RECOVERY_MASK 0x00000400
+#define DSI_VID_MODE_STS_VSG_RECOVERY(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS, VSG_RECOVERY, __x)
+#define DSI_VID_VCA_SETTING1 0x000000C0
+#define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT 0
+#define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK 0x0000FFFF
+#define DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT(__x) \
+ DSI_VAL2REG(DSI_VID_VCA_SETTING1, MAX_BURST_LIMIT, __x)
+#define DSI_VID_VCA_SETTING1_BURST_LP_SHIFT 16
+#define DSI_VID_VCA_SETTING1_BURST_LP_MASK 0x00010000
+#define DSI_VID_VCA_SETTING1_BURST_LP(__x) \
+ DSI_VAL2REG(DSI_VID_VCA_SETTING1, BURST_LP, __x)
+#define DSI_VID_VCA_SETTING2 0x000000C4
+#define DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT 0
+#define DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK 0x0000FFFF
+#define DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT(__x) \
+ DSI_VAL2REG(DSI_VID_VCA_SETTING2, EXACT_BURST_LIMIT, __x)
+#define DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT 16
+#define DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK 0xFFFF0000
+#define DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT(__x) \
+ DSI_VAL2REG(DSI_VID_VCA_SETTING2, MAX_LINE_LIMIT, __x)
+#define DSI_TVG_CTL 0x000000C8
+#define DSI_TVG_CTL_TVG_RUN_SHIFT 0
+#define DSI_TVG_CTL_TVG_RUN_MASK 0x00000001
+#define DSI_TVG_CTL_TVG_RUN(__x) \
+ DSI_VAL2REG(DSI_TVG_CTL, TVG_RUN, __x)
+#define DSI_TVG_CTL_TVG_STOPMODE_SHIFT 1
+#define DSI_TVG_CTL_TVG_STOPMODE_MASK 0x00000006
+#define DSI_TVG_CTL_TVG_STOPMODE(__x) \
+ DSI_VAL2REG(DSI_TVG_CTL, TVG_STOPMODE, __x)
+#define DSI_TVG_CTL_TVG_MODE_SHIFT 3
+#define DSI_TVG_CTL_TVG_MODE_MASK 0x00000018
+#define DSI_TVG_CTL_TVG_MODE(__x) \
+ DSI_VAL2REG(DSI_TVG_CTL, TVG_MODE, __x)
+#define DSI_TVG_CTL_TVG_STRIPE_SIZE_SHIFT 5
+#define DSI_TVG_CTL_TVG_STRIPE_SIZE_MASK 0x000000E0
+#define DSI_TVG_CTL_TVG_STRIPE_SIZE(__x) \
+ DSI_VAL2REG(DSI_TVG_CTL, TVG_STRIPE_SIZE, __x)
+#define DSI_TVG_IMG_SIZE 0x000000CC
+#define DSI_TVG_IMG_SIZE_TVG_LINE_SIZE_SHIFT 0
+#define DSI_TVG_IMG_SIZE_TVG_LINE_SIZE_MASK 0x00001FFF
+#define DSI_TVG_IMG_SIZE_TVG_LINE_SIZE(__x) \
+ DSI_VAL2REG(DSI_TVG_IMG_SIZE, TVG_LINE_SIZE, __x)
+#define DSI_TVG_IMG_SIZE_TVG_NBLINE_SHIFT 16
+#define DSI_TVG_IMG_SIZE_TVG_NBLINE_MASK 0x07FF0000
+#define DSI_TVG_IMG_SIZE_TVG_NBLINE(__x) \
+ DSI_VAL2REG(DSI_TVG_IMG_SIZE, TVG_NBLINE, __x)
+#define DSI_TVG_COLOR1 0x000000D0
+#define DSI_TVG_COLOR1_COL1_RED_SHIFT 0
+#define DSI_TVG_COLOR1_COL1_RED_MASK 0x000000FF
+#define DSI_TVG_COLOR1_COL1_RED(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR1, COL1_RED, __x)
+#define DSI_TVG_COLOR1_COL1_GREEN_SHIFT 8
+#define DSI_TVG_COLOR1_COL1_GREEN_MASK 0x0000FF00
+#define DSI_TVG_COLOR1_COL1_GREEN(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR1, COL1_GREEN, __x)
+#define DSI_TVG_COLOR1_COL1_BLUE_SHIFT 16
+#define DSI_TVG_COLOR1_COL1_BLUE_MASK 0x00FF0000
+#define DSI_TVG_COLOR1_COL1_BLUE(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR1, COL1_BLUE, __x)
+#define DSI_TVG_COLOR2 0x000000D4
+#define DSI_TVG_COLOR2_COL2_RED_SHIFT 0
+#define DSI_TVG_COLOR2_COL2_RED_MASK 0x000000FF
+#define DSI_TVG_COLOR2_COL2_RED(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR2, COL2_RED, __x)
+#define DSI_TVG_COLOR2_COL2_GREEN_SHIFT 8
+#define DSI_TVG_COLOR2_COL2_GREEN_MASK 0x0000FF00
+#define DSI_TVG_COLOR2_COL2_GREEN(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR2, COL2_GREEN, __x)
+#define DSI_TVG_COLOR2_COL2_BLUE_SHIFT 16
+#define DSI_TVG_COLOR2_COL2_BLUE_MASK 0x00FF0000
+#define DSI_TVG_COLOR2_COL2_BLUE(__x) \
+ DSI_VAL2REG(DSI_TVG_COLOR2, COL2_BLUE, __x)
+#define DSI_TVG_STS 0x000000D8
+#define DSI_TVG_STS_TVG_RUNNING_SHIFT 0
+#define DSI_TVG_STS_TVG_RUNNING_MASK 0x00000001
+#define DSI_TVG_STS_TVG_RUNNING(__x) \
+ DSI_VAL2REG(DSI_TVG_STS, TVG_RUNNING, __x)
+#define DSI_TBG_CTL 0x000000E0
+#define DSI_TBG_CTL_TBG_START_SHIFT 0
+#define DSI_TBG_CTL_TBG_START_MASK 0x00000001
+#define DSI_TBG_CTL_TBG_START(__x) \
+ DSI_VAL2REG(DSI_TBG_CTL, TBG_START, __x)
+#define DSI_TBG_CTL_TBG_HS_REQ_SHIFT 1
+#define DSI_TBG_CTL_TBG_HS_REQ_MASK 0x00000002
+#define DSI_TBG_CTL_TBG_HS_REQ(__x) \
+ DSI_VAL2REG(DSI_TBG_CTL, TBG_HS_REQ, __x)
+#define DSI_TBG_CTL_TBG_DATA_SEL_SHIFT 2
+#define DSI_TBG_CTL_TBG_DATA_SEL_MASK 0x00000004
+#define DSI_TBG_CTL_TBG_DATA_SEL(__x) \
+ DSI_VAL2REG(DSI_TBG_CTL, TBG_DATA_SEL, __x)
+#define DSI_TBG_CTL_TBG_MODE_SHIFT 3
+#define DSI_TBG_CTL_TBG_MODE_MASK 0x00000018
+#define DSI_TBG_CTL_TBG_MODE_1BYTE 0
+#define DSI_TBG_CTL_TBG_MODE_2BYTE 1
+#define DSI_TBG_CTL_TBG_MODE_BURST_COUNTER 2
+#define DSI_TBG_CTL_TBG_MODE_BURST 3
+#define DSI_TBG_CTL_TBG_MODE_ENUM(__x) \
+ DSI_VAL2REG(DSI_TBG_CTL, TBG_MODE, DSI_TBG_CTL_TBG_MODE_##__x)
+#define DSI_TBG_CTL_TBG_MODE(__x) \
+ DSI_VAL2REG(DSI_TBG_CTL, TBG_MODE, __x)
+#define DSI_TBG_SETTING 0x000000E4
+#define DSI_TBG_SETTING_TBG_DATA_SHIFT 0
+#define DSI_TBG_SETTING_TBG_DATA_MASK 0x0000FFFF
+#define DSI_TBG_SETTING_TBG_DATA(__x) \
+ DSI_VAL2REG(DSI_TBG_SETTING, TBG_DATA, __x)
+#define DSI_TBG_SETTING_TBG_CPT_SHIFT 16
+#define DSI_TBG_SETTING_TBG_CPT_MASK 0x0FFF0000
+#define DSI_TBG_SETTING_TBG_CPT(__x) \
+ DSI_VAL2REG(DSI_TBG_SETTING, TBG_CPT, __x)
+#define DSI_TBG_STS 0x000000E8
+#define DSI_TBG_STS_TBG_STATUS_SHIFT 0
+#define DSI_TBG_STS_TBG_STATUS_MASK 0x00000001
+#define DSI_TBG_STS_TBG_STATUS(__x) \
+ DSI_VAL2REG(DSI_TBG_STS, TBG_STATUS, __x)
+#define DSI_MCTL_MAIN_STS_CTL 0x000000F0
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EN_SHIFT 0
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EN_MASK 0x00000001
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, PLL_LOCK_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EN_SHIFT 1
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EN_MASK 0x00000002
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, CLKLANE_READY_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EN_SHIFT 2
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EN_MASK 0x00000004
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, DAT1_READY_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EN_SHIFT 3
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EN_MASK 0x00000008
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, DAT2_READY_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EN_SHIFT 4
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EN_MASK 0x00000010
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, HSTX_TO_ERR_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EN_SHIFT 5
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EN_MASK 0x00000020
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, LPRX_TO_ERR_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EN_SHIFT 6
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EN_MASK 0x00000040
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, CRS_UNTERM_PCK_ERR_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EN_SHIFT 7
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EN_MASK 0x00000080
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, VRS_UNTERM_PCK_ERR_EN, __x)
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EDGE_SHIFT 16
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EDGE_MASK 0x00010000
+#define DSI_MCTL_MAIN_STS_CTL_PLL_LOCK_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, PLL_LOCK_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EDGE_SHIFT 17
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EDGE_MASK 0x00020000
+#define DSI_MCTL_MAIN_STS_CTL_CLKLANE_READY_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, CLKLANE_READY_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EDGE_SHIFT 18
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EDGE_MASK 0x00040000
+#define DSI_MCTL_MAIN_STS_CTL_DAT1_READY_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, DAT1_READY_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EDGE_SHIFT 19
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EDGE_MASK 0x00080000
+#define DSI_MCTL_MAIN_STS_CTL_DAT2_READY_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, DAT2_READY_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EDGE_SHIFT 20
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EDGE_MASK 0x00100000
+#define DSI_MCTL_MAIN_STS_CTL_HSTX_TO_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, HSTX_TO_ERR_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EDGE_SHIFT 21
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EDGE_MASK 0x00200000
+#define DSI_MCTL_MAIN_STS_CTL_LPRX_TO_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, LPRX_TO_ERR_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EDGE_SHIFT 22
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EDGE_MASK 0x00400000
+#define DSI_MCTL_MAIN_STS_CTL_CRS_UNTERM_PCK_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, CRS_UNTERM_PCK_ERR_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EDGE_SHIFT 23
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EDGE_MASK 0x00800000
+#define DSI_MCTL_MAIN_STS_CTL_VRS_UNTERM_PCK_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CTL, VRS_UNTERM_PCK_ERR_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL 0x000000F4
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN_SHIFT 0
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN_MASK 0x00000001
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_NO_TE_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN_SHIFT 1
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN_MASK 0x00000002
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_TE_MISS_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EN_SHIFT 2
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EN_MASK 0x00000004
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_SDI1_UNDERRUN_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EN_SHIFT 3
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EN_MASK 0x00000008
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_SDI2_UNDERRUN_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EN_SHIFT 4
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EN_MASK 0x00000010
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_UNWANTED_RD_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EN_SHIFT 5
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EN_MASK 0x00000020
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EN(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, CSM_RUNNING_EN, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EDGE_SHIFT 16
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EDGE_MASK 0x00010000
+#define DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_NO_TE_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EDGE_SHIFT 17
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EDGE_MASK 0x00020000
+#define DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_TE_MISS_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EDGE_SHIFT 18
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EDGE_MASK 0x00040000
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI1_UNDERRUN_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_SDI1_UNDERRUN_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EDGE_SHIFT 19
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EDGE_MASK 0x00080000
+#define DSI_CMD_MODE_STS_CTL_ERR_SDI2_UNDERRUN_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_SDI2_UNDERRUN_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EDGE_SHIFT 20
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EDGE_MASK 0x00100000
+#define DSI_CMD_MODE_STS_CTL_ERR_UNWANTED_RD_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, ERR_UNWANTED_RD_EDGE, __x)
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EDGE_SHIFT 21
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EDGE_MASK 0x00200000
+#define DSI_CMD_MODE_STS_CTL_CSM_RUNNING_EDGE(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CTL, CSM_RUNNING_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL 0x000000F8
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EN_SHIFT 0
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EN_MASK 0x00000001
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, CMD_TRANSMISSION_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EN_SHIFT 1
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EN_MASK 0x00000002
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, WRITE_COMPLETED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EN_SHIFT 2
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EN_MASK 0x00000004
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TRIGGER_COMPLETED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EN_SHIFT 3
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EN_MASK 0x00000008
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, READ_COMPLETED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EN_SHIFT 4
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EN_MASK 0x00000010
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, ACKNOWLEDGE_RECEIVED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN_SHIFT 5
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN_MASK 0x00000020
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, ACKNOWLEDGE_WITH_ERR_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EN_SHIFT 6
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EN_MASK 0x00000040
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TRIGGER_RECEIVED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN_SHIFT 7
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN_MASK 0x00000080
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TE_RECEIVED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EN_SHIFT 8
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EN_MASK 0x00000100
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, BTA_COMPLETED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EN_SHIFT 9
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EN_MASK 0x00000200
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, BTA_FINISHED_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EN_SHIFT 10
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EN_MASK 0x00000400
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, READ_COMPLETED_WITH_ERR_EN, __x)
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EDGE_SHIFT 16
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EDGE_MASK 0x00010000
+#define DSI_DIRECT_CMD_STS_CTL_CMD_TRANSMISSION_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, CMD_TRANSMISSION_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EDGE_SHIFT 17
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EDGE_MASK 0x00020000
+#define DSI_DIRECT_CMD_STS_CTL_WRITE_COMPLETED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, WRITE_COMPLETED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EDGE_SHIFT 18
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EDGE_MASK 0x00040000
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_COMPLETED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TRIGGER_COMPLETED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EDGE_SHIFT 19
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EDGE_MASK 0x00080000
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, READ_COMPLETED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EDGE_SHIFT 20
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EDGE_MASK 0x00100000
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_RECEIVED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, ACKNOWLEDGE_RECEIVED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EDGE_SHIFT 21
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EDGE_MASK 0x00200000
+#define DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, ACKNOWLEDGE_WITH_ERR_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EDGE_SHIFT 22
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EDGE_MASK 0x00400000
+#define DSI_DIRECT_CMD_STS_CTL_TRIGGER_RECEIVED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TRIGGER_RECEIVED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EDGE_SHIFT 23
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EDGE_MASK 0x00800000
+#define DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, TE_RECEIVED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EDGE_SHIFT 24
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EDGE_MASK 0x01000000
+#define DSI_DIRECT_CMD_STS_CTL_BTA_COMPLETED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, BTA_COMPLETED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EDGE_SHIFT 25
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EDGE_MASK 0x02000000
+#define DSI_DIRECT_CMD_STS_CTL_BTA_FINISHED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, BTA_FINISHED_EDGE, __x)
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EDGE_SHIFT 26
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EDGE_MASK 0x04000000
+#define DSI_DIRECT_CMD_STS_CTL_READ_COMPLETED_WITH_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CTL, READ_COMPLETED_WITH_ERR_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL 0x000000FC
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EN_SHIFT 0
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EN_MASK 0x00000001
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_FIXED_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EN_SHIFT 1
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EN_MASK 0x00000002
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_UNCORRECTABLE_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EN_SHIFT 2
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EN_MASK 0x00000004
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_CHECKSUM_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EN_SHIFT 3
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EN_MASK 0x00000008
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_UNDECODABLE_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EN_SHIFT 4
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EN_MASK 0x00000010
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_RECEIVE_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EN_SHIFT 5
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EN_MASK 0x00000020
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_OVERSIZE_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EN_SHIFT 6
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EN_MASK 0x00000040
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_WRONG_LENGTH_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EN_SHIFT 7
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EN_MASK 0x00000080
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_MISSING_EOT_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EN_SHIFT 8
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EN_MASK 0x00000100
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EN(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_EOT_WITH_ERR_EN, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EDGE_SHIFT 16
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EDGE_MASK 0x00010000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_FIXED_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_FIXED_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EDGE_SHIFT 17
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EDGE_MASK 0x00020000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNCORRECTABLE_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_UNCORRECTABLE_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EDGE_SHIFT 18
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EDGE_MASK 0x00040000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_CHECKSUM_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_CHECKSUM_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EDGE_SHIFT 19
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EDGE_MASK 0x00080000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_UNDECODABLE_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_UNDECODABLE_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EDGE_SHIFT 20
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EDGE_MASK 0x00100000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_RECEIVE_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_RECEIVE_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EDGE_SHIFT 21
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EDGE_MASK 0x00200000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_OVERSIZE_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_OVERSIZE_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EDGE_SHIFT 22
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EDGE_MASK 0x00400000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_WRONG_LENGTH_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_WRONG_LENGTH_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EDGE_SHIFT 23
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EDGE_MASK 0x00800000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_MISSING_EOT_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_MISSING_EOT_EDGE, __x)
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EDGE_SHIFT 24
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EDGE_MASK 0x01000000
+#define DSI_DIRECT_CMD_RD_STS_CTL_ERR_EOT_WITH_ERR_EDGE(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CTL, ERR_EOT_WITH_ERR_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL 0x00000100
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EN_SHIFT 0
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EN_MASK 0x00000001
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, VSG_RUNNING_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EN_SHIFT 1
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EN_MASK 0x00000002
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_DATA_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EN_SHIFT 2
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EN_MASK 0x00000004
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_HSYNC_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EN_SHIFT 3
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EN_MASK 0x00000008
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_VSYNC_EN, __x)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EN_SHIFT 4
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EN_MASK 0x00000010
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, REG_ERR_SMALL_LENGTH_EN, __x)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EN_SHIFT 5
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EN_MASK 0x00000020
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, REG_ERR_SMALL_HEIGHT_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EN_SHIFT 6
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EN_MASK 0x00000040
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_BURSTWRITE_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EN_SHIFT 7
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EN_MASK 0x00000080
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_LONGWRITE_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EN_SHIFT 8
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EN_MASK 0x00000100
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_LONGREAD_EN, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EN_SHIFT 9
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EN_MASK 0x00000200
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EN(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_VRS_WRONG_LENGTH_EN, __x)
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EDGE_SHIFT 16
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EDGE_MASK 0x00010000
+#define DSI_VID_MODE_STS_CTL_VSG_RUNNING_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, VSG_RUNNING_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EDGE_SHIFT 17
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EDGE_MASK 0x00020000
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_DATA_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EDGE_SHIFT 18
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EDGE_MASK 0x00040000
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_HSYNC_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_HSYNC_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EDGE_SHIFT 19
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EDGE_MASK 0x00080000
+#define DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_MISSING_VSYNC_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EDGE_SHIFT 20
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EDGE_MASK 0x00100000
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_LENGTH_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, REG_ERR_SMALL_LENGTH_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EDGE_SHIFT 21
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EDGE_MASK 0x00200000
+#define DSI_VID_MODE_STS_CTL_REG_ERR_SMALL_HEIGHT_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, REG_ERR_SMALL_HEIGHT_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EDGE_SHIFT 22
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EDGE_MASK 0x00400000
+#define DSI_VID_MODE_STS_CTL_ERR_BURSTWRITE_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_BURSTWRITE_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EDGE_SHIFT 23
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EDGE_MASK 0x00800000
+#define DSI_VID_MODE_STS_CTL_ERR_LONGWRITE_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_LONGWRITE_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EDGE_SHIFT 24
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EDGE_MASK 0x01000000
+#define DSI_VID_MODE_STS_CTL_ERR_LONGREAD_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_LONGREAD_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EDGE_SHIFT 25
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EDGE_MASK 0x02000000
+#define DSI_VID_MODE_STS_CTL_ERR_VRS_WRONG_LENGTH_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, ERR_VRS_WRONG_LENGTH_EDGE, __x)
+#define DSI_VID_MODE_STS_CTL_VSG_RECOVERY_EDGE_SHIFT 26
+#define DSI_VID_MODE_STS_CTL_VSG_RECOVERY_EDGE_MASK 0x04000000
+#define DSI_VID_MODE_STS_CTL_VSG_RECOVERY_EDGE(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CTL, VSG_RECOVERY_EDGE, __x)
+#define DSI_TG_STS_CTL 0x00000104
+#define DSI_TG_STS_CTL_TVG_STS_EN_SHIFT 0
+#define DSI_TG_STS_CTL_TVG_STS_EN_MASK 0x00000001
+#define DSI_TG_STS_CTL_TVG_STS_EN(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CTL, TVG_STS_EN, __x)
+#define DSI_TG_STS_CTL_TBG_STS_EN_SHIFT 1
+#define DSI_TG_STS_CTL_TBG_STS_EN_MASK 0x00000002
+#define DSI_TG_STS_CTL_TBG_STS_EN(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CTL, TBG_STS_EN, __x)
+#define DSI_TG_STS_CTL_TVG_STS_EDGE_SHIFT 16
+#define DSI_TG_STS_CTL_TVG_STS_EDGE_MASK 0x00010000
+#define DSI_TG_STS_CTL_TVG_STS_EDGE(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CTL, TVG_STS_EDGE, __x)
+#define DSI_TG_STS_CTL_TBG_STS_EDGE_SHIFT 17
+#define DSI_TG_STS_CTL_TBG_STS_EDGE_MASK 0x00020000
+#define DSI_TG_STS_CTL_TBG_STS_EDGE(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CTL, TBG_STS_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL 0x00000108
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EN_SHIFT 6
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EN_MASK 0x00000040
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_ESC_1_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EN_SHIFT 7
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EN_MASK 0x00000080
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_ESC_2_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EN_SHIFT 8
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EN_MASK 0x00000100
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_SYNCESC_1_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EN_SHIFT 9
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EN_MASK 0x00000200
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_SYNCESC_2_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EN_SHIFT 10
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EN_MASK 0x00000400
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONTROL_1_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EN_SHIFT 11
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EN_MASK 0x00000800
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONTROL_2_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EN_SHIFT 12
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EN_MASK 0x00001000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP0_1_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EN_SHIFT 13
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EN_MASK 0x00002000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP0_2_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EN_SHIFT 14
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EN_MASK 0x00004000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP1_1_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EN_SHIFT 15
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EN_MASK 0x00008000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EN(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP1_2_EN, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EDGE_SHIFT 22
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EDGE_MASK 0x00400000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_1_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_ESC_1_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EDGE_SHIFT 23
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EDGE_MASK 0x00800000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_ESC_2_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_ESC_2_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EDGE_SHIFT 24
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EDGE_MASK 0x01000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_1_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_SYNCESC_1_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EDGE_SHIFT 25
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EDGE_MASK 0x02000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_SYNCESC_2_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_SYNCESC_2_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EDGE_SHIFT 26
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EDGE_MASK 0x04000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_1_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONTROL_1_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EDGE_SHIFT 27
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EDGE_MASK 0x08000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONTROL_2_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONTROL_2_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EDGE_SHIFT 28
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EDGE_MASK 0x10000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_1_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP0_1_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EDGE_SHIFT 29
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EDGE_MASK 0x20000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP0_2_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP0_2_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EDGE_SHIFT 30
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EDGE_MASK 0x40000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_1_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP1_1_EDGE, __x)
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EDGE_SHIFT 31
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EDGE_MASK 0x80000000
+#define DSI_MCTL_DHPY_ERR_CTL_ERR_CONT_LP1_2_EDGE(__x) \
+ DSI_VAL2REG(DSI_MCTL_DHPY_ERR_CTL, ERR_CONT_LP1_2_EDGE, __x)
+#define DSI_MCTL_MAIN_STS_CLR 0x00000110
+#define DSI_MCTL_MAIN_STS_CLR_PLL_LOCK_CLR_SHIFT 0
+#define DSI_MCTL_MAIN_STS_CLR_PLL_LOCK_CLR_MASK 0x00000001
+#define DSI_MCTL_MAIN_STS_CLR_PLL_LOCK_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, PLL_LOCK_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_CLKLANE_READY_CLR_SHIFT 1
+#define DSI_MCTL_MAIN_STS_CLR_CLKLANE_READY_CLR_MASK 0x00000002
+#define DSI_MCTL_MAIN_STS_CLR_CLKLANE_READY_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, CLKLANE_READY_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_DAT1_READY_CLR_SHIFT 2
+#define DSI_MCTL_MAIN_STS_CLR_DAT1_READY_CLR_MASK 0x00000004
+#define DSI_MCTL_MAIN_STS_CLR_DAT1_READY_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, DAT1_READY_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_DAT2_READY_CLR_SHIFT 3
+#define DSI_MCTL_MAIN_STS_CLR_DAT2_READY_CLR_MASK 0x00000008
+#define DSI_MCTL_MAIN_STS_CLR_DAT2_READY_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, DAT2_READY_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_HSTX_TO_ERR_CLR_SHIFT 4
+#define DSI_MCTL_MAIN_STS_CLR_HSTX_TO_ERR_CLR_MASK 0x00000010
+#define DSI_MCTL_MAIN_STS_CLR_HSTX_TO_ERR_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, HSTX_TO_ERR_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_LPRX_TO_ERR_CLR_SHIFT 5
+#define DSI_MCTL_MAIN_STS_CLR_LPRX_TO_ERR_CLR_MASK 0x00000020
+#define DSI_MCTL_MAIN_STS_CLR_LPRX_TO_ERR_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, LPRX_TO_ERR_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_CRS_UNTERM_PCK_CLR_SHIFT 6
+#define DSI_MCTL_MAIN_STS_CLR_CRS_UNTERM_PCK_CLR_MASK 0x00000040
+#define DSI_MCTL_MAIN_STS_CLR_CRS_UNTERM_PCK_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, CRS_UNTERM_PCK_CLR, __x)
+#define DSI_MCTL_MAIN_STS_CLR_VRS_UNTERM_PCK_CLR_SHIFT 7
+#define DSI_MCTL_MAIN_STS_CLR_VRS_UNTERM_PCK_CLR_MASK 0x00000080
+#define DSI_MCTL_MAIN_STS_CLR_VRS_UNTERM_PCK_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_CLR, VRS_UNTERM_PCK_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR 0x00000114
+#define DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR_SHIFT 0
+#define DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR_MASK 0x00000001
+#define DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, ERR_NO_TE_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR_SHIFT 1
+#define DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR_MASK 0x00000002
+#define DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, ERR_TE_MISS_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI1_UNDERRUN_CLR_SHIFT 2
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI1_UNDERRUN_CLR_MASK 0x00000004
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI1_UNDERRUN_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, ERR_SDI1_UNDERRUN_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI2_UNDERRUN_CLR_SHIFT 3
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI2_UNDERRUN_CLR_MASK 0x00000008
+#define DSI_CMD_MODE_STS_CLR_ERR_SDI2_UNDERRUN_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, ERR_SDI2_UNDERRUN_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR_ERR_UNWANTED_RD_CLR_SHIFT 4
+#define DSI_CMD_MODE_STS_CLR_ERR_UNWANTED_RD_CLR_MASK 0x00000010
+#define DSI_CMD_MODE_STS_CLR_ERR_UNWANTED_RD_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, ERR_UNWANTED_RD_CLR, __x)
+#define DSI_CMD_MODE_STS_CLR_CSM_RUNNING_CLR_SHIFT 5
+#define DSI_CMD_MODE_STS_CLR_CSM_RUNNING_CLR_MASK 0x00000020
+#define DSI_CMD_MODE_STS_CLR_CSM_RUNNING_CLR(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_CLR, CSM_RUNNING_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR 0x00000118
+#define DSI_DIRECT_CMD_STS_CLR_CMD_TRANSMISSION_CLR_SHIFT 0
+#define DSI_DIRECT_CMD_STS_CLR_CMD_TRANSMISSION_CLR_MASK 0x00000001
+#define DSI_DIRECT_CMD_STS_CLR_CMD_TRANSMISSION_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, CMD_TRANSMISSION_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_WRITE_COMPLETED_CLR_SHIFT 1
+#define DSI_DIRECT_CMD_STS_CLR_WRITE_COMPLETED_CLR_MASK 0x00000002
+#define DSI_DIRECT_CMD_STS_CLR_WRITE_COMPLETED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, WRITE_COMPLETED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_COMPLETED_CLR_SHIFT 2
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_COMPLETED_CLR_MASK 0x00000004
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_COMPLETED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, TRIGGER_COMPLETED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_CLR_SHIFT 3
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_CLR_MASK 0x00000008
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, READ_COMPLETED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_RECEIVED_CLR_SHIFT 4
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_RECEIVED_CLR_MASK 0x00000010
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_RECEIVED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, ACKNOWLEDGE_RECEIVED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR_SHIFT 5
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR_MASK 0x00000020
+#define DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_RECEIVED_CLR_SHIFT 6
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_RECEIVED_CLR_MASK 0x00000040
+#define DSI_DIRECT_CMD_STS_CLR_TRIGGER_RECEIVED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, TRIGGER_RECEIVED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR_SHIFT 7
+#define DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR_MASK 0x00000080
+#define DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, TE_RECEIVED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_BTA_COMPLETED_CLR_SHIFT 8
+#define DSI_DIRECT_CMD_STS_CLR_BTA_COMPLETED_CLR_MASK 0x00000100
+#define DSI_DIRECT_CMD_STS_CLR_BTA_COMPLETED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, BTA_COMPLETED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_BTA_FINISHED_CLR_SHIFT 9
+#define DSI_DIRECT_CMD_STS_CLR_BTA_FINISHED_CLR_MASK 0x00000200
+#define DSI_DIRECT_CMD_STS_CLR_BTA_FINISHED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, BTA_FINISHED_CLR, __x)
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_WITH_ERR_CLR_SHIFT 10
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_WITH_ERR_CLR_MASK 0x00000400
+#define DSI_DIRECT_CMD_STS_CLR_READ_COMPLETED_WITH_ERR_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_CLR, READ_COMPLETED_WITH_ERR_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR 0x0000011C
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_FIXED_CLR_SHIFT 0
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_FIXED_CLR_MASK 0x00000001
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_FIXED_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_FIXED_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNCORRECTABLE_CLR_SHIFT 1
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNCORRECTABLE_CLR_MASK 0x00000002
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNCORRECTABLE_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_UNCORRECTABLE_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_CHECKSUM_CLR_SHIFT 2
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_CHECKSUM_CLR_MASK 0x00000004
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_CHECKSUM_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_CHECKSUM_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNDECODABLE_CLR_SHIFT 3
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNDECODABLE_CLR_MASK 0x00000008
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_UNDECODABLE_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_UNDECODABLE_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_RECEIVE_CLR_SHIFT 4
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_RECEIVE_CLR_MASK 0x00000010
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_RECEIVE_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_RECEIVE_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_OVERSIZE_CLR_SHIFT 5
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_OVERSIZE_CLR_MASK 0x00000020
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_OVERSIZE_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_OVERSIZE_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_WRONG_LENGTH_CLR_SHIFT 6
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_WRONG_LENGTH_CLR_MASK 0x00000040
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_WRONG_LENGTH_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_WRONG_LENGTH_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_MISSING_EOT_CLR_SHIFT 7
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_MISSING_EOT_CLR_MASK 0x00000080
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_MISSING_EOT_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_MISSING_EOT_CLR, __x)
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_EOT_WITH_ERR_CLR_SHIFT 8
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_EOT_WITH_ERR_CLR_MASK 0x00000100
+#define DSI_DIRECT_CMD_RD_STS_CLR_ERR_EOT_WITH_ERR_CLR(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_CLR, ERR_EOT_WITH_ERR_CLR, __x)
+#define DSI_VID_MODE_STS_CLR 0x00000120
+#define DSI_VID_MODE_STS_CLR_VSG_STS_CLR_SHIFT 0
+#define DSI_VID_MODE_STS_CLR_VSG_STS_CLR_MASK 0x00000001
+#define DSI_VID_MODE_STS_CLR_VSG_STS_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, VSG_STS_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_DATA_CLR_SHIFT 1
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_DATA_CLR_MASK 0x00000002
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_DATA_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_MISSING_DATA_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_HSYNC_CLR_SHIFT 2
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_HSYNC_CLR_MASK 0x00000004
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_HSYNC_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_MISSING_HSYNC_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_VSYNC_CLR_SHIFT 3
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_VSYNC_CLR_MASK 0x00000008
+#define DSI_VID_MODE_STS_CLR_ERR_MISSING_VSYNC_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_MISSING_VSYNC_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_LENGTH_CLR_SHIFT 4
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_LENGTH_CLR_MASK 0x00000010
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_LENGTH_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, REG_ERR_SMALL_LENGTH_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_HEIGHT_CLR_SHIFT 5
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_HEIGHT_CLR_MASK 0x00000020
+#define DSI_VID_MODE_STS_CLR_REG_ERR_SMALL_HEIGHT_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, REG_ERR_SMALL_HEIGHT_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_BURSTWRITE_CLR_SHIFT 6
+#define DSI_VID_MODE_STS_CLR_ERR_BURSTWRITE_CLR_MASK 0x00000040
+#define DSI_VID_MODE_STS_CLR_ERR_BURSTWRITE_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_BURSTWRITE_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_LONGWRITE_CLR_SHIFT 7
+#define DSI_VID_MODE_STS_CLR_ERR_LONGWRITE_CLR_MASK 0x00000080
+#define DSI_VID_MODE_STS_CLR_ERR_LONGWRITE_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_LONGWRITE_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_LONGREAD_CLR_SHIFT 8
+#define DSI_VID_MODE_STS_CLR_ERR_LONGREAD_CLR_MASK 0x00000100
+#define DSI_VID_MODE_STS_CLR_ERR_LONGREAD_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_LONGREAD_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_ERR_VRS_WRONG_LENGTH_CLR_SHIFT 9
+#define DSI_VID_MODE_STS_CLR_ERR_VRS_WRONG_LENGTH_CLR_MASK 0x00000200
+#define DSI_VID_MODE_STS_CLR_ERR_VRS_WRONG_LENGTH_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, ERR_VRS_WRONG_LENGTH_CLR, __x)
+#define DSI_VID_MODE_STS_CLR_VSG_RECOVERY_CLR_SHIFT 10
+#define DSI_VID_MODE_STS_CLR_VSG_RECOVERY_CLR_MASK 0x00000400
+#define DSI_VID_MODE_STS_CLR_VSG_RECOVERY_CLR(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_CLR, VSG_RECOVERY_CLR, __x)
+#define DSI_TG_STS_CLR 0x00000124
+#define DSI_TG_STS_CLR_TVG_STS_CLR_SHIFT 0
+#define DSI_TG_STS_CLR_TVG_STS_CLR_MASK 0x00000001
+#define DSI_TG_STS_CLR_TVG_STS_CLR(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CLR, TVG_STS_CLR, __x)
+#define DSI_TG_STS_CLR_TBG_STS_CLR_SHIFT 1
+#define DSI_TG_STS_CLR_TBG_STS_CLR_MASK 0x00000002
+#define DSI_TG_STS_CLR_TBG_STS_CLR(__x) \
+ DSI_VAL2REG(DSI_TG_STS_CLR, TBG_STS_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR 0x00000128
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_1_CLR_SHIFT 6
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_1_CLR_MASK 0x00000040
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_1_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_ESC_1_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_2_CLR_SHIFT 7
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_2_CLR_MASK 0x00000080
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_ESC_2_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_ESC_2_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_1_CLR_SHIFT 8
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_1_CLR_MASK 0x00000100
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_1_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_SYNCESC_1_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_2_CLR_SHIFT 9
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_2_CLR_MASK 0x00000200
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_SYNCESC_2_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_SYNCESC_2_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_1_CLR_SHIFT 10
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_1_CLR_MASK 0x00000400
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_1_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONTROL_1_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_2_CLR_SHIFT 11
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_2_CLR_MASK 0x00000800
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONTROL_2_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONTROL_2_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_1_CLR_SHIFT 12
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_1_CLR_MASK 0x00001000
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_1_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONT_LP0_1_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_2_CLR_SHIFT 13
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_2_CLR_MASK 0x00002000
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP0_2_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONT_LP0_2_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_1_CLR_SHIFT 14
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_1_CLR_MASK 0x00004000
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_1_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONT_LP1_1_CLR, __x)
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_2_CLR_SHIFT 15
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_2_CLR_MASK 0x00008000
+#define DSI_MCTL_DPHY_ERR_CLR_ERR_CONT_LP1_2_CLR(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_CLR, ERR_CONT_LP1_2_CLR, __x)
+#define DSI_MCTL_MAIN_STS_FLAG 0x00000130
+#define DSI_MCTL_MAIN_STS_FLAG_PLL_LOCK_FLAG_SHIFT 0
+#define DSI_MCTL_MAIN_STS_FLAG_PLL_LOCK_FLAG_MASK 0x00000001
+#define DSI_MCTL_MAIN_STS_FLAG_PLL_LOCK_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, PLL_LOCK_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_CLKLANE_READY_FLAG_SHIFT 1
+#define DSI_MCTL_MAIN_STS_FLAG_CLKLANE_READY_FLAG_MASK 0x00000002
+#define DSI_MCTL_MAIN_STS_FLAG_CLKLANE_READY_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, CLKLANE_READY_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_DAT1_READY_FLAG_SHIFT 2
+#define DSI_MCTL_MAIN_STS_FLAG_DAT1_READY_FLAG_MASK 0x00000004
+#define DSI_MCTL_MAIN_STS_FLAG_DAT1_READY_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, DAT1_READY_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_DAT2_READY_FLAG_SHIFT 3
+#define DSI_MCTL_MAIN_STS_FLAG_DAT2_READY_FLAG_MASK 0x00000008
+#define DSI_MCTL_MAIN_STS_FLAG_DAT2_READY_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, DAT2_READY_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_HSTX_TO_ERR_FLAG_SHIFT 4
+#define DSI_MCTL_MAIN_STS_FLAG_HSTX_TO_ERR_FLAG_MASK 0x00000010
+#define DSI_MCTL_MAIN_STS_FLAG_HSTX_TO_ERR_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, HSTX_TO_ERR_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_LPRX_TO_ERR_FLAG_SHIFT 5
+#define DSI_MCTL_MAIN_STS_FLAG_LPRX_TO_ERR_FLAG_MASK 0x00000020
+#define DSI_MCTL_MAIN_STS_FLAG_LPRX_TO_ERR_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, LPRX_TO_ERR_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_CRS_UNTERM_PCK_FLAG_SHIFT 6
+#define DSI_MCTL_MAIN_STS_FLAG_CRS_UNTERM_PCK_FLAG_MASK 0x00000040
+#define DSI_MCTL_MAIN_STS_FLAG_CRS_UNTERM_PCK_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, CRS_UNTERM_PCK_FLAG, __x)
+#define DSI_MCTL_MAIN_STS_FLAG_VRS_UNTERM_PCK_FLAG_SHIFT 7
+#define DSI_MCTL_MAIN_STS_FLAG_VRS_UNTERM_PCK_FLAG_MASK 0x00000080
+#define DSI_MCTL_MAIN_STS_FLAG_VRS_UNTERM_PCK_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_MAIN_STS_FLAG, VRS_UNTERM_PCK_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG 0x00000134
+#define DSI_CMD_MODE_STS_FLAG_ERR_NO_TE_FLAG_SHIFT 0
+#define DSI_CMD_MODE_STS_FLAG_ERR_NO_TE_FLAG_MASK 0x00000001
+#define DSI_CMD_MODE_STS_FLAG_ERR_NO_TE_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, ERR_NO_TE_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG_ERR_TE_MISS_FLAG_SHIFT 1
+#define DSI_CMD_MODE_STS_FLAG_ERR_TE_MISS_FLAG_MASK 0x00000002
+#define DSI_CMD_MODE_STS_FLAG_ERR_TE_MISS_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, ERR_TE_MISS_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI1_UNDERRUN_FLAG_SHIFT 2
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI1_UNDERRUN_FLAG_MASK 0x00000004
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI1_UNDERRUN_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, ERR_SDI1_UNDERRUN_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI2_UNDERRUN_FLAG_SHIFT 3
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI2_UNDERRUN_FLAG_MASK 0x00000008
+#define DSI_CMD_MODE_STS_FLAG_ERR_SDI2_UNDERRUN_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, ERR_SDI2_UNDERRUN_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG_ERR_UNWANTED_RD_FLAG_SHIFT 4
+#define DSI_CMD_MODE_STS_FLAG_ERR_UNWANTED_RD_FLAG_MASK 0x00000010
+#define DSI_CMD_MODE_STS_FLAG_ERR_UNWANTED_RD_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, ERR_UNWANTED_RD_FLAG, __x)
+#define DSI_CMD_MODE_STS_FLAG_CSM_RUNNING_FLAG_SHIFT 5
+#define DSI_CMD_MODE_STS_FLAG_CSM_RUNNING_FLAG_MASK 0x00000020
+#define DSI_CMD_MODE_STS_FLAG_CSM_RUNNING_FLAG(__x) \
+ DSI_VAL2REG(DSI_CMD_MODE_STS_FLAG, CSM_RUNNING_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG 0x00000138
+#define DSI_DIRECT_CMD_STS_FLAG_CMD_TRANSMISSION_FLAG_SHIFT 0
+#define DSI_DIRECT_CMD_STS_FLAG_CMD_TRANSMISSION_FLAG_MASK 0x00000001
+#define DSI_DIRECT_CMD_STS_FLAG_CMD_TRANSMISSION_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, CMD_TRANSMISSION_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_WRITE_COMPLETED_FLAG_SHIFT 1
+#define DSI_DIRECT_CMD_STS_FLAG_WRITE_COMPLETED_FLAG_MASK 0x00000002
+#define DSI_DIRECT_CMD_STS_FLAG_WRITE_COMPLETED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, WRITE_COMPLETED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_COMPLETED_FLAG_SHIFT 2
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_COMPLETED_FLAG_MASK 0x00000004
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_COMPLETED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, TRIGGER_COMPLETED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_FLAG_SHIFT 3
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_FLAG_MASK 0x00000008
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, READ_COMPLETED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_RECEIVED_FLAG_SHIFT 4
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_RECEIVED_FLAG_MASK 0x00000010
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_RECEIVED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, ACKNOWLEDGE_RECEIVED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_WITH_ERR_RECEIVED_FLAG_SHIFT 5
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_WITH_ERR_RECEIVED_FLAG_MASK 0x00000020
+#define DSI_DIRECT_CMD_STS_FLAG_ACKNOWLEDGE_WITH_ERR_RECEIVED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, ACKNOWLEDGE_WITH_ERR_RECEIVED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_RECEIVED_FLAG_SHIFT 6
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_RECEIVED_FLAG_MASK 0x00000040
+#define DSI_DIRECT_CMD_STS_FLAG_TRIGGER_RECEIVED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, TRIGGER_RECEIVED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_TE_RECEIVED_FLAG_SHIFT 7
+#define DSI_DIRECT_CMD_STS_FLAG_TE_RECEIVED_FLAG_MASK 0x00000080
+#define DSI_DIRECT_CMD_STS_FLAG_TE_RECEIVED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, TE_RECEIVED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_COMPLETED_FLAG_SHIFT 8
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_COMPLETED_FLAG_MASK 0x00000100
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_COMPLETED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, BTA_COMPLETED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_FINISHED_FLAG_SHIFT 9
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_FINISHED_FLAG_MASK 0x00000200
+#define DSI_DIRECT_CMD_STS_FLAG_BTA_FINISHED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, BTA_FINISHED_FLAG, __x)
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_WITH_ERR_FLAG_SHIFT 10
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_WITH_ERR_FLAG_MASK 0x00000400
+#define DSI_DIRECT_CMD_STS_FLAG_READ_COMPLETED_WITH_ERR_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_STS_FLAG, READ_COMPLETED_WITH_ERR_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG 0x0000013C
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_FIXED_FLAG_SHIFT 0
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_FIXED_FLAG_MASK 0x00000001
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_FIXED_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_FIXED_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNCORRECTABLE_FLAG_SHIFT 1
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNCORRECTABLE_FLAG_MASK 0x00000002
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNCORRECTABLE_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_UNCORRECTABLE_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_CHECKSUM_FLAG_SHIFT 2
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_CHECKSUM_FLAG_MASK 0x00000004
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_CHECKSUM_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_CHECKSUM_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNDECODABLE_FLAG_SHIFT 3
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNDECODABLE_FLAG_MASK 0x00000008
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_UNDECODABLE_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_UNDECODABLE_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_RECEIVE_FLAG_SHIFT 4
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_RECEIVE_FLAG_MASK 0x00000010
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_RECEIVE_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_RECEIVE_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_OVERSIZE_FLAG_SHIFT 5
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_OVERSIZE_FLAG_MASK 0x00000020
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_OVERSIZE_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_OVERSIZE_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_WRONG_LENGTH_FLAG_SHIFT 6
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_WRONG_LENGTH_FLAG_MASK 0x00000040
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_WRONG_LENGTH_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_WRONG_LENGTH_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_MISSING_EOT_FLAG_SHIFT 7
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_MISSING_EOT_FLAG_MASK 0x00000080
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_MISSING_EOT_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_MISSING_EOT_FLAG, __x)
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_EOT_WITH_ERR_FLAG_SHIFT 8
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_EOT_WITH_ERR_FLAG_MASK 0x00000100
+#define DSI_DIRECT_CMD_RD_STS_FLAG_ERR_EOT_WITH_ERR_FLAG(__x) \
+ DSI_VAL2REG(DSI_DIRECT_CMD_RD_STS_FLAG, ERR_EOT_WITH_ERR_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG 0x00000140
+#define DSI_VID_MODE_STS_FLAG_VSG_STS_FLAG_SHIFT 0
+#define DSI_VID_MODE_STS_FLAG_VSG_STS_FLAG_MASK 0x00000001
+#define DSI_VID_MODE_STS_FLAG_VSG_STS_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, VSG_STS_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_DATA_FLAG_SHIFT 1
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_DATA_FLAG_MASK 0x00000002
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_DATA_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_MISSING_DATA_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_HSYNC_FLAG_SHIFT 2
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_HSYNC_FLAG_MASK 0x00000004
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_HSYNC_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_MISSING_HSYNC_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_VSYNC_FLAG_SHIFT 3
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_VSYNC_FLAG_MASK 0x00000008
+#define DSI_VID_MODE_STS_FLAG_ERR_MISSING_VSYNC_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_MISSING_VSYNC_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_LENGTH_FLAG_SHIFT 4
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_LENGTH_FLAG_MASK 0x00000010
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_LENGTH_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, REG_ERR_SMALL_LENGTH_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_HEIGHT_FLAG_SHIFT 5
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_HEIGHT_FLAG_MASK 0x00000020
+#define DSI_VID_MODE_STS_FLAG_REG_ERR_SMALL_HEIGHT_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, REG_ERR_SMALL_HEIGHT_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_BURSTWRITE_FLAG_SHIFT 6
+#define DSI_VID_MODE_STS_FLAG_ERR_BURSTWRITE_FLAG_MASK 0x00000040
+#define DSI_VID_MODE_STS_FLAG_ERR_BURSTWRITE_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_BURSTWRITE_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGWRITE_FLAG_SHIFT 7
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGWRITE_FLAG_MASK 0x00000080
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGWRITE_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_LONGWRITE_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGREAD_FLAG_SHIFT 8
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGREAD_FLAG_MASK 0x00000100
+#define DSI_VID_MODE_STS_FLAG_ERR_LONGREAD_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_LONGREAD_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_ERR_VRS_WRONG_LENGTH_FLAG_SHIFT 9
+#define DSI_VID_MODE_STS_FLAG_ERR_VRS_WRONG_LENGTH_FLAG_MASK 0x00000200
+#define DSI_VID_MODE_STS_FLAG_ERR_VRS_WRONG_LENGTH_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, ERR_VRS_WRONG_LENGTH_FLAG, __x)
+#define DSI_VID_MODE_STS_FLAG_VSG_RECOVERY_FLAG_SHIFT 10
+#define DSI_VID_MODE_STS_FLAG_VSG_RECOVERY_FLAG_MASK 0x00000400
+#define DSI_VID_MODE_STS_FLAG_VSG_RECOVERY_FLAG(__x) \
+ DSI_VAL2REG(DSI_VID_MODE_STS_FLAG, VSG_RECOVERY_FLAG, __x)
+#define DSI_TG_STS_FLAG 0x00000144
+#define DSI_TG_STS_FLAG_TVG_STS_FLAG_SHIFT 0
+#define DSI_TG_STS_FLAG_TVG_STS_FLAG_MASK 0x00000001
+#define DSI_TG_STS_FLAG_TVG_STS_FLAG(__x) \
+ DSI_VAL2REG(DSI_TG_STS_FLAG, TVG_STS_FLAG, __x)
+#define DSI_TG_STS_FLAG_TBG_STS_FLAG_SHIFT 1
+#define DSI_TG_STS_FLAG_TBG_STS_FLAG_MASK 0x00000002
+#define DSI_TG_STS_FLAG_TBG_STS_FLAG(__x) \
+ DSI_VAL2REG(DSI_TG_STS_FLAG, TBG_STS_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG 0x00000148
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_1_FLAG_SHIFT 6
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_1_FLAG_MASK 0x00000040
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_1_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_ESC_1_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_2_FLAG_SHIFT 7
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_2_FLAG_MASK 0x00000080
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_ESC_2_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_ESC_2_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_1_FLAG_SHIFT 8
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_1_FLAG_MASK 0x00000100
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_1_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_SYNCESC_1_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_2_FLAG_SHIFT 9
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_2_FLAG_MASK 0x00000200
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_SYNCESC_2_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_SYNCESC_2_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_1_FLAG_SHIFT 10
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_1_FLAG_MASK 0x00000400
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_1_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONTROL_1_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_2_FLAG_SHIFT 11
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_2_FLAG_MASK 0x00000800
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONTROL_2_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONTROL_2_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_1_FLAG_SHIFT 12
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_1_FLAG_MASK 0x00001000
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_1_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONT_LP0_1_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_2_FLAG_SHIFT 13
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_2_FLAG_MASK 0x00002000
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP0_2_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONT_LP0_2_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_1_FLAG_SHIFT 14
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_1_FLAG_MASK 0x00004000
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_1_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONT_LP1_1_FLAG, __x)
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_2_FLAG_SHIFT 15
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_2_FLAG_MASK 0x00008000
+#define DSI_MCTL_DPHY_ERR_FLAG_ERR_CONT_LP1_2_FLAG(__x) \
+ DSI_VAL2REG(DSI_MCTL_DPHY_ERR_FLAG, ERR_CONT_LP1_2_FLAG, __x)
+#define DSI_DPHY_LANES_TRIM 0x00000150
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT1_SHIFT 0
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT1_MASK 0x00000003
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT1(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_SKEW_DAT1, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_CD_OFF_DAT1_SHIFT 2
+#define DSI_DPHY_LANES_TRIM_DPHY_CD_OFF_DAT1_MASK 0x00000004
+#define DSI_DPHY_LANES_TRIM_DPHY_CD_OFF_DAT1(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_CD_OFF_DAT1, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT1_SHIFT 3
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT1_MASK 0x00000008
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT1(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_UP_DAT1, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT1_SHIFT 4
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT1_MASK 0x00000010
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT1(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_DOWN_DAT1, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT1_SHIFT 5
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT1_MASK 0x00000020
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT1(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_TEST_RESERVED_1_DAT1, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_CLK_SHIFT 6
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_CLK_MASK 0x000000C0
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_SKEW_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_RX_VIL_CLK_SHIFT 8
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_RX_VIL_CLK_MASK 0x00000300
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_RX_VIL_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_LP_RX_VIL_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_TX_SLEWRATE_CLK_SHIFT 10
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_TX_SLEWRATE_CLK_MASK 0x00000C00
+#define DSI_DPHY_LANES_TRIM_DPHY_LP_TX_SLEWRATE_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_LP_TX_SLEWRATE_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_SHIFT 12
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_MASK 0x00001000
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_81 0
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_90 1
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_ENUM(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_SPECS_90_81B, \
+ DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_##__x)
+#define DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_SPECS_90_81B, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_CLK_SHIFT 13
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_CLK_MASK 0x00002000
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_UP_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_CLK_SHIFT 14
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_CLK_MASK 0x00004000
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_DOWN_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_CLK_SHIFT 15
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_CLK_MASK 0x00008000
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_CLK(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_TEST_RESERVED_1_CLK, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT2_SHIFT 16
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT2_MASK 0x00030000
+#define DSI_DPHY_LANES_TRIM_DPHY_SKEW_DAT2(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_SKEW_DAT2, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT2_SHIFT 18
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT2_MASK 0x00040000
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_UP_DAT2(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_UP_DAT2, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT2_SHIFT 19
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT2_MASK 0x00080000
+#define DSI_DPHY_LANES_TRIM_DPHY_HSTX_SLEWRATE_DOWN_DAT2(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_HSTX_SLEWRATE_DOWN_DAT2, __x)
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT2_SHIFT 20
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT2_MASK 0x00100000
+#define DSI_DPHY_LANES_TRIM_DPHY_TEST_RESERVED_1_DAT2(__x) \
+ DSI_VAL2REG(DSI_DPHY_LANES_TRIM, DPHY_TEST_RESERVED_1_DAT2, __x)
+#define DSI_ID_REG 0x00000FF0
+#define DSI_ID_REG_Y_SHIFT 0
+#define DSI_ID_REG_Y_MASK 0x0000000F
+#define DSI_ID_REG_Y(__x) \
+ DSI_VAL2REG(DSI_ID_REG, Y, __x)
+#define DSI_ID_REG_X_SHIFT 4
+#define DSI_ID_REG_X_MASK 0x000000F0
+#define DSI_ID_REG_X(__x) \
+ DSI_VAL2REG(DSI_ID_REG, X, __x)
+#define DSI_ID_REG_H_SHIFT 8
+#define DSI_ID_REG_H_MASK 0x00000300
+#define DSI_ID_REG_H(__x) \
+ DSI_VAL2REG(DSI_ID_REG, H, __x)
+#define DSI_ID_REG_PRODUCT_ID_SHIFT 10
+#define DSI_ID_REG_PRODUCT_ID_MASK 0x0003FC00
+#define DSI_ID_REG_PRODUCT_ID(__x) \
+ DSI_VAL2REG(DSI_ID_REG, PRODUCT_ID, __x)
+#define DSI_ID_REG_VENDOR_ID_SHIFT 18
+#define DSI_ID_REG_VENDOR_ID_MASK 0xFFFC0000
+#define DSI_ID_REG_VENDOR_ID(__x) \
+ DSI_VAL2REG(DSI_ID_REG, VENDOR_ID, __x)
+#define DSI_IP_CONF 0x00000FF4
+#define DSI_IP_CONF_FIFO_SIZE_SHIFT 0
+#define DSI_IP_CONF_FIFO_SIZE_MASK 0x0000003F
+#define DSI_IP_CONF_FIFO_SIZE(__x) \
+ DSI_VAL2REG(DSI_IP_CONF, FIFO_SIZE, __x)
diff --git a/drivers/video/mcde/mcde_bus.c b/drivers/video/mcde/mcde_bus.c
new file mode 100644
index 00000000000..bdcf65b0fb9
--- /dev/null
+++ b/drivers/video/mcde/mcde_bus.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson MCDE display bus driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/notifier.h>
+
+#include <video/mcde_display.h>
+#include <video/mcde_dss.h>
+
+#define to_mcde_display_driver(__drv) \
+ container_of((__drv), struct mcde_display_driver, driver)
+
+static BLOCKING_NOTIFIER_HEAD(bus_notifier_list);
+
+static int mcde_drv_suspend(struct device *_dev, pm_message_t state);
+static int mcde_drv_resume(struct device *_dev);
+struct bus_type mcde_bus_type;
+
+static int mcde_suspend_device(struct device *dev, void *data)
+{
+ pm_message_t* state = (pm_message_t *) data;
+ if (dev->driver && dev->driver->suspend)
+ return dev->driver->suspend(dev, *state);
+ return 0;
+}
+
+static int mcde_resume_device(struct device *dev, void *data)
+{
+ if (dev->driver && dev->driver->resume)
+ return dev->driver->resume(dev);
+ return 0;
+}
+
+/* Bus driver */
+
+static int mcde_bus_match(struct device *_dev, struct device_driver *driver)
+{
+ pr_debug("Matching device %s with driver %s\n",
+ dev_name(_dev), driver->name);
+
+ return strncmp(dev_name(_dev), driver->name, strlen(driver->name)) == 0;
+}
+
+static int mcde_bus_suspend(struct device *_dev, pm_message_t state)
+{
+ int ret;
+ ret = bus_for_each_dev(&mcde_bus_type, NULL, &state,
+ mcde_suspend_device);
+ if (ret) {
+ /* TODO Resume all suspended devices */
+ /* mcde_bus_resume(dev); */
+ return ret;
+ }
+ return 0;
+}
+
+static int mcde_bus_resume(struct device *_dev)
+{
+ return bus_for_each_dev(&mcde_bus_type, NULL, NULL, mcde_resume_device);
+}
+
+struct bus_type mcde_bus_type = {
+ .name = "mcde_bus",
+ .match = mcde_bus_match,
+ .suspend = mcde_bus_suspend,
+ .resume = mcde_bus_resume,
+};
+
+static int mcde_drv_probe(struct device *_dev)
+{
+ struct mcde_display_driver *drv = to_mcde_display_driver(_dev->driver);
+ struct mcde_display_device *dev = to_mcde_display_device(_dev);
+
+ return drv->probe(dev);
+}
+
+static int mcde_drv_remove(struct device *_dev)
+{
+ struct mcde_display_driver *drv = to_mcde_display_driver(_dev->driver);
+ struct mcde_display_device *dev = to_mcde_display_device(_dev);
+
+ return drv->remove(dev);
+}
+
+static void mcde_drv_shutdown(struct device *_dev)
+{
+ struct mcde_display_driver *drv = to_mcde_display_driver(_dev->driver);
+ struct mcde_display_device *dev = to_mcde_display_device(_dev);
+
+ drv->shutdown(dev);
+}
+
+static int mcde_drv_suspend(struct device *_dev, pm_message_t state)
+{
+ struct mcde_display_driver *drv = to_mcde_display_driver(_dev->driver);
+ struct mcde_display_device *dev = to_mcde_display_device(_dev);
+
+ if (drv->suspend)
+ return drv->suspend(dev, state);
+ else
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ return dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF);
+#else
+ return 0;
+#endif
+}
+
+static int mcde_drv_resume(struct device *_dev)
+{
+ struct mcde_display_driver *drv = to_mcde_display_driver(_dev->driver);
+ struct mcde_display_device *dev = to_mcde_display_device(_dev);
+
+ if (drv->resume)
+ return drv->resume(dev);
+ else
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ return dev->set_power_mode(dev, MCDE_DISPLAY_PM_STANDBY);
+#else
+ return 0;
+#endif
+}
+
+/* Bus device */
+
+static void mcde_bus_release(struct device *dev)
+{
+}
+
+struct device mcde_bus = {
+ .init_name = "mcde_bus",
+ .release = mcde_bus_release
+};
+
+/* Public bus API */
+
+int mcde_display_driver_register(struct mcde_display_driver *drv)
+{
+ drv->driver.bus = &mcde_bus_type;
+ if (drv->probe)
+ drv->driver.probe = mcde_drv_probe;
+ if (drv->remove)
+ drv->driver.remove = mcde_drv_remove;
+ if (drv->shutdown)
+ drv->driver.shutdown = mcde_drv_shutdown;
+ drv->driver.suspend = mcde_drv_suspend;
+ drv->driver.resume = mcde_drv_resume;
+
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(mcde_display_driver_register);
+
+void mcde_display_driver_unregister(struct mcde_display_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(mcde_display_driver_unregister);
+
+static void mcde_display_dev_release(struct device *dev)
+{
+ /* Do nothing */
+}
+
+int mcde_display_device_register(struct mcde_display_device *dev)
+{
+ /* Setup device */
+ if (!dev)
+ return -EINVAL;
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ dev->dev.bus = &mcde_bus_type;
+ if (dev->dev.parent != NULL)
+ dev->dev.parent = &mcde_bus;
+ dev->dev.release = mcde_display_dev_release;
+ if (dev->id != -1)
+ dev_set_name(&dev->dev, "%s.%d", dev->name, dev->id);
+ else
+ dev_set_name(&dev->dev, dev->name);
+
+ mcde_display_init_device(dev);
+
+ return device_register(&dev->dev);
+}
+EXPORT_SYMBOL(mcde_display_device_register);
+
+void mcde_display_device_unregister(struct mcde_display_device *dev)
+{
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(mcde_display_device_unregister);
+
+/* Notifications */
+int mcde_dss_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&bus_notifier_list, nb);
+}
+EXPORT_SYMBOL(mcde_dss_register_notifier);
+
+int mcde_dss_unregister_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&bus_notifier_list, nb);
+}
+EXPORT_SYMBOL(mcde_dss_unregister_notifier);
+
+static int bus_notify_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+
+ if (event == BUS_NOTIFY_BOUND_DRIVER) {
+ ddev->initialized = true;
+ blocking_notifier_call_chain(&bus_notifier_list,
+ MCDE_DSS_EVENT_DISPLAY_REGISTERED, ddev);
+ } else if (event == BUS_NOTIFY_UNBIND_DRIVER) {
+ ddev->initialized = false;
+ blocking_notifier_call_chain(&bus_notifier_list,
+ MCDE_DSS_EVENT_DISPLAY_UNREGISTERED, ddev);
+ }
+ return 0;
+}
+
+struct notifier_block bus_nb = {
+ .notifier_call = bus_notify_callback,
+};
+
+/* Driver init/exit */
+
+int __init mcde_display_init(void)
+{
+ int ret;
+
+ ret = bus_register(&mcde_bus_type);
+ if (ret) {
+ pr_warning("Unable to register bus type\n");
+ goto no_bus_registration;
+ }
+ ret = device_register(&mcde_bus);
+ if (ret) {
+ pr_warning("Unable to register bus device\n");
+ goto no_device_registration;
+ }
+ ret = bus_register_notifier(&mcde_bus_type, &bus_nb);
+ if (ret) {
+ pr_warning("Unable to register bus notifier\n");
+ goto no_bus_notifier;
+ }
+
+ goto out;
+
+no_bus_notifier:
+ device_unregister(&mcde_bus);
+no_device_registration:
+ bus_unregister(&mcde_bus_type);
+no_bus_registration:
+out:
+ return ret;
+}
+
+void mcde_display_exit(void)
+{
+ bus_unregister_notifier(&mcde_bus_type, &bus_nb);
+ device_unregister(&mcde_bus);
+ bus_unregister(&mcde_bus_type);
+}
diff --git a/drivers/video/mcde/mcde_debugfs.c b/drivers/video/mcde/mcde_debugfs.c
new file mode 100644
index 00000000000..586b1787d00
--- /dev/null
+++ b/drivers/video/mcde/mcde_debugfs.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE base driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/stat.h>
+#include <linux/time.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <asm/page.h>
+
+#include "mcde_debugfs.h"
+
+#define MAX_NUM_OVERLAYS 2
+#define MAX_NUM_CHANNELS 4
+#define DEFAULT_DMESG_FPS_LOG_INTERVAL 100
+
+struct fps_info {
+ u32 enable_dmesg;
+ u32 interval_ms;
+ struct timespec timestamp_last;
+ u32 frame_counter_last;
+ u32 frame_counter;
+ u32 fpks;
+};
+
+struct overlay_info {
+ u8 id;
+ struct dentry *dentry;
+ struct fps_info fps;
+};
+
+struct channel_info {
+ u8 id;
+ struct dentry *dentry;
+ struct mcde_chnl_state *chnl;
+ struct fps_info fps;
+ struct overlay_info overlays[MAX_NUM_OVERLAYS];
+};
+
+static struct mcde_info {
+ struct device *dev;
+ struct dentry *dentry;
+ struct channel_info channels[MAX_NUM_CHANNELS];
+} mcde;
+
+/* Requires: lhs > rhs */
+static inline u32 timespec_ms_diff(struct timespec lhs, struct timespec rhs)
+{
+ struct timespec tmp_ts = timespec_sub(lhs, rhs);
+ u64 tmp_ns = (u64)timespec_to_ns(&tmp_ts);
+ do_div(tmp_ns, NSEC_PER_MSEC);
+ return (u32)tmp_ns;
+}
+
+/* Returns "frames per 1000 secs", divide by 1000 to get fps with 3 decimals */
+static u32 update_fps(struct fps_info *fps)
+{
+ struct timespec now;
+ u32 fpks = 0, ms_since_last, num_frames;
+
+ getrawmonotonic(&now);
+ fps->frame_counter++;
+
+ ms_since_last = timespec_ms_diff(now, fps->timestamp_last);
+ num_frames = fps->frame_counter - fps->frame_counter_last;
+ if (num_frames > 1 && ms_since_last >= fps->interval_ms) {
+ fpks = (num_frames * 1000000) / ms_since_last;
+ fps->timestamp_last = now;
+ fps->frame_counter_last = fps->frame_counter;
+ fps->fpks = fpks;
+ }
+
+ return fpks;
+}
+
+static void update_chnl_fps(struct channel_info *ci)
+{
+ u32 fpks = update_fps(&ci->fps);
+ if (fpks && ci->fps.enable_dmesg)
+ dev_info(mcde.dev, "FPS: chnl=%d fps=%d.%.3d\n", ci->id,
+ fpks / 1000, fpks % 1000);
+}
+
+static void update_ovly_fps(struct channel_info *ci, struct overlay_info *oi)
+{
+ u32 fpks = update_fps(&oi->fps);
+ if (fpks && oi->fps.enable_dmesg)
+ dev_info(mcde.dev, "FPS: ovly=%d.%d fps=%d.%.3d\n", ci->id,
+ oi->id, fpks / 1000, fpks % 1000);
+}
+
+int mcde_debugfs_create(struct device *dev)
+{
+ if (mcde.dev)
+ return -EBUSY;
+
+ mcde.dentry = debugfs_create_dir("mcde", NULL);
+ if (!mcde.dentry)
+ return -ENOMEM;
+ mcde.dev = dev;
+
+ return 0;
+}
+
+static struct channel_info *find_chnl(u8 chnl_id)
+{
+ if (chnl_id > MAX_NUM_CHANNELS)
+ return NULL;
+ return &mcde.channels[chnl_id];
+}
+
+static struct overlay_info *find_ovly(struct channel_info *ci, u8 ovly_id)
+{
+ if (!ci || ovly_id >= MAX_NUM_OVERLAYS)
+ return NULL;
+ return &ci->overlays[ovly_id];
+}
+
+static void create_fps_files(struct dentry *dentry, struct fps_info *fps)
+{
+ debugfs_create_u32("frame_counter", S_IRUGO, dentry,
+ &fps->frame_counter);
+ debugfs_create_u32("frames_per_ksecs", S_IRUGO, dentry, &fps->fpks);
+ debugfs_create_u32("interval_ms", S_IRUGO|S_IWUGO, dentry,
+ &fps->interval_ms);
+ debugfs_create_u32("dmesg", S_IRUGO|S_IWUGO, dentry,
+ &fps->enable_dmesg);
+}
+
+int mcde_debugfs_channel_create(u8 chnl_id, struct mcde_chnl_state *chnl)
+{
+ struct channel_info *ci = find_chnl(chnl_id);
+ char name[10];
+
+ if (!chnl || !ci)
+ return -EINVAL;
+ if (ci->chnl)
+ return -EBUSY;
+
+ snprintf(name, sizeof(name), "chnl%d", chnl_id);
+ ci->dentry = debugfs_create_dir(name, mcde.dentry);
+ if (!ci->dentry)
+ return -ENOMEM;
+
+ create_fps_files(ci->dentry, &ci->fps);
+
+ ci->fps.interval_ms = DEFAULT_DMESG_FPS_LOG_INTERVAL;
+ ci->id = chnl_id;
+ ci->chnl = chnl;
+
+ return 0;
+}
+
+int mcde_debugfs_overlay_create(u8 chnl_id, u8 ovly_id)
+{
+ struct channel_info *ci = find_chnl(chnl_id);
+ struct overlay_info *oi = find_ovly(ci, ovly_id);
+ char name[10];
+
+ if (!oi || !ci || ovly_id >= MAX_NUM_OVERLAYS)
+ return -EINVAL;
+ if (oi->dentry)
+ return -EBUSY;
+
+ snprintf(name, sizeof(name), "ovly%d", ovly_id);
+ oi->dentry = debugfs_create_dir(name, ci->dentry);
+ if (!oi->dentry)
+ return -ENOMEM;
+
+ create_fps_files(oi->dentry, &oi->fps);
+
+ oi->fps.interval_ms = DEFAULT_DMESG_FPS_LOG_INTERVAL;
+ oi->id = ovly_id;
+
+ return 0;
+}
+
+void mcde_debugfs_channel_update(u8 chnl_id)
+{
+ struct channel_info *ci = find_chnl(chnl_id);
+
+ if (!ci || !ci->chnl)
+ return;
+
+ update_chnl_fps(ci);
+}
+
+void mcde_debugfs_overlay_update(u8 chnl_id, u8 ovly_id)
+{
+ struct channel_info *ci = find_chnl(chnl_id);
+ struct overlay_info *oi = find_ovly(ci, ovly_id);
+
+ if (!oi || !oi->dentry)
+ return;
+
+ update_ovly_fps(ci, oi);
+}
+
diff --git a/drivers/video/mcde/mcde_debugfs.h b/drivers/video/mcde/mcde_debugfs.h
new file mode 100644
index 00000000000..9f1e7f18ea5
--- /dev/null
+++ b/drivers/video/mcde/mcde_debugfs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE base driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __MCDE_DEBUGFS__H__
+#define __MCDE_DEBUGFS__H__
+
+#include <video/mcde.h>
+
+int mcde_debugfs_create(struct device *dev);
+int mcde_debugfs_channel_create(u8 chnl_id, struct mcde_chnl_state *chnl);
+int mcde_debugfs_overlay_create(u8 chnl_id, u8 ovly_id);
+
+void mcde_debugfs_channel_update(u8 chnl_id);
+void mcde_debugfs_overlay_update(u8 chnl_id, u8 ovly_id);
+
+#endif /* __MCDE_DEBUGFS__H__ */
+
diff --git a/drivers/video/mcde/mcde_display.c b/drivers/video/mcde/mcde_display.c
new file mode 100644
index 00000000000..9e9eb78516e
--- /dev/null
+++ b/drivers/video/mcde/mcde_display.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include <video/mcde_display.h>
+
+/*temp*/
+#include <linux/delay.h>
+
+static void mcde_display_get_native_resolution_default(
+ struct mcde_display_device *ddev, u16 *x_res, u16 *y_res)
+{
+ if (x_res)
+ *x_res = ddev->native_x_res;
+ if (y_res)
+ *y_res = ddev->native_y_res;
+}
+
+static enum mcde_ovly_pix_fmt mcde_display_get_default_pixel_format_default(
+ struct mcde_display_device *ddev)
+{
+ return ddev->default_pixel_format;
+}
+
+static void mcde_display_get_physical_size_default(
+ struct mcde_display_device *ddev, u16 *width, u16 *height)
+{
+ if (width)
+ *width = ddev->physical_width;
+ if (height)
+ *height = ddev->physical_height;
+}
+
+static int mcde_display_set_power_mode_default(struct mcde_display_device *ddev,
+ enum mcde_display_power_mode power_mode)
+{
+ int ret = 0;
+
+ /* OFF -> STANDBY */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_OFF &&
+ power_mode != MCDE_DISPLAY_PM_OFF) {
+ if (ddev->platform_enable) {
+ ret = ddev->platform_enable(ddev);
+ if (ret)
+ return ret;
+ }
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ /* force register settings */
+ if (ddev->port->type == MCDE_PORTTYPE_DPI)
+ ddev->update_flags = UPDATE_FLAG_VIDEO_MODE | UPDATE_FLAG_PIXEL_FORMAT;
+ }
+
+ if (ddev->port->type == MCDE_PORTTYPE_DSI) {
+ /* STANDBY -> ON */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_ON) {
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_EXIT_SLEEP_MODE, NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_DISPLAY_ON, NULL, 0);
+ if (ret)
+ return ret;
+
+ ddev->power_mode = MCDE_DISPLAY_PM_ON;
+ } else if (ddev->power_mode == MCDE_DISPLAY_PM_ON &&
+ power_mode <= MCDE_DISPLAY_PM_STANDBY) {
+ /* ON -> STANDBY */
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_SET_DISPLAY_OFF, NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = mcde_dsi_dcs_write(ddev->chnl_state,
+ DCS_CMD_ENTER_SLEEP_MODE, NULL, 0);
+ if (ret)
+ return ret;
+
+ ddev->power_mode = MCDE_DISPLAY_PM_STANDBY;
+ }
+ } else if (ddev->port->type == MCDE_PORTTYPE_DPI) {
+ ddev->power_mode = power_mode;
+ } else if (ddev->power_mode != power_mode) {
+ return -EINVAL;
+ }
+
+ /* SLEEP -> OFF */
+ if (ddev->power_mode == MCDE_DISPLAY_PM_STANDBY &&
+ power_mode == MCDE_DISPLAY_PM_OFF) {
+ if (ddev->platform_disable) {
+ ret = ddev->platform_disable(ddev);
+ if (ret)
+ return ret;
+ }
+ ddev->power_mode = MCDE_DISPLAY_PM_OFF;
+ }
+
+ mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode);
+
+ return ret;
+}
+
+static inline enum mcde_display_power_mode mcde_display_get_power_mode_default(
+ struct mcde_display_device *ddev)
+{
+ return ddev->power_mode;
+}
+
+static inline int mcde_display_try_video_mode_default(
+ struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode)
+{
+ /*
+ * DSI video mode:
+ * This function is intended for configuring supported video mode(s).
+ * Overload it into the panel driver file and set up blanking
+ * intervals and pixel clock according to below recommendations.
+ *
+ * vertical blanking parameters vbp, vfp, vsw are given in lines
+ * horizontal blanking parameters hbp, hfp, hsw are given in pixels
+ *
+ * video_mode->pixclock is the time between two pixels (in picoseconds)
+ * The source of the pixel clock is DSI PLL and it shall be set to
+ * meet the requirement
+ *
+ * non-burst mode:
+ * pixel clock (Hz) = (VACT+VBP+VFP+VSA) * (HACT+HBP+HFP+HSA) *
+ * framerate * bpp / num_data_lanes
+ *
+ * burst mode:
+ * pixel clock (Hz) > (VACT+VBP+VFP+VSA) * (HACT+HBP+HFP+HSA) *
+ * framerate * bpp / num_data_lanes * 1.1
+ * (1.1 is a 10% margin needed for burst mode calculations)
+ */
+ return 0;
+}
+
+static int mcde_display_set_video_mode_default(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode)
+{
+ int ret;
+ struct mcde_video_mode channel_video_mode;
+
+ if (!video_mode)
+ return -EINVAL;
+
+ ddev->video_mode = *video_mode;
+ channel_video_mode = ddev->video_mode;
+ /* Dependant on if display should rotate or MCDE should rotate */
+ if (ddev->rotation == MCDE_DISPLAY_ROT_90_CCW ||
+ ddev->rotation == MCDE_DISPLAY_ROT_90_CW) {
+ channel_video_mode.xres = ddev->native_x_res;
+ channel_video_mode.yres = ddev->native_y_res;
+ }
+ ret = mcde_chnl_set_video_mode(ddev->chnl_state, &channel_video_mode);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to set video mode\n", __func__);
+ return ret;
+ }
+
+ ddev->update_flags |= UPDATE_FLAG_VIDEO_MODE;
+
+ return 0;
+}
+
+static inline void mcde_display_get_video_mode_default(
+ struct mcde_display_device *ddev, struct mcde_video_mode *video_mode)
+{
+ if (video_mode)
+ *video_mode = ddev->video_mode;
+}
+
+static int mcde_display_set_pixel_format_default(
+ struct mcde_display_device *ddev, enum mcde_ovly_pix_fmt format)
+{
+ int ret;
+
+ ddev->pixel_format = format;
+ ret = mcde_chnl_set_pixel_format(ddev->chnl_state,
+ ddev->port->pixel_format);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to set pixel format = %d\n",
+ __func__, format);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline enum mcde_ovly_pix_fmt mcde_display_get_pixel_format_default(
+ struct mcde_display_device *ddev)
+{
+ return ddev->pixel_format;
+}
+
+
+static int mcde_display_set_rotation_default(struct mcde_display_device *ddev,
+ enum mcde_display_rotation rotation)
+{
+ int ret;
+ u8 param = 0;
+ enum mcde_display_rotation final;
+
+ final = (360 + rotation - ddev->orientation) % 360;
+ ret = mcde_chnl_set_rotation(ddev->chnl_state, final);
+ if (WARN_ON(ret))
+ return ret;
+
+ if (final == MCDE_DISPLAY_ROT_180_CW)
+ param = 0x40; /* Horizontal flip */
+ (void)mcde_dsi_dcs_write(ddev->chnl_state, DCS_CMD_SET_ADDRESS_MODE,
+ &param, 1);
+
+ ddev->rotation = rotation;
+ ddev->update_flags |= UPDATE_FLAG_ROTATION;
+
+ return 0;
+}
+
+static inline enum mcde_display_rotation mcde_display_get_rotation_default(
+ struct mcde_display_device *ddev)
+{
+ return ddev->rotation;
+}
+
+static int mcde_display_apply_config_default(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ if (!ddev->update_flags)
+ return 0;
+
+ if (ddev->update_flags & UPDATE_FLAG_VIDEO_MODE)
+ mcde_chnl_stop_flow(ddev->chnl_state);
+
+ ret = mcde_chnl_apply(ddev->chnl_state);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to apply to channel\n",
+ __func__);
+ return ret;
+ }
+ ddev->update_flags = 0;
+ ddev->first_update = true;
+
+ return 0;
+}
+
+static int mcde_display_invalidate_area_default(
+ struct mcde_display_device *ddev,
+ struct mcde_rectangle *area)
+{
+ dev_vdbg(&ddev->dev, "%s\n", __func__);
+ if (area) {
+ /* take union of rects */
+ u16 t;
+ t = min(ddev->update_area.x, area->x);
+ /* note should be > 0 */
+ ddev->update_area.w = max(ddev->update_area.x +
+ ddev->update_area.w,
+ area->x + area->w) - t;
+ ddev->update_area.x = t;
+ t = min(ddev->update_area.y, area->y);
+ ddev->update_area.h = max(ddev->update_area.y +
+ ddev->update_area.h,
+ area->y + area->h) - t;
+ ddev->update_area.y = t;
+ /* TODO: Implement real clipping when partial refresh is
+ activated.*/
+ ddev->update_area.w = min((u16) ddev->video_mode.xres,
+ (u16) ddev->update_area.w);
+ ddev->update_area.h = min((u16) ddev->video_mode.yres,
+ (u16) ddev->update_area.h);
+ } else {
+ ddev->update_area.x = 0;
+ ddev->update_area.y = 0;
+ ddev->update_area.w = ddev->video_mode.xres;
+ ddev->update_area.h = ddev->video_mode.yres;
+ /* Invalidate_area(ddev, NULL) means reset area to empty
+ * rectangle really. After that the rectangle should grow by
+ * taking an union (above). This means that the code should
+ * really look like below, however the code above is a temp fix
+ * for rotation.
+ * TODO: fix
+ * ddev->update_area.x = ddev->video_mode.xres;
+ * ddev->update_area.y = ddev->video_mode.yres;
+ * ddev->update_area.w = 0;
+ * ddev->update_area.h = 0;
+ */
+ }
+
+ return 0;
+}
+
+static int mcde_display_update_default(struct mcde_display_device *ddev,
+ bool tripple_buffer)
+{
+ int ret = 0;
+
+ ret = mcde_chnl_update(ddev->chnl_state, &ddev->update_area,
+ tripple_buffer);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "%s:Failed to update channel\n", __func__);
+ return ret;
+ }
+ if (ddev->first_update && ddev->on_first_update)
+ ddev->on_first_update(ddev);
+
+ if (ddev->power_mode != MCDE_DISPLAY_PM_ON && ddev->set_power_mode) {
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_ON);
+ if (ret < 0) {
+ dev_warn(&ddev->dev,
+ "%s:Failed to set power mode to on\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ dev_vdbg(&ddev->dev, "Overlay updated, chnl=%d\n", ddev->chnl_id);
+
+ return 0;
+}
+
+static inline int mcde_display_on_first_update_default(
+ struct mcde_display_device *ddev)
+{
+ ddev->first_update = false;
+ return 0;
+}
+
+void mcde_display_init_device(struct mcde_display_device *ddev)
+{
+ /* Setup default callbacks */
+ ddev->get_native_resolution =
+ mcde_display_get_native_resolution_default;
+ ddev->get_default_pixel_format =
+ mcde_display_get_default_pixel_format_default;
+ ddev->get_physical_size = mcde_display_get_physical_size_default;
+ ddev->set_power_mode = mcde_display_set_power_mode_default;
+ ddev->get_power_mode = mcde_display_get_power_mode_default;
+ ddev->try_video_mode = mcde_display_try_video_mode_default;
+ ddev->set_video_mode = mcde_display_set_video_mode_default;
+ ddev->get_video_mode = mcde_display_get_video_mode_default;
+ ddev->set_pixel_format = mcde_display_set_pixel_format_default;
+ ddev->get_pixel_format = mcde_display_get_pixel_format_default;
+ ddev->set_rotation = mcde_display_set_rotation_default;
+ ddev->get_rotation = mcde_display_get_rotation_default;
+ ddev->apply_config = mcde_display_apply_config_default;
+ ddev->invalidate_area = mcde_display_invalidate_area_default;
+ ddev->update = mcde_display_update_default;
+ ddev->on_first_update = mcde_display_on_first_update_default;
+
+ mutex_init(&ddev->display_lock);
+}
+
diff --git a/drivers/video/mcde/mcde_dss.c b/drivers/video/mcde/mcde_dss.c
new file mode 100644
index 00000000000..35a6cbe9540
--- /dev/null
+++ b/drivers/video/mcde/mcde_dss.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE display sub system driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <video/mcde_dss.h>
+
+#define to_overlay(x) container_of(x, struct mcde_overlay, kobj)
+
+void overlay_release(struct kobject *kobj)
+{
+ struct mcde_overlay *ovly = to_overlay(kobj);
+
+ kfree(ovly);
+}
+
+struct kobj_type ovly_type = {
+ .release = overlay_release,
+};
+
+static int apply_overlay(struct mcde_overlay *ovly,
+ struct mcde_overlay_info *info, bool force)
+{
+ int ret = 0;
+ if (ovly->ddev->invalidate_area) {
+ /* TODO: transform ovly coord to screen coords (vmode):
+ * add offset
+ */
+ struct mcde_rectangle dirty = info->dirty;
+ mutex_lock(&ovly->ddev->display_lock);
+ ret = ovly->ddev->invalidate_area(ovly->ddev, &dirty);
+ mutex_unlock(&ovly->ddev->display_lock);
+ }
+
+ if (ovly->info.paddr != info->paddr || force)
+ mcde_ovly_set_source_buf(ovly->state, info->paddr);
+
+ if (ovly->info.stride != info->stride || ovly->info.fmt != info->fmt ||
+ force)
+ mcde_ovly_set_source_info(ovly->state, info->stride, info->fmt);
+ if (ovly->info.src_x != info->src_x ||
+ ovly->info.src_y != info->src_y ||
+ ovly->info.w != info->w ||
+ ovly->info.h != info->h || force)
+ mcde_ovly_set_source_area(ovly->state,
+ info->src_x, info->src_y, info->w, info->h);
+ if (ovly->info.dst_x != info->dst_x || ovly->info.dst_y != info->dst_y
+ || ovly->info.dst_z != info->dst_z ||
+ force)
+ mcde_ovly_set_dest_pos(ovly->state,
+ info->dst_x, info->dst_y, info->dst_z);
+
+ mcde_ovly_apply(ovly->state);
+ ovly->info = *info;
+
+ return ret;
+}
+
+/* MCDE DSS operations */
+
+int mcde_dss_open_channel(struct mcde_display_device *ddev)
+{
+ int ret = 0;
+ struct mcde_chnl_state *chnl;
+
+ mutex_lock(&ddev->display_lock);
+ /* Acquire MCDE resources */
+ chnl = mcde_chnl_get(ddev->chnl_id, ddev->fifo, ddev->port);
+ if (IS_ERR(chnl)) {
+ ret = PTR_ERR(chnl);
+ dev_warn(&ddev->dev, "Failed to acquire MCDE channel\n");
+ goto chnl_get_failed;
+ }
+ ddev->chnl_state = chnl;
+chnl_get_failed:
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_open_channel);
+
+void mcde_dss_close_channel(struct mcde_display_device *ddev)
+{
+ mutex_lock(&ddev->display_lock);
+ mcde_chnl_put(ddev->chnl_state);
+ ddev->chnl_state = NULL;
+ mutex_unlock(&ddev->display_lock);
+}
+EXPORT_SYMBOL(mcde_dss_close_channel);
+
+int mcde_dss_enable_display(struct mcde_display_device *ddev)
+{
+ int ret;
+
+ if (ddev->enabled)
+ return 0;
+
+ mutex_lock(&ddev->display_lock);
+ mcde_chnl_enable(ddev->chnl_state);
+
+ /* Initiate display communication */
+ ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY);
+ if (ret < 0) {
+ dev_warn(&ddev->dev, "Failed to initialize display\n");
+ goto display_failed;
+ }
+
+ ret = ddev->set_rotation(ddev, ddev->get_rotation(ddev));
+ if (ret < 0)
+ dev_warn(&ddev->dev, "Failed to set rotation\n");
+
+ dev_dbg(&ddev->dev, "Display enabled, chnl=%d\n",
+ ddev->chnl_id);
+ ddev->enabled = true;
+ mutex_unlock(&ddev->display_lock);
+
+ return 0;
+
+display_failed:
+ mcde_chnl_disable(ddev->chnl_state);
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_enable_display);
+
+void mcde_dss_disable_display(struct mcde_display_device *ddev)
+{
+ if (!ddev->enabled)
+ return;
+
+ /* TODO: Disable overlays */
+ mutex_lock(&ddev->display_lock);
+
+ mcde_chnl_stop_flow(ddev->chnl_state);
+
+ (void)ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_OFF);
+
+ mcde_chnl_disable(ddev->chnl_state);
+
+ ddev->enabled = false;
+ mutex_unlock(&ddev->display_lock);
+
+ dev_dbg(&ddev->dev, "Display disabled, chnl=%d\n", ddev->chnl_id);
+}
+EXPORT_SYMBOL(mcde_dss_disable_display);
+
+int mcde_dss_apply_channel(struct mcde_display_device *ddev)
+{
+ int ret;
+ if (!ddev->apply_config)
+ return -EINVAL;
+ mutex_lock(&ddev->display_lock);
+ ret = ddev->apply_config(ddev);
+ mutex_unlock(&ddev->display_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_apply_channel);
+
+struct mcde_overlay *mcde_dss_create_overlay(struct mcde_display_device *ddev,
+ struct mcde_overlay_info *info)
+{
+ struct mcde_overlay *ovly;
+
+ ovly = kzalloc(sizeof(struct mcde_overlay), GFP_KERNEL);
+ if (!ovly)
+ return NULL;
+
+ kobject_init(&ovly->kobj, &ovly_type); /* Local ref */
+ kobject_get(&ovly->kobj); /* Creator ref */
+ INIT_LIST_HEAD(&ovly->list);
+ mutex_lock(&ddev->display_lock);
+ list_add(&ddev->ovlys, &ovly->list);
+ mutex_unlock(&ddev->display_lock);
+ ovly->info = *info;
+ ovly->ddev = ddev;
+
+ return ovly;
+}
+EXPORT_SYMBOL(mcde_dss_create_overlay);
+
+void mcde_dss_destroy_overlay(struct mcde_overlay *ovly)
+{
+ list_del(&ovly->list);
+ if (ovly->state)
+ mcde_dss_disable_overlay(ovly);
+ kobject_put(&ovly->kobj);
+}
+EXPORT_SYMBOL(mcde_dss_destroy_overlay);
+
+int mcde_dss_enable_overlay(struct mcde_overlay *ovly)
+{
+ int ret;
+
+ if (!ovly->ddev->chnl_state)
+ return -EINVAL;
+
+ if (!ovly->state) {
+ struct mcde_ovly_state *state;
+ state = mcde_ovly_get(ovly->ddev->chnl_state);
+ if (IS_ERR(state)) {
+ ret = PTR_ERR(state);
+ dev_warn(&ovly->ddev->dev,
+ "Failed to acquire overlay\n");
+ return ret;
+ }
+ ovly->state = state;
+ }
+
+ apply_overlay(ovly, &ovly->info, true);
+
+ dev_vdbg(&ovly->ddev->dev, "Overlay enabled, chnl=%d\n",
+ ovly->ddev->chnl_id);
+ return 0;
+}
+EXPORT_SYMBOL(mcde_dss_enable_overlay);
+
+int mcde_dss_apply_overlay(struct mcde_overlay *ovly,
+ struct mcde_overlay_info *info)
+{
+ if (info == NULL)
+ info = &ovly->info;
+ return apply_overlay(ovly, info, false);
+}
+EXPORT_SYMBOL(mcde_dss_apply_overlay);
+
+void mcde_dss_disable_overlay(struct mcde_overlay *ovly)
+{
+ if (!ovly->state)
+ return;
+
+ mcde_ovly_put(ovly->state);
+
+ dev_dbg(&ovly->ddev->dev, "Overlay disabled, chnl=%d\n",
+ ovly->ddev->chnl_id);
+
+ ovly->state = NULL;
+}
+EXPORT_SYMBOL(mcde_dss_disable_overlay);
+
+int mcde_dss_update_overlay(struct mcde_overlay *ovly, bool tripple_buffer)
+{
+ int ret;
+ dev_vdbg(&ovly->ddev->dev, "Overlay update, chnl=%d\n",
+ ovly->ddev->chnl_id);
+
+ if (!ovly->state || !ovly->ddev->update || !ovly->ddev->invalidate_area)
+ return -EINVAL;
+
+ mutex_lock(&ovly->ddev->display_lock);
+ /* Do not perform an update if power mode is off */
+ if (ovly->ddev->get_power_mode(ovly->ddev) == MCDE_DISPLAY_PM_OFF) {
+ ret = 0;
+ goto power_mode_off;
+ }
+
+ ret = ovly->ddev->update(ovly->ddev, tripple_buffer);
+ if (ret)
+ goto update_failed;
+
+ ret = ovly->ddev->invalidate_area(ovly->ddev, NULL);
+
+power_mode_off:
+update_failed:
+ mutex_unlock(&ovly->ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_update_overlay);
+
+void mcde_dss_get_overlay_info(struct mcde_overlay *ovly,
+ struct mcde_overlay_info *info) {
+ if (info)
+ *info = ovly->info;
+}
+EXPORT_SYMBOL(mcde_dss_get_overlay_info);
+
+void mcde_dss_get_native_resolution(struct mcde_display_device *ddev,
+ u16 *x_res, u16 *y_res)
+{
+ u16 x_tmp, y_tmp;
+ mutex_lock(&ddev->display_lock);
+ ddev->get_native_resolution(ddev, &x_tmp, &y_tmp);
+ if (ddev->orientation == MCDE_DISPLAY_ROT_90_CW ||
+ ddev->orientation == MCDE_DISPLAY_ROT_90_CCW) {
+ *x_res = y_tmp;
+ *y_res = x_tmp;
+ } else {
+ *x_res = x_tmp;
+ *y_res = y_tmp;
+ }
+ mutex_unlock(&ddev->display_lock);
+}
+EXPORT_SYMBOL(mcde_dss_get_native_resolution);
+
+enum mcde_ovly_pix_fmt mcde_dss_get_default_pixel_format(
+ struct mcde_display_device *ddev)
+{
+ int ret;
+ mutex_lock(&ddev->display_lock);
+ ret = ddev->get_default_pixel_format(ddev);
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_get_default_pixel_format);
+
+void mcde_dss_get_physical_size(struct mcde_display_device *ddev,
+ u16 *physical_width, u16 *physical_height)
+{
+ mutex_lock(&ddev->display_lock);
+ ddev->get_physical_size(ddev, physical_width, physical_height);
+ mutex_unlock(&ddev->display_lock);
+}
+EXPORT_SYMBOL(mcde_dss_get_physical_size);
+
+int mcde_dss_try_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode)
+{
+ int ret;
+ mutex_lock(&ddev->display_lock);
+ ret = ddev->try_video_mode(ddev, video_mode);
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_try_video_mode);
+
+int mcde_dss_set_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *vmode)
+{
+ int ret = 0;
+ struct mcde_video_mode old_vmode;
+
+ mutex_lock(&ddev->display_lock);
+ /* Do not perform set_video_mode if power mode is off */
+ if (ddev->get_power_mode(ddev) == MCDE_DISPLAY_PM_OFF)
+ goto power_mode_off;
+
+ ddev->get_video_mode(ddev, &old_vmode);
+ if (memcmp(vmode, &old_vmode, sizeof(old_vmode)) == 0)
+ goto same_video_mode;
+
+ ret = ddev->set_video_mode(ddev, vmode);
+ if (ret)
+ goto set_video_mode_failed;
+
+ if (ddev->invalidate_area)
+ ret = ddev->invalidate_area(ddev, NULL);
+power_mode_off:
+same_video_mode:
+set_video_mode_failed:
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_set_video_mode);
+
+void mcde_dss_get_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode)
+{
+ mutex_lock(&ddev->display_lock);
+ ddev->get_video_mode(ddev, video_mode);
+ mutex_unlock(&ddev->display_lock);
+}
+EXPORT_SYMBOL(mcde_dss_get_video_mode);
+
+int mcde_dss_set_pixel_format(struct mcde_display_device *ddev,
+ enum mcde_ovly_pix_fmt pix_fmt)
+{
+ enum mcde_ovly_pix_fmt old_pix_fmt;
+ int ret;
+
+ mutex_lock(&ddev->display_lock);
+ old_pix_fmt = ddev->get_pixel_format(ddev);
+ if (old_pix_fmt == pix_fmt) {
+ ret = 0;
+ goto same_pixel_format;
+ }
+
+ ret = ddev->set_pixel_format(ddev, pix_fmt);
+
+same_pixel_format:
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_set_pixel_format);
+
+int mcde_dss_get_pixel_format(struct mcde_display_device *ddev)
+{
+ int ret;
+ mutex_lock(&ddev->display_lock);
+ ret = ddev->get_pixel_format(ddev);
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_get_pixel_format);
+
+int mcde_dss_set_rotation(struct mcde_display_device *ddev,
+ enum mcde_display_rotation rotation)
+{
+ int ret;
+ enum mcde_display_rotation old_rotation;
+
+ mutex_lock(&ddev->display_lock);
+ old_rotation = ddev->get_rotation(ddev);
+ if (old_rotation == rotation) {
+ ret = 0;
+ goto same_rotation;
+ }
+
+ ret = ddev->set_rotation(ddev, rotation);
+same_rotation:
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_set_rotation);
+
+enum mcde_display_rotation mcde_dss_get_rotation(
+ struct mcde_display_device *ddev)
+{
+ int ret;
+ mutex_lock(&ddev->display_lock);
+ ret = ddev->get_rotation(ddev);
+ mutex_unlock(&ddev->display_lock);
+ return ret;
+}
+EXPORT_SYMBOL(mcde_dss_get_rotation);
+
+int __init mcde_dss_init(void)
+{
+ return 0;
+}
+
+void mcde_dss_exit(void)
+{
+}
+
diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c
new file mode 100644
index 00000000000..7d877ec3e4f
--- /dev/null
+++ b/drivers/video/mcde/mcde_fb.c
@@ -0,0 +1,898 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson MCDE frame buffer driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/hwmem.h>
+#include <linux/io.h>
+
+#include <linux/console.h>
+
+#include <video/mcde_fb.h>
+
+#define MCDE_FB_BPP_MAX 16
+#define MCDE_FB_VXRES_MAX 1920
+#define MCDE_FB_VYRES_MAX 2160
+
+static struct fb_ops fb_ops;
+
+struct pix_fmt_info {
+ enum mcde_ovly_pix_fmt pix_fmt;
+
+ u32 bpp;
+ struct fb_bitfield r;
+ struct fb_bitfield g;
+ struct fb_bitfield b;
+ struct fb_bitfield a;
+ u32 nonstd;
+};
+
+struct pix_fmt_info pix_fmt_map[] = {
+ {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGB565,
+ .bpp = 16,
+ .r = { .offset = 11, .length = 5 },
+ .g = { .offset = 5, .length = 6 },
+ .b = { .offset = 0, .length = 5 },
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGBA5551,
+ .bpp = 16,
+ .r = { .offset = 11, .length = 5 },
+ .g = { .offset = 6, .length = 5 },
+ .b = { .offset = 1, .length = 5 },
+ .a = { .offset = 0, .length = 1 },
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGBA4444,
+ .bpp = 16,
+ .r = { .offset = 12, .length = 4 },
+ .g = { .offset = 8, .length = 4 },
+ .b = { .offset = 4, .length = 4 },
+ .a = { .offset = 0, .length = 4 },
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_YCbCr422,
+ .bpp = 16,
+ .nonstd = MCDE_OVLYPIXFMT_YCbCr422,
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGB888,
+ .bpp = 24,
+ .r = { .offset = 16, .length = 8 },
+ .g = { .offset = 8, .length = 8 },
+ .b = { .offset = 0, .length = 8 },
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGBA8888,
+ .bpp = 32,
+ .r = { .offset = 16, .length = 8 },
+ .g = { .offset = 8, .length = 8 },
+ .b = { .offset = 0, .length = 8 },
+ .a = { .offset = 24, .length = 8 },
+ }, {
+ .pix_fmt = MCDE_OVLYPIXFMT_RGBX8888,
+ .bpp = 32,
+ .r = { .offset = 16, .length = 8 },
+ .g = { .offset = 8, .length = 8 },
+ .b = { .offset = 0, .length = 8 },
+ }
+
+};
+
+static struct platform_device mcde_fb_device = {
+ .name = "mcde_fb",
+ .id = -1,
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void early_suspend(struct early_suspend *data)
+{
+ int i;
+ struct mcde_fb *mfb =
+ container_of(data, struct mcde_fb, early_suspend);
+
+ console_lock();
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ if (mfb->ovlys[i] && mfb->ovlys[i]->ddev &&
+ (mfb->ovlys[i]->ddev->stay_alive == false))
+ mcde_dss_disable_display(mfb->ovlys[i]->ddev);
+ }
+ console_unlock();
+}
+
+static void late_resume(struct early_suspend *data)
+{
+ int i;
+ struct mcde_fb *mfb =
+ container_of(data, struct mcde_fb, early_suspend);
+
+ console_lock();
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ if (mfb->ovlys[i]) {
+ struct mcde_overlay *ovly = mfb->ovlys[i];
+ (void) mcde_dss_enable_display(ovly->ddev);
+ }
+ }
+ console_unlock();
+}
+#endif
+
+/* Helpers */
+
+static struct pix_fmt_info *find_pix_fmt_info(enum mcde_ovly_pix_fmt pix_fmt)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pix_fmt_map); i++) {
+ if (pix_fmt_map[i].pix_fmt == pix_fmt)
+ return &pix_fmt_map[i];
+ }
+ return NULL;
+}
+
+static bool bitfield_cmp(struct fb_bitfield *bf1, struct fb_bitfield *bf2)
+{
+ return bf1->offset == bf2->offset &&
+ bf1->length == bf2->length &&
+ bf1->msb_right == bf2->msb_right;
+}
+
+static struct pix_fmt_info *var_to_pix_fmt_info(struct fb_var_screeninfo *var)
+{
+ int i;
+ struct pix_fmt_info *info;
+
+ if (var->nonstd)
+ return find_pix_fmt_info(var->nonstd);
+
+ for (i = 0; i < ARRAY_SIZE(pix_fmt_map); i++) {
+ info = &pix_fmt_map[i];
+ if (info->bpp == var->bits_per_pixel &&
+ bitfield_cmp(&info->r, &var->red) &&
+ bitfield_cmp(&info->g, &var->green) &&
+ bitfield_cmp(&info->b, &var->blue) &&
+ bitfield_cmp(&info->a, &var->transp))
+ return info;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pix_fmt_map); i++) {
+ info = &pix_fmt_map[i];
+ if (var->bits_per_pixel == info->bpp)
+ return info;
+ }
+
+ return NULL;
+}
+
+static void pix_fmt_info_to_var(struct pix_fmt_info *pix_fmt_info,
+ struct fb_var_screeninfo *var)
+{
+ var->bits_per_pixel = pix_fmt_info->bpp;
+ var->nonstd = pix_fmt_info->nonstd;
+ var->red = pix_fmt_info->r;
+ var->green = pix_fmt_info->g;
+ var->blue = pix_fmt_info->b;
+ var->transp = pix_fmt_info->a;
+}
+
+static int init_var_fmt(struct fb_var_screeninfo *var,
+ u16 w, u16 h, u16 vw, u16 vh, enum mcde_ovly_pix_fmt pix_fmt,
+ u32 rotate)
+{
+ struct pix_fmt_info *info;
+
+ info = find_pix_fmt_info(pix_fmt);
+ if (!info)
+ return -EINVAL;
+
+ var->bits_per_pixel = info->bpp;
+ var->nonstd = info->nonstd;
+ var->red = info->r;
+ var->green = info->g;
+ var->blue = info->b;
+ var->transp = info->a;
+ var->grayscale = false;
+
+ var->xres = w;
+ var->yres = h;
+ var->xres_virtual = vw;
+ var->yres_virtual = vh;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->activate = FB_ACTIVATE_NOW;
+ var->rotate = rotate;
+
+ return 0;
+};
+
+static int reallocate_fb_mem(struct fb_info *fbi, u32 size)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+ void *vaddr;
+ struct hwmem_alloc *alloc;
+ struct hwmem_mem_chunk mem_chunk;
+ size_t num_mem_chunks = 1;
+ int name;
+
+ size = PAGE_ALIGN(size);
+
+ if (size == fbi->screen_size)
+ return 0;
+
+/* TODO: Remove once hwmem has support for defragmentation */
+#ifdef CONFIG_MCDE_FB_AVOID_REALLOC
+ if (!mfb->alloc) {
+ u32 old_size = size;
+
+ size = MCDE_FB_BPP_MAX / 8 * MCDE_FB_VXRES_MAX *
+ MCDE_FB_VYRES_MAX;
+#endif
+
+ alloc = hwmem_alloc(size, HWMEM_ALLOC_HINT_WRITE_COMBINE |
+ HWMEM_ALLOC_HINT_UNCACHED,
+ (HWMEM_ACCESS_READ | HWMEM_ACCESS_WRITE |
+ HWMEM_ACCESS_IMPORT),
+ HWMEM_MEM_CONTIGUOUS_SYS);
+ if (IS_ERR(alloc))
+ return PTR_ERR(alloc);
+
+ name = hwmem_get_name(alloc);
+ if (name < 0) {
+ hwmem_release(alloc);
+ return name;
+ }
+
+ if (mfb->alloc) {
+ hwmem_kunmap(mfb->alloc);
+ hwmem_unpin(mfb->alloc);
+ hwmem_release(mfb->alloc);
+ }
+
+ (void)hwmem_pin(alloc, &mem_chunk, &num_mem_chunks);
+
+ vaddr = hwmem_kmap(alloc);
+ if (vaddr == NULL) {
+ hwmem_unpin(alloc);
+ hwmem_release(alloc);
+ return -ENOMEM;
+ }
+
+ mfb->alloc = alloc;
+ mfb->alloc_name = name;
+
+ fbi->screen_base = vaddr;
+ fbi->fix.smem_start = mem_chunk.paddr;
+
+#ifdef CONFIG_MCDE_FB_AVOID_REALLOC
+ size = old_size;
+ }
+#endif
+
+ fbi->screen_size = size;
+ fbi->fix.smem_len = size;
+
+ return 0;
+}
+
+static void free_fb_mem(struct fb_info *fbi)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+
+ if (mfb->alloc) {
+ hwmem_kunmap(mfb->alloc);
+ hwmem_unpin(mfb->alloc);
+ hwmem_release(mfb->alloc);
+ mfb->alloc = NULL;
+ mfb->alloc_name = 0;
+
+ fbi->fix.smem_start = 0;
+ fbi->fix.smem_len = 0;
+ fbi->screen_base = 0;
+ fbi->screen_size = 0;
+ }
+}
+
+static void init_fb(struct fb_info *fbi)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+
+ strlcpy(fbi->fix.id, "mcde_fb", sizeof(fbi->fix.id));
+ fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbi->fix.visual = FB_VISUAL_DIRECTCOLOR;
+ fbi->fix.xpanstep = 1;
+ fbi->fix.ypanstep = 1;
+ fbi->flags = FBINFO_HWACCEL_DISABLED;
+ fbi->fbops = &fb_ops;
+ fbi->pseudo_palette = &mfb->pseudo_palette[0];
+}
+
+static void get_ovly_info(struct fb_info *fbi, struct mcde_overlay *ovly,
+ struct mcde_overlay_info *info)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+
+ memset(info, 0, sizeof(*info));
+ info->paddr = fbi->fix.smem_start +
+ fbi->fix.line_length * fbi->var.yoffset;
+ info->vaddr = (u32 *)(fbi->screen_base +
+ fbi->fix.line_length * fbi->var.yoffset);
+ /* TODO: move mem check to check_var/pan_display */
+ if (info->paddr + fbi->fix.line_length * fbi->var.yres >
+ fbi->fix.smem_start + fbi->fix.smem_len) {
+ info->paddr = fbi->fix.smem_start;
+ info->vaddr = (u32 *)fbi->screen_base;
+ }
+ info->fmt = mfb->pix_fmt;
+ info->stride = fbi->fix.line_length;
+ if (ovly) {
+ info->src_x = ovly->info.src_x;
+ info->src_y = ovly->info.src_y;
+ info->dst_x = ovly->info.dst_x;
+ info->dst_y = ovly->info.dst_y;
+ info->dst_z = 1;
+ } else {
+ info->src_x = 0;
+ info->src_y = 0;
+ info->dst_x = 0;
+ info->dst_y = 0;
+ info->dst_z = 1;
+ }
+ info->w = fbi->var.xres;
+ info->h = fbi->var.yres;
+ info->dirty.x = 0;
+ info->dirty.y = 0;
+ info->dirty.w = fbi->var.xres;
+ info->dirty.h = fbi->var.yres;
+}
+
+void vmode_to_var(struct mcde_video_mode *video_mode,
+ struct fb_var_screeninfo *var)
+{
+ /* TODO: use only 1 vbp and 1 vfp */
+ var->xres = video_mode->xres;
+ var->yres = video_mode->yres;
+ var->pixclock = video_mode->pixclock;
+ var->upper_margin = video_mode->vbp;
+ var->lower_margin = video_mode->vfp;
+ var->vsync_len = video_mode->vsw;
+ var->left_margin = video_mode->hbp;
+ var->right_margin = video_mode->hfp;
+ var->hsync_len = video_mode->hsw;
+ var->vmode &= ~FB_VMODE_INTERLACED;
+ var->vmode |= video_mode->interlaced ?
+ FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+}
+
+void var_to_vmode(struct fb_var_screeninfo *var,
+ struct mcde_video_mode *video_mode)
+{
+ video_mode->xres = var->xres;
+ video_mode->yres = var->yres;
+ video_mode->pixclock = var->pixclock;
+ video_mode->vbp = var->upper_margin;
+ video_mode->vfp = var->lower_margin;
+ video_mode->vsw = var->vsync_len;
+ video_mode->hbp = var->left_margin;
+ video_mode->hfp = var->right_margin;
+ video_mode->hsw = var->hsync_len;
+ video_mode->interlaced = (var->vmode & FB_VMODE_INTERLACED) ==
+ FB_VMODE_INTERLACED;
+}
+
+enum mcde_display_rotation var_to_rotation(struct fb_var_screeninfo *var)
+{
+ enum mcde_display_rotation rot;
+
+ switch (var->rotate) {
+ case FB_ROTATE_UR:
+ rot = MCDE_DISPLAY_ROT_0;
+ break;
+ case FB_ROTATE_CW:
+ rot = MCDE_DISPLAY_ROT_90_CW;
+ break;
+ case FB_ROTATE_UD:
+ rot = MCDE_DISPLAY_ROT_180_CW;
+ break;
+ case FB_ROTATE_CCW:
+ rot = MCDE_DISPLAY_ROT_90_CCW;
+ break;
+ default:
+ rot = MCDE_DISPLAY_ROT_0;
+ break;
+ }
+ dev_vdbg(&mcde_fb_device.dev, "var_rot: %d -> mcde_rot: %d\n",
+ var->rotate, rot);
+ return rot;
+}
+
+static struct mcde_display_device *fb_to_display(struct fb_info *fbi)
+{
+ int i;
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ if (mfb->ovlys[i])
+ return mfb->ovlys[i]->ddev;
+ }
+ return NULL;
+}
+
+static int check_var(struct fb_var_screeninfo *var, struct fb_info *fbi,
+ struct mcde_display_device *ddev)
+{
+ int ret;
+ u16 w = -1, h = -1;
+ struct mcde_video_mode vmode;
+ struct pix_fmt_info *fmtinfo;
+
+ /* TODO: check sizes/offsets/memory validity */
+
+ /* Device physical size */
+ mcde_dss_get_physical_size(ddev, &w, &h);
+ var->width = w;
+ var->height = h;
+
+ /* Rotation */
+ if (var->rotate > 3) {
+ dev_info(&(ddev->dev), "check_var failed var->rotate\n");
+ return -EINVAL;
+ }
+
+ /* Video mode */
+ var_to_vmode(var, &vmode);
+ ret = mcde_dss_try_video_mode(ddev, &vmode);
+ if (ret < 0) {
+ dev_vdbg(&(ddev->dev), "check_var failed "
+ "mcde_dss_try_video_mode with size = %x\n", ret);
+ return ret;
+ }
+ vmode_to_var(&vmode, var);
+
+ /* Pixel format */
+ fmtinfo = var_to_pix_fmt_info(var);
+ if (!fmtinfo) {
+ dev_vdbg(&(ddev->dev), "check_var failed fmtinfo\n");
+ return -EINVAL;
+ }
+ pix_fmt_info_to_var(fmtinfo, var);
+
+ /* Not used */
+ var->grayscale = 0;
+ var->sync = 0;
+
+ return 0;
+}
+
+static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev)
+{
+ int ret, i;
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+ struct fb_var_screeninfo *var;
+ struct mcde_video_mode vmode;
+ struct pix_fmt_info *fmt;
+ u32 line_len, size;
+
+ if (!ddev)
+ return -ENODEV;
+
+ dev_vdbg(&(ddev->dev), "%s\n", __func__);
+
+ var = &fbi->var;
+
+ ddev->check_transparency = 60;
+
+ /* Reallocate memory */
+ line_len = (fbi->var.bits_per_pixel * var->xres_virtual) / 8;
+ line_len = ALIGN(line_len, MCDE_BUF_LINE_ALIGMENT);
+ size = line_len * var->yres_virtual;
+ ret = reallocate_fb_mem(fbi, size);
+ if (ret) {
+ dev_vdbg(&(ddev->dev), "apply_var failed with"
+ "reallocate mem with size = %d\n", size);
+ return ret;
+ }
+ fbi->fix.line_length = line_len;
+
+ if (ddev->fictive)
+ goto apply_var_end;
+
+ /* Apply pixel format */
+ fmt = var_to_pix_fmt_info(var);
+ mfb->pix_fmt = fmt->pix_fmt;
+
+ /* Apply rotation */
+ mcde_dss_set_rotation(ddev, var_to_rotation(var));
+ /* Apply video mode */
+ memset(&vmode, 0, sizeof(struct mcde_video_mode));
+ var_to_vmode(var, &vmode);
+ ret = mcde_dss_set_video_mode(ddev, &vmode);
+ if (ret)
+ return ret;
+
+ mcde_dss_apply_channel(ddev);
+
+ /* Apply overlay info */
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ struct mcde_overlay *ovly = mfb->ovlys[i];
+ struct mcde_overlay_info info;
+ int num_buffers;
+
+ get_ovly_info(fbi, ovly, &info);
+ (void) mcde_dss_apply_overlay(ovly, &info);
+
+ num_buffers = var->yres_virtual / var->yres;
+ mcde_dss_update_overlay(ovly, num_buffers == 3);
+ }
+
+apply_var_end:
+ return 0;
+}
+
+/* FB ops */
+
+static int mcde_fb_open(struct fb_info *fbi, int user)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int mcde_fb_release(struct fb_info *fbi, int user)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int mcde_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+ struct mcde_display_device *ddev = fb_to_display(fbi);
+
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ if (!ddev) {
+ printk(KERN_ERR "mcde_fb_check_var failed !ddev\n");
+ return -ENODEV;
+ }
+
+ return check_var(var, fbi, ddev);
+}
+
+static int mcde_fb_set_par(struct fb_info *fbi)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+ struct mcde_display_device *ddev = fb_to_display(fbi);
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ if (mfb->ovlys[0]->state == NULL &&
+ ddev->fictive == false) {
+ printk(KERN_INFO "%s() - Enable fb %p\n",
+ __func__,
+ mfb->ovlys[0]);
+ mcde_dss_enable_overlay(mfb->ovlys[0]);
+ }
+
+ return apply_var(fbi, ddev);
+}
+
+static int mcde_fb_blank(int blank, struct fb_info *fbi)
+{
+ int ret = 0;
+ struct mcde_display_device *ddev = fb_to_display(fbi);
+
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ if (ddev->fictive)
+ goto mcde_fb_blank_end;
+
+ switch (blank) {
+ case FB_BLANK_NORMAL:
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ mcde_dss_disable_display(ddev);
+ break;
+ case FB_BLANK_UNBLANK:
+ ret = mcde_dss_enable_display(ddev);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+mcde_fb_blank_end:
+ return ret;
+}
+
+static int mcde_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ if (var->xoffset == fbi->var.xoffset &&
+ var->yoffset == fbi->var.yoffset)
+ return 0;
+
+ fbi->var.xoffset = var->xoffset;
+ fbi->var.yoffset = var->yoffset;
+ return apply_var(fbi, fb_to_display(fbi));
+}
+
+static void mcde_fb_rotate(struct fb_info *fbi, int rotate)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+}
+
+static int mcde_fb_ioctl(struct fb_info *fbi, unsigned int cmd,
+ unsigned long arg)
+{
+ struct mcde_fb *mfb = to_mcde_fb(fbi);
+
+ if (cmd == MCDE_GET_BUFFER_NAME_IOC)
+ return mfb->alloc_name;
+
+ return -EINVAL;
+}
+
+static int mcde_fb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue, unsigned int transp,
+ struct fb_info *fbi)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ if (regno >= 256)
+ return 1;
+
+ if (regno < 17) {
+ u32 pseudo_val;
+ u32 r, g, b;
+
+ if (fbi->var.bits_per_pixel > 16) {
+ r = red >> 8;
+ g = green >> 8;
+ b = blue >> 8;
+ } else if (fbi->var.bits_per_pixel == 16) {
+ r = red >> (3 + 8);
+ g = green >> (2 + 8);
+ b = blue >> (3 + 8);
+ } else if (fbi->var.bits_per_pixel == 15) {
+ r = red >> (3 + 8);
+ g = green >> (3 + 8);
+ b = blue >> (3 + 8);
+ } else
+ r = b = g = (regno & 15);
+ pseudo_val = r << fbi->var.red.offset;
+ pseudo_val |= g << fbi->var.green.offset;
+ pseudo_val |= b << fbi->var.blue.offset;
+
+ ((u32 *)fbi->pseudo_palette)[regno] = pseudo_val;
+ }
+
+ return 0;
+}
+
+static int mcde_fb_setcmap(struct fb_cmap *cmap, struct fb_info *fbi)
+{
+ dev_vdbg(fbi->dev, "%s\n", __func__);
+
+ /*Nothing to see here, move along*/
+ return 0;
+}
+
+static struct fb_ops fb_ops = {
+ /* creg, cmap */
+ .owner = THIS_MODULE,
+ .fb_open = mcde_fb_open,
+ .fb_release = mcde_fb_release,
+ .fb_read = fb_sys_read,
+ .fb_write = fb_sys_write,
+ .fb_fillrect = sys_fillrect,
+ .fb_copyarea = sys_copyarea,
+ .fb_imageblit = sys_imageblit,
+ .fb_check_var = mcde_fb_check_var,
+ .fb_set_par = mcde_fb_set_par,
+ .fb_blank = mcde_fb_blank,
+ .fb_pan_display = mcde_fb_pan_display,
+ .fb_rotate = mcde_fb_rotate,
+ .fb_ioctl = mcde_fb_ioctl,
+ .fb_setcolreg = mcde_fb_setcolreg,
+ .fb_setcmap = mcde_fb_setcmap,
+};
+
+/* FB driver */
+
+struct fb_info *mcde_fb_create(struct mcde_display_device *ddev,
+ u16 w, u16 h, u16 vw, u16 vh, enum mcde_ovly_pix_fmt pix_fmt,
+ u32 rotate)
+{
+ int ret = 0;
+ struct fb_info *fbi;
+ struct mcde_fb *mfb;
+ struct mcde_overlay *ovly = NULL;
+ struct mcde_overlay_info ovly_info;
+
+ dev_vdbg(&ddev->dev, "%s\n", __func__);
+ if (!ddev->initialized) {
+ dev_warn(&ddev->dev, "%s: Device not initialized\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Init fb */
+ fbi = framebuffer_alloc(sizeof(struct mcde_fb), &mcde_fb_device.dev);
+ if (fbi == NULL) {
+ ret = -ENOMEM;
+ goto fb_alloc_failed;
+ }
+ init_fb(fbi);
+ mfb = to_mcde_fb(fbi);
+
+ if (ddev->fictive == false) {
+ ret = mcde_dss_open_channel(ddev);
+ if (ret)
+ goto channel_open_failed;
+
+ ret = mcde_dss_enable_display(ddev);
+ if (ret)
+ goto display_enable_failed;
+ }
+
+ /* Prepare var and allocate frame buffer memory */
+ init_var_fmt(&fbi->var, w, h, vw, vh, pix_fmt, rotate);
+ check_var(&fbi->var, fbi, ddev);
+ ret = apply_var(fbi, ddev);
+ if (ret)
+ goto apply_var_failed;
+
+ if (ddev->fictive == false)
+ mcde_dss_set_pixel_format(ddev, ddev->port->pixel_format);
+
+ /* Setup overlay */
+ get_ovly_info(fbi, NULL, &ovly_info);
+ ovly = mcde_dss_create_overlay(ddev, &ovly_info);
+ if (!ovly) {
+ ret = PTR_ERR(ovly);
+ goto ovly_alloc_failed;
+ }
+ mfb->ovlys[0] = ovly;
+ mfb->num_ovlys = 1;
+
+ if (ddev->fictive == false) {
+ ret = mcde_dss_enable_overlay(ovly);
+ if (ret)
+ goto ovly_enable_failed;
+ }
+
+ mfb->id = ddev->id;
+
+ /* Register framebuffer */
+ ret = register_framebuffer(fbi);
+ if (ret)
+ goto fb_register_failed;
+
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret)
+ dev_warn(&ddev->dev, "%s: Allocate color map memory failed!\n",
+ __func__);
+
+ ddev->fbi = fbi;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if (ddev->fictive == false) {
+ mfb->early_suspend.level =
+ EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ mfb->early_suspend.suspend = early_suspend;
+ mfb->early_suspend.resume = late_resume;
+ register_early_suspend(&mfb->early_suspend);
+ }
+#endif
+
+ goto out;
+fb_register_failed:
+ mcde_dss_disable_overlay(ovly);
+ovly_enable_failed:
+ mcde_dss_destroy_overlay(ovly);
+ovly_alloc_failed:
+ free_fb_mem(fbi);
+apply_var_failed:
+ mcde_dss_disable_display(ddev);
+display_enable_failed:
+ mcde_dss_close_channel(ddev);
+channel_open_failed:
+ framebuffer_release(fbi);
+ fbi = NULL;
+fb_alloc_failed:
+out:
+ return ret ? ERR_PTR(ret) : fbi;
+}
+EXPORT_SYMBOL(mcde_fb_create);
+
+int mcde_fb_attach_overlay(struct fb_info *fb_info, struct mcde_overlay *ovl)
+{
+ /* TODO: Attach extra overlay targets */
+ return -EINVAL;
+}
+
+void mcde_fb_destroy(struct mcde_display_device *dev)
+{
+ struct mcde_fb *mfb;
+ int i;
+
+ dev_vdbg(&dev->dev, "%s\n", __func__);
+
+ if (dev->fictive == false) {
+ mcde_dss_disable_display(dev);
+ mcde_dss_close_channel(dev);
+ }
+
+ mfb = to_mcde_fb(dev->fbi);
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ if (mfb->ovlys[i])
+ mcde_dss_destroy_overlay(mfb->ovlys[i]);
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if (dev->fictive == false)
+ unregister_early_suspend(&mfb->early_suspend);
+#endif
+ fb_dealloc_cmap(&dev->fbi->cmap);
+
+ unregister_framebuffer(dev->fbi);
+ free_fb_mem(dev->fbi);
+ framebuffer_release(dev->fbi);
+ dev->fbi = NULL;
+}
+
+/* Overlay fbs' platform device */
+static int mcde_fb_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int mcde_fb_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver mcde_fb_driver = {
+ .probe = mcde_fb_probe,
+ .remove = mcde_fb_remove,
+ .driver = {
+ .name = "mcde_fb",
+ .owner = THIS_MODULE,
+ },
+};
+
+/* MCDE fb init */
+
+int __init mcde_fb_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&mcde_fb_driver);
+ if (ret)
+ goto fb_driver_failed;
+ ret = platform_device_register(&mcde_fb_device);
+ if (ret)
+ goto fb_device_failed;
+
+ goto out;
+fb_device_failed:
+ platform_driver_unregister(&mcde_fb_driver);
+fb_driver_failed:
+out:
+ return ret;
+}
+
+void mcde_fb_exit(void)
+{
+ platform_device_unregister(&mcde_fb_device);
+ platform_driver_unregister(&mcde_fb_driver);
+}
diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c
new file mode 100644
index 00000000000..92cdb1ef7a9
--- /dev/null
+++ b/drivers/video/mcde/mcde_hw.c
@@ -0,0 +1,3834 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE base driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/dbx500-prcmu.h>
+
+#include <video/mcde.h>
+#include "dsilink_regs.h"
+#include "mcde_regs.h"
+#include "mcde_debugfs.h"
+
+
+/* MCDE channel states
+ *
+ * Allowed state transitions:
+ * IDLE <-> SUSPEND
+ * IDLE <-> DSI_READ
+ * IDLE <-> DSI_WRITE
+ * IDLE -> SETUP -> (WAIT_TE ->) RUNNING -> STOPPING1 -> STOPPING2 -> IDLE
+ * WAIT_TE -> STOPPED (for missing TE to allow re-enable)
+ */
+enum chnl_state {
+ CHNLSTATE_SUSPEND, /* HW in suspended mode, initial state */
+ CHNLSTATE_IDLE, /* Channel aquired, but not running, FLOEN==0 */
+ CHNLSTATE_DSI_READ, /* Executing DSI read */
+ CHNLSTATE_DSI_WRITE, /* Executing DSI write */
+ CHNLSTATE_SETUP, /* Channel register setup to prepare for running */
+ CHNLSTATE_WAIT_TE, /* Waiting for BTA or external TE */
+ CHNLSTATE_RUNNING, /* Update started, FLOEN=1, FLOEN==1 */
+ CHNLSTATE_STOPPING, /* Stopping, FLOEN=0, FLOEN==1, awaiting VCMP */
+ CHNLSTATE_STOPPED, /* Stopped, after VCMP, FLOEN==0|1 */
+};
+
+enum dsi_lane_status {
+ DSI_LANE_STATE_START = 0x00,
+ DSI_LANE_STATE_IDLE = 0x01,
+ DSI_LANE_STATE_WRITE = 0x02,
+ DSI_LANE_STATE_ULPM = 0x03,
+};
+
+static int set_channel_state_atomic(struct mcde_chnl_state *chnl,
+ enum chnl_state state);
+static int set_channel_state_sync(struct mcde_chnl_state *chnl,
+ enum chnl_state state);
+static void stop_channel(struct mcde_chnl_state *chnl);
+static int _mcde_chnl_enable(struct mcde_chnl_state *chnl);
+static int _mcde_chnl_apply(struct mcde_chnl_state *chnl);
+static void disable_flow(struct mcde_chnl_state *chnl);
+static void enable_flow(struct mcde_chnl_state *chnl);
+static void do_softwaretrig(struct mcde_chnl_state *chnl);
+static void dsi_te_poll_req(struct mcde_chnl_state *chnl);
+static void dsi_te_poll_set_timer(struct mcde_chnl_state *chnl,
+ unsigned int timeout);
+static void dsi_te_timer_function(unsigned long value);
+static int wait_for_vcmp(struct mcde_chnl_state *chnl);
+static int probe_hw(struct platform_device *pdev);
+static void wait_for_flow_disabled(struct mcde_chnl_state *chnl);
+
+#define OVLY_TIMEOUT 100
+#define CHNL_TIMEOUT 100
+#define FLOW_STOP_TIMEOUT 20
+#define SCREEN_PPL_HIGH 1280
+#define SCREEN_PPL_CEA2 720
+#define SCREEN_LPF_CEA2 480
+#define DSI_DELAY0_CEA2_ADD 10
+
+#define MCDE_SLEEP_WATCHDOG 500
+#define DSI_TE_NO_ANSWER_TIMEOUT_INIT 2500
+#define DSI_TE_NO_ANSWER_TIMEOUT 250
+#define DSI_WAIT_FOR_ULPM_STATE_MS 1
+#define DSI_ULPM_STATE_NBR_OF_RETRIES 10
+#define DSI_READ_TIMEOUT 200
+#define DSI_WRITE_CMD_TIMEOUT 1000
+#define DSI_READ_DELAY 5
+#define DSI_READ_NBR_OF_RETRIES 2
+#define MCDE_FLOWEN_MAX_TRIAL 60
+
+#define MCDE_VERSION_4_1_3 0x04010300
+#define MCDE_VERSION_4_0_4 0x04000400
+#define MCDE_VERSION_3_0_8 0x03000800
+#define MCDE_VERSION_3_0_5 0x03000500
+#define MCDE_VERSION_1_0_4 0x01000400
+
+#define CLK_MCDE "mcde"
+#define CLK_DPI "lcd"
+
+static u8 *mcdeio;
+static u8 **dsiio;
+static struct platform_device *mcde_dev;
+static u8 num_dsilinks;
+static u8 num_channels;
+static u8 num_overlays;
+static int mcde_irq;
+static u32 input_fifo_size;
+static u32 output_fifo_ab_size;
+static u32 output_fifo_c0c1_size;
+
+static struct regulator *regulator_vana;
+static struct regulator *regulator_mcde_epod;
+static struct regulator *regulator_esram_epod;
+static struct clk *clock_mcde;
+
+/* TODO remove when all platforms support dsilp and dsihs clocks */
+static struct clk *clock_dsi;
+static struct clk *clock_dsi_lp;
+
+static u8 mcde_is_enabled;
+static struct delayed_work hw_timeout_work;
+static u8 dsi_pll_is_enabled;
+static u8 dsi_ifc_is_supported;
+static u8 dsi_use_clk_framework;
+static u32 mcde_clk_rate; /* In Hz */
+
+static struct mutex mcde_hw_lock;
+static inline void mcde_lock(const char *func, int line)
+{
+ mutex_lock(&mcde_hw_lock);
+ dev_vdbg(&mcde_dev->dev, "Enter MCDE: %s:%d\n", func, line);
+}
+
+static inline void mcde_unlock(const char *func, int line)
+{
+ dev_vdbg(&mcde_dev->dev, "Exit MCDE: %s:%d\n", func, line);
+ mutex_unlock(&mcde_hw_lock);
+}
+
+static inline bool mcde_trylock(const char *func, int line)
+{
+ bool locked = mutex_trylock(&mcde_hw_lock) == 1;
+ if (locked)
+ dev_vdbg(&mcde_dev->dev, "Enter MCDE: %s:%d\n", func, line);
+ return locked;
+}
+
+static u8 mcde_dynamic_power_management = true;
+
+static inline u32 dsi_rreg(int i, u32 reg)
+{
+ return readl(dsiio[i] + reg);
+}
+static inline void dsi_wreg(int i, u32 reg, u32 val)
+{
+ writel(val, dsiio[i] + reg);
+}
+
+#define dsi_rfld(__i, __reg, __fld) \
+({ \
+ const u32 mask = __reg##_##__fld##_MASK; \
+ const u32 shift = __reg##_##__fld##_SHIFT; \
+ ((dsi_rreg(__i, __reg) & mask) >> shift); \
+})
+
+#define dsi_wfld(__i, __reg, __fld, __val) \
+({ \
+ const u32 mask = __reg##_##__fld##_MASK; \
+ const u32 shift = __reg##_##__fld##_SHIFT; \
+ const u32 oldval = dsi_rreg(__i, __reg); \
+ const u32 newval = ((__val) << shift); \
+ dsi_wreg(__i, __reg, (oldval & ~mask) | (newval & mask)); \
+})
+
+static inline u32 mcde_rreg(u32 reg)
+{
+ return readl(mcdeio + reg);
+}
+static inline void mcde_wreg(u32 reg, u32 val)
+{
+ writel(val, mcdeio + reg);
+}
+
+
+#define mcde_rfld(__reg, __fld) \
+({ \
+ const u32 mask = __reg##_##__fld##_MASK; \
+ const u32 shift = __reg##_##__fld##_SHIFT; \
+ ((mcde_rreg(__reg) & mask) >> shift); \
+})
+
+#define mcde_wfld(__reg, __fld, __val) \
+({ \
+ const u32 mask = __reg##_##__fld##_MASK; \
+ const u32 shift = __reg##_##__fld##_SHIFT; \
+ const u32 oldval = mcde_rreg(__reg); \
+ const u32 newval = ((__val) << shift); \
+ mcde_wreg(__reg, (oldval & ~mask) | (newval & mask)); \
+})
+
+struct ovly_regs {
+ bool enabled;
+ bool dirty;
+ bool dirty_buf;
+
+ u8 ch_id;
+ u32 baseaddress0;
+ u32 baseaddress1;
+ u8 bits_per_pixel;
+ u8 bpp;
+ bool bgr;
+ bool bebo;
+ bool opq;
+ u8 col_conv;
+ u8 alpha_source;
+ u8 alpha_value;
+ u8 pixoff;
+ u16 ppl;
+ u16 lpf;
+ u16 cropx;
+ u16 cropy;
+ u16 xpos;
+ u16 ypos;
+ u8 z;
+};
+
+struct mcde_ovly_state {
+ bool inuse;
+ u8 idx; /* MCDE overlay index */
+ struct mcde_chnl_state *chnl; /* Owner channel */
+ bool dirty;
+ bool dirty_buf;
+
+ /* Staged settings */
+ u32 paddr;
+ u16 stride;
+ enum mcde_ovly_pix_fmt pix_fmt;
+
+ u16 src_x;
+ u16 src_y;
+ u16 dst_x;
+ u16 dst_y;
+ u16 dst_z;
+ u16 w;
+ u16 h;
+
+ u8 alpha_source;
+ u8 alpha_value;
+
+ /* Applied settings */
+ struct ovly_regs regs;
+};
+
+static struct mcde_ovly_state *overlays;
+
+struct chnl_regs {
+ bool dirty;
+
+ bool floen;
+ u16 x;
+ u16 y;
+ u16 ppl;
+ u16 lpf;
+ u8 bpp;
+ bool internal_clk; /* CLKTYPE field */
+ u16 pcd;
+ u8 clksel;
+ u8 cdwin;
+ u16 (*map_r)(u8);
+ u16 (*map_g)(u8);
+ u16 (*map_b)(u8);
+ bool palette_enable;
+ bool bcd;
+ bool roten;
+ u8 rotdir;
+ u32 rotbuf1;
+ u32 rotbuf2;
+ u32 rotbufsize;
+
+ /* Blending */
+ u8 blend_ctrl;
+ bool blend_en;
+ u8 alpha_blend;
+
+ /* DSI */
+ u8 dsipacking;
+};
+
+struct col_regs {
+ bool dirty;
+
+ u16 y_red;
+ u16 y_green;
+ u16 y_blue;
+ u16 cb_red;
+ u16 cb_green;
+ u16 cb_blue;
+ u16 cr_red;
+ u16 cr_green;
+ u16 cr_blue;
+ u16 off_y;
+ u16 off_cb;
+ u16 off_cr;
+};
+
+struct tv_regs {
+ bool dirty;
+
+ u16 dho; /* TV mode: left border width; destination horizontal offset */
+ /* LCD MODE: horizontal back porch */
+ u16 alw; /* TV mode: right border width */
+ /* LCD mode: horizontal front porch */
+ u16 hsw; /* horizontal synch width */
+ u16 dvo; /* TV mode: top border width; destination horizontal offset */
+ /* LCD MODE: vertical back porch */
+ u16 bsl; /* TV mode: bottom border width; blanking start line */
+ /* LCD MODE: vertical front porch */
+ /* field 1 */
+ u16 bel1; /* TV mode: field total vertical blanking lines */
+ /* LCD mode: vertical sync width */
+ u16 fsl1; /* field vbp */
+ /* field 2 */
+ u16 bel2;
+ u16 fsl2;
+ u8 tv_mode;
+ bool sel_mode_tv;
+ bool inv_clk;
+ bool interlaced_en;
+ u32 lcdtim1;
+};
+
+struct mcde_chnl_state {
+ bool enabled;
+ bool reserved;
+ enum mcde_chnl id;
+ enum mcde_fifo fifo;
+ struct mcde_port port;
+ struct mcde_ovly_state *ovly0;
+ struct mcde_ovly_state *ovly1;
+ enum chnl_state state;
+ wait_queue_head_t state_waitq;
+ wait_queue_head_t vcmp_waitq;
+ atomic_t vcmp_cnt;
+ struct timer_list dsi_te_timer;
+ struct clk *clk_dsi_lp;
+ struct clk *clk_dsi_hs;
+ struct clk *clk_dpi;
+
+ enum mcde_display_power_mode power_mode;
+
+ /* Staged settings */
+ u16 (*map_r)(u8);
+ u16 (*map_g)(u8);
+ u16 (*map_b)(u8);
+ bool palette_enable;
+ struct mcde_video_mode vmode;
+ enum mcde_display_rotation rotation;
+ u32 rotbuf1;
+ u32 rotbuf2;
+ u32 rotbufsize;
+
+ struct mcde_col_transform rgb_2_ycbcr;
+ struct mcde_col_transform ycbcr_2_rgb;
+ struct mcde_col_transform *transform;
+
+ /* Blending */
+ u8 blend_ctrl;
+ bool blend_en;
+ u8 alpha_blend;
+
+ /* Applied settings */
+ struct chnl_regs regs;
+ struct col_regs col_regs;
+ struct tv_regs tv_regs;
+
+ /* an interlaced digital TV signal generates a VCMP per field */
+ bool vcmp_per_field;
+ bool even_vcmp;
+
+ bool formatter_updated;
+ bool esram_is_enabled;
+};
+
+static struct mcde_chnl_state *channels;
+/*
+ * Wait for CSM_RUNNING, all data sent for display
+ */
+static inline void wait_while_dsi_running(int lnk)
+{
+ u8 counter = DSI_READ_TIMEOUT;
+ while (dsi_rfld(lnk, DSI_CMD_MODE_STS, CSM_RUNNING) && --counter) {
+ dev_vdbg(&mcde_dev->dev,
+ "%s: DSI link %u read running state retry %u times\n"
+ , __func__, lnk, (DSI_READ_TIMEOUT - counter));
+ udelay(DSI_READ_DELAY);
+ }
+ WARN_ON(!counter);
+ if (!counter)
+ dev_warn(&mcde_dev->dev,
+ "%s: DSI link %u read timeout!\n", __func__, lnk);
+}
+
+static void enable_clocks_and_power(struct platform_device *pdev)
+{
+ struct mcde_platform_data *pdata = pdev->dev.platform_data;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ /* VANA should be enabled before a DSS hard reset */
+ if (regulator_vana)
+ WARN_ON_ONCE(regulator_enable(regulator_vana));
+
+ WARN_ON_ONCE(regulator_enable(regulator_mcde_epod));
+
+ if (!dsi_use_clk_framework)
+ pdata->platform_set_clocks();
+
+ WARN_ON_ONCE(clk_enable(clock_mcde));
+}
+
+static void disable_clocks_and_power(struct platform_device *pdev)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ clk_disable(clock_mcde);
+
+ WARN_ON_ONCE(regulator_disable(regulator_mcde_epod));
+
+ if (regulator_vana)
+ WARN_ON_ONCE(regulator_disable(regulator_vana));
+}
+
+static void update_mcde_registers(void)
+{
+ struct mcde_platform_data *pdata = mcde_dev->dev.platform_data;
+
+ /* Setup output muxing */
+ mcde_wreg(MCDE_CONF0,
+ MCDE_CONF0_IFIFOCTRLWTRMRKLVL(7) |
+ MCDE_CONF0_OUTMUX0(pdata->outmux[0]) |
+ MCDE_CONF0_OUTMUX1(pdata->outmux[1]) |
+ MCDE_CONF0_OUTMUX2(pdata->outmux[2]) |
+ MCDE_CONF0_OUTMUX3(pdata->outmux[3]) |
+ MCDE_CONF0_OUTMUX4(pdata->outmux[4]) |
+ pdata->syncmux);
+
+ mcde_wfld(MCDE_RISPP, VCMPARIS, 1);
+ mcde_wfld(MCDE_RISPP, VCMPBRIS, 1);
+ mcde_wfld(MCDE_RISPP, VCMPC0RIS, 1);
+ mcde_wfld(MCDE_RISPP, VCMPC1RIS, 1);
+
+ /* Enable channel VCMP interrupts */
+ mcde_wreg(MCDE_IMSCPP,
+ MCDE_IMSCPP_VCMPAIM(true) |
+ MCDE_IMSCPP_VCMPBIM(true) |
+ MCDE_IMSCPP_VCMPC0IM(true) |
+ MCDE_IMSCPP_VCMPC1IM(true));
+
+ mcde_wreg(MCDE_IMSCCHNL, MCDE_IMSCCHNL_CHNLAIM(0xf));
+ mcde_wreg(MCDE_IMSCERR, 0xFFFF01FF);
+
+ /* Setup sync pulse length
+ * Setting VSPMAX=0 disables the filter and VSYNC
+ * is generated after VSPMIN mcde cycles
+ */
+ mcde_wreg(MCDE_VSCRC0,
+ MCDE_VSCRC0_VSPMIN(0) |
+ MCDE_VSCRC0_VSPMAX(0));
+ mcde_wreg(MCDE_VSCRC1,
+ MCDE_VSCRC1_VSPMIN(1) |
+ MCDE_VSCRC1_VSPMAX(0xff));
+}
+
+static void dsi_link_handle_reset(u8 link, bool release)
+{
+ u32 value;
+
+ value = prcmu_read(DB8500_PRCM_DSI_SW_RESET);
+ if (release) {
+ switch (link) {
+ case 0:
+ value |= DB8500_PRCM_DSI_SW_RESET_DSI0_SW_RESETN;
+ break;
+ case 1:
+ value |= DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN;
+ break;
+ case 2:
+ value |= DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (link) {
+ case 0:
+ value &= ~DB8500_PRCM_DSI_SW_RESET_DSI0_SW_RESETN;
+ break;
+ case 1:
+ value &= ~DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN;
+ break;
+ case 2:
+ value &= ~DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN;
+ break;
+ default:
+ break;
+ }
+ }
+ prcmu_write(DB8500_PRCM_DSI_SW_RESET, value);
+}
+
+static void dsi_link_switch_byte_clk(u8 link, bool to_system_clock)
+{
+ u32 value;
+
+ value = prcmu_read(DB8500_PRCM_DSI_GLITCHFREE_EN);
+ if (to_system_clock) {
+ switch (link) {
+ case 0:
+ value |= DB8500_PRCM_DSI_GLITCHFREE_EN_DSI0_BYTE_CLK;
+ break;
+ case 1:
+ value |= DB8500_PRCM_DSI_GLITCHFREE_EN_DSI1_BYTE_CLK;
+ break;
+ case 2:
+ value |= DB8500_PRCM_DSI_GLITCHFREE_EN_DSI2_BYTE_CLK;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (link) {
+ case 0:
+ value &= ~DB8500_PRCM_DSI_GLITCHFREE_EN_DSI0_BYTE_CLK;
+ break;
+ case 1:
+ value &= ~DB8500_PRCM_DSI_GLITCHFREE_EN_DSI1_BYTE_CLK;
+ break;
+ case 2:
+ value &= ~DB8500_PRCM_DSI_GLITCHFREE_EN_DSI2_BYTE_CLK;
+ break;
+ default:
+ break;
+ }
+
+ }
+ prcmu_write(DB8500_PRCM_DSI_GLITCHFREE_EN, value);
+ dsi_wfld(link, DSI_MCTL_PLL_CTL, PLL_OUT_SEL, to_system_clock);
+}
+
+static void dsi_link_handle_ulpm(struct mcde_port *port, bool enter_ulpm)
+{
+ u8 link = port->link;
+ u8 num_data_lanes = port->phy.dsi.num_data_lanes;
+ u8 nbr_of_retries = 0;
+ u8 lane_state;
+
+ /*
+ * The D-PHY protocol specifies the time to leave the ULP mode
+ * in ms. It will at least take 1 ms to exit ULPM.
+ * The ULPOUT time value is using number of system clock ticks
+ * divided by 1000. The system clock for the DSI link is the MCDE
+ * clock.
+ */
+ dsi_wreg(link, DSI_MCTL_ULPOUT_TIME,
+ DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME(0x1FF) |
+ DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME(0x1FF));
+
+ if (enter_ulpm) {
+ lane_state = DSI_LANE_STATE_ULPM;
+ dsi_link_switch_byte_clk(link, true);
+ }
+
+ dsi_wfld(link, DSI_MCTL_MAIN_EN, DAT1_ULPM_REQ, enter_ulpm);
+ dsi_wfld(link, DSI_MCTL_MAIN_EN, DAT2_ULPM_REQ,
+ enter_ulpm && num_data_lanes == 2);
+ dsi_wfld(link, DSI_MCTL_MAIN_EN, CLKLANE_ULPM_REQ, enter_ulpm);
+
+ if (!enter_ulpm) {
+ lane_state = DSI_LANE_STATE_IDLE;
+ dsi_link_switch_byte_clk(link, false);
+ }
+
+ /* Wait for data lanes to enter ULPM */
+ while (dsi_rfld(link, DSI_MCTL_LANE_STS, DATLANE1_STATE)
+ != lane_state ||
+ (dsi_rfld(link, DSI_MCTL_LANE_STS, DATLANE2_STATE)
+ != lane_state &&
+ num_data_lanes > 1)) {
+ mdelay(DSI_WAIT_FOR_ULPM_STATE_MS);
+ if (nbr_of_retries++ == DSI_ULPM_STATE_NBR_OF_RETRIES) {
+ dev_dbg(&mcde_dev->dev,
+ "Could not enter correct state=%d (link=%d)!\n",
+ lane_state, link);
+ break;
+ }
+ }
+
+ nbr_of_retries = 0;
+ /* Wait for clock lane to enter ULPM */
+ while (dsi_rfld(link, DSI_MCTL_LANE_STS, CLKLANE_STATE)
+ != lane_state) {
+ mdelay(DSI_WAIT_FOR_ULPM_STATE_MS);
+ if (nbr_of_retries++ == DSI_ULPM_STATE_NBR_OF_RETRIES) {
+ dev_dbg(&mcde_dev->dev,
+ "Could not enter correct state=%d (link=%d)!\n",
+ lane_state, link);
+ break;
+ }
+ }
+}
+
+static int dsi_link_enable(struct mcde_chnl_state *chnl)
+{
+ int ret = 0;
+ u8 link = chnl->port.link;
+
+ if (dsi_use_clk_framework) {
+ WARN_ON_ONCE(clk_enable(chnl->clk_dsi_lp));
+ WARN_ON_ONCE(clk_enable(chnl->clk_dsi_hs));
+ dsi_link_handle_reset(link, true);
+ } else {
+ WARN_ON_ONCE(clk_enable(clock_dsi));
+ WARN_ON_ONCE(clk_enable(clock_dsi_lp));
+
+ if (!dsi_pll_is_enabled) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ ret = pdata->platform_enable_dsipll();
+ if (ret < 0) {
+ dev_warn(&mcde_dev->dev, "%s: "
+ "enable_dsipll failed ret = %d\n",
+ __func__, ret);
+ goto enable_dsipll_err;
+ }
+ dev_dbg(&mcde_dev->dev, "%s enable dsipll\n",
+ __func__);
+ }
+ dsi_pll_is_enabled++;
+ }
+
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, LINK_EN, true);
+
+ dev_dbg(&mcde_dev->dev, "DSI%d LINK_EN\n", link);
+
+ return 0;
+
+enable_dsipll_err:
+ clk_disable(clock_dsi_lp);
+ clk_disable(clock_dsi);
+ return ret;
+}
+
+static void dsi_link_disable(struct mcde_chnl_state *chnl, bool suspend)
+{
+ wait_while_dsi_running(chnl->port.link);
+ dsi_link_handle_ulpm(&chnl->port, true);
+ if (dsi_use_clk_framework) {
+ clk_disable(chnl->clk_dsi_lp);
+ clk_disable(chnl->clk_dsi_hs);
+ } else {
+ if (dsi_pll_is_enabled && (--dsi_pll_is_enabled == 0)) {
+ struct mcde_platform_data *pdata =
+ mcde_dev->dev.platform_data;
+ dev_dbg(&mcde_dev->dev, "%s disable dsipll\n",
+ __func__);
+ pdata->platform_disable_dsipll();
+ }
+ clk_disable(clock_dsi);
+ clk_disable(clock_dsi_lp);
+ }
+}
+
+static void disable_mcde_hw(bool force_disable, bool suspend)
+{
+ int i;
+ bool mcde_up = false;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!mcde_is_enabled)
+ return;
+
+ for (i = 0; i < num_channels; i++) {
+ struct mcde_chnl_state *chnl = &channels[i];
+ if (force_disable || (chnl->enabled &&
+ chnl->state != CHNLSTATE_RUNNING)) {
+ stop_channel(chnl);
+ set_channel_state_sync(chnl, CHNLSTATE_SUSPEND);
+
+ if (chnl->formatter_updated) {
+ if (chnl->port.type == MCDE_PORTTYPE_DSI)
+ dsi_link_disable(chnl, suspend);
+ else if (chnl->port.type == MCDE_PORTTYPE_DPI)
+ clk_disable(chnl->clk_dpi);
+ chnl->formatter_updated = false;
+ }
+ if (chnl->esram_is_enabled) {
+ WARN_ON_ONCE(regulator_disable(
+ regulator_esram_epod));
+ chnl->esram_is_enabled = false;
+ }
+ } else if (chnl->enabled && chnl->state == CHNLSTATE_RUNNING) {
+ mcde_up = true;
+ }
+ }
+
+ if (mcde_up)
+ return;
+
+ free_irq(mcde_irq, &mcde_dev->dev);
+
+ disable_clocks_and_power(mcde_dev);
+
+ mcde_is_enabled = false;
+}
+
+static void dpi_video_mode_apply(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+ chnl->tv_regs.interlaced_en = chnl->vmode.interlaced;
+
+ chnl->tv_regs.sel_mode_tv = chnl->port.phy.dpi.tv_mode;
+ if (chnl->tv_regs.sel_mode_tv) {
+ /* TV mode */
+ u32 bel;
+ /* -4 since hsw is excluding SAV/EAV, 2 bytes each */
+ chnl->tv_regs.hsw = chnl->vmode.hbp + chnl->vmode.hfp - 4;
+ /* vbp_field2 = vbp_field1 + 1 */
+ chnl->tv_regs.fsl1 = chnl->vmode.vbp / 2;
+ chnl->tv_regs.fsl2 = chnl->vmode.vbp - chnl->tv_regs.fsl1;
+ /* +1 since vbp_field2 = vbp_field1 + 1 */
+ bel = chnl->vmode.vbp + chnl->vmode.vfp;
+ /* in TV mode: bel2 = bel1 + 1 */
+ chnl->tv_regs.bel1 = bel / 2;
+ chnl->tv_regs.bel2 = bel - chnl->tv_regs.bel1;
+ if (chnl->port.phy.dpi.bus_width == 4)
+ chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P_BE;
+ else
+ chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P;
+ chnl->tv_regs.inv_clk = true;
+ } else {
+ /* LCD mode */
+ u32 polarity;
+ chnl->tv_regs.hsw = chnl->vmode.hsw;
+ chnl->tv_regs.dho = chnl->vmode.hbp;
+ chnl->tv_regs.alw = chnl->vmode.hfp;
+ chnl->tv_regs.bel1 = chnl->vmode.vsw;
+ chnl->tv_regs.bel2 = chnl->tv_regs.bel1;
+ chnl->tv_regs.dvo = chnl->vmode.vbp;
+ chnl->tv_regs.bsl = chnl->vmode.vfp;
+ chnl->tv_regs.fsl1 = 0;
+ chnl->tv_regs.fsl2 = 0;
+ polarity = chnl->port.phy.dpi.polarity;
+ chnl->tv_regs.lcdtim1 = MCDE_LCDTIM1A_IHS(
+ (polarity & DPI_ACT_LOW_HSYNC) != 0);
+ chnl->tv_regs.lcdtim1 |= MCDE_LCDTIM1A_IVS(
+ (polarity & DPI_ACT_LOW_VSYNC) != 0);
+ chnl->tv_regs.lcdtim1 |= MCDE_LCDTIM1A_IOE(
+ (polarity & DPI_ACT_LOW_DATA_ENABLE) != 0);
+ chnl->tv_regs.lcdtim1 |= MCDE_LCDTIM1A_IPC(
+ (polarity & DPI_ACT_ON_FALLING_EDGE) != 0);
+ }
+ chnl->tv_regs.dirty = true;
+}
+
+static void update_dpi_registers(enum mcde_chnl chnl_id, struct tv_regs *regs)
+{
+ u8 idx = chnl_id;
+
+ dev_dbg(&mcde_dev->dev, "%s\n", __func__);
+ mcde_wreg(MCDE_TVCRA + idx * MCDE_TVCRA_GROUPOFFSET,
+ MCDE_TVCRA_SEL_MOD(regs->sel_mode_tv) |
+ MCDE_TVCRA_INTEREN(regs->interlaced_en) |
+ MCDE_TVCRA_IFIELD(0) |
+ MCDE_TVCRA_TVMODE(regs->tv_mode) |
+ MCDE_TVCRA_SDTVMODE(MCDE_TVCRA_SDTVMODE_Y0CBY1CR) |
+ MCDE_TVCRA_CKINV(regs->inv_clk) |
+ MCDE_TVCRA_AVRGEN(0));
+ mcde_wreg(MCDE_TVBLUA + idx * MCDE_TVBLUA_GROUPOFFSET,
+ MCDE_TVBLUA_TVBLU(MCDE_CONFIG_TVOUT_BACKGROUND_LUMINANCE) |
+ MCDE_TVBLUA_TVBCB(MCDE_CONFIG_TVOUT_BACKGROUND_CHROMINANCE_CB)|
+ MCDE_TVBLUA_TVBCR(MCDE_CONFIG_TVOUT_BACKGROUND_CHROMINANCE_CR));
+
+ /* Vertical timing registers */
+ mcde_wreg(MCDE_TVDVOA + idx * MCDE_TVDVOA_GROUPOFFSET,
+ MCDE_TVDVOA_DVO1(regs->dvo) |
+ MCDE_TVDVOA_DVO2(regs->dvo));
+ mcde_wreg(MCDE_TVBL1A + idx * MCDE_TVBL1A_GROUPOFFSET,
+ MCDE_TVBL1A_BEL1(regs->bel1) |
+ MCDE_TVBL1A_BSL1(regs->bsl));
+ mcde_wreg(MCDE_TVBL2A + idx * MCDE_TVBL1A_GROUPOFFSET,
+ MCDE_TVBL2A_BEL2(regs->bel2) |
+ MCDE_TVBL2A_BSL2(regs->bsl));
+ mcde_wreg(MCDE_TVISLA + idx * MCDE_TVISLA_GROUPOFFSET,
+ MCDE_TVISLA_FSL1(regs->fsl1) |
+ MCDE_TVISLA_FSL2(regs->fsl2));
+
+ /* Horizontal timing registers */
+ mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET,
+ MCDE_TVLBALWA_LBW(regs->hsw) |
+ MCDE_TVLBALWA_ALW(regs->alw));
+ mcde_wreg(MCDE_TVTIM1A + idx * MCDE_TVTIM1A_GROUPOFFSET,
+ MCDE_TVTIM1A_DHO(regs->dho));
+ if (!regs->sel_mode_tv)
+ mcde_wreg(MCDE_LCDTIM1A + idx * MCDE_LCDTIM1A_GROUPOFFSET,
+ regs->lcdtim1);
+ regs->dirty = false;
+}
+
+static void update_col_registers(enum mcde_chnl chnl_id, struct col_regs *regs)
+{
+ u8 idx = chnl_id;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+ mcde_wreg(MCDE_RGBCONV1A + idx * MCDE_RGBCONV1A_GROUPOFFSET,
+ MCDE_RGBCONV1A_YR_RED(regs->y_red) |
+ MCDE_RGBCONV1A_YR_GREEN(regs->y_green));
+ mcde_wreg(MCDE_RGBCONV2A + idx * MCDE_RGBCONV2A_GROUPOFFSET,
+ MCDE_RGBCONV2A_YR_BLUE(regs->y_blue) |
+ MCDE_RGBCONV2A_CR_RED(regs->cr_red));
+ mcde_wreg(MCDE_RGBCONV3A + idx * MCDE_RGBCONV3A_GROUPOFFSET,
+ MCDE_RGBCONV3A_CR_GREEN(regs->cr_green) |
+ MCDE_RGBCONV3A_CR_BLUE(regs->cr_blue));
+ mcde_wreg(MCDE_RGBCONV4A + idx * MCDE_RGBCONV4A_GROUPOFFSET,
+ MCDE_RGBCONV4A_CB_RED(regs->cb_red) |
+ MCDE_RGBCONV4A_CB_GREEN(regs->cb_green));
+ mcde_wreg(MCDE_RGBCONV5A + idx * MCDE_RGBCONV5A_GROUPOFFSET,
+ MCDE_RGBCONV5A_CB_BLUE(regs->cb_blue) |
+ MCDE_RGBCONV5A_OFF_RED(regs->off_cr));
+ mcde_wreg(MCDE_RGBCONV6A + idx * MCDE_RGBCONV6A_GROUPOFFSET,
+ MCDE_RGBCONV6A_OFF_GREEN(regs->off_y) |
+ MCDE_RGBCONV6A_OFF_BLUE(regs->off_cb));
+ regs->dirty = false;
+}
+
+/* MCDE internal helpers */
+static u8 portfmt2dsipacking(enum mcde_port_pix_fmt pix_fmt)
+{
+ switch (pix_fmt) {
+ case MCDE_PORTPIXFMT_DSI_16BPP:
+ return MCDE_DSIVID0CONF0_PACKING_RGB565;
+ case MCDE_PORTPIXFMT_DSI_18BPP_PACKED:
+ return MCDE_DSIVID0CONF0_PACKING_RGB666;
+ case MCDE_PORTPIXFMT_DSI_18BPP:
+ case MCDE_PORTPIXFMT_DSI_24BPP:
+ default:
+ return MCDE_DSIVID0CONF0_PACKING_RGB888;
+ case MCDE_PORTPIXFMT_DSI_YCBCR422:
+ return MCDE_DSIVID0CONF0_PACKING_HDTV;
+ }
+}
+
+static u8 portfmt2bpp(enum mcde_port_pix_fmt pix_fmt)
+{
+ /* TODO: Check DPI spec *//* REVIEW: Remove or check */
+ switch (pix_fmt) {
+ case MCDE_PORTPIXFMT_DPI_16BPP_C1:
+ case MCDE_PORTPIXFMT_DPI_16BPP_C2:
+ case MCDE_PORTPIXFMT_DPI_16BPP_C3:
+ case MCDE_PORTPIXFMT_DSI_16BPP:
+ case MCDE_PORTPIXFMT_DSI_YCBCR422:
+ return 16;
+ case MCDE_PORTPIXFMT_DPI_18BPP_C1:
+ case MCDE_PORTPIXFMT_DPI_18BPP_C2:
+ case MCDE_PORTPIXFMT_DSI_18BPP_PACKED:
+ return 18;
+ case MCDE_PORTPIXFMT_DSI_18BPP:
+ case MCDE_PORTPIXFMT_DPI_24BPP:
+ case MCDE_PORTPIXFMT_DSI_24BPP:
+ return 24;
+ default:
+ return 1;
+ }
+}
+
+static u8 bpp2outbpp(u8 bpp)
+{
+ switch (bpp) {
+ case 16:
+ return MCDE_CRA1_OUTBPP_16BPP;
+ case 18:
+ return MCDE_CRA1_OUTBPP_18BPP;
+ case 24:
+ return MCDE_CRA1_OUTBPP_24BPP;
+ default:
+ return 0;
+ }
+}
+
+static u8 portfmt2cdwin(enum mcde_port_pix_fmt pix_fmt)
+{
+ switch (pix_fmt) {
+ case MCDE_PORTPIXFMT_DPI_16BPP_C1:
+ return MCDE_CRA1_CDWIN_16BPP_C1;
+ case MCDE_PORTPIXFMT_DPI_16BPP_C2:
+ return MCDE_CRA1_CDWIN_16BPP_C2;
+ case MCDE_PORTPIXFMT_DPI_16BPP_C3:
+ return MCDE_CRA1_CDWIN_16BPP_C3;
+ case MCDE_PORTPIXFMT_DPI_18BPP_C1:
+ return MCDE_CRA1_CDWIN_18BPP_C1;
+ case MCDE_PORTPIXFMT_DPI_18BPP_C2:
+ return MCDE_CRA1_CDWIN_18BPP_C2;
+ case MCDE_PORTPIXFMT_DPI_24BPP:
+ return MCDE_CRA1_CDWIN_24BPP;
+ default:
+ /* only DPI formats are relevant */
+ return 0;
+ }
+}
+
+static u32 get_output_fifo_size(enum mcde_fifo fifo)
+{
+ u32 ret = 1; /* Avoid div by zero */
+
+ switch (fifo) {
+ case MCDE_FIFO_A:
+ case MCDE_FIFO_B:
+ ret = output_fifo_ab_size;
+ break;
+ case MCDE_FIFO_C0:
+ case MCDE_FIFO_C1:
+ ret = output_fifo_c0c1_size;
+ break;
+ default:
+ dev_warn(&mcde_dev->dev, "Unsupported fifo");
+ break;
+ }
+ return ret;
+}
+
+static inline u8 get_dsi_formatter_id(const struct mcde_port *port)
+{
+ if (dsi_ifc_is_supported)
+ return 2 * port->link + port->ifc;
+ else
+ return port->link;
+}
+
+static struct mcde_chnl_state *find_channel_by_dsilink(int link)
+{
+ struct mcde_chnl_state *chnl = &channels[0];
+ for (; chnl < &channels[num_channels]; chnl++)
+ if (chnl->enabled && chnl->port.link == link &&
+ chnl->port.type == MCDE_PORTTYPE_DSI)
+ return chnl;
+ return NULL;
+}
+
+static inline void mcde_handle_vcmp(struct mcde_chnl_state *chnl)
+{
+ if (!chnl->vcmp_per_field ||
+ (chnl->vcmp_per_field && chnl->even_vcmp)) {
+ atomic_inc(&chnl->vcmp_cnt);
+ if (chnl->state == CHNLSTATE_STOPPING)
+ set_channel_state_atomic(chnl, CHNLSTATE_STOPPED);
+ wake_up_all(&chnl->vcmp_waitq);
+ }
+ chnl->even_vcmp = !chnl->even_vcmp;
+}
+
+static void handle_dsi_irq(struct mcde_chnl_state *chnl, int i)
+{
+ u32 irq_status = dsi_rfld(i, DSI_DIRECT_CMD_STS_FLAG, TE_RECEIVED_FLAG);
+ if (irq_status) {
+ dsi_wreg(i, DSI_DIRECT_CMD_STS_CLR,
+ DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR(true));
+ dev_vdbg(&mcde_dev->dev, "BTA TE DSI%d\n", i);
+ if (chnl->port.frame_trig == MCDE_TRIG_SW)
+ do_softwaretrig(chnl);
+ }
+
+ irq_status = dsi_rfld(i, DSI_CMD_MODE_STS_FLAG, ERR_NO_TE_FLAG);
+ if (irq_status) {
+ dsi_wreg(i, DSI_CMD_MODE_STS_CLR,
+ DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR(true));
+ dev_warn(&mcde_dev->dev, "NO_TE DSI%d\n", i);
+ set_channel_state_atomic(chnl, CHNLSTATE_STOPPED);
+ }
+
+ irq_status = dsi_rfld(i, DSI_DIRECT_CMD_STS, TRIGGER_RECEIVED);
+ if (irq_status) {
+ /* DSI TE polling answer received */
+ dsi_wreg(i, DSI_DIRECT_CMD_STS_CLR,
+ DSI_DIRECT_CMD_STS_CLR_TRIGGER_RECEIVED_CLR(true));
+
+ /* Reset TE watchdog timer */
+ if (chnl->port.sync_src == MCDE_SYNCSRC_TE_POLLING)
+ dsi_te_poll_set_timer(chnl, DSI_TE_NO_ANSWER_TIMEOUT);
+ }
+}
+
+static irqreturn_t mcde_irq_handler(int irq, void *dev)
+{
+ int i;
+ u32 irq_status;
+
+ irq_status = mcde_rreg(MCDE_MISCHNL);
+ if (irq_status) {
+ dev_err(&mcde_dev->dev, "chnl error=%.8x\n", irq_status);
+ mcde_wreg(MCDE_RISCHNL, irq_status);
+ }
+ irq_status = mcde_rreg(MCDE_MISERR);
+ if (irq_status) {
+ dev_err(&mcde_dev->dev, "error=%.8x\n", irq_status);
+ mcde_wreg(MCDE_RISERR, irq_status);
+ }
+
+ /* Handle channel irqs */
+ irq_status = mcde_rreg(MCDE_RISPP);
+ if (irq_status & MCDE_RISPP_VCMPARIS_MASK)
+ mcde_handle_vcmp(&channels[MCDE_CHNL_A]);
+ if (irq_status & MCDE_RISPP_VCMPBRIS_MASK)
+ mcde_handle_vcmp(&channels[MCDE_CHNL_B]);
+ if (irq_status & MCDE_RISPP_VCMPC0RIS_MASK)
+ mcde_handle_vcmp(&channels[MCDE_CHNL_C0]);
+ if (irq_status & MCDE_RISPP_VCMPC1RIS_MASK)
+ mcde_handle_vcmp(&channels[MCDE_CHNL_C1]);
+ mcde_wreg(MCDE_RISPP, irq_status);
+
+ for (i = 0; i < num_dsilinks; i++) {
+ struct mcde_chnl_state *chnl_from_dsi;
+
+ chnl_from_dsi = find_channel_by_dsilink(i);
+
+ if (chnl_from_dsi == NULL)
+ continue;
+
+ handle_dsi_irq(chnl_from_dsi, i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Transitions allowed: WAIT_TE -> UPDATE -> STOPPING */
+static int set_channel_state_atomic(struct mcde_chnl_state *chnl,
+ enum chnl_state state)
+{
+ enum chnl_state chnl_state = chnl->state;
+
+ dev_dbg(&mcde_dev->dev, "Channel state change"
+ " (chnl=%d, old=%d, new=%d)\n", chnl->id, chnl_state, state);
+
+ if ((chnl_state == CHNLSTATE_SETUP && state == CHNLSTATE_WAIT_TE) ||
+ (chnl_state == CHNLSTATE_SETUP && state == CHNLSTATE_RUNNING) ||
+ (chnl_state == CHNLSTATE_WAIT_TE && state == CHNLSTATE_RUNNING) ||
+ (chnl_state == CHNLSTATE_RUNNING && state == CHNLSTATE_STOPPING)) {
+ /* Set wait TE, running, or stopping state */
+ chnl->state = state;
+ return 0;
+ } else if ((chnl_state == CHNLSTATE_STOPPING &&
+ state == CHNLSTATE_STOPPED) ||
+ (chnl_state == CHNLSTATE_WAIT_TE &&
+ state == CHNLSTATE_STOPPED)) {
+ /* Set stopped state */
+ chnl->state = state;
+ wake_up_all(&chnl->state_waitq);
+ return 0;
+ } else if (state == CHNLSTATE_IDLE) {
+ /* Set idle state */
+ WARN_ON_ONCE(chnl_state != CHNLSTATE_DSI_READ &&
+ chnl_state != CHNLSTATE_DSI_WRITE &&
+ chnl_state != CHNLSTATE_SUSPEND);
+ chnl->state = state;
+ wake_up_all(&chnl->state_waitq);
+ return 0;
+ } else {
+ /* Invalid atomic state transition */
+ dev_warn(&mcde_dev->dev, "Channel state change error (chnl=%d,"
+ " old=%d, new=%d)\n", chnl->id, chnl_state, state);
+ WARN_ON_ONCE(true);
+ return -EINVAL;
+ }
+}
+
+/* LOCKING: mcde_hw_lock */
+static int set_channel_state_sync(struct mcde_chnl_state *chnl,
+ enum chnl_state state)
+{
+ int ret = 0;
+ enum chnl_state chnl_state = chnl->state;
+
+ dev_dbg(&mcde_dev->dev, "Channel state change"
+ " (chnl=%d, old=%d, new=%d)\n", chnl->id, chnl->state, state);
+
+ /* No change */
+ if (chnl_state == state)
+ return 0;
+
+ /* Wait for IDLE before changing state */
+ if (chnl_state != CHNLSTATE_IDLE) {
+ ret = wait_event_timeout(chnl->state_waitq,
+ /* STOPPED -> IDLE is manual, so wait for both */
+ chnl->state == CHNLSTATE_STOPPED ||
+ chnl->state == CHNLSTATE_IDLE,
+ msecs_to_jiffies(CHNL_TIMEOUT));
+ if (WARN_ON_ONCE(!ret))
+ dev_warn(&mcde_dev->dev, "Wait for channel timeout "
+ "(chnl=%d, curr=%d, new=%d)\n",
+ chnl->id, chnl->state, state);
+ chnl_state = chnl->state;
+ }
+
+ /* Do manual transition from STOPPED to IDLE */
+ if (chnl_state == CHNLSTATE_STOPPED)
+ wait_for_flow_disabled(chnl);
+
+ /* State is IDLE, do transition to new state */
+ chnl->state = state;
+
+ return ret;
+}
+
+static int wait_for_vcmp(struct mcde_chnl_state *chnl)
+{
+ u64 vcmp = atomic_read(&chnl->vcmp_cnt) + 1;
+ int ret = wait_event_timeout(chnl->vcmp_waitq,
+ atomic_read(&chnl->vcmp_cnt) >= vcmp,
+ msecs_to_jiffies(CHNL_TIMEOUT));
+ return ret;
+}
+
+static void get_vid_operating_mode(const struct mcde_port *port,
+ bool *burst_mode, bool *sync_is_pulse, bool *tvg_enable)
+{
+ switch (port->phy.dsi.vid_mode) {
+ case NON_BURST_MODE_WITH_SYNC_EVENT:
+ *burst_mode = false;
+ *sync_is_pulse = false;
+ *tvg_enable = false;
+ break;
+ case NON_BURST_MODE_WITH_SYNC_EVENT_TVG_ENABLED:
+ *burst_mode = false;
+ *sync_is_pulse = false;
+ *tvg_enable = true;
+ break;
+ case BURST_MODE_WITH_SYNC_EVENT:
+ *burst_mode = true;
+ *sync_is_pulse = false;
+ *tvg_enable = false;
+ break;
+ case BURST_MODE_WITH_SYNC_PULSE:
+ *burst_mode = true;
+ *sync_is_pulse = true;
+ *tvg_enable = false;
+ break;
+ default:
+ dev_err(&mcde_dev->dev, "Unsupported video mode");
+ break;
+ }
+}
+
+static void update_vid_static_registers(const struct mcde_port *port)
+{
+ u8 link = port->link;
+ bool burst_mode, sync_is_pulse, tvg_enable;
+
+ get_vid_operating_mode(port, &burst_mode, &sync_is_pulse, &tvg_enable);
+
+ /* burst mode or non-burst mode */
+ dsi_wfld(link, DSI_VID_MAIN_CTL, BURST_MODE, burst_mode);
+
+ /* sync is pulse or event */
+ dsi_wfld(link, DSI_VID_MAIN_CTL, SYNC_PULSE_ACTIVE, sync_is_pulse);
+ dsi_wfld(link, DSI_VID_MAIN_CTL, SYNC_PULSE_HORIZONTAL, sync_is_pulse);
+
+ /* disable video stream when using TVG */
+ if (tvg_enable) {
+ dsi_wfld(link, DSI_MCTL_MAIN_EN, IF1_EN, false);
+ dsi_wfld(link, DSI_MCTL_MAIN_EN, IF2_EN, false);
+ }
+
+ /*
+ * behavior during blanking time
+ * 00: NULL packet 1x:LP 01:blanking-packet
+ */
+ dsi_wfld(link, DSI_VID_MAIN_CTL, REG_BLKLINE_MODE, 1);
+
+ /*
+ * behavior during eol
+ * 00: NULL packet 1x:LP 01:blanking-packet
+ */
+ dsi_wfld(link, DSI_VID_MAIN_CTL, REG_BLKEOL_MODE, 2);
+
+ /* time to perform LP->HS on D-PHY */
+ dsi_wfld(link, DSI_VID_DPHY_TIME, REG_WAKEUP_TIME,
+ port->phy.dsi.vid_wakeup_time);
+
+ /*
+ * video stream starts on VSYNC packet
+ * and stops at the end of a frame
+ */
+ dsi_wfld(link, DSI_VID_MAIN_CTL, VID_ID, port->phy.dsi.virt_id);
+ dsi_wfld(link, DSI_VID_MAIN_CTL, START_MODE, 0);
+ dsi_wfld(link, DSI_VID_MAIN_CTL, STOP_MODE, 0);
+
+ /* 1: if1 in video mode, 0: if1 in command mode */
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, IF1_MODE, 1);
+
+ /* 1: enables the link, 0: disables the link */
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, VID_EN, 1);
+}
+
+static int update_channel_static_registers(struct mcde_chnl_state *chnl)
+{
+ const struct mcde_port *port = &chnl->port;
+
+ switch (chnl->fifo) {
+ case MCDE_FIFO_A:
+ mcde_wreg(MCDE_CHNL0MUXING + chnl->id *
+ MCDE_CHNL0MUXING_GROUPOFFSET,
+ MCDE_CHNL0MUXING_FIFO_ID_ENUM(FIFO_A));
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ mcde_wfld(MCDE_CTRLA, FORMTYPE,
+ MCDE_CTRLA_FORMTYPE_DPITV);
+ mcde_wfld(MCDE_CTRLA, FORMID, port->link);
+ } else if (port->type == MCDE_PORTTYPE_DSI) {
+ mcde_wfld(MCDE_CTRLA, FORMTYPE,
+ MCDE_CTRLA_FORMTYPE_DSI);
+ mcde_wfld(MCDE_CTRLA, FORMID,
+ get_dsi_formatter_id(port));
+ }
+ break;
+ case MCDE_FIFO_B:
+ mcde_wreg(MCDE_CHNL0MUXING + chnl->id *
+ MCDE_CHNL0MUXING_GROUPOFFSET,
+ MCDE_CHNL0MUXING_FIFO_ID_ENUM(FIFO_B));
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ mcde_wfld(MCDE_CTRLB, FORMTYPE,
+ MCDE_CTRLB_FORMTYPE_DPITV);
+ mcde_wfld(MCDE_CTRLB, FORMID, port->link);
+ } else if (port->type == MCDE_PORTTYPE_DSI) {
+ mcde_wfld(MCDE_CTRLB, FORMTYPE,
+ MCDE_CTRLB_FORMTYPE_DSI);
+ mcde_wfld(MCDE_CTRLB, FORMID,
+ get_dsi_formatter_id(port));
+ }
+
+ break;
+ case MCDE_FIFO_C0:
+ mcde_wreg(MCDE_CHNL0MUXING + chnl->id *
+ MCDE_CHNL0MUXING_GROUPOFFSET,
+ MCDE_CHNL0MUXING_FIFO_ID_ENUM(FIFO_C0));
+ if (port->type == MCDE_PORTTYPE_DPI)
+ return -EINVAL;
+ mcde_wfld(MCDE_CTRLC0, FORMTYPE,
+ MCDE_CTRLC0_FORMTYPE_DSI);
+ mcde_wfld(MCDE_CTRLC0, FORMID, get_dsi_formatter_id(port));
+ break;
+ case MCDE_FIFO_C1:
+ mcde_wreg(MCDE_CHNL0MUXING + chnl->id *
+ MCDE_CHNL0MUXING_GROUPOFFSET,
+ MCDE_CHNL0MUXING_FIFO_ID_ENUM(FIFO_C1));
+ if (port->type == MCDE_PORTTYPE_DPI)
+ return -EINVAL;
+ mcde_wfld(MCDE_CTRLC1, FORMTYPE,
+ MCDE_CTRLC1_FORMTYPE_DSI);
+ mcde_wfld(MCDE_CTRLC1, FORMID, get_dsi_formatter_id(port));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Formatter */
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ int i = 0;
+ u8 idx;
+ u8 lnk = port->link;
+
+ idx = get_dsi_formatter_id(port);
+
+ if (dsi_link_enable(chnl))
+ goto failed_to_enable_link;
+
+ if (port->sync_src == MCDE_SYNCSRC_TE_POLLING) {
+ /* Enable DSI TE polling */
+ dsi_te_poll_req(chnl);
+
+ /* Set timer to detect non TE answer */
+ dsi_te_poll_set_timer(chnl,
+ DSI_TE_NO_ANSWER_TIMEOUT_INIT);
+ } else {
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, BTA_EN, true);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, READ_EN, true);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, REG_TE_EN, true);
+ }
+
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, HOST_EOT_GEN,
+ port->phy.dsi.host_eot_gen);
+
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, DLX_REMAP_EN,
+ port->phy.dsi.data_lanes_swap);
+
+ dsi_wreg(lnk, DSI_MCTL_DPHY_STATIC,
+ DSI_MCTL_DPHY_STATIC_UI_X4(port->phy.dsi.ui));
+ dsi_wreg(lnk, DSI_DPHY_LANES_TRIM,
+ DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_ENUM(0_90));
+ dsi_wreg(lnk, DSI_MCTL_DPHY_TIMEOUT,
+ DSI_MCTL_DPHY_TIMEOUT_CLK_DIV(0xf) |
+ DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL(0x3fff) |
+ DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL(0x3fff));
+ dsi_wreg(lnk, DSI_MCTL_MAIN_PHY_CTL,
+ DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME(0xf) |
+ DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN(true) |
+ DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN(true) |
+ DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN(true) |
+ DSI_MCTL_MAIN_PHY_CTL_LANE2_EN(
+ port->phy.dsi.num_data_lanes >= 2) |
+ DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS(
+ port->phy.dsi.clk_cont));
+ /* TODO: make enum */
+ dsi_wfld(lnk, DSI_CMD_MODE_CTL, ARB_MODE, false);
+ /* TODO: make enum */
+ dsi_wfld(lnk, DSI_CMD_MODE_CTL, ARB_PRI, port->ifc == 1);
+ dsi_wreg(lnk, DSI_MCTL_MAIN_EN,
+ DSI_MCTL_MAIN_EN_PLL_START(true) |
+ DSI_MCTL_MAIN_EN_CKLANE_EN(true) |
+ DSI_MCTL_MAIN_EN_DAT1_EN(true) |
+ DSI_MCTL_MAIN_EN_DAT2_EN(port->phy.dsi.num_data_lanes
+ == 2) |
+ DSI_MCTL_MAIN_EN_IF1_EN(port->ifc == 0) |
+ DSI_MCTL_MAIN_EN_IF2_EN(port->ifc == 1));
+ while (dsi_rfld(lnk, DSI_MCTL_MAIN_STS, CLKLANE_READY) == 0 ||
+ dsi_rfld(lnk, DSI_MCTL_MAIN_STS, DAT1_READY) == 0 ||
+ (dsi_rfld(lnk, DSI_MCTL_MAIN_STS, DAT2_READY) == 0 &&
+ port->phy.dsi.num_data_lanes > 1)) {
+ mdelay(1);
+ if (i++ == 10) {
+ dev_warn(&mcde_dev->dev,
+ "DSI lane not ready (link=%d)!\n", lnk);
+ goto dsi_link_error;
+ }
+ }
+
+ dsi_link_handle_ulpm(&chnl->port, false);
+ mcde_wreg(MCDE_DSIVID0CONF0 +
+ idx * MCDE_DSIVID0CONF0_GROUPOFFSET,
+ MCDE_DSIVID0CONF0_BLANKING(0) |
+ MCDE_DSIVID0CONF0_VID_MODE(
+ port->mode == MCDE_PORTMODE_VID) |
+ MCDE_DSIVID0CONF0_CMD8(true) |
+ MCDE_DSIVID0CONF0_BIT_SWAP(false) |
+ MCDE_DSIVID0CONF0_BYTE_SWAP(false) |
+ MCDE_DSIVID0CONF0_DCSVID_NOTGEN(true));
+
+ if (port->mode == MCDE_PORTMODE_VID) {
+ update_vid_static_registers(port);
+ } else {
+ if (port->ifc == 0)
+ dsi_wfld(port->link, DSI_CMD_MODE_CTL, IF1_ID,
+ port->phy.dsi.virt_id);
+ else if (port->ifc == 1)
+ dsi_wfld(port->link, DSI_CMD_MODE_CTL, IF2_ID,
+ port->phy.dsi.virt_id);
+ }
+ }
+
+ if (port->type == MCDE_PORTTYPE_DPI) {
+ if (port->phy.dpi.lcd_freq != clk_round_rate(chnl->clk_dpi,
+ port->phy.dpi.lcd_freq))
+ dev_warn(&mcde_dev->dev, "Could not set lcd freq"
+ " to %d\n", port->phy.dpi.lcd_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dpi,
+ port->phy.dpi.lcd_freq));
+ WARN_ON_ONCE(clk_enable(chnl->clk_dpi));
+ }
+
+ mcde_wfld(MCDE_CR, MCDEEN, true);
+ chnl->formatter_updated = true;
+
+ dev_vdbg(&mcde_dev->dev, "Static registers setup, chnl=%d\n", chnl->id);
+
+ return 0;
+dsi_link_error:
+ dsi_link_disable(chnl, true);
+failed_to_enable_link:
+ return -EINVAL;
+}
+
+void mcde_chnl_col_convert_apply(struct mcde_chnl_state *chnl,
+ struct mcde_col_transform *transform)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (chnl->transform != transform) {
+
+ chnl->col_regs.y_red = transform->matrix[0][0];
+ chnl->col_regs.y_green = transform->matrix[0][1];
+ chnl->col_regs.y_blue = transform->matrix[0][2];
+ chnl->col_regs.cb_red = transform->matrix[1][0];
+ chnl->col_regs.cb_green = transform->matrix[1][1];
+ chnl->col_regs.cb_blue = transform->matrix[1][2];
+ chnl->col_regs.cr_red = transform->matrix[2][0];
+ chnl->col_regs.cr_green = transform->matrix[2][1];
+ chnl->col_regs.cr_blue = transform->matrix[2][2];
+ chnl->col_regs.off_y = transform->offset[0];
+ chnl->col_regs.off_cb = transform->offset[1];
+ chnl->col_regs.off_cr = transform->offset[2];
+ chnl->col_regs.dirty = true;
+
+ chnl->transform = transform;
+ }
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+}
+
+static void chnl_ovly_pixel_format_apply(struct mcde_chnl_state *chnl,
+ struct mcde_ovly_state *ovly)
+{
+ struct mcde_port *port = &chnl->port;
+ struct ovly_regs *regs = &ovly->regs;
+
+ /* Note: YUV -> YUV: blending YUV overlays will not make sense. */
+ static struct mcde_col_transform crycb_2_ycbcr = {
+ /* Note that in MCDE YUV 422 pixels come as VYU pixels */
+ .matrix = {
+ {0x0000, 0x0100, 0x0000},
+ {0x0000, 0x0000, 0x0100},
+ {0x0100, 0x0000, 0x0000},
+ },
+ .offset = {0, 0, 0},
+ };
+
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ if (port->pixel_format != MCDE_PORTPIXFMT_DSI_YCBCR422) {
+ if (ovly->pix_fmt != MCDE_OVLYPIXFMT_YCbCr422) {
+ /* standard case: DSI: RGB -> RGB */
+ regs->col_conv = MCDE_OVL0CR_COLCCTRL_DISABLED;
+ } else {
+ /* DSI: YUV -> RGB */
+ /* TODO change matrix */
+ regs->col_conv =
+ MCDE_OVL0CR_COLCCTRL_ENABLED_SAT;
+ mcde_chnl_col_convert_apply(chnl,
+ &chnl->ycbcr_2_rgb);
+ }
+ } else {
+ if (ovly->pix_fmt != MCDE_OVLYPIXFMT_YCbCr422)
+ /* DSI: RGB -> YUV */
+ mcde_chnl_col_convert_apply(chnl,
+ &chnl->rgb_2_ycbcr);
+ else
+ /* DSI: YUV -> YUV */
+ mcde_chnl_col_convert_apply(chnl,
+ &crycb_2_ycbcr);
+ regs->col_conv = MCDE_OVL0CR_COLCCTRL_ENABLED_NO_SAT;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI && port->phy.dpi.tv_mode) {
+ regs->col_conv = MCDE_OVL0CR_COLCCTRL_ENABLED_NO_SAT;
+ if (ovly->pix_fmt != MCDE_OVLYPIXFMT_YCbCr422)
+ mcde_chnl_col_convert_apply(chnl, &chnl->rgb_2_ycbcr);
+ else
+ mcde_chnl_col_convert_apply(chnl, &crycb_2_ycbcr);
+ } else if (port->type == MCDE_PORTTYPE_DPI) {
+ /* Note: YUV is not support port pixel format for DPI */
+ if (ovly->pix_fmt != MCDE_OVLYPIXFMT_YCbCr422) {
+ /* standard case: DPI: RGB -> RGB */
+ regs->col_conv = MCDE_OVL0CR_COLCCTRL_DISABLED;
+ } else {
+ /* DPI: YUV -> RGB */
+ regs->col_conv =
+ MCDE_OVL0CR_COLCCTRL_ENABLED_SAT;
+ mcde_chnl_col_convert_apply(chnl,
+ &chnl->ycbcr_2_rgb);
+ }
+ }
+}
+
+/* REVIEW: Make update_* an mcde_rectangle? */
+static void update_overlay_registers(u8 idx, struct ovly_regs *regs,
+ struct mcde_port *port, enum mcde_fifo fifo,
+ u16 update_x, u16 update_y, u16 update_w,
+ u16 update_h, s16 stride, bool interlaced,
+ enum mcde_display_rotation rotation)
+{
+ /* TODO: fix clipping for small overlay */
+ u32 lmrgn = (regs->cropx + update_x) * regs->bits_per_pixel;
+ u32 tmrgn = (regs->cropy + update_y) * stride;
+ u32 ppl = regs->ppl - update_x;
+ u32 lpf = regs->lpf - update_y;
+ s32 ljinc = stride;
+ u32 pixelfetchwtrmrklevel;
+ u8 nr_of_bufs = 1;
+ u32 sel_mod = MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+
+ if (rotation == MCDE_DISPLAY_ROT_180_CCW) {
+ ljinc = -ljinc;
+ tmrgn += stride * (regs->lpf - 1) / 8;
+ }
+
+ /*
+ * Preferably most of this is done in some apply function instead of for
+ * every update. However lpf has a dependency on update_y.
+ */
+ if (interlaced && port->type == MCDE_PORTTYPE_DSI) {
+ nr_of_bufs = 2;
+ lpf = lpf / 2;
+ ljinc *= 2;
+ }
+
+ if ((fifo == MCDE_FIFO_A || fifo == MCDE_FIFO_B) &&
+ regs->ppl >= SCREEN_PPL_HIGH)
+ pixelfetchwtrmrklevel = input_fifo_size * 2;
+ else
+ pixelfetchwtrmrklevel = input_fifo_size / 2;
+
+ if (port->update_auto_trig && port->type == MCDE_PORTTYPE_DSI) {
+ switch (port->sync_src) {
+ case MCDE_SYNCSRC_OFF:
+ sel_mod = MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+ break;
+ case MCDE_SYNCSRC_TE0:
+ case MCDE_SYNCSRC_TE1:
+ case MCDE_SYNCSRC_TE_POLLING:
+ default:
+ sel_mod = MCDE_EXTSRC0CR_SEL_MOD_AUTO_TOGGLE;
+ break;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI)
+ sel_mod = MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL;
+
+ mcde_wreg(MCDE_EXTSRC0CONF + idx * MCDE_EXTSRC0CONF_GROUPOFFSET,
+ MCDE_EXTSRC0CONF_BUF_ID(0) |
+ MCDE_EXTSRC0CONF_BUF_NB(nr_of_bufs) |
+ MCDE_EXTSRC0CONF_PRI_OVLID(idx) |
+ MCDE_EXTSRC0CONF_BPP(regs->bpp) |
+ MCDE_EXTSRC0CONF_BGR(regs->bgr) |
+ MCDE_EXTSRC0CONF_BEBO(regs->bebo) |
+ MCDE_EXTSRC0CONF_BEPO(false));
+ mcde_wreg(MCDE_EXTSRC0CR + idx * MCDE_EXTSRC0CR_GROUPOFFSET,
+ MCDE_EXTSRC0CR_SEL_MOD(sel_mod) |
+ MCDE_EXTSRC0CR_MULTIOVL_CTRL_ENUM(PRIMARY) |
+ MCDE_EXTSRC0CR_FS_DIV_DISABLE(false) |
+ MCDE_EXTSRC0CR_FORCE_FS_DIV(false));
+ mcde_wreg(MCDE_OVL0CR + idx * MCDE_OVL0CR_GROUPOFFSET,
+ MCDE_OVL0CR_OVLEN(regs->enabled) |
+ MCDE_OVL0CR_COLCCTRL(regs->col_conv) |
+ MCDE_OVL0CR_CKEYGEN(false) |
+ MCDE_OVL0CR_ALPHAPMEN(false) |
+ MCDE_OVL0CR_OVLF(false) |
+ MCDE_OVL0CR_OVLR(false) |
+ MCDE_OVL0CR_OVLB(false) |
+ MCDE_OVL0CR_FETCH_ROPC(0) |
+ MCDE_OVL0CR_STBPRIO(0) |
+ MCDE_OVL0CR_BURSTSIZE_ENUM(HW_8W) |
+ /* TODO: enum, get from ovly */
+ MCDE_OVL0CR_MAXOUTSTANDING_ENUM(8_REQ) |
+ /* TODO: _HW_8W, calculate? */
+ MCDE_OVL0CR_ROTBURSTSIZE_ENUM(HW_8W));
+ mcde_wreg(MCDE_OVL0CONF + idx * MCDE_OVL0CONF_GROUPOFFSET,
+ MCDE_OVL0CONF_PPL(ppl) |
+ MCDE_OVL0CONF_EXTSRC_ID(idx) |
+ MCDE_OVL0CONF_LPF(lpf));
+ mcde_wreg(MCDE_OVL0CONF2 + idx * MCDE_OVL0CONF2_GROUPOFFSET,
+ MCDE_OVL0CONF2_BP(regs->alpha_source) |
+ MCDE_OVL0CONF2_ALPHAVALUE(regs->alpha_value) |
+ MCDE_OVL0CONF2_OPQ(regs->opq) |
+ MCDE_OVL0CONF2_PIXOFF(lmrgn & 63) |
+ MCDE_OVL0CONF2_PIXELFETCHERWATERMARKLEVEL(
+ pixelfetchwtrmrklevel));
+ mcde_wreg(MCDE_OVL0LJINC + idx * MCDE_OVL0LJINC_GROUPOFFSET,
+ ljinc);
+ mcde_wreg(MCDE_OVL0CROP + idx * MCDE_OVL0CROP_GROUPOFFSET,
+ MCDE_OVL0CROP_TMRGN(tmrgn) |
+ MCDE_OVL0CROP_LMRGN(lmrgn >> 6));
+ regs->dirty = false;
+
+ dev_vdbg(&mcde_dev->dev, "Overlay registers setup, idx=%d\n", idx);
+}
+
+static void update_overlay_registers_on_the_fly(u8 idx, struct ovly_regs *regs)
+{
+ mcde_wreg(MCDE_OVL0COMP + idx * MCDE_OVL0COMP_GROUPOFFSET,
+ MCDE_OVL0COMP_XPOS(regs->xpos) |
+ MCDE_OVL0COMP_CH_ID(regs->ch_id) |
+ MCDE_OVL0COMP_YPOS(regs->ypos) |
+ MCDE_OVL0COMP_Z(regs->z));
+
+ mcde_wreg(MCDE_EXTSRC0A0 + idx * MCDE_EXTSRC0A0_GROUPOFFSET,
+ regs->baseaddress0);
+ mcde_wreg(MCDE_EXTSRC0A1 + idx * MCDE_EXTSRC0A1_GROUPOFFSET,
+ regs->baseaddress1);
+ regs->dirty_buf = false;
+}
+
+static void do_softwaretrig(struct mcde_chnl_state *chnl)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ enable_flow(chnl);
+ mcde_wreg(MCDE_CHNL0SYNCHSW +
+ chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET,
+ MCDE_CHNL0SYNCHSW_SW_TRIG(true));
+ disable_flow(chnl);
+
+ local_irq_restore(flags);
+
+ dev_vdbg(&mcde_dev->dev, "Software TRIG on channel %d\n", chnl->id);
+}
+
+static void disable_flow(struct mcde_chnl_state *chnl)
+{
+ unsigned long flags;
+
+ if (WARN_ON_ONCE(chnl->state != CHNLSTATE_RUNNING))
+ return;
+
+ local_irq_save(flags);
+
+ switch (chnl->id) {
+ case MCDE_CHNL_A:
+ mcde_wfld(MCDE_CRA0, FLOEN, false);
+ break;
+ case MCDE_CHNL_B:
+ mcde_wfld(MCDE_CRB0, FLOEN, false);
+ break;
+ case MCDE_CHNL_C0:
+ mcde_wfld(MCDE_CRC, C1EN, false);
+ break;
+ case MCDE_CHNL_C1:
+ mcde_wfld(MCDE_CRC, C2EN, false);
+ break;
+ }
+
+ set_channel_state_atomic(chnl, CHNLSTATE_STOPPING);
+
+ local_irq_restore(flags);
+}
+
+static void stop_channel(struct mcde_chnl_state *chnl)
+{
+ const struct mcde_port *port = &chnl->port;
+ bool dpi_lcd_mode;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (chnl->state != CHNLSTATE_RUNNING)
+ return;
+
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ dsi_wfld(port->link, DSI_MCTL_MAIN_PHY_CTL, CLK_CONTINUOUS,
+ false);
+ if (port->sync_src == MCDE_SYNCSRC_TE_POLLING)
+ del_timer(&chnl->dsi_te_timer);
+ }
+
+ disable_flow(chnl);
+ /*
+ * Needs to manually trigger VCOMP after the channel is
+ * disabled. For all channels using video mode
+ * except for dpi lcd.
+ */
+ dpi_lcd_mode = (port->type == MCDE_PORTTYPE_DPI &&
+ !chnl->port.phy.dpi.tv_mode);
+
+ if (chnl->port.update_auto_trig && !dpi_lcd_mode)
+ mcde_wreg(MCDE_SISPP, 1 << chnl->id);
+}
+
+static void wait_for_flow_disabled(struct mcde_chnl_state *chnl)
+{
+ int i = 0;
+
+ switch (chnl->id) {
+ case MCDE_CHNL_A:
+ for (i = 0; i < MCDE_FLOWEN_MAX_TRIAL; i++) {
+ if (!mcde_rfld(MCDE_CRA0, FLOEN)) {
+ dev_vdbg(&mcde_dev->dev,
+ "Flow (A) disable after >= %d ms\n", i);
+ break;
+ }
+ msleep(1);
+ }
+ break;
+ case MCDE_CHNL_B:
+ for (i = 0; i < MCDE_FLOWEN_MAX_TRIAL; i++) {
+ if (!mcde_rfld(MCDE_CRB0, FLOEN)) {
+ dev_vdbg(&mcde_dev->dev,
+ "Flow (B) disable after >= %d ms\n", i);
+ break;
+ }
+ msleep(1);
+ }
+ break;
+ case MCDE_CHNL_C0:
+ for (i = 0; i < MCDE_FLOWEN_MAX_TRIAL; i++) {
+ if (!mcde_rfld(MCDE_CRC, C1EN)) {
+ dev_vdbg(&mcde_dev->dev,
+ "Flow (C1) disable after >= %d ms\n", i);
+ break;
+ }
+ msleep(1);
+ }
+ break;
+ case MCDE_CHNL_C1:
+ for (i = 0; i < MCDE_FLOWEN_MAX_TRIAL; i++) {
+ if (!mcde_rfld(MCDE_CRC, C2EN)) {
+ dev_vdbg(&mcde_dev->dev,
+ "Flow (C2) disable after >= %d ms\n", i);
+ break;
+ }
+ msleep(1);
+ }
+ break;
+ }
+ if (i == MCDE_FLOWEN_MAX_TRIAL)
+ dev_err(&mcde_dev->dev, "%s: channel %d timeout\n",
+ __func__, chnl->id);
+}
+
+static void enable_flow(struct mcde_chnl_state *chnl)
+{
+ const struct mcde_port *port = &chnl->port;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (port->type == MCDE_PORTTYPE_DSI)
+ dsi_wfld(port->link, DSI_MCTL_MAIN_PHY_CTL, CLK_CONTINUOUS,
+ port->phy.dsi.clk_cont);
+
+ /*
+ * When ROTEN is set, the FLOEN bit will also be set but
+ * the flow has to be started anyway.
+ */
+ switch (chnl->id) {
+ case MCDE_CHNL_A:
+ WARN_ON_ONCE(mcde_rfld(MCDE_CRA0, FLOEN));
+ mcde_wfld(MCDE_CRA0, ROTEN, chnl->regs.roten);
+ mcde_wfld(MCDE_CRA0, FLOEN, true);
+ break;
+ case MCDE_CHNL_B:
+ WARN_ON_ONCE(mcde_rfld(MCDE_CRB0, FLOEN));
+ mcde_wfld(MCDE_CRB0, ROTEN, chnl->regs.roten);
+ mcde_wfld(MCDE_CRB0, FLOEN, true);
+ break;
+ case MCDE_CHNL_C0:
+ WARN_ON_ONCE(mcde_rfld(MCDE_CRC, C1EN));
+ mcde_wfld(MCDE_CRC, C1EN, true);
+ break;
+ case MCDE_CHNL_C1:
+ WARN_ON_ONCE(mcde_rfld(MCDE_CRC, C2EN));
+ mcde_wfld(MCDE_CRC, C2EN, true);
+ break;
+ }
+
+ set_channel_state_atomic(chnl, CHNLSTATE_RUNNING);
+}
+
+static void work_sleep_function(struct work_struct *ptr)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+ if (mcde_trylock(__func__, __LINE__)) {
+ if (mcde_dynamic_power_management)
+ disable_mcde_hw(false, false);
+ mcde_unlock(__func__, __LINE__);
+ }
+}
+
+/* TODO get from register */
+#define MCDE_CLK_FREQ_MHZ 160
+static u32 get_pkt_div(u32 disp_ppl,
+ struct mcde_port *port,
+ enum mcde_fifo fifo)
+{
+ /*
+ * The lines can be split in several packets only on DSI CMD mode.
+ * In DSI VIDEO mode, 1 line = 1 packet.
+ * DPI is like DSI VIDEO (watermark = 1 line).
+ * DPI waits for fifo ready only for the first line of the first frame.
+ * If line is wider than fifo size, one can set watermark
+ * at fifo size, or set it to line size as watermark will be
+ * saturated at fifo size inside MCDE.
+ */
+ switch (port->type) {
+ case MCDE_PORTTYPE_DSI:
+ if (port->mode == MCDE_PORTMODE_CMD)
+ /* Equivalent of ceil(disp_ppl/fifo_size) */
+ return (disp_ppl - 1) / get_output_fifo_size(fifo) + 1;
+ else
+ return 1;
+ break;
+ case MCDE_PORTTYPE_DPI:
+ return 1;
+ break;
+ default:
+ break;
+ }
+ return 1;
+}
+
+static void update_vid_horizontal_blanking(struct mcde_port *port,
+ struct mcde_video_mode *vmode, bool sync_is_pulse, u8 bpp)
+{
+ int hfp, hbp, hsa;
+ u8 link = port->link;
+
+ /*
+ * vmode->hfp, vmode->hbp and vmode->hsw are given in pixels
+ * and must be re-calculated into bytes
+ *
+ * 6 + 2 is HFP header + checksum
+ */
+ hfp = vmode->hfp * bpp - 6 - 2;
+ if (sync_is_pulse) {
+ /*
+ * 6 is HBP header + checksum
+ * 4 is RGB header + checksum
+ */
+ hbp = vmode->hbp * bpp - 4 - 6;
+ /*
+ * 6 is HBP header + checksum
+ * 4 is HSW packet bytes
+ * 4 is RGB header + checksum
+ */
+ hsa = vmode->hsw * bpp - 4 - 4 - 6;
+ } else {
+ /*
+ * 6 is HBP header + checksum
+ * 4 is HSW packet bytes
+ * 4 is RGB header + checksum
+ */
+ hbp = (vmode->hbp + vmode->hsw) * bpp - 4 - 4 - 6;
+ /* HSA is not considered in this mode and set to 0 */
+ hsa = 0;
+ }
+ if (hfp < 0) {
+ hfp = 0;
+ dev_warn(&mcde_dev->dev,
+ "%s: negative calc for hfp, set to 0\n", __func__);
+ }
+ if (hbp < 0) {
+ hbp = 0;
+ dev_warn(&mcde_dev->dev,
+ "%s: negative calc for hbp, set to 0\n", __func__);
+ }
+ if (hsa < 0) {
+ hsa = 0;
+ dev_warn(&mcde_dev->dev,
+ "%s: negative calc for hsa, set to 0\n", __func__);
+ }
+
+ dsi_wfld(link, DSI_VID_HSIZE1, HFP_LENGTH, hfp);
+ dsi_wfld(link, DSI_VID_HSIZE1, HBP_LENGTH, hbp);
+ dsi_wfld(link, DSI_VID_HSIZE1, HSA_LENGTH, hsa);
+}
+
+static void update_vid_frame_parameters(struct mcde_port *port,
+ struct mcde_video_mode *vmode, u8 bpp)
+{
+ u8 link = port->link;
+ bool burst_mode, sync_is_pulse, tvg_enable;
+ u32 hs_byte_clk, pck_len, blkline_pck, line_duration;
+ u32 blkeol_pck, blkeol_duration;
+ u8 pixel_mode;
+ u8 rgb_header;
+
+ get_vid_operating_mode(port, &burst_mode, &sync_is_pulse, &tvg_enable);
+
+ dsi_wfld(link, DSI_VID_VSIZE, VFP_LENGTH, vmode->vfp);
+ dsi_wfld(link, DSI_VID_VSIZE, VBP_LENGTH, vmode->vbp);
+ dsi_wfld(link, DSI_VID_VSIZE, VSA_LENGTH, vmode->vsw);
+ update_vid_horizontal_blanking(port, vmode, sync_is_pulse, bpp);
+
+ dsi_wfld(link, DSI_VID_VSIZE, VACT_LENGTH, vmode->yres);
+ dsi_wfld(link, DSI_VID_HSIZE2, RGB_SIZE, vmode->xres * bpp);
+
+ /*
+ * The rgb_header identifies the pixel stream format,
+ * as described in the MIPI DSI Specification:
+ *
+ * 0x0E: Packed pixel stream, 16-bit RGB, 565 format
+ * 0x1E: Packed pixel stream, 18-bit RGB, 666 format
+ * 0x2E: Loosely Packed pixel stream, 18-bit RGB, 666 format
+ * 0x3E: Packed pixel stream, 24-bit RGB, 888 format
+ */
+ switch (port->pixel_format) {
+ case MCDE_PORTPIXFMT_DSI_16BPP:
+ pixel_mode = 0;
+ rgb_header = 0x0E;
+ break;
+ case MCDE_PORTPIXFMT_DSI_18BPP:
+ pixel_mode = 2;
+ rgb_header = 0x2E;
+ break;
+ case MCDE_PORTPIXFMT_DSI_18BPP_PACKED:
+ pixel_mode = 1;
+ rgb_header = 0x1E;
+ break;
+ case MCDE_PORTPIXFMT_DSI_24BPP:
+ pixel_mode = 3;
+ rgb_header = 0x3E;
+ break;
+ default:
+ pixel_mode = 3;
+ rgb_header = 0x3E;
+ dev_warn(&mcde_dev->dev,
+ "%s: invalid pixel format %d\n",
+ __func__, port->pixel_format);
+ break;
+ }
+
+ dsi_wfld(link, DSI_VID_MAIN_CTL, VID_PIXEL_MODE, pixel_mode);
+ dsi_wfld(link, DSI_VID_MAIN_CTL, HEADER, rgb_header);
+
+ if (tvg_enable) {
+ /*
+ * with these settings, expect to see 64 pixels wide
+ * red and green vertical stripes on the screen when
+ * tvg_enable = 1
+ */
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, TVG_SEL, 1);
+
+ dsi_wfld(link, DSI_TVG_CTL, TVG_STRIPE_SIZE, 6);
+ dsi_wfld(link, DSI_TVG_CTL, TVG_MODE, 2);
+ dsi_wfld(link, DSI_TVG_CTL, TVG_STOPMODE, 2);
+ dsi_wfld(link, DSI_TVG_CTL, TVG_RUN, 1);
+
+ dsi_wfld(link, DSI_TVG_IMG_SIZE, TVG_NBLINE, vmode->yres);
+ dsi_wfld(link, DSI_TVG_IMG_SIZE, TVG_LINE_SIZE,
+ vmode->xres * bpp);
+
+ dsi_wfld(link, DSI_TVG_COLOR1, COL1_BLUE, 0);
+ dsi_wfld(link, DSI_TVG_COLOR1, COL1_GREEN, 0);
+ dsi_wfld(link, DSI_TVG_COLOR1, COL1_RED, 0xFF);
+
+ dsi_wfld(link, DSI_TVG_COLOR2, COL2_BLUE, 0);
+ dsi_wfld(link, DSI_TVG_COLOR2, COL2_GREEN, 0xFF);
+ dsi_wfld(link, DSI_TVG_COLOR2, COL2_RED, 0);
+ }
+
+ /*
+ * vid->pixclock is the time between two pixels (in picoseconds)
+ *
+ * hs_byte_clk is the amount of transferred bytes per lane and
+ * second (in MHz)
+ */
+ hs_byte_clk = 1000000 / vmode->pixclock / 8;
+ pck_len = 1000000 * hs_byte_clk / port->refresh_rate /
+ (vmode->vsw + vmode->vbp + vmode->yres + vmode->vfp) *
+ port->phy.dsi.num_data_lanes;
+
+ /*
+ * 6 is header + checksum, header = 4 bytes, checksum = 2 bytes
+ * 4 is short packet for vsync/hsync
+ */
+ if (sync_is_pulse)
+ blkline_pck = pck_len - vmode->hsw - 6;
+ else
+ blkline_pck = pck_len - 4 - 6;
+
+ line_duration = (blkline_pck + 6) / port->phy.dsi.num_data_lanes;
+ blkeol_pck = pck_len -
+ (vmode->hsw + vmode->hbp + vmode->xres + vmode->hfp) * bpp - 6;
+ blkeol_duration = (blkeol_pck + 6) / port->phy.dsi.num_data_lanes;
+
+ if (sync_is_pulse)
+ dsi_wfld(link, DSI_VID_BLKSIZE2, BLKLINE_PULSE_PCK,
+ blkline_pck);
+ else
+ dsi_wfld(link, DSI_VID_BLKSIZE1, BLKLINE_EVENT_PCK,
+ blkline_pck);
+ dsi_wfld(link, DSI_VID_DPHY_TIME, REG_LINE_DURATION, line_duration);
+ if (burst_mode) {
+ dsi_wfld(link, DSI_VID_BLKSIZE1, BLKEOL_PCK, blkeol_pck);
+ dsi_wfld(link, DSI_VID_PCK_TIME, BLKEOL_DURATION,
+ blkeol_duration);
+ dsi_wfld(link, DSI_VID_VCA_SETTING1, MAX_BURST_LIMIT,
+ blkeol_pck - 6);
+ dsi_wfld(link, DSI_VID_VCA_SETTING2, EXACT_BURST_LIMIT,
+ blkeol_pck);
+ }
+ if (sync_is_pulse)
+ dsi_wfld(link, DSI_VID_VCA_SETTING2, MAX_LINE_LIMIT,
+ blkline_pck - 6);
+}
+
+static void set_vsync_method(u8 idx, struct mcde_port *port)
+{
+ u32 out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ u32 src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ switch (port->frame_trig) {
+ case MCDE_TRIG_HW:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ break;
+ case MCDE_TRIG_SW:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
+ break;
+ default:
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ break;
+ }
+
+ switch (port->sync_src) {
+ case MCDE_SYNCSRC_OFF:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ break;
+ case MCDE_SYNCSRC_TE0:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE0;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE0 defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ case MCDE_SYNCSRC_TE1:
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE1;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE1 defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ case MCDE_SYNCSRC_BTA:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ break;
+ case MCDE_SYNCSRC_TE_POLLING:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ if (src_synch ==
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) {
+ dev_dbg(&mcde_dev->dev, "%s: badly configured "
+ "frame sync, TE_POLLING defaulting "
+ "to hw frame trig\n", __func__);
+ src_synch =
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ }
+ break;
+ default:
+ out_synch_src =
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ src_synch = MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE;
+ dev_dbg(&mcde_dev->dev, "%s: no sync src selected, "
+ "defaulting to DSI BTA with "
+ "hw frame trig\n", __func__);
+ break;
+ }
+ } else if (port->type == MCDE_PORTTYPE_DPI) {
+ out_synch_src = MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER;
+ src_synch = port->update_auto_trig ?
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE :
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE;
+ }
+
+ mcde_wreg(MCDE_CHNL0SYNCHMOD +
+ idx * MCDE_CHNL0SYNCHMOD_GROUPOFFSET,
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH(src_synch) |
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC(out_synch_src));
+}
+
+void update_channel_registers(enum mcde_chnl chnl_id, struct chnl_regs *regs,
+ struct mcde_port *port, enum mcde_fifo fifo,
+ struct mcde_video_mode *video_mode)
+{
+ u8 idx = chnl_id;
+ u32 fifo_wtrmrk = 0;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ /*
+ * Select appropriate fifo watermark.
+ * Watermark will be saturated at fifo size inside MCDE.
+ */
+ fifo_wtrmrk = video_mode->xres /
+ get_pkt_div(video_mode->xres, port, fifo);
+
+ dev_vdbg(&mcde_dev->dev, "%s fifo_watermark=%d for chnl_id=%d\n",
+ __func__, fifo_wtrmrk, chnl_id);
+
+ switch (chnl_id) {
+ case MCDE_CHNL_A:
+ mcde_wfld(MCDE_CTRLA, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_B:
+ mcde_wfld(MCDE_CTRLB, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_C0:
+ mcde_wfld(MCDE_CTRLC0, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ case MCDE_CHNL_C1:
+ mcde_wfld(MCDE_CTRLC1, FIFOWTRMRK, fifo_wtrmrk);
+ break;
+ default:
+ break;
+ }
+
+ set_vsync_method(idx, port);
+
+ mcde_wreg(MCDE_CHNL0CONF + idx * MCDE_CHNL0CONF_GROUPOFFSET,
+ MCDE_CHNL0CONF_PPL(regs->ppl-1) |
+ MCDE_CHNL0CONF_LPF(regs->lpf-1));
+ mcde_wreg(MCDE_CHNL0STAT + idx * MCDE_CHNL0STAT_GROUPOFFSET,
+ MCDE_CHNL0STAT_CHNLBLBCKGND_EN(false) |
+ MCDE_CHNL0STAT_CHNLRD(true));
+ mcde_wreg(MCDE_CHNL0BCKGNDCOL + idx * MCDE_CHNL0BCKGNDCOL_GROUPOFFSET,
+ MCDE_CHNL0BCKGNDCOL_B(0) |
+ MCDE_CHNL0BCKGNDCOL_G(0) |
+ MCDE_CHNL0BCKGNDCOL_R(0));
+
+ if (chnl_id == MCDE_CHNL_A || chnl_id == MCDE_CHNL_B) {
+ u32 mcde_crx1;
+ u32 mcde_pal0x;
+ u32 mcde_pal1x;
+ if (chnl_id == MCDE_CHNL_A) {
+ mcde_crx1 = MCDE_CRA1;
+ mcde_pal0x = MCDE_PAL0A;
+ mcde_pal1x = MCDE_PAL1A;
+ mcde_wfld(MCDE_CRA0, PALEN, regs->palette_enable);
+ } else {
+ mcde_crx1 = MCDE_CRB1;
+ mcde_pal0x = MCDE_PAL0B;
+ mcde_pal1x = MCDE_PAL1B;
+ mcde_wfld(MCDE_CRB0, PALEN, regs->palette_enable);
+ }
+ mcde_wreg(mcde_crx1,
+ MCDE_CRA1_PCD(regs->pcd) |
+ MCDE_CRA1_CLKSEL(regs->clksel) |
+ MCDE_CRA1_CDWIN(regs->cdwin) |
+ MCDE_CRA1_OUTBPP(bpp2outbpp(regs->bpp)) |
+ MCDE_CRA1_BCD(regs->bcd) |
+ MCDE_CRA1_CLKTYPE(regs->internal_clk));
+ if (regs->palette_enable) {
+ int i;
+ for (i = 0; i < 256; i++) {
+ mcde_wreg(mcde_pal0x,
+ MCDE_PAL0A_GREEN(regs->map_g(i)) |
+ MCDE_PAL0A_BLUE(regs->map_b(i)));
+ mcde_wreg(mcde_pal1x,
+ MCDE_PAL1A_RED(regs->map_r(i)));
+ }
+ }
+ }
+
+ /* Formatter */
+ if (port->type == MCDE_PORTTYPE_DSI) {
+ u8 fidx;
+ u32 temp, packet;
+ /* pkt_div is used to avoid underflow in output fifo for
+ * large packets */
+ u32 pkt_div = 1;
+ u32 dsi_delay0 = 0;
+ u32 screen_ppl, screen_lpf;
+
+ fidx = get_dsi_formatter_id(port);
+
+ screen_ppl = video_mode->xres;
+ screen_lpf = video_mode->yres;
+
+ pkt_div = get_pkt_div(screen_ppl, port, fifo);
+
+ if (video_mode->interlaced)
+ screen_lpf /= 2;
+
+ /* pkt_delay_progressive = pixelclock * htot /
+ * (1E12 / 160E6) / pkt_div */
+ dsi_delay0 = (video_mode->pixclock) *
+ (video_mode->xres + video_mode->hbp +
+ video_mode->hfp) /
+ (100000000 / ((mcde_clk_rate / 10000))) / pkt_div;
+
+ if ((screen_ppl == SCREEN_PPL_CEA2) &&
+ (screen_lpf == SCREEN_LPF_CEA2))
+ dsi_delay0 += DSI_DELAY0_CEA2_ADD;
+
+ temp = mcde_rreg(MCDE_DSIVID0CONF0 +
+ fidx * MCDE_DSIVID0CONF0_GROUPOFFSET);
+ mcde_wreg(MCDE_DSIVID0CONF0 +
+ fidx * MCDE_DSIVID0CONF0_GROUPOFFSET,
+ (temp & ~MCDE_DSIVID0CONF0_PACKING_MASK) |
+ MCDE_DSIVID0CONF0_PACKING(regs->dsipacking));
+ /* no extra command byte in video mode */
+ if (port->mode == MCDE_PORTMODE_CMD)
+ packet = ((screen_ppl / pkt_div * regs->bpp) >> 3) + 1;
+ else
+ packet = ((screen_ppl / pkt_div * regs->bpp) >> 3);
+ mcde_wreg(MCDE_DSIVID0FRAME +
+ fidx * MCDE_DSIVID0FRAME_GROUPOFFSET,
+ MCDE_DSIVID0FRAME_FRAME(packet * pkt_div * screen_lpf));
+ mcde_wreg(MCDE_DSIVID0PKT + fidx * MCDE_DSIVID0PKT_GROUPOFFSET,
+ MCDE_DSIVID0PKT_PACKET(packet));
+ mcde_wreg(MCDE_DSIVID0SYNC +
+ fidx * MCDE_DSIVID0SYNC_GROUPOFFSET,
+ MCDE_DSIVID0SYNC_SW(0) |
+ MCDE_DSIVID0SYNC_DMA(0));
+ mcde_wreg(MCDE_DSIVID0CMDW +
+ fidx * MCDE_DSIVID0CMDW_GROUPOFFSET,
+ MCDE_DSIVID0CMDW_CMDW_START(DCS_CMD_WRITE_START) |
+ MCDE_DSIVID0CMDW_CMDW_CONTINUE(DCS_CMD_WRITE_CONTINUE));
+ mcde_wreg(MCDE_DSIVID0DELAY0 +
+ fidx * MCDE_DSIVID0DELAY0_GROUPOFFSET,
+ MCDE_DSIVID0DELAY0_INTPKTDEL(dsi_delay0));
+ mcde_wreg(MCDE_DSIVID0DELAY1 +
+ fidx * MCDE_DSIVID0DELAY1_GROUPOFFSET,
+ MCDE_DSIVID0DELAY1_TEREQDEL(0) |
+ MCDE_DSIVID0DELAY1_FRAMESTARTDEL(0));
+
+ if (port->mode == MCDE_PORTMODE_VID)
+ update_vid_frame_parameters(port, video_mode,
+ regs->bpp / 8);
+ } else if (port->type == MCDE_PORTTYPE_DPI &&
+ !port->phy.dpi.tv_mode) {
+ /* DPI LCD Mode */
+ if (chnl_id == MCDE_CHNL_A) {
+ mcde_wreg(MCDE_SYNCHCONFA,
+ MCDE_SYNCHCONFA_HWREQVEVENT_ENUM(
+ ACTIVE_VIDEO) |
+ MCDE_SYNCHCONFA_HWREQVCNT(
+ video_mode->yres - 1) |
+ MCDE_SYNCHCONFA_SWINTVEVENT_ENUM(
+ ACTIVE_VIDEO) |
+ MCDE_SYNCHCONFA_SWINTVCNT(
+ video_mode->yres - 1));
+ } else if (chnl_id == MCDE_CHNL_B) {
+ mcde_wreg(MCDE_SYNCHCONFB,
+ MCDE_SYNCHCONFB_HWREQVEVENT_ENUM(
+ ACTIVE_VIDEO) |
+ MCDE_SYNCHCONFB_HWREQVCNT(
+ video_mode->yres - 1) |
+ MCDE_SYNCHCONFB_SWINTVEVENT_ENUM(
+ ACTIVE_VIDEO) |
+ MCDE_SYNCHCONFB_SWINTVCNT(
+ video_mode->yres - 1));
+ }
+ }
+
+ if (regs->roten) {
+ u32 stripwidth;
+ u32 stripwidth_val;
+
+ /* calc strip width, 32 bits used internally */
+ stripwidth = regs->rotbufsize / (video_mode->yres * 4);
+ if (stripwidth >= 32)
+ stripwidth_val = MCDE_ROTACONF_STRIP_WIDTH_32PIX;
+ else if (stripwidth >= 16)
+ stripwidth_val = MCDE_ROTACONF_STRIP_WIDTH_16PIX;
+ else if (stripwidth >= 8)
+ stripwidth_val = MCDE_ROTACONF_STRIP_WIDTH_8PIX;
+ else if (stripwidth >= 4)
+ stripwidth_val = MCDE_ROTACONF_STRIP_WIDTH_4PIX;
+ else
+ stripwidth_val = MCDE_ROTACONF_STRIP_WIDTH_2PIX;
+ dev_vdbg(&mcde_dev->dev, "%s stripwidth=%d\n", __func__,
+ 1 << (stripwidth_val + 1));
+ mcde_wreg(MCDE_ROTADD0A + chnl_id * MCDE_ROTADD0A_GROUPOFFSET,
+ regs->rotbuf1);
+ mcde_wreg(MCDE_ROTADD1A + chnl_id * MCDE_ROTADD1A_GROUPOFFSET,
+ regs->rotbuf2);
+ mcde_wreg(MCDE_ROTACONF + chnl_id * MCDE_ROTACONF_GROUPOFFSET,
+ MCDE_ROTACONF_ROTBURSTSIZE_ENUM(HW_8W) |
+ MCDE_ROTACONF_ROTDIR(regs->rotdir) |
+ MCDE_ROTACONF_STRIP_WIDTH(stripwidth_val) |
+ MCDE_ROTACONF_RD_MAXOUT_ENUM(4_REQ) |
+ MCDE_ROTACONF_WR_MAXOUT_ENUM(8_REQ));
+ }
+
+ /* Blending */
+ if (chnl_id == MCDE_CHNL_A) {
+ mcde_wfld(MCDE_CRA0, BLENDEN, regs->blend_en);
+ mcde_wfld(MCDE_CRA0, BLENDCTRL, regs->blend_ctrl);
+ mcde_wfld(MCDE_CRA0, ALPHABLEND, regs->alpha_blend);
+ } else if (chnl_id == MCDE_CHNL_B) {
+ mcde_wfld(MCDE_CRB0, BLENDEN, regs->blend_en);
+ mcde_wfld(MCDE_CRB0, BLENDCTRL, regs->blend_ctrl);
+ mcde_wfld(MCDE_CRB0, ALPHABLEND, regs->alpha_blend);
+ }
+
+ dev_vdbg(&mcde_dev->dev, "Channel registers setup, chnl=%d\n", chnl_id);
+ regs->dirty = false;
+}
+
+static int enable_mcde_hw(void)
+{
+ int ret;
+ int i;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ cancel_delayed_work(&hw_timeout_work);
+ schedule_delayed_work(&hw_timeout_work,
+ msecs_to_jiffies(MCDE_SLEEP_WATCHDOG));
+
+ for (i = 0; i < num_channels; i++) {
+ struct mcde_chnl_state *chnl = &channels[i];
+ if (chnl->state == CHNLSTATE_SUSPEND) {
+ /* Mark all registers as dirty */
+ set_channel_state_atomic(chnl, CHNLSTATE_IDLE);
+ chnl->ovly0->regs.dirty = true;
+ chnl->ovly0->regs.dirty_buf = true;
+ if (chnl->ovly1) {
+ chnl->ovly1->regs.dirty = true;
+ chnl->ovly1->regs.dirty_buf = true;
+ }
+ chnl->regs.dirty = true;
+ chnl->col_regs.dirty = true;
+ chnl->tv_regs.dirty = true;
+ atomic_set(&chnl->vcmp_cnt, 0);
+ }
+ }
+
+ if (mcde_is_enabled) {
+ dev_vdbg(&mcde_dev->dev, "%s - already enabled\n", __func__);
+ return 0;
+ }
+
+ enable_clocks_and_power(mcde_dev);
+
+ ret = request_irq(mcde_irq, mcde_irq_handler, 0, "mcde",
+ &mcde_dev->dev);
+ if (ret) {
+ dev_dbg(&mcde_dev->dev, "Failed to request irq (irq=%d)\n",
+ mcde_irq);
+ cancel_delayed_work(&hw_timeout_work);
+ return -EINVAL;
+ }
+
+ update_mcde_registers();
+
+ dev_vdbg(&mcde_dev->dev, "%s - enable done\n", __func__);
+
+ mcde_is_enabled = true;
+ return 0;
+}
+
+/* DSI */
+static int mcde_dsi_direct_cmd_write(struct mcde_chnl_state *chnl,
+ bool dcs, u8 cmd, u8 *data, int len)
+{
+ int i, ret = 0;
+ u32 wrdat[4] = { 0, 0, 0, 0 };
+ u32 settings;
+ u8 link = chnl->port.link;
+ u8 virt_id = chnl->port.phy.dsi.virt_id;
+ u32 counter = DSI_WRITE_CMD_TIMEOUT;
+
+ if (len > MCDE_MAX_DSI_DIRECT_CMD_WRITE ||
+ chnl->port.type != MCDE_PORTTYPE_DSI)
+ return -EINVAL;
+
+ mcde_lock(__func__, __LINE__);
+
+ _mcde_chnl_enable(chnl);
+ if (enable_mcde_hw()) {
+ mcde_unlock(__func__, __LINE__);
+ return -EINVAL;
+ }
+ if (!chnl->formatter_updated)
+ (void)update_channel_static_registers(chnl);
+
+ set_channel_state_sync(chnl, CHNLSTATE_DSI_WRITE);
+
+ if (dcs) {
+ wrdat[0] = cmd;
+ for (i = 1; i <= len; i++)
+ wrdat[i>>2] |= ((u32)data[i-1] << ((i & 3) * 8));
+ } else {
+ /* no explicit cmd byte for generic_write, only params */
+ for (i = 0; i < len; i++)
+ wrdat[i>>2] |= ((u32)data[i] << ((i & 3) * 8));
+ }
+
+ settings = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(WRITE) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(len > 1) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(virt_id) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(len+1) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(true);
+ if (dcs) {
+ if (len == 0)
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ DCS_SHORT_WRITE_0);
+ else if (len == 1)
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ DCS_SHORT_WRITE_1);
+ else
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ DCS_LONG_WRITE);
+ } else {
+ if (len == 0)
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ GENERIC_SHORT_WRITE_0);
+ else if (len == 1)
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ GENERIC_SHORT_WRITE_1);
+ else if (len == 2)
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ GENERIC_SHORT_WRITE_2);
+ else
+ settings |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ GENERIC_LONG_WRITE);
+ }
+
+ dsi_wreg(link, DSI_DIRECT_CMD_MAIN_SETTINGS, settings);
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT0, wrdat[0]);
+ if (len > 3)
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT1, wrdat[1]);
+ if (len > 7)
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT2, wrdat[2]);
+ if (len > 11)
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT3, wrdat[3]);
+ dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0);
+ dsi_wreg(link, DSI_CMD_MODE_STS_CLR, ~0);
+ dsi_wreg(link, DSI_DIRECT_CMD_SEND, true);
+
+ /* loop will normally run zero or one time until WRITE_COMPLETED */
+ while (!dsi_rfld(link, DSI_DIRECT_CMD_STS, WRITE_COMPLETED)
+ && --counter)
+ cpu_relax();
+
+ if (!counter) {
+ dev_err(&mcde_dev->dev,
+ "%s: DSI write cmd 0x%x timeout on DSI link %u!\n",
+ __func__, cmd, link);
+ ret = -ETIME;
+ } else {
+ /* inform if >100 loops before command completion */
+ if (counter < (DSI_WRITE_CMD_TIMEOUT-DSI_WRITE_CMD_TIMEOUT/10))
+ dev_vdbg(&mcde_dev->dev,
+ "%s: %u loops for DSI command %x completion\n",
+ __func__, (DSI_WRITE_CMD_TIMEOUT - counter),
+ cmd);
+
+ dev_vdbg(&mcde_dev->dev, "DSI Write ok %x error %x\n",
+ dsi_rreg(link, DSI_DIRECT_CMD_STS_FLAG),
+ dsi_rreg(link, DSI_CMD_MODE_STS_FLAG));
+ }
+
+ set_channel_state_atomic(chnl, CHNLSTATE_IDLE);
+
+ mcde_unlock(__func__, __LINE__);
+
+ return ret;
+}
+
+int mcde_dsi_generic_write(struct mcde_chnl_state *chnl, u8* para, int len)
+{
+ return mcde_dsi_direct_cmd_write(chnl, false, 0, para, len);
+}
+
+int mcde_dsi_dcs_write(struct mcde_chnl_state *chnl, u8 cmd, u8* data, int len)
+{
+ return mcde_dsi_direct_cmd_write(chnl, true, cmd, data, len);
+}
+
+int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl,
+ u8 cmd, u32 *data, int *len)
+{
+ int ret = 0;
+ u8 link = chnl->port.link;
+ u8 virt_id = chnl->port.phy.dsi.virt_id;
+ u32 settings;
+ bool ok = false;
+ bool error, ack_with_err;
+ u8 nbr_of_retries = DSI_READ_NBR_OF_RETRIES;
+
+ if (*len > MCDE_MAX_DCS_READ || chnl->port.type != MCDE_PORTTYPE_DSI)
+ return -EINVAL;
+
+ mcde_lock(__func__, __LINE__);
+
+ _mcde_chnl_enable(chnl);
+ if (enable_mcde_hw()) {
+ mcde_unlock(__func__, __LINE__);
+ return -EINVAL;
+ }
+ if (!chnl->formatter_updated)
+ (void)update_channel_static_registers(chnl);
+
+ set_channel_state_sync(chnl, CHNLSTATE_DSI_READ);
+
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, BTA_EN, true);
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, READ_EN, true);
+ settings = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(READ) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(false) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(virt_id) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(1) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(true) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(DCS_READ);
+ dsi_wreg(link, DSI_DIRECT_CMD_MAIN_SETTINGS, settings);
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT0, cmd);
+
+ do {
+ u8 wait = DSI_READ_TIMEOUT;
+ dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0);
+ dsi_wreg(link, DSI_DIRECT_CMD_RD_STS_CLR, ~0);
+ dsi_wreg(link, DSI_DIRECT_CMD_SEND, true);
+
+ while (wait-- && !(error = dsi_rfld(link, DSI_DIRECT_CMD_STS,
+ READ_COMPLETED_WITH_ERR)) &&
+ !(ok = dsi_rfld(link, DSI_DIRECT_CMD_STS,
+ READ_COMPLETED)))
+ udelay(DSI_READ_DELAY);
+
+ ack_with_err = dsi_rfld(link, DSI_DIRECT_CMD_STS,
+ ACKNOWLEDGE_WITH_ERR_RECEIVED);
+ if (ack_with_err)
+ dev_warn(&mcde_dev->dev,
+ "DCS Acknowledge Error Report %.4X\n",
+ dsi_rfld(link, DSI_DIRECT_CMD_STS, ACK_VAL));
+ } while (--nbr_of_retries && ack_with_err);
+
+ if (ok) {
+ int rdsize;
+ u32 rddat;
+
+ rdsize = dsi_rfld(link, DSI_DIRECT_CMD_RD_PROPERTY, RD_SIZE);
+ rddat = dsi_rreg(link, DSI_DIRECT_CMD_RDDAT);
+ if (rdsize < *len)
+ dev_warn(&mcde_dev->dev, "DCS incomplete read %d<%d"
+ " (%.8X)\n", rdsize, *len, rddat);
+ *len = min(*len, rdsize);
+ memcpy(data, &rddat, *len);
+ } else {
+ dev_err(&mcde_dev->dev, "DCS read failed, err=%d, sts=%X\n",
+ error, dsi_rreg(link, DSI_DIRECT_CMD_STS));
+ ret = -EIO;
+ }
+
+ dsi_wreg(link, DSI_CMD_MODE_STS_CLR, ~0);
+ dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR, ~0);
+
+ set_channel_state_atomic(chnl, CHNLSTATE_IDLE);
+
+ mcde_unlock(__func__, __LINE__);
+
+ return ret;
+}
+
+/*
+ * Set Maximum Return Packet size is a command that specifies the
+ * maximum size of the payload transmitted from peripheral back to
+ * the host processor.
+ *
+ * During power-on or reset sequence, the Maximum Return Packet Size
+ * is set to a default value of one. In order to be able to use
+ * mcde_dsi_dcs_read for reading more than 1 byte at a time, this
+ * parameter should be set by the host processor to the desired value
+ * in the initialization routine before commencing normal operation.
+ */
+int mcde_dsi_set_max_pkt_size(struct mcde_chnl_state *chnl)
+{
+ u32 settings;
+ u8 link = chnl->port.link;
+ u8 virt_id = chnl->port.phy.dsi.virt_id;
+
+ if (chnl->port.type != MCDE_PORTTYPE_DSI)
+ return -EINVAL;
+
+ mcde_lock(__func__, __LINE__);
+
+ if (enable_mcde_hw()) {
+ mcde_unlock(__func__, __LINE__);
+ return -EIO;
+ }
+
+ set_channel_state_sync(chnl, CHNLSTATE_DSI_WRITE);
+
+ /*
+ * Set Maximum Return Packet Size is a two-byte command packet
+ * that specifies the maximum size of the payload as u16 value.
+ * The order of bytes is: MaxSize LSB, MaxSize MSB
+ */
+ settings = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(WRITE) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(false) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(virt_id) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(2) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(true) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(
+ SET_MAX_PKT_SIZE);
+ dsi_wreg(link, DSI_DIRECT_CMD_MAIN_SETTINGS, settings);
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT0, MCDE_MAX_DCS_READ);
+ dsi_wreg(link, DSI_DIRECT_CMD_SEND, true);
+
+ set_channel_state_atomic(chnl, CHNLSTATE_IDLE);
+
+ mcde_unlock(__func__, __LINE__);
+
+ return 0;
+}
+
+static void dsi_te_poll_req(struct mcde_chnl_state *chnl)
+{
+ u8 lnk = chnl->port.link;
+ const struct mcde_port *port = &chnl->port;
+
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, REG_TE_EN, false);
+ if (port->ifc == 0)
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, IF1_TE_EN, true);
+ if (port->ifc == 1)
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, IF2_TE_EN, true);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, BTA_EN, true);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, READ_EN, true);
+ dsi_wfld(lnk, DSI_CMD_MODE_CTL, TE_TIMEOUT, 0x3FF);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_DATA_CTL, TE_POLLING_EN, true);
+}
+
+static void dsi_te_poll_set_timer(struct mcde_chnl_state *chnl,
+ unsigned int timeout)
+{
+ mod_timer(&chnl->dsi_te_timer,
+ jiffies +
+ msecs_to_jiffies(timeout));
+}
+
+static void dsi_te_timer_function(unsigned long arg)
+{
+ struct mcde_chnl_state *chnl;
+ u8 lnk;
+
+ if (arg >= num_channels) {
+ dev_err(&mcde_dev->dev, "%s invalid arg:%ld\n", __func__, arg);
+ return;
+ }
+
+ chnl = &channels[arg];
+
+ if (mcde_is_enabled && chnl->enabled && chnl->formatter_updated) {
+ lnk = chnl->port.link;
+ /* No TE answer; force stop */
+ dsi_wfld(lnk, DSI_MCTL_MAIN_PHY_CTL, FORCE_STOP_MODE, true);
+ udelay(20);
+ dsi_wfld(lnk, DSI_MCTL_MAIN_PHY_CTL, FORCE_STOP_MODE, false);
+ dev_info(&mcde_dev->dev, "DSI%d force stop\n", lnk);
+ dsi_te_poll_set_timer(chnl, DSI_TE_NO_ANSWER_TIMEOUT);
+ } else {
+ dev_info(&mcde_dev->dev, "1:DSI force stop\n");
+ }
+}
+
+static void dsi_te_request(struct mcde_chnl_state *chnl)
+{
+ u8 link = chnl->port.link;
+ u8 virt_id = chnl->port.phy.dsi.virt_id;
+ u32 settings;
+
+ dev_vdbg(&mcde_dev->dev, "Request BTA TE, chnl=%d\n",
+ chnl->id);
+
+ set_channel_state_atomic(chnl, CHNLSTATE_WAIT_TE);
+
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, BTA_EN, true);
+ dsi_wfld(link, DSI_MCTL_MAIN_DATA_CTL, REG_TE_EN, true);
+ dsi_wfld(link, DSI_CMD_MODE_CTL, TE_TIMEOUT, 0x3FF);
+ settings = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_ENUM(TE_REQ) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT(false) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID(virt_id) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE(2) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN(true) |
+ DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_ENUM(DCS_SHORT_WRITE_1);
+ dsi_wreg(link, DSI_DIRECT_CMD_MAIN_SETTINGS, settings);
+ dsi_wreg(link, DSI_DIRECT_CMD_WRDAT0, DCS_CMD_SET_TEAR_ON);
+ dsi_wreg(link, DSI_DIRECT_CMD_STS_CLR,
+ DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR(true));
+ dsi_wfld(link, DSI_DIRECT_CMD_STS_CTL, TE_RECEIVED_EN, true);
+ dsi_wreg(link, DSI_CMD_MODE_STS_CLR,
+ DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR(true));
+ dsi_wfld(link, DSI_CMD_MODE_STS_CTL, ERR_NO_TE_EN, true);
+ dsi_wreg(link, DSI_DIRECT_CMD_SEND, true);
+}
+
+/* MCDE channels */
+static struct mcde_chnl_state *_mcde_chnl_get(enum mcde_chnl chnl_id,
+ enum mcde_fifo fifo, const struct mcde_port *port)
+{
+ int i;
+ struct mcde_chnl_state *chnl = NULL;
+ struct mcde_platform_data *pdata = mcde_dev->dev.platform_data;
+
+ static struct mcde_col_transform ycbcr_2_rgb = {
+ /* Note that in MCDE YUV 422 pixels come as VYU pixels */
+ .matrix = {
+ {0xff30, 0x012a, 0xff9c},
+ {0x0000, 0x012a, 0x0204},
+ {0x0199, 0x012a, 0x0000},
+ },
+ .offset = {0x0088, 0xfeeb, 0xff21},
+ };
+
+ static struct mcde_col_transform rgb_2_ycbcr = {
+ .matrix = {
+ {0x0042, 0x0081, 0x0019},
+ {0xffda, 0xffb6, 0x0070},
+ {0x0070, 0xffa2, 0xffee},
+ },
+ .offset = {0x0010, 0x0080, 0x0080},
+ };
+
+ /* Allocate channel */
+ for (i = 0; i < num_channels; i++) {
+ if (chnl_id == channels[i].id)
+ chnl = &channels[i];
+ }
+ if (!chnl) {
+ dev_dbg(&mcde_dev->dev, "Invalid channel, chnl=%d\n", chnl_id);
+ return ERR_PTR(-EINVAL);
+ }
+ if (chnl->reserved) {
+ dev_dbg(&mcde_dev->dev, "Channel in use, chnl=%d\n", chnl_id);
+ return ERR_PTR(-EBUSY);
+ }
+
+ chnl->port = *port;
+ chnl->fifo = fifo;
+ chnl->formatter_updated = false;
+ chnl->ycbcr_2_rgb = ycbcr_2_rgb;
+ chnl->rgb_2_ycbcr = rgb_2_ycbcr;
+
+ chnl->blend_en = true;
+ chnl->blend_ctrl = MCDE_CRA0_BLENDCTRL_SOURCE;
+ chnl->alpha_blend = 0xFF;
+ chnl->rotbuf1 = pdata->rotbuf1;
+ chnl->rotbuf2 = pdata->rotbuf2;
+ chnl->rotbufsize = pdata->rotbufsize;
+
+ _mcde_chnl_apply(chnl);
+ chnl->reserved = true;
+
+ if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ chnl->clk_dpi = clk_get(&mcde_dev->dev, CLK_DPI);
+ if (chnl->port.phy.dpi.tv_mode)
+ chnl->vcmp_per_field = true;
+ } else if (chnl->port.type == MCDE_PORTTYPE_DSI &&
+ dsi_use_clk_framework) {
+ char dsihs_name[10];
+ char dsilp_name[10];
+
+ sprintf(dsihs_name, "dsihs%d", port->link);
+ sprintf(dsilp_name, "dsilp%d", port->link);
+
+ chnl->clk_dsi_lp = clk_get(&mcde_dev->dev, dsilp_name);
+ chnl->clk_dsi_hs = clk_get(&mcde_dev->dev, dsihs_name);
+ if (port->phy.dsi.lp_freq != clk_round_rate(chnl->clk_dsi_lp,
+ port->phy.dsi.lp_freq))
+ dev_warn(&mcde_dev->dev, "Could not set dsi lp freq"
+ " to %d\n", port->phy.dsi.lp_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dsi_lp,
+ port->phy.dsi.lp_freq));
+ if (port->phy.dsi.hs_freq != clk_round_rate(chnl->clk_dsi_hs,
+ port->phy.dsi.hs_freq))
+ dev_warn(&mcde_dev->dev, "Could not set dsi hs freq"
+ " to %d\n", port->phy.dsi.hs_freq);
+ WARN_ON_ONCE(clk_set_rate(chnl->clk_dsi_hs,
+ port->phy.dsi.hs_freq));
+ }
+ return chnl;
+}
+
+static int _mcde_chnl_apply(struct mcde_chnl_state *chnl)
+{
+ bool roten = false;
+ u8 rotdir = 0;
+
+ if (chnl->rotation == MCDE_DISPLAY_ROT_90_CCW) {
+ roten = true;
+ rotdir = MCDE_ROTACONF_ROTDIR_CCW;
+ } else if (chnl->rotation == MCDE_DISPLAY_ROT_90_CW) {
+ roten = true;
+ rotdir = MCDE_ROTACONF_ROTDIR_CW;
+ }
+ /* REVIEW: 180 deg? */
+
+ chnl->regs.bpp = portfmt2bpp(chnl->port.pixel_format);
+ chnl->regs.roten = roten;
+ chnl->regs.rotdir = rotdir;
+ chnl->regs.rotbuf1 = chnl->rotbuf1;
+ chnl->regs.rotbuf2 = chnl->rotbuf2;
+ chnl->regs.rotbufsize = chnl->rotbufsize;
+ chnl->regs.palette_enable = chnl->palette_enable;
+ chnl->regs.map_r = chnl->map_r;
+ chnl->regs.map_g = chnl->map_g;
+ chnl->regs.map_b = chnl->map_b;
+ if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+ chnl->regs.clksel = MCDE_CRA1_CLKSEL_MCDECLK;
+ chnl->regs.dsipacking =
+ portfmt2dsipacking(chnl->port.pixel_format);
+ } else if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ if (chnl->port.phy.dpi.tv_mode) {
+ chnl->regs.internal_clk = false;
+ chnl->regs.bcd = true;
+ if (chnl->id == MCDE_CHNL_A)
+ chnl->regs.clksel = MCDE_CRA1_CLKSEL_TV1CLK;
+ else
+ chnl->regs.clksel = MCDE_CRA1_CLKSEL_TV2CLK;
+ } else {
+ chnl->regs.internal_clk = true;
+ chnl->regs.clksel = MCDE_CRA1_CLKSEL_CLKPLL72;
+ chnl->regs.cdwin =
+ portfmt2cdwin(chnl->port.pixel_format);
+ chnl->regs.bcd = (chnl->port.phy.dpi.clock_div < 2);
+ if (!chnl->regs.bcd)
+ chnl->regs.pcd =
+ chnl->port.phy.dpi.clock_div - 2;
+ }
+ dpi_video_mode_apply(chnl);
+ }
+
+ chnl->regs.blend_ctrl = chnl->blend_ctrl;
+ chnl->regs.blend_en = chnl->blend_en;
+ chnl->regs.alpha_blend = chnl->alpha_blend;
+
+ chnl->regs.dirty = true;
+
+ dev_vdbg(&mcde_dev->dev, "Channel applied, chnl=%d\n", chnl->id);
+ return 0;
+}
+
+static void setup_channel(struct mcde_chnl_state *chnl)
+{
+ set_channel_state_sync(chnl, CHNLSTATE_SETUP);
+
+ if (chnl->port.type == MCDE_PORTTYPE_DPI && chnl->tv_regs.dirty)
+ update_dpi_registers(chnl->id, &chnl->tv_regs);
+ if ((chnl->id == MCDE_CHNL_A || chnl->id == MCDE_CHNL_B) &&
+ chnl->col_regs.dirty)
+ update_col_registers(chnl->id, &chnl->col_regs);
+ if (chnl->regs.dirty)
+ update_channel_registers(chnl->id, &chnl->regs, &chnl->port,
+ chnl->fifo, &chnl->vmode);
+}
+
+static void chnl_update_continous(struct mcde_chnl_state *chnl,
+ bool tripple_buffer)
+{
+ if (chnl->state == CHNLSTATE_RUNNING) {
+ if (!tripple_buffer)
+ wait_for_vcmp(chnl);
+ return;
+ }
+
+ setup_channel(chnl);
+ if (chnl->port.sync_src == MCDE_SYNCSRC_TE0) {
+ mcde_wfld(MCDE_CRC, SYCEN0, true);
+ } else if (chnl->port.sync_src == MCDE_SYNCSRC_TE1) {
+ mcde_wfld(MCDE_VSCRC1, VSSEL, 1);
+ mcde_wfld(MCDE_CRC, SYCEN1, true);
+ }
+
+ enable_flow(chnl);
+}
+
+static void chnl_update_non_continous(struct mcde_chnl_state *chnl)
+{
+ /* Commit settings to registers */
+ setup_channel(chnl);
+
+ if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+ if (chnl->port.sync_src == MCDE_SYNCSRC_OFF) {
+ if (chnl->port.frame_trig == MCDE_TRIG_SW) {
+ do_softwaretrig(chnl);
+ } else {
+ enable_flow(chnl);
+ disable_flow(chnl);
+ }
+ dev_vdbg(&mcde_dev->dev, "Channel update (no sync), "
+ "chnl=%d\n", chnl->id);
+ } else if (chnl->port.sync_src == MCDE_SYNCSRC_BTA) {
+ if (chnl->power_mode == MCDE_DISPLAY_PM_ON) {
+ dsi_te_request(chnl);
+ } else {
+ if (chnl->port.frame_trig == MCDE_TRIG_SW)
+ do_softwaretrig(chnl);
+ }
+ if (chnl->port.frame_trig == MCDE_TRIG_HW) {
+ /*
+ * During BTA TE the MCDE block will be stalled,
+ * once the TE is received the DMA trig will
+ * happen
+ */
+ enable_flow(chnl);
+ disable_flow(chnl);
+ }
+ }
+ }
+}
+
+static void chnl_update_overlay(struct mcde_chnl_state *chnl,
+ struct mcde_ovly_state *ovly)
+{
+ if (!ovly)
+ return;
+
+ if (ovly->regs.dirty_buf) {
+ if (!chnl->port.update_auto_trig)
+ set_channel_state_sync(chnl, CHNLSTATE_SETUP);
+ update_overlay_registers_on_the_fly(ovly->idx, &ovly->regs);
+ mcde_debugfs_overlay_update(chnl->id, ovly != chnl->ovly0);
+ }
+ if (ovly->regs.dirty) {
+ if (!chnl->port.update_auto_trig)
+ set_channel_state_sync(chnl, CHNLSTATE_SETUP);
+ chnl_ovly_pixel_format_apply(chnl, ovly);
+ update_overlay_registers(ovly->idx, &ovly->regs, &chnl->port,
+ chnl->fifo, chnl->regs.x, chnl->regs.y,
+ chnl->regs.ppl, chnl->regs.lpf, ovly->stride,
+ chnl->vmode.interlaced, chnl->rotation);
+ if (chnl->id == MCDE_CHNL_A || chnl->id == MCDE_CHNL_B)
+ update_col_registers(chnl->id, &chnl->col_regs);
+ }
+}
+
+static int _mcde_chnl_update(struct mcde_chnl_state *chnl,
+ struct mcde_rectangle *update_area,
+ bool tripple_buffer)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ /* TODO: lock & make wait->trig async */
+ if (!chnl->enabled || !update_area
+ || (update_area->w == 0 && update_area->h == 0)) {
+ return -EINVAL;
+ }
+
+ if (chnl->port.update_auto_trig && tripple_buffer)
+ wait_for_vcmp(chnl);
+
+ chnl->regs.x = update_area->x;
+ chnl->regs.y = update_area->y;
+ /* TODO Crop against video_mode.xres and video_mode.yres */
+ chnl->regs.ppl = update_area->w;
+ chnl->regs.lpf = update_area->h;
+ if (chnl->port.type == MCDE_PORTTYPE_DPI &&
+ chnl->port.phy.dpi.tv_mode) {
+ /* subtract border */
+ chnl->regs.ppl -= chnl->tv_regs.dho + chnl->tv_regs.alw;
+ /* subtract double borders, ie. for both fields */
+ chnl->regs.lpf -= 2 * (chnl->tv_regs.dvo + chnl->tv_regs.bsl);
+ } else if (chnl->port.type == MCDE_PORTTYPE_DSI &&
+ chnl->vmode.interlaced)
+ chnl->regs.lpf /= 2;
+
+ chnl_update_overlay(chnl, chnl->ovly0);
+ chnl_update_overlay(chnl, chnl->ovly1);
+
+ if (chnl->port.update_auto_trig)
+ chnl_update_continous(chnl, tripple_buffer);
+ else
+ chnl_update_non_continous(chnl);
+
+ dev_vdbg(&mcde_dev->dev, "Channel updated, chnl=%d\n", chnl->id);
+ mcde_debugfs_channel_update(chnl->id);
+ return 0;
+}
+
+static int _mcde_chnl_enable(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+ chnl->enabled = true;
+ return 0;
+}
+
+/* API entry points */
+/* MCDE channels */
+struct mcde_chnl_state *mcde_chnl_get(enum mcde_chnl chnl_id,
+ enum mcde_fifo fifo, const struct mcde_port *port)
+{
+ struct mcde_chnl_state *chnl;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+ chnl = _mcde_chnl_get(chnl_id, fifo, port);
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+
+ return chnl;
+}
+
+int mcde_chnl_set_pixel_format(struct mcde_chnl_state *chnl,
+ enum mcde_port_pix_fmt pix_fmt)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+ chnl->port.pixel_format = pix_fmt;
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+
+ return 0;
+}
+
+int mcde_chnl_set_palette(struct mcde_chnl_state *chnl,
+ struct mcde_palette_table *palette)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+ if (palette != NULL) {
+ chnl->map_r = palette->map_col_ch0;
+ chnl->map_g = palette->map_col_ch1;
+ chnl->map_b = palette->map_col_ch2;
+ chnl->palette_enable = true;
+ } else {
+ chnl->map_r = NULL;
+ chnl->map_g = NULL;
+ chnl->map_b = NULL;
+ chnl->palette_enable = false;
+ }
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+ return 0;
+}
+
+void mcde_chnl_set_col_convert(struct mcde_chnl_state *chnl,
+ struct mcde_col_transform *transform,
+ enum mcde_col_convert convert)
+{
+ switch (convert) {
+ case MCDE_CONVERT_RGB_2_YCBCR:
+ memcpy(&chnl->rgb_2_ycbcr, transform,
+ sizeof(struct mcde_col_transform));
+ /* force update: */
+ if (chnl->transform == &chnl->rgb_2_ycbcr) {
+ chnl->transform = NULL;
+ chnl->ovly0->dirty = true;
+ chnl->ovly1->dirty = true;
+ }
+ break;
+ case MCDE_CONVERT_YCBCR_2_RGB:
+ memcpy(&chnl->ycbcr_2_rgb, transform,
+ sizeof(struct mcde_col_transform));
+ /* force update: */
+ if (chnl->transform == &chnl->ycbcr_2_rgb) {
+ chnl->transform = NULL;
+ chnl->ovly0->dirty = true;
+ chnl->ovly1->dirty = true;
+ }
+ break;
+ default:
+ /* Trivial transforms are handled internally */
+ dev_warn(&mcde_dev->dev,
+ "%s: unsupported col convert\n", __func__);
+ break;
+ }
+}
+
+int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl,
+ struct mcde_video_mode *vmode)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (chnl == NULL || vmode == NULL)
+ return -EINVAL;
+
+ chnl->vmode = *vmode;
+
+ chnl->ovly0->dirty = true;
+ if (chnl->ovly1)
+ chnl->ovly1->dirty = true;
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+
+ return 0;
+}
+EXPORT_SYMBOL(mcde_chnl_set_video_mode);
+
+int mcde_chnl_set_rotation(struct mcde_chnl_state *chnl,
+ enum mcde_display_rotation rotation)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+
+ if ((rotation == MCDE_DISPLAY_ROT_90_CW ||
+ rotation == MCDE_DISPLAY_ROT_90_CCW) &&
+ (chnl->id != MCDE_CHNL_A && chnl->id != MCDE_CHNL_B))
+ return -EINVAL;
+
+ chnl->rotation = rotation;
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+
+ return 0;
+}
+
+int mcde_chnl_set_power_mode(struct mcde_chnl_state *chnl,
+ enum mcde_display_power_mode power_mode)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+
+ chnl->power_mode = power_mode;
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+
+ return 0;
+}
+
+int mcde_chnl_apply(struct mcde_chnl_state *chnl)
+{
+ int ret ;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+
+ mcde_lock(__func__, __LINE__);
+ ret = _mcde_chnl_apply(chnl);
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "%s exit with ret %d\n", __func__, ret);
+
+ return ret;
+}
+
+int mcde_chnl_update(struct mcde_chnl_state *chnl,
+ struct mcde_rectangle *update_area,
+ bool tripple_buffer)
+{
+ int ret;
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return -EINVAL;
+
+ mcde_lock(__func__, __LINE__);
+ enable_mcde_hw();
+ if (!chnl->formatter_updated)
+ (void)update_channel_static_registers(chnl);
+
+ if (chnl->regs.roten && !chnl->esram_is_enabled) {
+ WARN_ON_ONCE(regulator_enable(regulator_esram_epod));
+ chnl->esram_is_enabled = true;
+ } else if (!chnl->regs.roten && chnl->esram_is_enabled) {
+ WARN_ON_ONCE(regulator_disable(regulator_esram_epod));
+ chnl->esram_is_enabled = false;
+ }
+
+ ret = _mcde_chnl_update(chnl, update_area, tripple_buffer);
+
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "%s exit with ret %d\n", __func__, ret);
+
+ return ret;
+}
+
+void mcde_chnl_put(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (chnl->enabled) {
+ stop_channel(chnl);
+ cancel_delayed_work(&hw_timeout_work);
+ disable_mcde_hw(false, true);
+ chnl->enabled = false;
+ }
+
+ chnl->reserved = false;
+ if (chnl->port.type == MCDE_PORTTYPE_DPI) {
+ clk_put(chnl->clk_dpi);
+ if (chnl->port.phy.dpi.tv_mode) {
+ chnl->vcmp_per_field = false;
+ chnl->even_vcmp = false;
+ }
+ } else if (chnl->port.type == MCDE_PORTTYPE_DSI) {
+ if (dsi_use_clk_framework) {
+ clk_put(chnl->clk_dsi_lp);
+ clk_put(chnl->clk_dsi_hs);
+ }
+ }
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+}
+
+void mcde_chnl_stop_flow(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ mcde_lock(__func__, __LINE__);
+ if (mcde_is_enabled && chnl->enabled)
+ stop_channel(chnl);
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+}
+
+void mcde_chnl_enable(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ mcde_lock(__func__, __LINE__);
+ _mcde_chnl_enable(chnl);
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+}
+
+void mcde_chnl_disable(struct mcde_chnl_state *chnl)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ mcde_lock(__func__, __LINE__);
+ cancel_delayed_work(&hw_timeout_work);
+ /* The channel must be stopped before it is disabled */
+ WARN_ON_ONCE(chnl->state == CHNLSTATE_RUNNING);
+ disable_mcde_hw(false, true);
+ chnl->enabled = false;
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "%s exit\n", __func__);
+}
+
+/* MCDE overlays */
+struct mcde_ovly_state *mcde_ovly_get(struct mcde_chnl_state *chnl)
+{
+ struct mcde_ovly_state *ovly;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!chnl->reserved)
+ return ERR_PTR(-EINVAL);
+
+ if (!chnl->ovly0->inuse)
+ ovly = chnl->ovly0;
+ else if (chnl->ovly1 && !chnl->ovly1->inuse)
+ ovly = chnl->ovly1;
+ else
+ ovly = ERR_PTR(-EBUSY);
+
+ if (!IS_ERR(ovly)) {
+ ovly->inuse = true;
+ ovly->paddr = 0;
+ ovly->stride = 0;
+ ovly->pix_fmt = MCDE_OVLYPIXFMT_RGB565;
+ ovly->src_x = 0;
+ ovly->src_y = 0;
+ ovly->dst_x = 0;
+ ovly->dst_y = 0;
+ ovly->dst_z = 0;
+ ovly->w = 0;
+ ovly->h = 0;
+ ovly->alpha_value = 0xFF;
+ ovly->alpha_source = MCDE_OVL1CONF2_BP_PER_PIXEL_ALPHA;
+ ovly->dirty = true;
+ mcde_ovly_apply(ovly);
+ }
+
+ return ovly;
+}
+
+void mcde_ovly_put(struct mcde_ovly_state *ovly)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ if (!ovly->inuse)
+ return;
+ if (ovly->regs.enabled) {
+ ovly->paddr = 0;
+ ovly->dirty = true;
+ mcde_ovly_apply(ovly);/* REVIEW: API call calling API call! */
+ }
+ ovly->inuse = false;
+}
+
+void mcde_ovly_set_source_buf(struct mcde_ovly_state *ovly, u32 paddr)
+{
+ if (!ovly->inuse)
+ return;
+
+ ovly->dirty = paddr == 0 || ovly->paddr == 0;
+ ovly->dirty_buf = true;
+
+ ovly->paddr = paddr;
+}
+
+void mcde_ovly_set_source_info(struct mcde_ovly_state *ovly,
+ u32 stride, enum mcde_ovly_pix_fmt pix_fmt)
+{
+ if (!ovly->inuse)
+ return;
+
+ ovly->stride = stride;
+ ovly->pix_fmt = pix_fmt;
+ ovly->dirty = true;
+}
+
+void mcde_ovly_set_source_area(struct mcde_ovly_state *ovly,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ if (!ovly->inuse)
+ return;
+
+ ovly->src_x = x;
+ ovly->src_y = y;
+ ovly->w = w;
+ ovly->h = h;
+ ovly->dirty = true;
+}
+
+void mcde_ovly_set_dest_pos(struct mcde_ovly_state *ovly, u16 x, u16 y, u8 z)
+{
+ if (!ovly->inuse)
+ return;
+
+ ovly->dst_x = x;
+ ovly->dst_y = y;
+ ovly->dst_z = z;
+ ovly->dirty = true;
+}
+
+void mcde_ovly_apply(struct mcde_ovly_state *ovly)
+{
+ if (!ovly->inuse)
+ return;
+
+ mcde_lock(__func__, __LINE__);
+
+ if (ovly->dirty || ovly->dirty_buf) {
+ ovly->regs.ch_id = ovly->chnl->id;
+ ovly->regs.enabled = ovly->paddr != 0;
+ ovly->regs.baseaddress0 = ovly->paddr;
+ ovly->regs.baseaddress1 =
+ ovly->regs.baseaddress0 + ovly->stride;
+ ovly->regs.dirty_buf = true;
+ ovly->dirty_buf = false;
+ }
+ if (!ovly->dirty) {
+ mcde_unlock(__func__, __LINE__);
+ return;
+ }
+
+ switch (ovly->pix_fmt) {/* REVIEW: Extract to table */
+ case MCDE_OVLYPIXFMT_RGB565:
+ ovly->regs.bits_per_pixel = 16;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_RGB565;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = true;
+ break;
+ case MCDE_OVLYPIXFMT_RGBA5551:
+ ovly->regs.bits_per_pixel = 16;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_IRGB1555;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = false;
+ break;
+ case MCDE_OVLYPIXFMT_RGBA4444:
+ ovly->regs.bits_per_pixel = 16;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_ARGB4444;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = false;
+ break;
+ case MCDE_OVLYPIXFMT_RGB888:
+ ovly->regs.bits_per_pixel = 24;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_RGB888;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = true;
+ break;
+ case MCDE_OVLYPIXFMT_RGBX8888:
+ ovly->regs.bits_per_pixel = 32;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_XRGB8888;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = true;
+ ovly->regs.opq = true;
+ break;
+ case MCDE_OVLYPIXFMT_RGBA8888:
+ ovly->regs.bits_per_pixel = 32;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_ARGB8888;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = false;
+ break;
+ case MCDE_OVLYPIXFMT_YCbCr422:
+ ovly->regs.bits_per_pixel = 16;
+ ovly->regs.bpp = MCDE_EXTSRC0CONF_BPP_YCBCR422;
+ ovly->regs.bgr = false;
+ ovly->regs.bebo = false;
+ ovly->regs.opq = true;
+ break;
+ default:
+ break;
+ }
+
+ ovly->regs.ppl = ovly->w;
+ ovly->regs.lpf = ovly->h;
+ ovly->regs.cropx = ovly->src_x;
+ ovly->regs.cropy = ovly->src_y;
+ ovly->regs.xpos = ovly->dst_x;
+ ovly->regs.ypos = ovly->dst_y;
+ ovly->regs.z = ovly->dst_z > 0; /* 0 or 1 */
+ ovly->regs.col_conv = MCDE_OVL0CR_COLCCTRL_DISABLED;
+ ovly->regs.alpha_source = ovly->alpha_source;
+ ovly->regs.alpha_value = ovly->alpha_value;
+
+ ovly->regs.dirty = true;
+ ovly->dirty = false;
+
+ mcde_unlock(__func__, __LINE__);
+
+ dev_vdbg(&mcde_dev->dev, "Overlay applied, idx=%d chnl=%d\n",
+ ovly->idx, ovly->chnl->id);
+}
+
+static int init_clocks_and_power(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mcde_platform_data *pdata = pdev->dev.platform_data;
+
+ if (pdata->regulator_mcde_epod_id) {
+ regulator_mcde_epod = regulator_get(&pdev->dev,
+ pdata->regulator_mcde_epod_id);
+ if (IS_ERR(regulator_mcde_epod)) {
+ ret = PTR_ERR(regulator_mcde_epod);
+ dev_warn(&pdev->dev,
+ "%s: Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_mcde_epod_id);
+ regulator_mcde_epod = NULL;
+ return ret;
+ }
+ } else {
+ dev_warn(&pdev->dev, "%s: No mcde regulator id supplied\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (pdata->regulator_esram_epod_id) {
+ regulator_esram_epod = regulator_get(&pdev->dev,
+ pdata->regulator_esram_epod_id);
+ if (IS_ERR(regulator_esram_epod)) {
+ ret = PTR_ERR(regulator_esram_epod);
+ dev_warn(&pdev->dev,
+ "%s: Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_esram_epod_id);
+ regulator_esram_epod = NULL;
+ goto regulator_esram_err;
+ }
+ } else {
+ dev_warn(&pdev->dev, "%s: No esram regulator id supplied\n",
+ __func__);
+ }
+
+ if (pdata->regulator_vana_id) {
+ regulator_vana = regulator_get(&pdev->dev,
+ pdata->regulator_vana_id);
+ if (IS_ERR(regulator_vana)) {
+ ret = PTR_ERR(regulator_vana);
+ dev_warn(&pdev->dev,
+ "%s: Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_vana_id);
+ regulator_vana = NULL;
+ goto regulator_vana_err;
+ }
+ } else {
+ dev_dbg(&pdev->dev, "%s: No vana regulator id supplied\n",
+ __func__);
+ }
+
+ if (!dsi_use_clk_framework) {
+ clock_dsi = clk_get(&pdev->dev, pdata->clock_dsi_id);
+ if (IS_ERR(clock_dsi))
+ dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
+ __func__, pdata->clock_dsi_id);
+
+ clock_dsi_lp = clk_get(&pdev->dev, pdata->clock_dsi_lp_id);
+ if (IS_ERR(clock_dsi_lp))
+ dev_dbg(&pdev->dev, "%s: Failed to get clock '%s'\n",
+ __func__, pdata->clock_dsi_lp_id);
+ }
+
+ clock_mcde = clk_get(&pdev->dev, CLK_MCDE);
+ if (IS_ERR(clock_mcde)) {
+ ret = PTR_ERR(clock_mcde);
+ dev_warn(&pdev->dev, "%s: Failed to get mcde_clk\n", __func__);
+ goto clk_mcde_err;
+ }
+
+ return ret;
+
+clk_mcde_err:
+ if (!dsi_use_clk_framework) {
+ clk_put(clock_dsi_lp);
+ clk_put(clock_dsi);
+ }
+
+ if (regulator_vana)
+ regulator_put(regulator_vana);
+regulator_vana_err:
+ if (regulator_esram_epod)
+ regulator_put(regulator_esram_epod);
+regulator_esram_err:
+ regulator_put(regulator_mcde_epod);
+ return ret;
+}
+
+static void remove_clocks_and_power(struct platform_device *pdev)
+{
+ /* REVIEW: Release only if exist */
+ /* REVIEW: Remove make sure MCDE is done */
+ if (!dsi_use_clk_framework) {
+ clk_put(clock_dsi_lp);
+ clk_put(clock_dsi);
+ }
+ clk_put(clock_mcde);
+ if (regulator_vana)
+ regulator_put(regulator_vana);
+ regulator_put(regulator_mcde_epod);
+ regulator_put(regulator_esram_epod);
+}
+
+static int probe_hw(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+ u32 pid;
+ struct resource *res;
+
+ dev_info(&mcde_dev->dev, "Probe HW\n");
+
+ /* Get MCDE HW version */
+ regulator_enable(regulator_mcde_epod);
+ clk_enable(clock_mcde);
+ pid = mcde_rreg(MCDE_PID);
+
+ dev_info(&mcde_dev->dev, "MCDE HW revision 0x%.8X\n", pid);
+
+ clk_disable(clock_mcde);
+ regulator_disable(regulator_mcde_epod);
+
+ switch (pid) {
+ case MCDE_VERSION_3_0_8:
+ num_dsilinks = 3;
+ num_channels = 4;
+ num_overlays = 6;
+ dsi_ifc_is_supported = true;
+ input_fifo_size = 128;
+ output_fifo_ab_size = 640;
+ output_fifo_c0c1_size = 160;
+ dsi_use_clk_framework = false;
+ dev_info(&mcde_dev->dev, "db8500 V2 HW\n");
+ break;
+ case MCDE_VERSION_4_0_4:
+ num_dsilinks = 2;
+ num_channels = 2;
+ num_overlays = 3;
+ input_fifo_size = 80;
+ output_fifo_ab_size = 320;
+ dsi_ifc_is_supported = false;
+ dsi_use_clk_framework = false;
+ dev_info(&mcde_dev->dev, "db5500 V2 HW\n");
+ break;
+ case MCDE_VERSION_4_1_3:
+ num_dsilinks = 3;
+ num_channels = 4;
+ num_overlays = 6;
+ dsi_ifc_is_supported = true;
+ input_fifo_size = 192;
+ output_fifo_ab_size = 640;
+ output_fifo_c0c1_size = 160;
+ dsi_use_clk_framework = false;
+ dev_info(&mcde_dev->dev, "db9540 V1 HW\n");
+ break;
+ case MCDE_VERSION_3_0_5:
+ /* Intentional */
+ case MCDE_VERSION_1_0_4:
+ /* Intentional */
+ default:
+ dev_err(&mcde_dev->dev, "Unsupported HW version\n");
+ ret = -ENOTSUPP;
+ goto unsupported_hw;
+ break;
+ }
+
+ channels = kzalloc(num_channels * sizeof(struct mcde_chnl_state),
+ GFP_KERNEL);
+ if (!channels) {
+ ret = -ENOMEM;
+ goto failed_channels_alloc;
+ }
+
+ overlays = kzalloc(num_overlays * sizeof(struct mcde_ovly_state),
+ GFP_KERNEL);
+ if (!overlays) {
+ ret = -ENOMEM;
+ goto failed_overlays_alloc;
+ }
+
+ dsiio = kzalloc(num_dsilinks * sizeof(*dsiio), GFP_KERNEL);
+ if (!dsiio) {
+ ret = -ENOMEM;
+ goto failed_dsi_alloc;
+ }
+
+ for (i = 0; i < num_dsilinks; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1+i);
+ if (!res) {
+ dev_dbg(&pdev->dev, "No DSI%d io defined\n", i);
+ ret = -EINVAL;
+ goto failed_get_dsi_io;
+ }
+ dsiio[i] = ioremap(res->start, res->end - res->start + 1);
+ if (!dsiio[i]) {
+ dev_dbg(&pdev->dev, "MCDE DSI%d iomap failed\n", i);
+ ret = -EINVAL;
+ goto failed_map_dsi_io;
+ }
+ dev_info(&pdev->dev, "MCDE DSI%d iomap: 0x%.8X->0x%.8X\n",
+ i, (u32)res->start, (u32)dsiio[i]);
+ }
+
+ /* Init MCDE */
+ for (i = 0; i < num_overlays; i++)
+ overlays[i].idx = i;
+
+ channels[0].ovly0 = &overlays[0];
+ channels[0].ovly1 = &overlays[1];
+ channels[1].ovly0 = &overlays[2];
+
+ if (pid == MCDE_VERSION_3_0_8) {
+ channels[1].ovly1 = &overlays[3];
+ channels[2].ovly0 = &overlays[4];
+ channels[3].ovly0 = &overlays[5];
+ }
+
+ mcde_debugfs_create(&mcde_dev->dev);
+ for (i = 0; i < num_channels; i++) {
+ channels[i].id = i;
+
+ channels[i].ovly0->chnl = &channels[i];
+ if (channels[i].ovly1)
+ channels[i].ovly1->chnl = &channels[i];
+
+ init_waitqueue_head(&channels[i].state_waitq);
+ init_waitqueue_head(&channels[i].vcmp_waitq);
+ init_timer(&channels[i].dsi_te_timer);
+ channels[i].dsi_te_timer.function =
+ dsi_te_timer_function;
+ channels[i].dsi_te_timer.data = i;
+
+ mcde_debugfs_channel_create(i, &channels[i]);
+ mcde_debugfs_overlay_create(i, 0);
+ if (channels[i].ovly1)
+ mcde_debugfs_overlay_create(i, 1);
+ }
+ (void) prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, "mcde", 100);
+ mcde_clk_rate = clk_get_rate(clock_mcde);
+ dev_info(&mcde_dev->dev, "MCDE_CLK is %d MHz\n", mcde_clk_rate);
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "mcde");
+
+ return 0;
+
+failed_map_dsi_io:
+ for (i = 0; i < num_dsilinks; i++) {
+ if (dsiio[i])
+ iounmap(dsiio[i]);
+ }
+failed_get_dsi_io:
+ kfree(dsiio);
+ dsiio = NULL;
+failed_dsi_alloc:
+ kfree(overlays);
+ overlays = NULL;
+failed_overlays_alloc:
+ kfree(channels);
+ channels = NULL;
+unsupported_hw:
+failed_channels_alloc:
+ num_dsilinks = 0;
+ num_channels = 0;
+ num_overlays = 0;
+ return ret;
+}
+
+static int __devinit mcde_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res;
+ struct mcde_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
+ mcde_dev = pdev;
+
+ /* Hook up irq */
+ mcde_irq = platform_get_irq(pdev, 0);
+ if (mcde_irq <= 0) {
+ dev_dbg(&pdev->dev, "No irq defined\n");
+ ret = -EINVAL;
+ goto failed_irq_get;
+ }
+
+ /* Map I/O */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_dbg(&pdev->dev, "No MCDE io defined\n");
+ ret = -EINVAL;
+ goto failed_get_mcde_io;
+ }
+ mcdeio = ioremap(res->start, res->end - res->start + 1);
+ if (!mcdeio) {
+ dev_dbg(&pdev->dev, "MCDE iomap failed\n");
+ ret = -EINVAL;
+ goto failed_map_mcde_io;
+ }
+ dev_info(&pdev->dev, "MCDE iomap: 0x%.8X->0x%.8X\n",
+ (u32)res->start, (u32)mcdeio);
+
+ ret = init_clocks_and_power(pdev);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "%s: init_clocks_and_power failed\n"
+ , __func__);
+ goto failed_init_clocks;
+ }
+
+ INIT_DELAYED_WORK_DEFERRABLE(&hw_timeout_work, work_sleep_function);
+
+ ret = probe_hw(pdev);
+ if (ret)
+ goto failed_probe_hw;
+
+ ret = enable_mcde_hw();
+ if (ret)
+ goto failed_mcde_enable;
+
+ return 0;
+
+failed_mcde_enable:
+failed_probe_hw:
+ remove_clocks_and_power(pdev);
+failed_init_clocks:
+ iounmap(mcdeio);
+failed_map_mcde_io:
+failed_get_mcde_io:
+failed_irq_get:
+ return ret;
+}
+
+static int __devexit mcde_remove(struct platform_device *pdev)
+{
+ struct mcde_chnl_state *chnl = &channels[0];
+
+ for (; chnl < &channels[num_channels]; chnl++) {
+ if (del_timer(&chnl->dsi_te_timer))
+ dev_vdbg(&mcde_dev->dev,
+ "%s dsi timer could not be stopped\n"
+ , __func__);
+ }
+
+ remove_clocks_and_power(pdev);
+ return 0;
+}
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+static int mcde_resume(struct platform_device *pdev)
+{
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ mcde_lock(__func__, __LINE__);
+
+ if (enable_mcde_hw()) {
+ mcde_unlock(__func__, __LINE__);
+ return -EINVAL;
+ }
+
+ mcde_unlock(__func__, __LINE__);
+
+ return 0;
+}
+
+static int mcde_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret;
+
+ dev_vdbg(&mcde_dev->dev, "%s\n", __func__);
+
+ mcde_lock(__func__, __LINE__);
+
+ cancel_delayed_work(&hw_timeout_work);
+
+ if (!mcde_is_enabled) {
+ mcde_unlock(__func__, __LINE__);
+ return 0;
+ }
+ disable_mcde_hw(true, true);
+
+ mcde_unlock(__func__, __LINE__);
+
+ return ret;
+}
+#endif
+
+static struct platform_driver mcde_driver = {
+ .probe = mcde_probe,
+ .remove = mcde_remove,
+#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)
+ .suspend = mcde_suspend,
+ .resume = mcde_resume,
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+ .driver = {
+ .name = "mcde",
+ },
+};
+
+int __init mcde_init(void)
+{
+ mutex_init(&mcde_hw_lock);
+ return platform_driver_register(&mcde_driver);
+}
+
+void mcde_exit(void)
+{
+ /* REVIEW: shutdown MCDE? */
+ platform_driver_unregister(&mcde_driver);
+}
diff --git a/drivers/video/mcde/mcde_mod.c b/drivers/video/mcde/mcde_mod.c
new file mode 100644
index 00000000000..60df0d4965f
--- /dev/null
+++ b/drivers/video/mcde/mcde_mod.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson MCDE driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <video/mcde.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+#include <video/mcde_display.h>
+
+/* Module init */
+
+static int __init mcde_subsystem_init(void)
+{
+ int ret;
+ pr_info("MCDE subsystem init begin\n");
+
+ /* MCDE module init sequence */
+ ret = mcde_init();
+ if (ret)
+ goto mcde_failed;
+ ret = mcde_display_init();
+ if (ret)
+ goto mcde_display_failed;
+ ret = mcde_dss_init();
+ if (ret)
+ goto mcde_dss_failed;
+ ret = mcde_fb_init();
+ if (ret)
+ goto mcde_fb_failed;
+ pr_info("MCDE subsystem init done\n");
+
+ goto done;
+mcde_fb_failed:
+ mcde_dss_exit();
+mcde_dss_failed:
+ mcde_display_exit();
+mcde_display_failed:
+ mcde_exit();
+mcde_failed:
+done:
+ return ret;
+}
+#ifdef MODULE
+module_init(mcde_subsystem_init);
+#else
+fs_initcall(mcde_subsystem_init);
+#endif
+
+static void __exit mcde_module_exit(void)
+{
+ mcde_exit();
+ mcde_display_exit();
+ mcde_dss_exit();
+}
+module_exit(mcde_module_exit);
+
+MODULE_AUTHOR("Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ST-Ericsson MCDE driver");
+
diff --git a/drivers/video/mcde/mcde_regs.h b/drivers/video/mcde/mcde_regs.h
new file mode 100644
index 00000000000..0eece3faea2
--- /dev/null
+++ b/drivers/video/mcde/mcde_regs.h
@@ -0,0 +1,5096 @@
+
+#define MCDE_VAL2REG(__reg, __fld, __val) \
+ (((__val) << __reg##_##__fld##_SHIFT) & __reg##_##__fld##_MASK)
+#define MCDE_REG2VAL(__reg, __fld, __val) \
+ (((__val) & __reg##_##__fld##_MASK) >> __reg##_##__fld##_SHIFT)
+
+#define MCDE_CR 0x00000000
+#define MCDE_CR_IFIFOCTRLEN_SHIFT 15
+#define MCDE_CR_IFIFOCTRLEN_MASK 0x00008000
+#define MCDE_CR_IFIFOCTRLEN(__x) \
+ MCDE_VAL2REG(MCDE_CR, IFIFOCTRLEN, __x)
+#define MCDE_CR_AUTOCLKG_EN_SHIFT 30
+#define MCDE_CR_AUTOCLKG_EN_MASK 0x40000000
+#define MCDE_CR_AUTOCLKG_EN(__x) \
+ MCDE_VAL2REG(MCDE_CR, AUTOCLKG_EN, __x)
+#define MCDE_CR_MCDEEN_SHIFT 31
+#define MCDE_CR_MCDEEN_MASK 0x80000000
+#define MCDE_CR_MCDEEN(__x) \
+ MCDE_VAL2REG(MCDE_CR, MCDEEN, __x)
+#define MCDE_CONF0 0x00000004
+#define MCDE_CONF0_SYNCMUX0_SHIFT 0
+#define MCDE_CONF0_SYNCMUX0_MASK 0x00000001
+#define MCDE_CONF0_SYNCMUX0(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX0, __x)
+#define MCDE_CONF0_SYNCMUX1_SHIFT 1
+#define MCDE_CONF0_SYNCMUX1_MASK 0x00000002
+#define MCDE_CONF0_SYNCMUX1(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX1, __x)
+#define MCDE_CONF0_SYNCMUX2_SHIFT 2
+#define MCDE_CONF0_SYNCMUX2_MASK 0x00000004
+#define MCDE_CONF0_SYNCMUX2(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX2, __x)
+#define MCDE_CONF0_SYNCMUX3_SHIFT 3
+#define MCDE_CONF0_SYNCMUX3_MASK 0x00000008
+#define MCDE_CONF0_SYNCMUX3(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX3, __x)
+#define MCDE_CONF0_SYNCMUX4_SHIFT 4
+#define MCDE_CONF0_SYNCMUX4_MASK 0x00000010
+#define MCDE_CONF0_SYNCMUX4(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX4, __x)
+#define MCDE_CONF0_SYNCMUX5_SHIFT 5
+#define MCDE_CONF0_SYNCMUX5_MASK 0x00000020
+#define MCDE_CONF0_SYNCMUX5(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX5, __x)
+#define MCDE_CONF0_SYNCMUX6_SHIFT 6
+#define MCDE_CONF0_SYNCMUX6_MASK 0x00000040
+#define MCDE_CONF0_SYNCMUX6(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX6, __x)
+#define MCDE_CONF0_SYNCMUX7_SHIFT 7
+#define MCDE_CONF0_SYNCMUX7_MASK 0x00000080
+#define MCDE_CONF0_SYNCMUX7(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, SYNCMUX7, __x)
+#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT 12
+#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_MASK 0x00007000
+#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, IFIFOCTRLWTRMRKLVL, __x)
+#define MCDE_CONF0_OUTMUX0_SHIFT 16
+#define MCDE_CONF0_OUTMUX0_MASK 0x00070000
+#define MCDE_CONF0_OUTMUX0(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, OUTMUX0, __x)
+#define MCDE_CONF0_OUTMUX1_SHIFT 19
+#define MCDE_CONF0_OUTMUX1_MASK 0x00380000
+#define MCDE_CONF0_OUTMUX1(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, OUTMUX1, __x)
+#define MCDE_CONF0_OUTMUX2_SHIFT 22
+#define MCDE_CONF0_OUTMUX2_MASK 0x01C00000
+#define MCDE_CONF0_OUTMUX2(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, OUTMUX2, __x)
+#define MCDE_CONF0_OUTMUX3_SHIFT 25
+#define MCDE_CONF0_OUTMUX3_MASK 0x0E000000
+#define MCDE_CONF0_OUTMUX3(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, OUTMUX3, __x)
+#define MCDE_CONF0_OUTMUX4_SHIFT 28
+#define MCDE_CONF0_OUTMUX4_MASK 0x70000000
+#define MCDE_CONF0_OUTMUX4(__x) \
+ MCDE_VAL2REG(MCDE_CONF0, OUTMUX4, __x)
+#define MCDE_SSP 0x00000008
+#define MCDE_SSP_SSPDATA_SHIFT 0
+#define MCDE_SSP_SSPDATA_MASK 0x000000FF
+#define MCDE_SSP_SSPDATA(__x) \
+ MCDE_VAL2REG(MCDE_SSP, SSPDATA, __x)
+#define MCDE_SSP_SSPCMD_SHIFT 8
+#define MCDE_SSP_SSPCMD_MASK 0x00000100
+#define MCDE_SSP_SSPCMD_DATA 0
+#define MCDE_SSP_SSPCMD_COMMAND 1
+#define MCDE_SSP_SSPCMD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_SSP, SSPCMD, MCDE_SSP_SSPCMD_##__x)
+#define MCDE_SSP_SSPCMD(__x) \
+ MCDE_VAL2REG(MCDE_SSP, SSPCMD, __x)
+#define MCDE_SSP_SSPEN_SHIFT 16
+#define MCDE_SSP_SSPEN_MASK 0x00010000
+#define MCDE_SSP_SSPEN(__x) \
+ MCDE_VAL2REG(MCDE_SSP, SSPEN, __x)
+#define MCDE_AIS 0x00000100
+#define MCDE_AIS_MCDEPPI_SHIFT 0
+#define MCDE_AIS_MCDEPPI_MASK 0x00000001
+#define MCDE_AIS_MCDEPPI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, MCDEPPI, __x)
+#define MCDE_AIS_MCDEOVLI_SHIFT 1
+#define MCDE_AIS_MCDEOVLI_MASK 0x00000002
+#define MCDE_AIS_MCDEOVLI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, MCDEOVLI, __x)
+#define MCDE_AIS_MCDECHNLI_SHIFT 2
+#define MCDE_AIS_MCDECHNLI_MASK 0x00000004
+#define MCDE_AIS_MCDECHNLI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, MCDECHNLI, __x)
+#define MCDE_AIS_MCDEERRI_SHIFT 3
+#define MCDE_AIS_MCDEERRI_MASK 0x00000008
+#define MCDE_AIS_MCDEERRI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, MCDEERRI, __x)
+#define MCDE_AIS_DSI0AI_SHIFT 4
+#define MCDE_AIS_DSI0AI_MASK 0x00000010
+#define MCDE_AIS_DSI0AI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, DSI0AI, __x)
+#define MCDE_AIS_DSI1AI_SHIFT 5
+#define MCDE_AIS_DSI1AI_MASK 0x00000020
+#define MCDE_AIS_DSI1AI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, DSI1AI, __x)
+#define MCDE_AIS_DSI2AI_SHIFT 6
+#define MCDE_AIS_DSI2AI_MASK 0x00000040
+#define MCDE_AIS_DSI2AI(__x) \
+ MCDE_VAL2REG(MCDE_AIS, DSI2AI, __x)
+#define MCDE_IMSCPP 0x00000104
+#define MCDE_IMSCPP_VCMPAIM_SHIFT 0
+#define MCDE_IMSCPP_VCMPAIM_MASK 0x00000001
+#define MCDE_IMSCPP_VCMPAIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VCMPAIM, __x)
+#define MCDE_IMSCPP_VCMPBIM_SHIFT 1
+#define MCDE_IMSCPP_VCMPBIM_MASK 0x00000002
+#define MCDE_IMSCPP_VCMPBIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VCMPBIM, __x)
+#define MCDE_IMSCPP_VSCC0IM_SHIFT 2
+#define MCDE_IMSCPP_VSCC0IM_MASK 0x00000004
+#define MCDE_IMSCPP_VSCC0IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VSCC0IM, __x)
+#define MCDE_IMSCPP_VSCC1IM_SHIFT 3
+#define MCDE_IMSCPP_VSCC1IM_MASK 0x00000008
+#define MCDE_IMSCPP_VSCC1IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VSCC1IM, __x)
+#define MCDE_IMSCPP_VCMPC0IM_SHIFT 4
+#define MCDE_IMSCPP_VCMPC0IM_MASK 0x00000010
+#define MCDE_IMSCPP_VCMPC0IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VCMPC0IM, __x)
+#define MCDE_IMSCPP_VCMPC1IM_SHIFT 5
+#define MCDE_IMSCPP_VCMPC1IM_MASK 0x00000020
+#define MCDE_IMSCPP_VCMPC1IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, VCMPC1IM, __x)
+#define MCDE_IMSCPP_ROTFDIM_B_SHIFT 6
+#define MCDE_IMSCPP_ROTFDIM_B_MASK 0x00000040
+#define MCDE_IMSCPP_ROTFDIM_B(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, ROTFDIM_B, __x)
+#define MCDE_IMSCPP_ROTFDIM_A_SHIFT 7
+#define MCDE_IMSCPP_ROTFDIM_A_MASK 0x00000080
+#define MCDE_IMSCPP_ROTFDIM_A(__x) \
+ MCDE_VAL2REG(MCDE_IMSCPP, ROTFDIM_A, __x)
+#define MCDE_IMSCOVL 0x00000108
+#define MCDE_IMSCOVL_OVLRDIM_SHIFT 0
+#define MCDE_IMSCOVL_OVLRDIM_MASK 0x0000FFFF
+#define MCDE_IMSCOVL_OVLRDIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCOVL, OVLRDIM, __x)
+#define MCDE_IMSCOVL_OVLFDIM_SHIFT 16
+#define MCDE_IMSCOVL_OVLFDIM_MASK 0xFFFF0000
+#define MCDE_IMSCOVL_OVLFDIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCOVL, OVLFDIM, __x)
+#define MCDE_IMSCCHNL 0x0000010C
+#define MCDE_IMSCCHNL_CHNLRDIM_SHIFT 0
+#define MCDE_IMSCCHNL_CHNLRDIM_MASK 0x0000FFFF
+#define MCDE_IMSCCHNL_CHNLRDIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCCHNL, CHNLRDIM, __x)
+#define MCDE_IMSCCHNL_CHNLAIM_SHIFT 16
+#define MCDE_IMSCCHNL_CHNLAIM_MASK 0xFFFF0000
+#define MCDE_IMSCCHNL_CHNLAIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCCHNL, CHNLAIM, __x)
+#define MCDE_IMSCERR 0x00000110
+#define MCDE_IMSCERR_FUAIM_SHIFT 0
+#define MCDE_IMSCERR_FUAIM_MASK 0x00000001
+#define MCDE_IMSCERR_FUAIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, FUAIM, __x)
+#define MCDE_IMSCERR_FUBIM_SHIFT 1
+#define MCDE_IMSCERR_FUBIM_MASK 0x00000002
+#define MCDE_IMSCERR_FUBIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, FUBIM, __x)
+#define MCDE_IMSCERR_SCHBLCKDIM_SHIFT 2
+#define MCDE_IMSCERR_SCHBLCKDIM_MASK 0x00000004
+#define MCDE_IMSCERR_SCHBLCKDIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, SCHBLCKDIM, __x)
+#define MCDE_IMSCERR_ROTAFEIM_WRITE_SHIFT 3
+#define MCDE_IMSCERR_ROTAFEIM_WRITE_MASK 0x00000008
+#define MCDE_IMSCERR_ROTAFEIM_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, ROTAFEIM_WRITE, __x)
+#define MCDE_IMSCERR_ROTAFEIM_READ_SHIFT 4
+#define MCDE_IMSCERR_ROTAFEIM_READ_MASK 0x00000010
+#define MCDE_IMSCERR_ROTAFEIM_READ(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, ROTAFEIM_READ, __x)
+#define MCDE_IMSCERR_ROTBFEIM_WRITE_SHIFT 5
+#define MCDE_IMSCERR_ROTBFEIM_WRITE_MASK 0x00000020
+#define MCDE_IMSCERR_ROTBFEIM_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, ROTBFEIM_WRITE, __x)
+#define MCDE_IMSCERR_ROTBFEIM_READ_SHIFT 6
+#define MCDE_IMSCERR_ROTBFEIM_READ_MASK 0x00000040
+#define MCDE_IMSCERR_ROTBFEIM_READ(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, ROTBFEIM_READ, __x)
+#define MCDE_IMSCERR_FUC0IM_SHIFT 7
+#define MCDE_IMSCERR_FUC0IM_MASK 0x00000080
+#define MCDE_IMSCERR_FUC0IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, FUC0IM, __x)
+#define MCDE_IMSCERR_FUC1IM_SHIFT 8
+#define MCDE_IMSCERR_FUC1IM_MASK 0x00000100
+#define MCDE_IMSCERR_FUC1IM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, FUC1IM, __x)
+#define MCDE_IMSCERR_OVLFERRIM_SHIFT 16
+#define MCDE_IMSCERR_OVLFERRIM_MASK 0xFFFF0000
+#define MCDE_IMSCERR_OVLFERRIM(__x) \
+ MCDE_VAL2REG(MCDE_IMSCERR, OVLFERRIM, __x)
+#define MCDE_RISPP 0x00000114
+#define MCDE_RISPP_VCMPARIS_SHIFT 0
+#define MCDE_RISPP_VCMPARIS_MASK 0x00000001
+#define MCDE_RISPP_VCMPARIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VCMPARIS, __x)
+#define MCDE_RISPP_VCMPBRIS_SHIFT 1
+#define MCDE_RISPP_VCMPBRIS_MASK 0x00000002
+#define MCDE_RISPP_VCMPBRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VCMPBRIS, __x)
+#define MCDE_RISPP_VSCC0RIS_SHIFT 2
+#define MCDE_RISPP_VSCC0RIS_MASK 0x00000004
+#define MCDE_RISPP_VSCC0RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VSCC0RIS, __x)
+#define MCDE_RISPP_VSCC1RIS_SHIFT 3
+#define MCDE_RISPP_VSCC1RIS_MASK 0x00000008
+#define MCDE_RISPP_VSCC1RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VSCC1RIS, __x)
+#define MCDE_RISPP_VCMPC0RIS_SHIFT 4
+#define MCDE_RISPP_VCMPC0RIS_MASK 0x00000010
+#define MCDE_RISPP_VCMPC0RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VCMPC0RIS, __x)
+#define MCDE_RISPP_VCMPC1RIS_SHIFT 5
+#define MCDE_RISPP_VCMPC1RIS_MASK 0x00000020
+#define MCDE_RISPP_VCMPC1RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, VCMPC1RIS, __x)
+#define MCDE_RISPP_ROTFDRIS_B_SHIFT 6
+#define MCDE_RISPP_ROTFDRIS_B_MASK 0x00000040
+#define MCDE_RISPP_ROTFDRIS_B(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, ROTFDRIS_B, __x)
+#define MCDE_RISPP_ROTFDRIS_A_SHIFT 7
+#define MCDE_RISPP_ROTFDRIS_A_MASK 0x00000080
+#define MCDE_RISPP_ROTFDRIS_A(__x) \
+ MCDE_VAL2REG(MCDE_RISPP, ROTFDRIS_A, __x)
+#define MCDE_RISOVL 0x00000118
+#define MCDE_RISOVL_OVLRDRIS_SHIFT 0
+#define MCDE_RISOVL_OVLRDRIS_MASK 0x0000FFFF
+#define MCDE_RISOVL_OVLRDRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISOVL, OVLRDRIS, __x)
+#define MCDE_RISOVL_OVLFDRIS_SHIFT 16
+#define MCDE_RISOVL_OVLFDRIS_MASK 0xFFFF0000
+#define MCDE_RISOVL_OVLFDRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISOVL, OVLFDRIS, __x)
+#define MCDE_RISCHNL 0x0000011C
+#define MCDE_RISCHNL_CHNLRDRIS_SHIFT 0
+#define MCDE_RISCHNL_CHNLRDRIS_MASK 0x0000FFFF
+#define MCDE_RISCHNL_CHNLRDRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISCHNL, CHNLRDRIS, __x)
+#define MCDE_RISCHNL_CHNLARIS_SHIFT 16
+#define MCDE_RISCHNL_CHNLARIS_MASK 0xFFFF0000
+#define MCDE_RISCHNL_CHNLARIS(__x) \
+ MCDE_VAL2REG(MCDE_RISCHNL, CHNLARIS, __x)
+#define MCDE_RISERR 0x00000120
+#define MCDE_RISERR_FUARIS_SHIFT 0
+#define MCDE_RISERR_FUARIS_MASK 0x00000001
+#define MCDE_RISERR_FUARIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, FUARIS, __x)
+#define MCDE_RISERR_FUBRIS_SHIFT 1
+#define MCDE_RISERR_FUBRIS_MASK 0x00000002
+#define MCDE_RISERR_FUBRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, FUBRIS, __x)
+#define MCDE_RISERR_SCHBLCKDRIS_SHIFT 2
+#define MCDE_RISERR_SCHBLCKDRIS_MASK 0x00000004
+#define MCDE_RISERR_SCHBLCKDRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, SCHBLCKDRIS, __x)
+#define MCDE_RISERR_ROTAFERIS_WRITE_SHIFT 3
+#define MCDE_RISERR_ROTAFERIS_WRITE_MASK 0x00000008
+#define MCDE_RISERR_ROTAFERIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, ROTAFERIS_WRITE, __x)
+#define MCDE_RISERR_ROTAFERIS_READ_SHIFT 4
+#define MCDE_RISERR_ROTAFERIS_READ_MASK 0x00000010
+#define MCDE_RISERR_ROTAFERIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, ROTAFERIS_READ, __x)
+#define MCDE_RISERR_ROTBFERIS_WRITE_SHIFT 5
+#define MCDE_RISERR_ROTBFERIS_WRITE_MASK 0x00000020
+#define MCDE_RISERR_ROTBFERIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, ROTBFERIS_WRITE, __x)
+#define MCDE_RISERR_ROTBFERIS_READ_SHIFT 6
+#define MCDE_RISERR_ROTBFERIS_READ_MASK 0x00000040
+#define MCDE_RISERR_ROTBFERIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, ROTBFERIS_READ, __x)
+#define MCDE_RISERR_FUC0RIS_SHIFT 7
+#define MCDE_RISERR_FUC0RIS_MASK 0x00000080
+#define MCDE_RISERR_FUC0RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, FUC0RIS, __x)
+#define MCDE_RISERR_FUC1RIS_SHIFT 8
+#define MCDE_RISERR_FUC1RIS_MASK 0x00000100
+#define MCDE_RISERR_FUC1RIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, FUC1RIS, __x)
+#define MCDE_RISERR_OVLFERRRIS_SHIFT 16
+#define MCDE_RISERR_OVLFERRRIS_MASK 0xFFFF0000
+#define MCDE_RISERR_OVLFERRRIS(__x) \
+ MCDE_VAL2REG(MCDE_RISERR, OVLFERRRIS, __x)
+#define MCDE_MISPP 0x00000124
+#define MCDE_MISPP_VCMPAMIS_SHIFT 0
+#define MCDE_MISPP_VCMPAMIS_MASK 0x00000001
+#define MCDE_MISPP_VCMPAMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VCMPAMIS, __x)
+#define MCDE_MISPP_VCMPBMIS_SHIFT 1
+#define MCDE_MISPP_VCMPBMIS_MASK 0x00000002
+#define MCDE_MISPP_VCMPBMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VCMPBMIS, __x)
+#define MCDE_MISPP_VSCC0MIS_SHIFT 2
+#define MCDE_MISPP_VSCC0MIS_MASK 0x00000004
+#define MCDE_MISPP_VSCC0MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VSCC0MIS, __x)
+#define MCDE_MISPP_VSCC1MIS_SHIFT 3
+#define MCDE_MISPP_VSCC1MIS_MASK 0x00000008
+#define MCDE_MISPP_VSCC1MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VSCC1MIS, __x)
+#define MCDE_MISPP_VCMPC0MIS_SHIFT 4
+#define MCDE_MISPP_VCMPC0MIS_MASK 0x00000010
+#define MCDE_MISPP_VCMPC0MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VCMPC0MIS, __x)
+#define MCDE_MISPP_VCMPC1MIS_SHIFT 5
+#define MCDE_MISPP_VCMPC1MIS_MASK 0x00000020
+#define MCDE_MISPP_VCMPC1MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, VCMPC1MIS, __x)
+#define MCDE_MISPP_ROTFDMIS_A_SHIFT 6
+#define MCDE_MISPP_ROTFDMIS_A_MASK 0x00000040
+#define MCDE_MISPP_ROTFDMIS_A(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, ROTFDMIS_A, __x)
+#define MCDE_MISPP_ROTFDMIS_B_SHIFT 7
+#define MCDE_MISPP_ROTFDMIS_B_MASK 0x00000080
+#define MCDE_MISPP_ROTFDMIS_B(__x) \
+ MCDE_VAL2REG(MCDE_MISPP, ROTFDMIS_B, __x)
+#define MCDE_MISOVL 0x00000128
+#define MCDE_MISOVL_OVLRDMIS_SHIFT 0
+#define MCDE_MISOVL_OVLRDMIS_MASK 0x0000FFFF
+#define MCDE_MISOVL_OVLRDMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISOVL, OVLRDMIS, __x)
+#define MCDE_MISOVL_OVLFDMIS_SHIFT 16
+#define MCDE_MISOVL_OVLFDMIS_MASK 0xFFFF0000
+#define MCDE_MISOVL_OVLFDMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISOVL, OVLFDMIS, __x)
+#define MCDE_MISCHNL 0x0000012C
+#define MCDE_MISCHNL_CHNLRDMIS_SHIFT 0
+#define MCDE_MISCHNL_CHNLRDMIS_MASK 0x0000FFFF
+#define MCDE_MISCHNL_CHNLRDMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISCHNL, CHNLRDMIS, __x)
+#define MCDE_MISCHNL_CHNLAMIS_SHIFT 16
+#define MCDE_MISCHNL_CHNLAMIS_MASK 0xFFFF0000
+#define MCDE_MISCHNL_CHNLAMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISCHNL, CHNLAMIS, __x)
+#define MCDE_MISERR 0x00000130
+#define MCDE_MISERR_FUAMIS_SHIFT 0
+#define MCDE_MISERR_FUAMIS_MASK 0x00000001
+#define MCDE_MISERR_FUAMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, FUAMIS, __x)
+#define MCDE_MISERR_FUBMIS_SHIFT 1
+#define MCDE_MISERR_FUBMIS_MASK 0x00000002
+#define MCDE_MISERR_FUBMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, FUBMIS, __x)
+#define MCDE_MISERR_SCHBLCKDMIS_SHIFT 2
+#define MCDE_MISERR_SCHBLCKDMIS_MASK 0x00000004
+#define MCDE_MISERR_SCHBLCKDMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, SCHBLCKDMIS, __x)
+#define MCDE_MISERR_ROTAFEMIS_WRITE_SHIFT 3
+#define MCDE_MISERR_ROTAFEMIS_WRITE_MASK 0x00000008
+#define MCDE_MISERR_ROTAFEMIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, ROTAFEMIS_WRITE, __x)
+#define MCDE_MISERR_ROTAFEMIS_READ_SHIFT 4
+#define MCDE_MISERR_ROTAFEMIS_READ_MASK 0x00000010
+#define MCDE_MISERR_ROTAFEMIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, ROTAFEMIS_READ, __x)
+#define MCDE_MISERR_ROTBFEMIS_WRITE_SHIFT 5
+#define MCDE_MISERR_ROTBFEMIS_WRITE_MASK 0x00000020
+#define MCDE_MISERR_ROTBFEMIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, ROTBFEMIS_WRITE, __x)
+#define MCDE_MISERR_ROTBFEMIS_READ_SHIFT 6
+#define MCDE_MISERR_ROTBFEMIS_READ_MASK 0x00000040
+#define MCDE_MISERR_ROTBFEMIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, ROTBFEMIS_READ, __x)
+#define MCDE_MISERR_FUC0MIS_SHIFT 7
+#define MCDE_MISERR_FUC0MIS_MASK 0x00000080
+#define MCDE_MISERR_FUC0MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, FUC0MIS, __x)
+#define MCDE_MISERR_FUC1MIS_SHIFT 8
+#define MCDE_MISERR_FUC1MIS_MASK 0x00000100
+#define MCDE_MISERR_FUC1MIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, FUC1MIS, __x)
+#define MCDE_MISERR_OVLFERMIS_SHIFT 16
+#define MCDE_MISERR_OVLFERMIS_MASK 0xFFFF0000
+#define MCDE_MISERR_OVLFERMIS(__x) \
+ MCDE_VAL2REG(MCDE_MISERR, OVLFERMIS, __x)
+#define MCDE_SISPP 0x00000134
+#define MCDE_SISPP_VCMPASIS_SHIFT 0
+#define MCDE_SISPP_VCMPASIS_MASK 0x00000001
+#define MCDE_SISPP_VCMPASIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VCMPASIS, __x)
+#define MCDE_SISPP_VCMPBSIS_SHIFT 1
+#define MCDE_SISPP_VCMPBSIS_MASK 0x00000002
+#define MCDE_SISPP_VCMPBSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VCMPBSIS, __x)
+#define MCDE_SISPP_VSCC0SIS_SHIFT 2
+#define MCDE_SISPP_VSCC0SIS_MASK 0x00000004
+#define MCDE_SISPP_VSCC0SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VSCC0SIS, __x)
+#define MCDE_SISPP_VSCC1SIS_SHIFT 3
+#define MCDE_SISPP_VSCC1SIS_MASK 0x00000008
+#define MCDE_SISPP_VSCC1SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VSCC1SIS, __x)
+#define MCDE_SISPP_VCMPC0SIS_SHIFT 4
+#define MCDE_SISPP_VCMPC0SIS_MASK 0x00000010
+#define MCDE_SISPP_VCMPC0SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VCMPC0SIS, __x)
+#define MCDE_SISPP_VCMPC1SIS_SHIFT 5
+#define MCDE_SISPP_VCMPC1SIS_MASK 0x00000020
+#define MCDE_SISPP_VCMPC1SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, VCMPC1SIS, __x)
+#define MCDE_SISPP_ROTFDSIS_A_SHIFT 6
+#define MCDE_SISPP_ROTFDSIS_A_MASK 0x00000040
+#define MCDE_SISPP_ROTFDSIS_A(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, ROTFDSIS_A, __x)
+#define MCDE_SISPP_ROTFDSIS_B_SHIFT 7
+#define MCDE_SISPP_ROTFDSIS_B_MASK 0x00000080
+#define MCDE_SISPP_ROTFDSIS_B(__x) \
+ MCDE_VAL2REG(MCDE_SISPP, ROTFDSIS_B, __x)
+#define MCDE_SISOVL 0x00000138
+#define MCDE_SISOVL_OVLRDSIS_SHIFT 0
+#define MCDE_SISOVL_OVLRDSIS_MASK 0x0000FFFF
+#define MCDE_SISOVL_OVLRDSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISOVL, OVLRDSIS, __x)
+#define MCDE_SISOVL_OVLFDSIS_SHIFT 16
+#define MCDE_SISOVL_OVLFDSIS_MASK 0xFFFF0000
+#define MCDE_SISOVL_OVLFDSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISOVL, OVLFDSIS, __x)
+#define MCDE_SISCHNL 0x0000013C
+#define MCDE_SISCHNL_CHNLRDSIS_SHIFT 0
+#define MCDE_SISCHNL_CHNLRDSIS_MASK 0x0000FFFF
+#define MCDE_SISCHNL_CHNLRDSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISCHNL, CHNLRDSIS, __x)
+#define MCDE_SISCHNL_CHNLASIS_SHIFT 16
+#define MCDE_SISCHNL_CHNLASIS_MASK 0xFFFF0000
+#define MCDE_SISCHNL_CHNLASIS(__x) \
+ MCDE_VAL2REG(MCDE_SISCHNL, CHNLASIS, __x)
+#define MCDE_SISERR 0x00000140
+#define MCDE_SISERR_FUASIS_SHIFT 0
+#define MCDE_SISERR_FUASIS_MASK 0x00000001
+#define MCDE_SISERR_FUASIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, FUASIS, __x)
+#define MCDE_SISERR_FUBSIS_SHIFT 1
+#define MCDE_SISERR_FUBSIS_MASK 0x00000002
+#define MCDE_SISERR_FUBSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, FUBSIS, __x)
+#define MCDE_SISERR_SCHBLCKDSIS_SHIFT 2
+#define MCDE_SISERR_SCHBLCKDSIS_MASK 0x00000004
+#define MCDE_SISERR_SCHBLCKDSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, SCHBLCKDSIS, __x)
+#define MCDE_SISERR_ROTAFESIS_WRITE_SHIFT 3
+#define MCDE_SISERR_ROTAFESIS_WRITE_MASK 0x00000008
+#define MCDE_SISERR_ROTAFESIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, ROTAFESIS_WRITE, __x)
+#define MCDE_SISERR_ROTAFESIS_READ_SHIFT 4
+#define MCDE_SISERR_ROTAFESIS_READ_MASK 0x00000010
+#define MCDE_SISERR_ROTAFESIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, ROTAFESIS_READ, __x)
+#define MCDE_SISERR_ROTBFESIS_WRITE_SHIFT 5
+#define MCDE_SISERR_ROTBFESIS_WRITE_MASK 0x00000020
+#define MCDE_SISERR_ROTBFESIS_WRITE(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, ROTBFESIS_WRITE, __x)
+#define MCDE_SISERR_ROTBFESIS_READ_SHIFT 6
+#define MCDE_SISERR_ROTBFESIS_READ_MASK 0x00000040
+#define MCDE_SISERR_ROTBFESIS_READ(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, ROTBFESIS_READ, __x)
+#define MCDE_SISERR_FUC0SIS_SHIFT 7
+#define MCDE_SISERR_FUC0SIS_MASK 0x00000080
+#define MCDE_SISERR_FUC0SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, FUC0SIS, __x)
+#define MCDE_SISERR_FUC1SIS_SHIFT 8
+#define MCDE_SISERR_FUC1SIS_MASK 0x00000100
+#define MCDE_SISERR_FUC1SIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, FUC1SIS, __x)
+#define MCDE_SISERR_OVLFERSIS_SHIFT 16
+#define MCDE_SISERR_OVLFERSIS_MASK 0xFFFF0000
+#define MCDE_SISERR_OVLFERSIS(__x) \
+ MCDE_VAL2REG(MCDE_SISERR, OVLFERSIS, __x)
+#define MCDE_PID 0x000001FC
+#define MCDE_PID_METALFIX_VERSION_SHIFT 0
+#define MCDE_PID_METALFIX_VERSION_MASK 0x000000FF
+#define MCDE_PID_METALFIX_VERSION(__x) \
+ MCDE_VAL2REG(MCDE_PID, METALFIX_VERSION, __x)
+#define MCDE_PID_DEVELOPMENT_VERSION_SHIFT 8
+#define MCDE_PID_DEVELOPMENT_VERSION_MASK 0x0000FF00
+#define MCDE_PID_DEVELOPMENT_VERSION(__x) \
+ MCDE_VAL2REG(MCDE_PID, DEVELOPMENT_VERSION, __x)
+#define MCDE_PID_MINOR_VERSION_SHIFT 16
+#define MCDE_PID_MINOR_VERSION_MASK 0x00FF0000
+#define MCDE_PID_MINOR_VERSION(__x) \
+ MCDE_VAL2REG(MCDE_PID, MINOR_VERSION, __x)
+#define MCDE_PID_MAJOR_VERSION_SHIFT 24
+#define MCDE_PID_MAJOR_VERSION_MASK 0xFF000000
+#define MCDE_PID_MAJOR_VERSION(__x) \
+ MCDE_VAL2REG(MCDE_PID, MAJOR_VERSION, __x)
+#define MCDE_EXTSRC0A0 0x00000200
+#define MCDE_EXTSRC0A0_GROUPOFFSET 0x20
+#define MCDE_EXTSRC0A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC0A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC0A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC1A0 0x00000220
+#define MCDE_EXTSRC1A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC1A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC1A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC2A0 0x00000240
+#define MCDE_EXTSRC2A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC2A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC2A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC3A0 0x00000260
+#define MCDE_EXTSRC3A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC3A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC3A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC4A0 0x00000280
+#define MCDE_EXTSRC4A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC4A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC4A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC5A0 0x000002A0
+#define MCDE_EXTSRC5A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC5A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC5A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC6A0 0x000002C0
+#define MCDE_EXTSRC6A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC6A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC6A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC7A0 0x000002E0
+#define MCDE_EXTSRC7A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC7A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC7A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC8A0 0x00000300
+#define MCDE_EXTSRC8A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC8A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC8A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC9A0 0x00000320
+#define MCDE_EXTSRC9A0_BASEADDRESS0_SHIFT 3
+#define MCDE_EXTSRC9A0_BASEADDRESS0_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC9A0_BASEADDRESS0(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9A0, BASEADDRESS0, __x)
+#define MCDE_EXTSRC0A1 0x00000204
+#define MCDE_EXTSRC0A1_GROUPOFFSET 0x20
+#define MCDE_EXTSRC0A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC0A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC0A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC1A1 0x00000224
+#define MCDE_EXTSRC1A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC1A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC1A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC2A1 0x00000244
+#define MCDE_EXTSRC2A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC2A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC2A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC3A1 0x00000264
+#define MCDE_EXTSRC3A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC3A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC3A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC4A1 0x00000284
+#define MCDE_EXTSRC4A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC4A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC4A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC5A1 0x000002A4
+#define MCDE_EXTSRC5A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC5A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC5A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC6A1 0x000002C4
+#define MCDE_EXTSRC6A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC6A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC6A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC7A1 0x000002E4
+#define MCDE_EXTSRC7A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC7A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC7A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC8A1 0x00000304
+#define MCDE_EXTSRC8A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC8A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC8A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC9A1 0x00000324
+#define MCDE_EXTSRC9A1_BASEADDRESS1_SHIFT 3
+#define MCDE_EXTSRC9A1_BASEADDRESS1_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC9A1_BASEADDRESS1(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9A1, BASEADDRESS1, __x)
+#define MCDE_EXTSRC6A2 0x000002C8
+#define MCDE_EXTSRC6A2_BASEADDRESS2_SHIFT 3
+#define MCDE_EXTSRC6A2_BASEADDRESS2_MASK 0xFFFFFFF8
+#define MCDE_EXTSRC6A2_BASEADDRESS2(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6A2, BASEADDRESS2, __x)
+#define MCDE_EXTSRC0CONF 0x0000020C
+#define MCDE_EXTSRC0CONF_GROUPOFFSET 0x20
+#define MCDE_EXTSRC0CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC0CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC0CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BUF_ID, __x)
+#define MCDE_EXTSRC0CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC0CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC0CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BUF_NB, __x)
+#define MCDE_EXTSRC0CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC0CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC0CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC0CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC0CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC0CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC0CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC0CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC0CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC0CONF_BPP_RGB444 4
+#define MCDE_EXTSRC0CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC0CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC0CONF_BPP_RGB565 7
+#define MCDE_EXTSRC0CONF_BPP_RGB888 8
+#define MCDE_EXTSRC0CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC0CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC0CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC0CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BPP, MCDE_EXTSRC0CONF_BPP_##__x)
+#define MCDE_EXTSRC0CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BPP, __x)
+#define MCDE_EXTSRC0CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC0CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC0CONF_BGR_RGB 0
+#define MCDE_EXTSRC0CONF_BGR_BGR 1
+#define MCDE_EXTSRC0CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BGR, MCDE_EXTSRC0CONF_BGR_##__x)
+#define MCDE_EXTSRC0CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BGR, __x)
+#define MCDE_EXTSRC0CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC0CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC0CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC0CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC0CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BEBO, MCDE_EXTSRC0CONF_BEBO_##__x)
+#define MCDE_EXTSRC0CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BEBO, __x)
+#define MCDE_EXTSRC0CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC0CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC0CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC0CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC0CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BEPO, MCDE_EXTSRC0CONF_BEPO_##__x)
+#define MCDE_EXTSRC0CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CONF, BEPO, __x)
+#define MCDE_EXTSRC1CONF 0x0000022C
+#define MCDE_EXTSRC1CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC1CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC1CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BUF_ID, __x)
+#define MCDE_EXTSRC1CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC1CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC1CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BUF_NB, __x)
+#define MCDE_EXTSRC1CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC1CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC1CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC1CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC1CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC1CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC1CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC1CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC1CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC1CONF_BPP_RGB444 4
+#define MCDE_EXTSRC1CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC1CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC1CONF_BPP_RGB565 7
+#define MCDE_EXTSRC1CONF_BPP_RGB888 8
+#define MCDE_EXTSRC1CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC1CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC1CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC1CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BPP, MCDE_EXTSRC1CONF_BPP_##__x)
+#define MCDE_EXTSRC1CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BPP, __x)
+#define MCDE_EXTSRC1CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC1CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC1CONF_BGR_RGB 0
+#define MCDE_EXTSRC1CONF_BGR_BGR 1
+#define MCDE_EXTSRC1CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BGR, MCDE_EXTSRC1CONF_BGR_##__x)
+#define MCDE_EXTSRC1CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BGR, __x)
+#define MCDE_EXTSRC1CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC1CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC1CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC1CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC1CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BEBO, MCDE_EXTSRC1CONF_BEBO_##__x)
+#define MCDE_EXTSRC1CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BEBO, __x)
+#define MCDE_EXTSRC1CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC1CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC1CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC1CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC1CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BEPO, MCDE_EXTSRC1CONF_BEPO_##__x)
+#define MCDE_EXTSRC1CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CONF, BEPO, __x)
+#define MCDE_EXTSRC2CONF 0x0000024C
+#define MCDE_EXTSRC2CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC2CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC2CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BUF_ID, __x)
+#define MCDE_EXTSRC2CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC2CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC2CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BUF_NB, __x)
+#define MCDE_EXTSRC2CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC2CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC2CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC2CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC2CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC2CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC2CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC2CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC2CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC2CONF_BPP_RGB444 4
+#define MCDE_EXTSRC2CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC2CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC2CONF_BPP_RGB565 7
+#define MCDE_EXTSRC2CONF_BPP_RGB888 8
+#define MCDE_EXTSRC2CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC2CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC2CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC2CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BPP, MCDE_EXTSRC2CONF_BPP_##__x)
+#define MCDE_EXTSRC2CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BPP, __x)
+#define MCDE_EXTSRC2CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC2CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC2CONF_BGR_RGB 0
+#define MCDE_EXTSRC2CONF_BGR_BGR 1
+#define MCDE_EXTSRC2CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BGR, MCDE_EXTSRC2CONF_BGR_##__x)
+#define MCDE_EXTSRC2CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BGR, __x)
+#define MCDE_EXTSRC2CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC2CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC2CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC2CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC2CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BEBO, MCDE_EXTSRC2CONF_BEBO_##__x)
+#define MCDE_EXTSRC2CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BEBO, __x)
+#define MCDE_EXTSRC2CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC2CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC2CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC2CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC2CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BEPO, MCDE_EXTSRC2CONF_BEPO_##__x)
+#define MCDE_EXTSRC2CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CONF, BEPO, __x)
+#define MCDE_EXTSRC3CONF 0x0000026C
+#define MCDE_EXTSRC3CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC3CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC3CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BUF_ID, __x)
+#define MCDE_EXTSRC3CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC3CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC3CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BUF_NB, __x)
+#define MCDE_EXTSRC3CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC3CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC3CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC3CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC3CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC3CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC3CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC3CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC3CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC3CONF_BPP_RGB444 4
+#define MCDE_EXTSRC3CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC3CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC3CONF_BPP_RGB565 7
+#define MCDE_EXTSRC3CONF_BPP_RGB888 8
+#define MCDE_EXTSRC3CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC3CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC3CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC3CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BPP, MCDE_EXTSRC3CONF_BPP_##__x)
+#define MCDE_EXTSRC3CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BPP, __x)
+#define MCDE_EXTSRC3CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC3CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC3CONF_BGR_RGB 0
+#define MCDE_EXTSRC3CONF_BGR_BGR 1
+#define MCDE_EXTSRC3CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BGR, MCDE_EXTSRC3CONF_BGR_##__x)
+#define MCDE_EXTSRC3CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BGR, __x)
+#define MCDE_EXTSRC3CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC3CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC3CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC3CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC3CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BEBO, MCDE_EXTSRC3CONF_BEBO_##__x)
+#define MCDE_EXTSRC3CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BEBO, __x)
+#define MCDE_EXTSRC3CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC3CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC3CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC3CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC3CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BEPO, MCDE_EXTSRC3CONF_BEPO_##__x)
+#define MCDE_EXTSRC3CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CONF, BEPO, __x)
+#define MCDE_EXTSRC4CONF 0x0000028C
+#define MCDE_EXTSRC4CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC4CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC4CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BUF_ID, __x)
+#define MCDE_EXTSRC4CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC4CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC4CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BUF_NB, __x)
+#define MCDE_EXTSRC4CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC4CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC4CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC4CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC4CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC4CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC4CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC4CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC4CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC4CONF_BPP_RGB444 4
+#define MCDE_EXTSRC4CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC4CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC4CONF_BPP_RGB565 7
+#define MCDE_EXTSRC4CONF_BPP_RGB888 8
+#define MCDE_EXTSRC4CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC4CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC4CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC4CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BPP, MCDE_EXTSRC4CONF_BPP_##__x)
+#define MCDE_EXTSRC4CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BPP, __x)
+#define MCDE_EXTSRC4CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC4CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC4CONF_BGR_RGB 0
+#define MCDE_EXTSRC4CONF_BGR_BGR 1
+#define MCDE_EXTSRC4CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BGR, MCDE_EXTSRC4CONF_BGR_##__x)
+#define MCDE_EXTSRC4CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BGR, __x)
+#define MCDE_EXTSRC4CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC4CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC4CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC4CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC4CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BEBO, MCDE_EXTSRC4CONF_BEBO_##__x)
+#define MCDE_EXTSRC4CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BEBO, __x)
+#define MCDE_EXTSRC4CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC4CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC4CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC4CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC4CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BEPO, MCDE_EXTSRC4CONF_BEPO_##__x)
+#define MCDE_EXTSRC4CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CONF, BEPO, __x)
+#define MCDE_EXTSRC5CONF 0x000002AC
+#define MCDE_EXTSRC5CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC5CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC5CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BUF_ID, __x)
+#define MCDE_EXTSRC5CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC5CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC5CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BUF_NB, __x)
+#define MCDE_EXTSRC5CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC5CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC5CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC5CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC5CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC5CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC5CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC5CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC5CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC5CONF_BPP_RGB444 4
+#define MCDE_EXTSRC5CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC5CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC5CONF_BPP_RGB565 7
+#define MCDE_EXTSRC5CONF_BPP_RGB888 8
+#define MCDE_EXTSRC5CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC5CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC5CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC5CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BPP, MCDE_EXTSRC5CONF_BPP_##__x)
+#define MCDE_EXTSRC5CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BPP, __x)
+#define MCDE_EXTSRC5CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC5CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC5CONF_BGR_RGB 0
+#define MCDE_EXTSRC5CONF_BGR_BGR 1
+#define MCDE_EXTSRC5CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BGR, MCDE_EXTSRC5CONF_BGR_##__x)
+#define MCDE_EXTSRC5CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BGR, __x)
+#define MCDE_EXTSRC5CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC5CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC5CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC5CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC5CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BEBO, MCDE_EXTSRC5CONF_BEBO_##__x)
+#define MCDE_EXTSRC5CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BEBO, __x)
+#define MCDE_EXTSRC5CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC5CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC5CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC5CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC5CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BEPO, MCDE_EXTSRC5CONF_BEPO_##__x)
+#define MCDE_EXTSRC5CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CONF, BEPO, __x)
+#define MCDE_EXTSRC6CONF 0x000002CC
+#define MCDE_EXTSRC6CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC6CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC6CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BUF_ID, __x)
+#define MCDE_EXTSRC6CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC6CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC6CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BUF_NB, __x)
+#define MCDE_EXTSRC6CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC6CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC6CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC6CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC6CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC6CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC6CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC6CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC6CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC6CONF_BPP_RGB444 4
+#define MCDE_EXTSRC6CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC6CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC6CONF_BPP_RGB565 7
+#define MCDE_EXTSRC6CONF_BPP_RGB888 8
+#define MCDE_EXTSRC6CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC6CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC6CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC6CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BPP, MCDE_EXTSRC6CONF_BPP_##__x)
+#define MCDE_EXTSRC6CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BPP, __x)
+#define MCDE_EXTSRC6CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC6CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC6CONF_BGR_RGB 0
+#define MCDE_EXTSRC6CONF_BGR_BGR 1
+#define MCDE_EXTSRC6CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BGR, MCDE_EXTSRC6CONF_BGR_##__x)
+#define MCDE_EXTSRC6CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BGR, __x)
+#define MCDE_EXTSRC6CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC6CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC6CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC6CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC6CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BEBO, MCDE_EXTSRC6CONF_BEBO_##__x)
+#define MCDE_EXTSRC6CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BEBO, __x)
+#define MCDE_EXTSRC6CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC6CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC6CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC6CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC6CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BEPO, MCDE_EXTSRC6CONF_BEPO_##__x)
+#define MCDE_EXTSRC6CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CONF, BEPO, __x)
+#define MCDE_EXTSRC7CONF 0x000002EC
+#define MCDE_EXTSRC7CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC7CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC7CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BUF_ID, __x)
+#define MCDE_EXTSRC7CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC7CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC7CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BUF_NB, __x)
+#define MCDE_EXTSRC7CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC7CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC7CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC7CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC7CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC7CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC7CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC7CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC7CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC7CONF_BPP_RGB444 4
+#define MCDE_EXTSRC7CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC7CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC7CONF_BPP_RGB565 7
+#define MCDE_EXTSRC7CONF_BPP_RGB888 8
+#define MCDE_EXTSRC7CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC7CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC7CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC7CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BPP, MCDE_EXTSRC7CONF_BPP_##__x)
+#define MCDE_EXTSRC7CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BPP, __x)
+#define MCDE_EXTSRC7CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC7CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC7CONF_BGR_RGB 0
+#define MCDE_EXTSRC7CONF_BGR_BGR 1
+#define MCDE_EXTSRC7CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BGR, MCDE_EXTSRC7CONF_BGR_##__x)
+#define MCDE_EXTSRC7CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BGR, __x)
+#define MCDE_EXTSRC7CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC7CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC7CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC7CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC7CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BEBO, MCDE_EXTSRC7CONF_BEBO_##__x)
+#define MCDE_EXTSRC7CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BEBO, __x)
+#define MCDE_EXTSRC7CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC7CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC7CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC7CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC7CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BEPO, MCDE_EXTSRC7CONF_BEPO_##__x)
+#define MCDE_EXTSRC7CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CONF, BEPO, __x)
+#define MCDE_EXTSRC8CONF 0x0000030C
+#define MCDE_EXTSRC8CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC8CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC8CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BUF_ID, __x)
+#define MCDE_EXTSRC8CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC8CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC8CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BUF_NB, __x)
+#define MCDE_EXTSRC8CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC8CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC8CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC8CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC8CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC8CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC8CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC8CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC8CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC8CONF_BPP_RGB444 4
+#define MCDE_EXTSRC8CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC8CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC8CONF_BPP_RGB565 7
+#define MCDE_EXTSRC8CONF_BPP_RGB888 8
+#define MCDE_EXTSRC8CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC8CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC8CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC8CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BPP, MCDE_EXTSRC8CONF_BPP_##__x)
+#define MCDE_EXTSRC8CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BPP, __x)
+#define MCDE_EXTSRC8CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC8CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC8CONF_BGR_RGB 0
+#define MCDE_EXTSRC8CONF_BGR_BGR 1
+#define MCDE_EXTSRC8CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BGR, MCDE_EXTSRC8CONF_BGR_##__x)
+#define MCDE_EXTSRC8CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BGR, __x)
+#define MCDE_EXTSRC8CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC8CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC8CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC8CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC8CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BEBO, MCDE_EXTSRC8CONF_BEBO_##__x)
+#define MCDE_EXTSRC8CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BEBO, __x)
+#define MCDE_EXTSRC8CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC8CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC8CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC8CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC8CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BEPO, MCDE_EXTSRC8CONF_BEPO_##__x)
+#define MCDE_EXTSRC8CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CONF, BEPO, __x)
+#define MCDE_EXTSRC9CONF 0x0000032C
+#define MCDE_EXTSRC9CONF_BUF_ID_SHIFT 0
+#define MCDE_EXTSRC9CONF_BUF_ID_MASK 0x00000003
+#define MCDE_EXTSRC9CONF_BUF_ID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BUF_ID, __x)
+#define MCDE_EXTSRC9CONF_BUF_NB_SHIFT 2
+#define MCDE_EXTSRC9CONF_BUF_NB_MASK 0x0000000C
+#define MCDE_EXTSRC9CONF_BUF_NB(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BUF_NB, __x)
+#define MCDE_EXTSRC9CONF_PRI_OVLID_SHIFT 4
+#define MCDE_EXTSRC9CONF_PRI_OVLID_MASK 0x000000F0
+#define MCDE_EXTSRC9CONF_PRI_OVLID(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, PRI_OVLID, __x)
+#define MCDE_EXTSRC9CONF_BPP_SHIFT 8
+#define MCDE_EXTSRC9CONF_BPP_MASK 0x00000F00
+#define MCDE_EXTSRC9CONF_BPP_1BPP_PAL 0
+#define MCDE_EXTSRC9CONF_BPP_2BPP_PAL 1
+#define MCDE_EXTSRC9CONF_BPP_4BPP_PAL 2
+#define MCDE_EXTSRC9CONF_BPP_8BPP_PAL 3
+#define MCDE_EXTSRC9CONF_BPP_RGB444 4
+#define MCDE_EXTSRC9CONF_BPP_ARGB4444 5
+#define MCDE_EXTSRC9CONF_BPP_IRGB1555 6
+#define MCDE_EXTSRC9CONF_BPP_RGB565 7
+#define MCDE_EXTSRC9CONF_BPP_RGB888 8
+#define MCDE_EXTSRC9CONF_BPP_XRGB8888 9
+#define MCDE_EXTSRC9CONF_BPP_ARGB8888 10
+#define MCDE_EXTSRC9CONF_BPP_YCBCR422 11
+#define MCDE_EXTSRC9CONF_BPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BPP, MCDE_EXTSRC9CONF_BPP_##__x)
+#define MCDE_EXTSRC9CONF_BPP(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BPP, __x)
+#define MCDE_EXTSRC9CONF_BGR_SHIFT 12
+#define MCDE_EXTSRC9CONF_BGR_MASK 0x00001000
+#define MCDE_EXTSRC9CONF_BGR_RGB 0
+#define MCDE_EXTSRC9CONF_BGR_BGR 1
+#define MCDE_EXTSRC9CONF_BGR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BGR, MCDE_EXTSRC9CONF_BGR_##__x)
+#define MCDE_EXTSRC9CONF_BGR(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BGR, __x)
+#define MCDE_EXTSRC9CONF_BEBO_SHIFT 13
+#define MCDE_EXTSRC9CONF_BEBO_MASK 0x00002000
+#define MCDE_EXTSRC9CONF_BEBO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC9CONF_BEBO_BIG_ENDIAN 1
+#define MCDE_EXTSRC9CONF_BEBO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BEBO, MCDE_EXTSRC9CONF_BEBO_##__x)
+#define MCDE_EXTSRC9CONF_BEBO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BEBO, __x)
+#define MCDE_EXTSRC9CONF_BEPO_SHIFT 14
+#define MCDE_EXTSRC9CONF_BEPO_MASK 0x00004000
+#define MCDE_EXTSRC9CONF_BEPO_LITTLE_ENDIAN 0
+#define MCDE_EXTSRC9CONF_BEPO_BIG_ENDIAN 1
+#define MCDE_EXTSRC9CONF_BEPO_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BEPO, MCDE_EXTSRC9CONF_BEPO_##__x)
+#define MCDE_EXTSRC9CONF_BEPO(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CONF, BEPO, __x)
+#define MCDE_EXTSRC0CR 0x00000210
+#define MCDE_EXTSRC0CR_GROUPOFFSET 0x20
+#define MCDE_EXTSRC0CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC0CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC0CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC0CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC0CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC0CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, SEL_MOD, MCDE_EXTSRC0CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC0CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, SEL_MOD, __x)
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC0CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC0CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC0CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC0CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC0CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC0CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC0CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC0CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC0CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC1CR 0x00000230
+#define MCDE_EXTSRC1CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC1CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC1CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC1CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC1CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC1CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, SEL_MOD, MCDE_EXTSRC1CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC1CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, SEL_MOD, __x)
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC1CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC1CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC1CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC1CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC1CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC1CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC1CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC1CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC1CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC2CR 0x00000250
+#define MCDE_EXTSRC2CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC2CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC2CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC2CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC2CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC2CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, SEL_MOD, MCDE_EXTSRC2CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC2CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, SEL_MOD, __x)
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC2CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC2CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC2CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC2CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC2CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC2CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC2CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC2CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC2CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC3CR 0x00000270
+#define MCDE_EXTSRC3CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC3CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC3CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC3CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC3CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC3CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, SEL_MOD, MCDE_EXTSRC3CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC3CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, SEL_MOD, __x)
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC3CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC3CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC3CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC3CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC3CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC3CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC3CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC3CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC3CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC4CR 0x00000290
+#define MCDE_EXTSRC4CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC4CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC4CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC4CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC4CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC4CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, SEL_MOD, MCDE_EXTSRC4CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC4CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, SEL_MOD, __x)
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC4CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC4CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC4CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC4CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC4CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC4CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC4CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC4CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC4CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC5CR 0x000002B0
+#define MCDE_EXTSRC5CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC5CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC5CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC5CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC5CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC5CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, SEL_MOD, MCDE_EXTSRC5CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC5CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, SEL_MOD, __x)
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC5CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC5CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC5CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC5CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC5CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC5CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC5CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC5CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC5CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC6CR 0x000002D0
+#define MCDE_EXTSRC6CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC6CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC6CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC6CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC6CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC6CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, SEL_MOD, MCDE_EXTSRC6CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC6CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, SEL_MOD, __x)
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC6CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC6CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC6CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC6CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC6CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC6CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC6CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC6CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC6CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC7CR 0x000002F0
+#define MCDE_EXTSRC7CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC7CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC7CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC7CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC7CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC7CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, SEL_MOD, MCDE_EXTSRC7CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC7CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, SEL_MOD, __x)
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC7CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC7CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC7CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC7CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC7CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC7CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC7CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC7CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC7CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC8CR 0x00000310
+#define MCDE_EXTSRC8CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC8CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC8CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC8CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC8CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC8CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, SEL_MOD, MCDE_EXTSRC8CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC8CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, SEL_MOD, __x)
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC8CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC8CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC8CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC8CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC8CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC8CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC8CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC8CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC8CR, FORCE_FS_DIV, __x)
+#define MCDE_EXTSRC9CR 0x00000330
+#define MCDE_EXTSRC9CR_SEL_MOD_SHIFT 0
+#define MCDE_EXTSRC9CR_SEL_MOD_MASK 0x00000003
+#define MCDE_EXTSRC9CR_SEL_MOD_EXTERNAL_SEL 0
+#define MCDE_EXTSRC9CR_SEL_MOD_AUTO_TOGGLE 1
+#define MCDE_EXTSRC9CR_SEL_MOD_SOFTWARE_SEL 2
+#define MCDE_EXTSRC9CR_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, SEL_MOD, MCDE_EXTSRC9CR_SEL_MOD_##__x)
+#define MCDE_EXTSRC9CR_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, SEL_MOD, __x)
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL_SHIFT 2
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL_MASK 0x00000004
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL_ALL 0
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL_PRIMARY 1
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, MULTIOVL_CTRL, \
+ MCDE_EXTSRC9CR_MULTIOVL_CTRL_##__x)
+#define MCDE_EXTSRC9CR_MULTIOVL_CTRL(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, MULTIOVL_CTRL, __x)
+#define MCDE_EXTSRC9CR_FS_DIV_DISABLE_SHIFT 3
+#define MCDE_EXTSRC9CR_FS_DIV_DISABLE_MASK 0x00000008
+#define MCDE_EXTSRC9CR_FS_DIV_DISABLE(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, FS_DIV_DISABLE, __x)
+#define MCDE_EXTSRC9CR_FORCE_FS_DIV_SHIFT 4
+#define MCDE_EXTSRC9CR_FORCE_FS_DIV_MASK 0x00000010
+#define MCDE_EXTSRC9CR_FORCE_FS_DIV(__x) \
+ MCDE_VAL2REG(MCDE_EXTSRC9CR, FORCE_FS_DIV, __x)
+#define MCDE_OVL0CR 0x00000400
+#define MCDE_OVL0CR_GROUPOFFSET 0x20
+#define MCDE_OVL0CR_OVLEN_SHIFT 0
+#define MCDE_OVL0CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL0CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, OVLEN, __x)
+#define MCDE_OVL0CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL0CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL0CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL0CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL0CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL0CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, COLCCTRL, MCDE_OVL0CR_COLCCTRL_##__x)
+#define MCDE_OVL0CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, COLCCTRL, __x)
+#define MCDE_OVL0CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL0CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL0CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, CKEYGEN, __x)
+#define MCDE_OVL0CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL0CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL0CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, ALPHAPMEN, __x)
+#define MCDE_OVL0CR_OVLF_SHIFT 5
+#define MCDE_OVL0CR_OVLF_MASK 0x00000020
+#define MCDE_OVL0CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, OVLF, __x)
+#define MCDE_OVL0CR_OVLR_SHIFT 6
+#define MCDE_OVL0CR_OVLR_MASK 0x00000040
+#define MCDE_OVL0CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, OVLR, __x)
+#define MCDE_OVL0CR_OVLB_SHIFT 7
+#define MCDE_OVL0CR_OVLB_MASK 0x00000080
+#define MCDE_OVL0CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, OVLB, __x)
+#define MCDE_OVL0CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL0CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL0CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, FETCH_ROPC, __x)
+#define MCDE_OVL0CR_STBPRIO_SHIFT 16
+#define MCDE_OVL0CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL0CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, STBPRIO, __x)
+#define MCDE_OVL0CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL0CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL0CR_BURSTSIZE_1W 0
+#define MCDE_OVL0CR_BURSTSIZE_2W 1
+#define MCDE_OVL0CR_BURSTSIZE_4W 2
+#define MCDE_OVL0CR_BURSTSIZE_8W 3
+#define MCDE_OVL0CR_BURSTSIZE_16W 4
+#define MCDE_OVL0CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL0CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL0CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL0CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL0CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL0CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, BURSTSIZE, MCDE_OVL0CR_BURSTSIZE_##__x)
+#define MCDE_OVL0CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, BURSTSIZE, __x)
+#define MCDE_OVL0CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL0CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL0CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL0CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL0CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL0CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL0CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL0CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, MAXOUTSTANDING, \
+ MCDE_OVL0CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL0CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL0CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL0CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL0CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL0CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL0CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL0CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL0CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL0CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL0CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL0CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL0CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL0CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL0CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, ROTBURSTSIZE, MCDE_OVL0CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL0CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL1CR 0x00000420
+#define MCDE_OVL1CR_OVLEN_SHIFT 0
+#define MCDE_OVL1CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL1CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, OVLEN, __x)
+#define MCDE_OVL1CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL1CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL1CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL1CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL1CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL1CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, COLCCTRL, MCDE_OVL1CR_COLCCTRL_##__x)
+#define MCDE_OVL1CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, COLCCTRL, __x)
+#define MCDE_OVL1CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL1CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL1CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, CKEYGEN, __x)
+#define MCDE_OVL1CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL1CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL1CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, ALPHAPMEN, __x)
+#define MCDE_OVL1CR_OVLF_SHIFT 5
+#define MCDE_OVL1CR_OVLF_MASK 0x00000020
+#define MCDE_OVL1CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, OVLF, __x)
+#define MCDE_OVL1CR_OVLR_SHIFT 6
+#define MCDE_OVL1CR_OVLR_MASK 0x00000040
+#define MCDE_OVL1CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, OVLR, __x)
+#define MCDE_OVL1CR_OVLB_SHIFT 7
+#define MCDE_OVL1CR_OVLB_MASK 0x00000080
+#define MCDE_OVL1CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, OVLB, __x)
+#define MCDE_OVL1CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL1CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL1CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, FETCH_ROPC, __x)
+#define MCDE_OVL1CR_STBPRIO_SHIFT 16
+#define MCDE_OVL1CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL1CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, STBPRIO, __x)
+#define MCDE_OVL1CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL1CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL1CR_BURSTSIZE_1W 0
+#define MCDE_OVL1CR_BURSTSIZE_2W 1
+#define MCDE_OVL1CR_BURSTSIZE_4W 2
+#define MCDE_OVL1CR_BURSTSIZE_8W 3
+#define MCDE_OVL1CR_BURSTSIZE_16W 4
+#define MCDE_OVL1CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL1CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL1CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL1CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL1CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL1CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, BURSTSIZE, MCDE_OVL1CR_BURSTSIZE_##__x)
+#define MCDE_OVL1CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, BURSTSIZE, __x)
+#define MCDE_OVL1CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL1CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL1CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL1CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL1CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL1CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL1CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL1CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, MAXOUTSTANDING, \
+ MCDE_OVL1CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL1CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL1CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL1CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL1CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL1CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL1CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL1CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL1CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL1CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL1CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL1CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL1CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL1CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL1CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, ROTBURSTSIZE, MCDE_OVL1CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL1CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL2CR 0x00000440
+#define MCDE_OVL2CR_OVLEN_SHIFT 0
+#define MCDE_OVL2CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL2CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, OVLEN, __x)
+#define MCDE_OVL2CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL2CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL2CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL2CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL2CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL2CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, COLCCTRL, MCDE_OVL2CR_COLCCTRL_##__x)
+#define MCDE_OVL2CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, COLCCTRL, __x)
+#define MCDE_OVL2CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL2CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL2CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, CKEYGEN, __x)
+#define MCDE_OVL2CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL2CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL2CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, ALPHAPMEN, __x)
+#define MCDE_OVL2CR_OVLF_SHIFT 5
+#define MCDE_OVL2CR_OVLF_MASK 0x00000020
+#define MCDE_OVL2CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, OVLF, __x)
+#define MCDE_OVL2CR_OVLR_SHIFT 6
+#define MCDE_OVL2CR_OVLR_MASK 0x00000040
+#define MCDE_OVL2CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, OVLR, __x)
+#define MCDE_OVL2CR_OVLB_SHIFT 7
+#define MCDE_OVL2CR_OVLB_MASK 0x00000080
+#define MCDE_OVL2CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, OVLB, __x)
+#define MCDE_OVL2CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL2CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL2CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, FETCH_ROPC, __x)
+#define MCDE_OVL2CR_STBPRIO_SHIFT 16
+#define MCDE_OVL2CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL2CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, STBPRIO, __x)
+#define MCDE_OVL2CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL2CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL2CR_BURSTSIZE_1W 0
+#define MCDE_OVL2CR_BURSTSIZE_2W 1
+#define MCDE_OVL2CR_BURSTSIZE_4W 2
+#define MCDE_OVL2CR_BURSTSIZE_8W 3
+#define MCDE_OVL2CR_BURSTSIZE_16W 4
+#define MCDE_OVL2CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL2CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL2CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL2CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL2CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL2CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, BURSTSIZE, MCDE_OVL2CR_BURSTSIZE_##__x)
+#define MCDE_OVL2CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, BURSTSIZE, __x)
+#define MCDE_OVL2CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL2CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL2CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL2CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL2CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL2CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL2CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL2CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, MAXOUTSTANDING, \
+ MCDE_OVL2CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL2CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL2CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL2CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL2CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL2CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL2CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL2CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL2CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL2CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL2CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL2CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL2CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL2CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL2CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, ROTBURSTSIZE, MCDE_OVL2CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL2CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL3CR 0x00000460
+#define MCDE_OVL3CR_OVLEN_SHIFT 0
+#define MCDE_OVL3CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL3CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, OVLEN, __x)
+#define MCDE_OVL3CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL3CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL3CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL3CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL3CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL3CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, COLCCTRL, MCDE_OVL3CR_COLCCTRL_##__x)
+#define MCDE_OVL3CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, COLCCTRL, __x)
+#define MCDE_OVL3CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL3CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL3CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, CKEYGEN, __x)
+#define MCDE_OVL3CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL3CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL3CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, ALPHAPMEN, __x)
+#define MCDE_OVL3CR_OVLF_SHIFT 5
+#define MCDE_OVL3CR_OVLF_MASK 0x00000020
+#define MCDE_OVL3CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, OVLF, __x)
+#define MCDE_OVL3CR_OVLR_SHIFT 6
+#define MCDE_OVL3CR_OVLR_MASK 0x00000040
+#define MCDE_OVL3CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, OVLR, __x)
+#define MCDE_OVL3CR_OVLB_SHIFT 7
+#define MCDE_OVL3CR_OVLB_MASK 0x00000080
+#define MCDE_OVL3CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, OVLB, __x)
+#define MCDE_OVL3CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL3CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL3CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, FETCH_ROPC, __x)
+#define MCDE_OVL3CR_STBPRIO_SHIFT 16
+#define MCDE_OVL3CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL3CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, STBPRIO, __x)
+#define MCDE_OVL3CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL3CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL3CR_BURSTSIZE_1W 0
+#define MCDE_OVL3CR_BURSTSIZE_2W 1
+#define MCDE_OVL3CR_BURSTSIZE_4W 2
+#define MCDE_OVL3CR_BURSTSIZE_8W 3
+#define MCDE_OVL3CR_BURSTSIZE_16W 4
+#define MCDE_OVL3CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL3CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL3CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL3CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL3CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL3CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, BURSTSIZE, MCDE_OVL3CR_BURSTSIZE_##__x)
+#define MCDE_OVL3CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, BURSTSIZE, __x)
+#define MCDE_OVL3CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL3CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL3CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL3CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL3CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL3CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL3CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL3CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, MAXOUTSTANDING, \
+ MCDE_OVL3CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL3CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL3CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL3CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL3CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL3CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL3CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL3CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL3CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL3CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL3CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL3CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL3CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL3CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL3CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, ROTBURSTSIZE, MCDE_OVL3CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL3CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL4CR 0x00000480
+#define MCDE_OVL4CR_OVLEN_SHIFT 0
+#define MCDE_OVL4CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL4CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, OVLEN, __x)
+#define MCDE_OVL4CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL4CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL4CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL4CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL4CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL4CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, COLCCTRL, MCDE_OVL4CR_COLCCTRL_##__x)
+#define MCDE_OVL4CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, COLCCTRL, __x)
+#define MCDE_OVL4CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL4CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL4CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, CKEYGEN, __x)
+#define MCDE_OVL4CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL4CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL4CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, ALPHAPMEN, __x)
+#define MCDE_OVL4CR_OVLF_SHIFT 5
+#define MCDE_OVL4CR_OVLF_MASK 0x00000020
+#define MCDE_OVL4CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, OVLF, __x)
+#define MCDE_OVL4CR_OVLR_SHIFT 6
+#define MCDE_OVL4CR_OVLR_MASK 0x00000040
+#define MCDE_OVL4CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, OVLR, __x)
+#define MCDE_OVL4CR_OVLB_SHIFT 7
+#define MCDE_OVL4CR_OVLB_MASK 0x00000080
+#define MCDE_OVL4CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, OVLB, __x)
+#define MCDE_OVL4CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL4CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL4CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, FETCH_ROPC, __x)
+#define MCDE_OVL4CR_STBPRIO_SHIFT 16
+#define MCDE_OVL4CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL4CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, STBPRIO, __x)
+#define MCDE_OVL4CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL4CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL4CR_BURSTSIZE_1W 0
+#define MCDE_OVL4CR_BURSTSIZE_2W 1
+#define MCDE_OVL4CR_BURSTSIZE_4W 2
+#define MCDE_OVL4CR_BURSTSIZE_8W 3
+#define MCDE_OVL4CR_BURSTSIZE_16W 4
+#define MCDE_OVL4CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL4CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL4CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL4CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL4CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL4CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, BURSTSIZE, MCDE_OVL4CR_BURSTSIZE_##__x)
+#define MCDE_OVL4CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, BURSTSIZE, __x)
+#define MCDE_OVL4CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL4CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL4CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL4CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL4CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL4CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL4CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL4CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, MAXOUTSTANDING, \
+ MCDE_OVL4CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL4CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL4CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL4CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL4CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL4CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL4CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL4CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL4CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL4CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL4CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL4CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL4CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL4CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL4CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, ROTBURSTSIZE, MCDE_OVL4CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL4CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL5CR 0x000004A0
+#define MCDE_OVL5CR_OVLEN_SHIFT 0
+#define MCDE_OVL5CR_OVLEN_MASK 0x00000001
+#define MCDE_OVL5CR_OVLEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, OVLEN, __x)
+#define MCDE_OVL5CR_COLCCTRL_SHIFT 1
+#define MCDE_OVL5CR_COLCCTRL_MASK 0x00000006
+#define MCDE_OVL5CR_COLCCTRL_DISABLED 0
+#define MCDE_OVL5CR_COLCCTRL_ENABLED_NO_SAT 1
+#define MCDE_OVL5CR_COLCCTRL_ENABLED_SAT 2
+#define MCDE_OVL5CR_COLCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, COLCCTRL, MCDE_OVL5CR_COLCCTRL_##__x)
+#define MCDE_OVL5CR_COLCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, COLCCTRL, __x)
+#define MCDE_OVL5CR_CKEYGEN_SHIFT 3
+#define MCDE_OVL5CR_CKEYGEN_MASK 0x00000008
+#define MCDE_OVL5CR_CKEYGEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, CKEYGEN, __x)
+#define MCDE_OVL5CR_ALPHAPMEN_SHIFT 4
+#define MCDE_OVL5CR_ALPHAPMEN_MASK 0x00000010
+#define MCDE_OVL5CR_ALPHAPMEN(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, ALPHAPMEN, __x)
+#define MCDE_OVL5CR_OVLF_SHIFT 5
+#define MCDE_OVL5CR_OVLF_MASK 0x00000020
+#define MCDE_OVL5CR_OVLF(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, OVLF, __x)
+#define MCDE_OVL5CR_OVLR_SHIFT 6
+#define MCDE_OVL5CR_OVLR_MASK 0x00000040
+#define MCDE_OVL5CR_OVLR(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, OVLR, __x)
+#define MCDE_OVL5CR_OVLB_SHIFT 7
+#define MCDE_OVL5CR_OVLB_MASK 0x00000080
+#define MCDE_OVL5CR_OVLB(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, OVLB, __x)
+#define MCDE_OVL5CR_FETCH_ROPC_SHIFT 8
+#define MCDE_OVL5CR_FETCH_ROPC_MASK 0x0000FF00
+#define MCDE_OVL5CR_FETCH_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, FETCH_ROPC, __x)
+#define MCDE_OVL5CR_STBPRIO_SHIFT 16
+#define MCDE_OVL5CR_STBPRIO_MASK 0x000F0000
+#define MCDE_OVL5CR_STBPRIO(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, STBPRIO, __x)
+#define MCDE_OVL5CR_BURSTSIZE_SHIFT 20
+#define MCDE_OVL5CR_BURSTSIZE_MASK 0x00F00000
+#define MCDE_OVL5CR_BURSTSIZE_1W 0
+#define MCDE_OVL5CR_BURSTSIZE_2W 1
+#define MCDE_OVL5CR_BURSTSIZE_4W 2
+#define MCDE_OVL5CR_BURSTSIZE_8W 3
+#define MCDE_OVL5CR_BURSTSIZE_16W 4
+#define MCDE_OVL5CR_BURSTSIZE_HW_1W 8
+#define MCDE_OVL5CR_BURSTSIZE_HW_2W 9
+#define MCDE_OVL5CR_BURSTSIZE_HW_4W 10
+#define MCDE_OVL5CR_BURSTSIZE_HW_8W 11
+#define MCDE_OVL5CR_BURSTSIZE_HW_16W 12
+#define MCDE_OVL5CR_BURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, BURSTSIZE, MCDE_OVL5CR_BURSTSIZE_##__x)
+#define MCDE_OVL5CR_BURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, BURSTSIZE, __x)
+#define MCDE_OVL5CR_MAXOUTSTANDING_SHIFT 24
+#define MCDE_OVL5CR_MAXOUTSTANDING_MASK 0x0F000000
+#define MCDE_OVL5CR_MAXOUTSTANDING_1_REQ 0
+#define MCDE_OVL5CR_MAXOUTSTANDING_2_REQ 1
+#define MCDE_OVL5CR_MAXOUTSTANDING_4_REQ 2
+#define MCDE_OVL5CR_MAXOUTSTANDING_8_REQ 3
+#define MCDE_OVL5CR_MAXOUTSTANDING_16_REQ 4
+#define MCDE_OVL5CR_MAXOUTSTANDING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, MAXOUTSTANDING, \
+ MCDE_OVL5CR_MAXOUTSTANDING_##__x)
+#define MCDE_OVL5CR_MAXOUTSTANDING(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, MAXOUTSTANDING, __x)
+#define MCDE_OVL5CR_ROTBURSTSIZE_SHIFT 28
+#define MCDE_OVL5CR_ROTBURSTSIZE_MASK 0xF0000000
+#define MCDE_OVL5CR_ROTBURSTSIZE_1W 0
+#define MCDE_OVL5CR_ROTBURSTSIZE_2W 1
+#define MCDE_OVL5CR_ROTBURSTSIZE_4W 2
+#define MCDE_OVL5CR_ROTBURSTSIZE_8W 3
+#define MCDE_OVL5CR_ROTBURSTSIZE_16W 4
+#define MCDE_OVL5CR_ROTBURSTSIZE_HW_1W 8
+#define MCDE_OVL5CR_ROTBURSTSIZE_HW_2W 9
+#define MCDE_OVL5CR_ROTBURSTSIZE_HW_4W 10
+#define MCDE_OVL5CR_ROTBURSTSIZE_HW_8W 11
+#define MCDE_OVL5CR_ROTBURSTSIZE_HW_16W 12
+#define MCDE_OVL5CR_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, ROTBURSTSIZE, MCDE_OVL5CR_ROTBURSTSIZE_##__x)
+#define MCDE_OVL5CR_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CR, ROTBURSTSIZE, __x)
+#define MCDE_OVL0CONF 0x00000404
+#define MCDE_OVL0CONF_GROUPOFFSET 0x20
+#define MCDE_OVL0CONF_PPL_SHIFT 0
+#define MCDE_OVL0CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL0CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF, PPL, __x)
+#define MCDE_OVL0CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL0CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL0CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF, EXTSRC_ID, __x)
+#define MCDE_OVL0CONF_LPF_SHIFT 16
+#define MCDE_OVL0CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL0CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF, LPF, __x)
+#define MCDE_OVL1CONF 0x00000424
+#define MCDE_OVL1CONF_PPL_SHIFT 0
+#define MCDE_OVL1CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL1CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF, PPL, __x)
+#define MCDE_OVL1CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL1CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL1CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF, EXTSRC_ID, __x)
+#define MCDE_OVL1CONF_LPF_SHIFT 16
+#define MCDE_OVL1CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL1CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF, LPF, __x)
+#define MCDE_OVL2CONF 0x00000444
+#define MCDE_OVL2CONF_PPL_SHIFT 0
+#define MCDE_OVL2CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL2CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF, PPL, __x)
+#define MCDE_OVL2CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL2CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL2CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF, EXTSRC_ID, __x)
+#define MCDE_OVL2CONF_LPF_SHIFT 16
+#define MCDE_OVL2CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL2CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF, LPF, __x)
+#define MCDE_OVL3CONF 0x00000464
+#define MCDE_OVL3CONF_PPL_SHIFT 0
+#define MCDE_OVL3CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL3CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF, PPL, __x)
+#define MCDE_OVL3CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL3CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL3CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF, EXTSRC_ID, __x)
+#define MCDE_OVL3CONF_LPF_SHIFT 16
+#define MCDE_OVL3CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL3CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF, LPF, __x)
+#define MCDE_OVL4CONF 0x00000484
+#define MCDE_OVL4CONF_PPL_SHIFT 0
+#define MCDE_OVL4CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL4CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF, PPL, __x)
+#define MCDE_OVL4CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL4CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL4CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF, EXTSRC_ID, __x)
+#define MCDE_OVL4CONF_LPF_SHIFT 16
+#define MCDE_OVL4CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL4CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF, LPF, __x)
+#define MCDE_OVL5CONF 0x000004A4
+#define MCDE_OVL5CONF_PPL_SHIFT 0
+#define MCDE_OVL5CONF_PPL_MASK 0x000007FF
+#define MCDE_OVL5CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF, PPL, __x)
+#define MCDE_OVL5CONF_EXTSRC_ID_SHIFT 11
+#define MCDE_OVL5CONF_EXTSRC_ID_MASK 0x00007800
+#define MCDE_OVL5CONF_EXTSRC_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF, EXTSRC_ID, __x)
+#define MCDE_OVL5CONF_LPF_SHIFT 16
+#define MCDE_OVL5CONF_LPF_MASK 0x07FF0000
+#define MCDE_OVL5CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF, LPF, __x)
+#define MCDE_OVL0CONF2 0x00000408
+#define MCDE_OVL0CONF2_GROUPOFFSET 0x20
+#define MCDE_OVL0CONF2_BP_SHIFT 0
+#define MCDE_OVL0CONF2_BP_MASK 0x00000001
+#define MCDE_OVL0CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL0CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL0CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, BP, MCDE_OVL0CONF2_BP_##__x)
+#define MCDE_OVL0CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, BP, __x)
+#define MCDE_OVL0CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL0CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL0CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL0CONF2_OPQ_SHIFT 9
+#define MCDE_OVL0CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL0CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, OPQ, __x)
+#define MCDE_OVL0CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL0CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL0CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, PIXOFF, __x)
+#define MCDE_OVL0CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL0CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL0CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL1CONF2 0x00000428
+#define MCDE_OVL1CONF2_BP_SHIFT 0
+#define MCDE_OVL1CONF2_BP_MASK 0x00000001
+#define MCDE_OVL1CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL1CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL1CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, BP, MCDE_OVL1CONF2_BP_##__x)
+#define MCDE_OVL1CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, BP, __x)
+#define MCDE_OVL1CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL1CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL1CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL1CONF2_OPQ_SHIFT 9
+#define MCDE_OVL1CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL1CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, OPQ, __x)
+#define MCDE_OVL1CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL1CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL1CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, PIXOFF, __x)
+#define MCDE_OVL1CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL1CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL1CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL2CONF2 0x00000448
+#define MCDE_OVL2CONF2_BP_SHIFT 0
+#define MCDE_OVL2CONF2_BP_MASK 0x00000001
+#define MCDE_OVL2CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL2CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL2CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, BP, MCDE_OVL2CONF2_BP_##__x)
+#define MCDE_OVL2CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, BP, __x)
+#define MCDE_OVL2CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL2CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL2CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL2CONF2_OPQ_SHIFT 9
+#define MCDE_OVL2CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL2CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, OPQ, __x)
+#define MCDE_OVL2CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL2CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL2CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, PIXOFF, __x)
+#define MCDE_OVL2CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL2CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL2CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL3CONF2 0x00000468
+#define MCDE_OVL3CONF2_BP_SHIFT 0
+#define MCDE_OVL3CONF2_BP_MASK 0x00000001
+#define MCDE_OVL3CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL3CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL3CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, BP, MCDE_OVL3CONF2_BP_##__x)
+#define MCDE_OVL3CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, BP, __x)
+#define MCDE_OVL3CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL3CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL3CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL3CONF2_OPQ_SHIFT 9
+#define MCDE_OVL3CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL3CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, OPQ, __x)
+#define MCDE_OVL3CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL3CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL3CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, PIXOFF, __x)
+#define MCDE_OVL3CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL3CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL3CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL4CONF2 0x00000488
+#define MCDE_OVL4CONF2_BP_SHIFT 0
+#define MCDE_OVL4CONF2_BP_MASK 0x00000001
+#define MCDE_OVL4CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL4CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL4CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, BP, MCDE_OVL4CONF2_BP_##__x)
+#define MCDE_OVL4CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, BP, __x)
+#define MCDE_OVL4CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL4CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL4CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL4CONF2_OPQ_SHIFT 9
+#define MCDE_OVL4CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL4CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, OPQ, __x)
+#define MCDE_OVL4CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL4CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL4CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, PIXOFF, __x)
+#define MCDE_OVL4CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL4CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL4CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL5CONF2 0x000004A8
+#define MCDE_OVL5CONF2_BP_SHIFT 0
+#define MCDE_OVL5CONF2_BP_MASK 0x00000001
+#define MCDE_OVL5CONF2_BP_PER_PIXEL_ALPHA 0
+#define MCDE_OVL5CONF2_BP_CONSTANT_ALPHA 1
+#define MCDE_OVL5CONF2_BP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, BP, MCDE_OVL5CONF2_BP_##__x)
+#define MCDE_OVL5CONF2_BP(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, BP, __x)
+#define MCDE_OVL5CONF2_ALPHAVALUE_SHIFT 1
+#define MCDE_OVL5CONF2_ALPHAVALUE_MASK 0x000001FE
+#define MCDE_OVL5CONF2_ALPHAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, ALPHAVALUE, __x)
+#define MCDE_OVL5CONF2_OPQ_SHIFT 9
+#define MCDE_OVL5CONF2_OPQ_MASK 0x00000200
+#define MCDE_OVL5CONF2_OPQ(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, OPQ, __x)
+#define MCDE_OVL5CONF2_PIXOFF_SHIFT 10
+#define MCDE_OVL5CONF2_PIXOFF_MASK 0x0000FC00
+#define MCDE_OVL5CONF2_PIXOFF(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, PIXOFF, __x)
+#define MCDE_OVL5CONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT 16
+#define MCDE_OVL5CONF2_PIXELFETCHERWATERMARKLEVEL_MASK 0x1FFF0000
+#define MCDE_OVL5CONF2_PIXELFETCHERWATERMARKLEVEL(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CONF2, PIXELFETCHERWATERMARKLEVEL, __x)
+#define MCDE_OVL0LJINC 0x0000040C
+#define MCDE_OVL0LJINC_GROUPOFFSET 0x20
+#define MCDE_OVL0LJINC_LJINC_SHIFT 0
+#define MCDE_OVL0LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL0LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL0LJINC, LJINC, __x)
+#define MCDE_OVL1LJINC 0x0000042C
+#define MCDE_OVL1LJINC_LJINC_SHIFT 0
+#define MCDE_OVL1LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL1LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL1LJINC, LJINC, __x)
+#define MCDE_OVL2LJINC 0x0000044C
+#define MCDE_OVL2LJINC_LJINC_SHIFT 0
+#define MCDE_OVL2LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL2LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL2LJINC, LJINC, __x)
+#define MCDE_OVL3LJINC 0x0000046C
+#define MCDE_OVL3LJINC_LJINC_SHIFT 0
+#define MCDE_OVL3LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL3LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL3LJINC, LJINC, __x)
+#define MCDE_OVL4LJINC 0x0000048C
+#define MCDE_OVL4LJINC_LJINC_SHIFT 0
+#define MCDE_OVL4LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL4LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL4LJINC, LJINC, __x)
+#define MCDE_OVL5LJINC 0x000004AC
+#define MCDE_OVL5LJINC_LJINC_SHIFT 0
+#define MCDE_OVL5LJINC_LJINC_MASK 0xFFFFFFFF
+#define MCDE_OVL5LJINC_LJINC(__x) \
+ MCDE_VAL2REG(MCDE_OVL5LJINC, LJINC, __x)
+#define MCDE_OVL0CROP 0x00000410
+#define MCDE_OVL0CROP_GROUPOFFSET 0x20
+#define MCDE_OVL0CROP_TMRGN_SHIFT 0
+#define MCDE_OVL0CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL0CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CROP, TMRGN, __x)
+#define MCDE_OVL0CROP_LMRGN_SHIFT 22
+#define MCDE_OVL0CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL0CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL0CROP, LMRGN, __x)
+#define MCDE_OVL1CROP 0x00000430
+#define MCDE_OVL1CROP_TMRGN_SHIFT 0
+#define MCDE_OVL1CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL1CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CROP, TMRGN, __x)
+#define MCDE_OVL1CROP_LMRGN_SHIFT 22
+#define MCDE_OVL1CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL1CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL1CROP, LMRGN, __x)
+#define MCDE_OVL2CROP 0x00000450
+#define MCDE_OVL2CROP_TMRGN_SHIFT 0
+#define MCDE_OVL2CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL2CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CROP, TMRGN, __x)
+#define MCDE_OVL2CROP_LMRGN_SHIFT 22
+#define MCDE_OVL2CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL2CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL2CROP, LMRGN, __x)
+#define MCDE_OVL3CROP 0x00000470
+#define MCDE_OVL3CROP_TMRGN_SHIFT 0
+#define MCDE_OVL3CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL3CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CROP, TMRGN, __x)
+#define MCDE_OVL3CROP_LMRGN_SHIFT 22
+#define MCDE_OVL3CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL3CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL3CROP, LMRGN, __x)
+#define MCDE_OVL4CROP 0x00000490
+#define MCDE_OVL4CROP_TMRGN_SHIFT 0
+#define MCDE_OVL4CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL4CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CROP, TMRGN, __x)
+#define MCDE_OVL4CROP_LMRGN_SHIFT 22
+#define MCDE_OVL4CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL4CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL4CROP, LMRGN, __x)
+#define MCDE_OVL5CROP 0x000004B0
+#define MCDE_OVL5CROP_TMRGN_SHIFT 0
+#define MCDE_OVL5CROP_TMRGN_MASK 0x003FFFFF
+#define MCDE_OVL5CROP_TMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CROP, TMRGN, __x)
+#define MCDE_OVL5CROP_LMRGN_SHIFT 22
+#define MCDE_OVL5CROP_LMRGN_MASK 0xFFC00000
+#define MCDE_OVL5CROP_LMRGN(__x) \
+ MCDE_VAL2REG(MCDE_OVL5CROP, LMRGN, __x)
+#define MCDE_OVL0COMP 0x00000414
+#define MCDE_OVL0COMP_GROUPOFFSET 0x20
+#define MCDE_OVL0COMP_XPOS_SHIFT 0
+#define MCDE_OVL0COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL0COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL0COMP, XPOS, __x)
+#define MCDE_OVL0COMP_CH_ID_SHIFT 11
+#define MCDE_OVL0COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL0COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL0COMP, CH_ID, __x)
+#define MCDE_OVL0COMP_YPOS_SHIFT 16
+#define MCDE_OVL0COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL0COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL0COMP, YPOS, __x)
+#define MCDE_OVL0COMP_Z_SHIFT 27
+#define MCDE_OVL0COMP_Z_MASK 0x78000000
+#define MCDE_OVL0COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL0COMP, Z, __x)
+#define MCDE_OVL1COMP 0x00000434
+#define MCDE_OVL1COMP_XPOS_SHIFT 0
+#define MCDE_OVL1COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL1COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL1COMP, XPOS, __x)
+#define MCDE_OVL1COMP_CH_ID_SHIFT 11
+#define MCDE_OVL1COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL1COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL1COMP, CH_ID, __x)
+#define MCDE_OVL1COMP_YPOS_SHIFT 16
+#define MCDE_OVL1COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL1COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL1COMP, YPOS, __x)
+#define MCDE_OVL1COMP_Z_SHIFT 27
+#define MCDE_OVL1COMP_Z_MASK 0x78000000
+#define MCDE_OVL1COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL1COMP, Z, __x)
+#define MCDE_OVL2COMP 0x00000454
+#define MCDE_OVL2COMP_XPOS_SHIFT 0
+#define MCDE_OVL2COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL2COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL2COMP, XPOS, __x)
+#define MCDE_OVL2COMP_CH_ID_SHIFT 11
+#define MCDE_OVL2COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL2COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL2COMP, CH_ID, __x)
+#define MCDE_OVL2COMP_YPOS_SHIFT 16
+#define MCDE_OVL2COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL2COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL2COMP, YPOS, __x)
+#define MCDE_OVL2COMP_Z_SHIFT 27
+#define MCDE_OVL2COMP_Z_MASK 0x78000000
+#define MCDE_OVL2COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL2COMP, Z, __x)
+#define MCDE_OVL3COMP 0x00000474
+#define MCDE_OVL3COMP_XPOS_SHIFT 0
+#define MCDE_OVL3COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL3COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL3COMP, XPOS, __x)
+#define MCDE_OVL3COMP_CH_ID_SHIFT 11
+#define MCDE_OVL3COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL3COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL3COMP, CH_ID, __x)
+#define MCDE_OVL3COMP_YPOS_SHIFT 16
+#define MCDE_OVL3COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL3COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL3COMP, YPOS, __x)
+#define MCDE_OVL3COMP_Z_SHIFT 27
+#define MCDE_OVL3COMP_Z_MASK 0x78000000
+#define MCDE_OVL3COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL3COMP, Z, __x)
+#define MCDE_OVL4COMP 0x00000494
+#define MCDE_OVL4COMP_XPOS_SHIFT 0
+#define MCDE_OVL4COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL4COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL4COMP, XPOS, __x)
+#define MCDE_OVL4COMP_CH_ID_SHIFT 11
+#define MCDE_OVL4COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL4COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL4COMP, CH_ID, __x)
+#define MCDE_OVL4COMP_YPOS_SHIFT 16
+#define MCDE_OVL4COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL4COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL4COMP, YPOS, __x)
+#define MCDE_OVL4COMP_Z_SHIFT 27
+#define MCDE_OVL4COMP_Z_MASK 0x78000000
+#define MCDE_OVL4COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL4COMP, Z, __x)
+#define MCDE_OVL5COMP 0x000004B4
+#define MCDE_OVL5COMP_XPOS_SHIFT 0
+#define MCDE_OVL5COMP_XPOS_MASK 0x000007FF
+#define MCDE_OVL5COMP_XPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL5COMP, XPOS, __x)
+#define MCDE_OVL5COMP_CH_ID_SHIFT 11
+#define MCDE_OVL5COMP_CH_ID_MASK 0x00007800
+#define MCDE_OVL5COMP_CH_ID(__x) \
+ MCDE_VAL2REG(MCDE_OVL5COMP, CH_ID, __x)
+#define MCDE_OVL5COMP_YPOS_SHIFT 16
+#define MCDE_OVL5COMP_YPOS_MASK 0x07FF0000
+#define MCDE_OVL5COMP_YPOS(__x) \
+ MCDE_VAL2REG(MCDE_OVL5COMP, YPOS, __x)
+#define MCDE_OVL5COMP_Z_SHIFT 27
+#define MCDE_OVL5COMP_Z_MASK 0x78000000
+#define MCDE_OVL5COMP_Z(__x) \
+ MCDE_VAL2REG(MCDE_OVL5COMP, Z, __x)
+#define MCDE_CHNL0CONF 0x00000600
+#define MCDE_CHNL0CONF_GROUPOFFSET 0x20
+#define MCDE_CHNL0CONF_PPL_SHIFT 0
+#define MCDE_CHNL0CONF_PPL_MASK 0x000007FF
+#define MCDE_CHNL0CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0CONF, PPL, __x)
+#define MCDE_CHNL0CONF_LPF_SHIFT 16
+#define MCDE_CHNL0CONF_LPF_MASK 0x07FF0000
+#define MCDE_CHNL0CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0CONF, LPF, __x)
+#define MCDE_CHNL1CONF 0x00000620
+#define MCDE_CHNL1CONF_PPL_SHIFT 0
+#define MCDE_CHNL1CONF_PPL_MASK 0x000007FF
+#define MCDE_CHNL1CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1CONF, PPL, __x)
+#define MCDE_CHNL1CONF_LPF_SHIFT 16
+#define MCDE_CHNL1CONF_LPF_MASK 0x07FF0000
+#define MCDE_CHNL1CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1CONF, LPF, __x)
+#define MCDE_CHNL2CONF 0x00000640
+#define MCDE_CHNL2CONF_PPL_SHIFT 0
+#define MCDE_CHNL2CONF_PPL_MASK 0x000007FF
+#define MCDE_CHNL2CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2CONF, PPL, __x)
+#define MCDE_CHNL2CONF_LPF_SHIFT 16
+#define MCDE_CHNL2CONF_LPF_MASK 0x07FF0000
+#define MCDE_CHNL2CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2CONF, LPF, __x)
+#define MCDE_CHNL3CONF 0x00000660
+#define MCDE_CHNL3CONF_PPL_SHIFT 0
+#define MCDE_CHNL3CONF_PPL_MASK 0x000007FF
+#define MCDE_CHNL3CONF_PPL(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3CONF, PPL, __x)
+#define MCDE_CHNL3CONF_LPF_SHIFT 16
+#define MCDE_CHNL3CONF_LPF_MASK 0x07FF0000
+#define MCDE_CHNL3CONF_LPF(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3CONF, LPF, __x)
+#define MCDE_CHNL0STAT 0x00000604
+#define MCDE_CHNL0STAT_GROUPOFFSET 0x20
+#define MCDE_CHNL0STAT_CHNLRD_SHIFT 0
+#define MCDE_CHNL0STAT_CHNLRD_MASK 0x00000001
+#define MCDE_CHNL0STAT_CHNLRD(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0STAT, CHNLRD, __x)
+#define MCDE_CHNL0STAT_CHNLA_SHIFT 1
+#define MCDE_CHNL0STAT_CHNLA_MASK 0x00000002
+#define MCDE_CHNL0STAT_CHNLA(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0STAT, CHNLA, __x)
+#define MCDE_CHNL0STAT_CHNLBLBCKGND_EN_SHIFT 16
+#define MCDE_CHNL0STAT_CHNLBLBCKGND_EN_MASK 0x00010000
+#define MCDE_CHNL0STAT_CHNLBLBCKGND_EN(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0STAT, CHNLBLBCKGND_EN, __x)
+#define MCDE_CHNL1STAT 0x00000624
+#define MCDE_CHNL1STAT_CHNLRD_SHIFT 0
+#define MCDE_CHNL1STAT_CHNLRD_MASK 0x00000001
+#define MCDE_CHNL1STAT_CHNLRD(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1STAT, CHNLRD, __x)
+#define MCDE_CHNL1STAT_CHNLA_SHIFT 1
+#define MCDE_CHNL1STAT_CHNLA_MASK 0x00000002
+#define MCDE_CHNL1STAT_CHNLA(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1STAT, CHNLA, __x)
+#define MCDE_CHNL1STAT_CHNLBLBCKGND_EN_SHIFT 16
+#define MCDE_CHNL1STAT_CHNLBLBCKGND_EN_MASK 0x00010000
+#define MCDE_CHNL1STAT_CHNLBLBCKGND_EN(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1STAT, CHNLBLBCKGND_EN, __x)
+#define MCDE_CHNL2STAT 0x00000644
+#define MCDE_CHNL2STAT_CHNLRD_SHIFT 0
+#define MCDE_CHNL2STAT_CHNLRD_MASK 0x00000001
+#define MCDE_CHNL2STAT_CHNLRD(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2STAT, CHNLRD, __x)
+#define MCDE_CHNL2STAT_CHNLA_SHIFT 1
+#define MCDE_CHNL2STAT_CHNLA_MASK 0x00000002
+#define MCDE_CHNL2STAT_CHNLA(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2STAT, CHNLA, __x)
+#define MCDE_CHNL2STAT_CHNLBLBCKGND_EN_SHIFT 16
+#define MCDE_CHNL2STAT_CHNLBLBCKGND_EN_MASK 0x00010000
+#define MCDE_CHNL2STAT_CHNLBLBCKGND_EN(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2STAT, CHNLBLBCKGND_EN, __x)
+#define MCDE_CHNL3STAT 0x00000664
+#define MCDE_CHNL3STAT_CHNLRD_SHIFT 0
+#define MCDE_CHNL3STAT_CHNLRD_MASK 0x00000001
+#define MCDE_CHNL3STAT_CHNLRD(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3STAT, CHNLRD, __x)
+#define MCDE_CHNL3STAT_CHNLA_SHIFT 1
+#define MCDE_CHNL3STAT_CHNLA_MASK 0x00000002
+#define MCDE_CHNL3STAT_CHNLA(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3STAT, CHNLA, __x)
+#define MCDE_CHNL3STAT_CHNLBLBCKGND_EN_SHIFT 16
+#define MCDE_CHNL3STAT_CHNLBLBCKGND_EN_MASK 0x00010000
+#define MCDE_CHNL3STAT_CHNLBLBCKGND_EN(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3STAT, CHNLBLBCKGND_EN, __x)
+#define MCDE_CHNL0SYNCHMOD 0x00000608
+#define MCDE_CHNL0SYNCHMOD_GROUPOFFSET 0x20
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SHIFT 0
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_MASK 0x00000003
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE 0
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_NO_SYNCH 1
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE 2
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0SYNCHMOD, SRC_SYNCH, \
+ MCDE_CHNL0SYNCHMOD_SRC_SYNCH_##__x)
+#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0SYNCHMOD, SRC_SYNCH, __x)
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_SHIFT 2
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_MASK 0x0000001C
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_FORMATTER 0
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE0 1
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_TE1 2
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0SYNCHMOD, OUT_SYNCH_SRC, \
+ MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC_##__x)
+#define MCDE_CHNL0SYNCHMOD_OUT_SYNCH_SRC(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0SYNCHMOD, OUT_SYNCH_SRC, __x)
+#define MCDE_CHNL1SYNCHMOD 0x00000628
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_SHIFT 0
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_MASK 0x00000003
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_HARDWARE 0
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_NO_SYNCH 1
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_SOFTWARE 2
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1SYNCHMOD, SRC_SYNCH, \
+ MCDE_CHNL1SYNCHMOD_SRC_SYNCH_##__x)
+#define MCDE_CHNL1SYNCHMOD_SRC_SYNCH(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1SYNCHMOD, SRC_SYNCH, __x)
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_SHIFT 2
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_MASK 0x0000001C
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_FORMATTER 0
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_TE0 1
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_TE1 2
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1SYNCHMOD, OUT_SYNCH_SRC, \
+ MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC_##__x)
+#define MCDE_CHNL1SYNCHMOD_OUT_SYNCH_SRC(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1SYNCHMOD, OUT_SYNCH_SRC, __x)
+#define MCDE_CHNL2SYNCHMOD 0x00000648
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_SHIFT 0
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_MASK 0x00000003
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_HARDWARE 0
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_NO_SYNCH 1
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_SOFTWARE 2
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2SYNCHMOD, SRC_SYNCH, \
+ MCDE_CHNL2SYNCHMOD_SRC_SYNCH_##__x)
+#define MCDE_CHNL2SYNCHMOD_SRC_SYNCH(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2SYNCHMOD, SRC_SYNCH, __x)
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_SHIFT 2
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_MASK 0x0000001C
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_FORMATTER 0
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_TE0 1
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_TE1 2
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2SYNCHMOD, OUT_SYNCH_SRC, \
+ MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC_##__x)
+#define MCDE_CHNL2SYNCHMOD_OUT_SYNCH_SRC(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2SYNCHMOD, OUT_SYNCH_SRC, __x)
+#define MCDE_CHNL3SYNCHMOD 0x00000668
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_SHIFT 0
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_MASK 0x00000003
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_HARDWARE 0
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_NO_SYNCH 1
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_SOFTWARE 2
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3SYNCHMOD, SRC_SYNCH, \
+ MCDE_CHNL3SYNCHMOD_SRC_SYNCH_##__x)
+#define MCDE_CHNL3SYNCHMOD_SRC_SYNCH(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3SYNCHMOD, SRC_SYNCH, __x)
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_SHIFT 2
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_MASK 0x0000001C
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_FORMATTER 0
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_TE0 1
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_TE1 2
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3SYNCHMOD, OUT_SYNCH_SRC, \
+ MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC_##__x)
+#define MCDE_CHNL3SYNCHMOD_OUT_SYNCH_SRC(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3SYNCHMOD, OUT_SYNCH_SRC, __x)
+#define MCDE_CHNL0SYNCHSW 0x0000060C
+#define MCDE_CHNL0SYNCHSW_GROUPOFFSET 0x20
+#define MCDE_CHNL0SYNCHSW_SW_TRIG_SHIFT 0
+#define MCDE_CHNL0SYNCHSW_SW_TRIG_MASK 0x00000001
+#define MCDE_CHNL0SYNCHSW_SW_TRIG(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0SYNCHSW, SW_TRIG, __x)
+#define MCDE_CHNL1SYNCHSW 0x0000062C
+#define MCDE_CHNL1SYNCHSW_SW_TRIG_SHIFT 0
+#define MCDE_CHNL1SYNCHSW_SW_TRIG_MASK 0x00000001
+#define MCDE_CHNL1SYNCHSW_SW_TRIG(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1SYNCHSW, SW_TRIG, __x)
+#define MCDE_CHNL2SYNCHSW 0x0000064C
+#define MCDE_CHNL2SYNCHSW_SW_TRIG_SHIFT 0
+#define MCDE_CHNL2SYNCHSW_SW_TRIG_MASK 0x00000001
+#define MCDE_CHNL2SYNCHSW_SW_TRIG(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2SYNCHSW, SW_TRIG, __x)
+#define MCDE_CHNL3SYNCHSW 0x0000066C
+#define MCDE_CHNL3SYNCHSW_SW_TRIG_SHIFT 0
+#define MCDE_CHNL3SYNCHSW_SW_TRIG_MASK 0x00000001
+#define MCDE_CHNL3SYNCHSW_SW_TRIG(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3SYNCHSW, SW_TRIG, __x)
+#define MCDE_CHNL0BCKGNDCOL 0x00000610
+#define MCDE_CHNL0BCKGNDCOL_GROUPOFFSET 0x20
+#define MCDE_CHNL0BCKGNDCOL_B_SHIFT 0
+#define MCDE_CHNL0BCKGNDCOL_B_MASK 0x000000FF
+#define MCDE_CHNL0BCKGNDCOL_B(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0BCKGNDCOL, B, __x)
+#define MCDE_CHNL0BCKGNDCOL_G_SHIFT 8
+#define MCDE_CHNL0BCKGNDCOL_G_MASK 0x0000FF00
+#define MCDE_CHNL0BCKGNDCOL_G(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0BCKGNDCOL, G, __x)
+#define MCDE_CHNL0BCKGNDCOL_R_SHIFT 16
+#define MCDE_CHNL0BCKGNDCOL_R_MASK 0x00FF0000
+#define MCDE_CHNL0BCKGNDCOL_R(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0BCKGNDCOL, R, __x)
+#define MCDE_CHNL1BCKGNDCOL 0x00000630
+#define MCDE_CHNL1BCKGNDCOL_B_SHIFT 0
+#define MCDE_CHNL1BCKGNDCOL_B_MASK 0x000000FF
+#define MCDE_CHNL1BCKGNDCOL_B(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1BCKGNDCOL, B, __x)
+#define MCDE_CHNL1BCKGNDCOL_G_SHIFT 8
+#define MCDE_CHNL1BCKGNDCOL_G_MASK 0x0000FF00
+#define MCDE_CHNL1BCKGNDCOL_G(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1BCKGNDCOL, G, __x)
+#define MCDE_CHNL1BCKGNDCOL_R_SHIFT 16
+#define MCDE_CHNL1BCKGNDCOL_R_MASK 0x00FF0000
+#define MCDE_CHNL1BCKGNDCOL_R(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1BCKGNDCOL, R, __x)
+#define MCDE_CHNL2BCKGNDCOL 0x00000650
+#define MCDE_CHNL2BCKGNDCOL_B_SHIFT 0
+#define MCDE_CHNL2BCKGNDCOL_B_MASK 0x000000FF
+#define MCDE_CHNL2BCKGNDCOL_B(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2BCKGNDCOL, B, __x)
+#define MCDE_CHNL2BCKGNDCOL_G_SHIFT 8
+#define MCDE_CHNL2BCKGNDCOL_G_MASK 0x0000FF00
+#define MCDE_CHNL2BCKGNDCOL_G(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2BCKGNDCOL, G, __x)
+#define MCDE_CHNL2BCKGNDCOL_R_SHIFT 16
+#define MCDE_CHNL2BCKGNDCOL_R_MASK 0x00FF0000
+#define MCDE_CHNL2BCKGNDCOL_R(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2BCKGNDCOL, R, __x)
+#define MCDE_CHNL3BCKGNDCOL 0x00000670
+#define MCDE_CHNL3BCKGNDCOL_B_SHIFT 0
+#define MCDE_CHNL3BCKGNDCOL_B_MASK 0x000000FF
+#define MCDE_CHNL3BCKGNDCOL_B(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3BCKGNDCOL, B, __x)
+#define MCDE_CHNL3BCKGNDCOL_G_SHIFT 8
+#define MCDE_CHNL3BCKGNDCOL_G_MASK 0x0000FF00
+#define MCDE_CHNL3BCKGNDCOL_G(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3BCKGNDCOL, G, __x)
+#define MCDE_CHNL3BCKGNDCOL_R_SHIFT 16
+#define MCDE_CHNL3BCKGNDCOL_R_MASK 0x00FF0000
+#define MCDE_CHNL3BCKGNDCOL_R(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3BCKGNDCOL, R, __x)
+#define MCDE_CHNL0MUXING 0x00000614
+#define MCDE_CHNL0MUXING_GROUPOFFSET 0x20
+#define MCDE_CHNL0MUXING_FIFO_ID_SHIFT 0
+#define MCDE_CHNL0MUXING_FIFO_ID_MASK 0x00000007
+#define MCDE_CHNL0MUXING_FIFO_ID_FIFO_A 0
+#define MCDE_CHNL0MUXING_FIFO_ID_FIFO_B 1
+#define MCDE_CHNL0MUXING_FIFO_ID_FIFO_C0 2
+#define MCDE_CHNL0MUXING_FIFO_ID_FIFO_C1 3
+#define MCDE_CHNL0MUXING_FIFO_ID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0MUXING, FIFO_ID, MCDE_CHNL0MUXING_FIFO_ID_##__x)
+#define MCDE_CHNL0MUXING_FIFO_ID(__x) \
+ MCDE_VAL2REG(MCDE_CHNL0MUXING, FIFO_ID, __x)
+#define MCDE_CHNL1MUXING 0x00000634
+#define MCDE_CHNL1MUXING_FIFO_ID_SHIFT 0
+#define MCDE_CHNL1MUXING_FIFO_ID_MASK 0x00000007
+#define MCDE_CHNL1MUXING_FIFO_ID_FIFO_A 0
+#define MCDE_CHNL1MUXING_FIFO_ID_FIFO_B 1
+#define MCDE_CHNL1MUXING_FIFO_ID_FIFO_C0 2
+#define MCDE_CHNL1MUXING_FIFO_ID_FIFO_C1 3
+#define MCDE_CHNL1MUXING_FIFO_ID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1MUXING, FIFO_ID, MCDE_CHNL1MUXING_FIFO_ID_##__x)
+#define MCDE_CHNL1MUXING_FIFO_ID(__x) \
+ MCDE_VAL2REG(MCDE_CHNL1MUXING, FIFO_ID, __x)
+#define MCDE_CHNL2MUXING 0x00000654
+#define MCDE_CHNL2MUXING_FIFO_ID_SHIFT 0
+#define MCDE_CHNL2MUXING_FIFO_ID_MASK 0x00000007
+#define MCDE_CHNL2MUXING_FIFO_ID_FIFO_A 0
+#define MCDE_CHNL2MUXING_FIFO_ID_FIFO_B 1
+#define MCDE_CHNL2MUXING_FIFO_ID_FIFO_C0 2
+#define MCDE_CHNL2MUXING_FIFO_ID_FIFO_C1 3
+#define MCDE_CHNL2MUXING_FIFO_ID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2MUXING, FIFO_ID, MCDE_CHNL2MUXING_FIFO_ID_##__x)
+#define MCDE_CHNL2MUXING_FIFO_ID(__x) \
+ MCDE_VAL2REG(MCDE_CHNL2MUXING, FIFO_ID, __x)
+#define MCDE_CHNL3MUXING 0x00000674
+#define MCDE_CHNL3MUXING_FIFO_ID_SHIFT 0
+#define MCDE_CHNL3MUXING_FIFO_ID_MASK 0x00000007
+#define MCDE_CHNL3MUXING_FIFO_ID_FIFO_A 0
+#define MCDE_CHNL3MUXING_FIFO_ID_FIFO_B 1
+#define MCDE_CHNL3MUXING_FIFO_ID_FIFO_C0 2
+#define MCDE_CHNL3MUXING_FIFO_ID_FIFO_C1 3
+#define MCDE_CHNL3MUXING_FIFO_ID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3MUXING, FIFO_ID, MCDE_CHNL3MUXING_FIFO_ID_##__x)
+#define MCDE_CHNL3MUXING_FIFO_ID(__x) \
+ MCDE_VAL2REG(MCDE_CHNL3MUXING, FIFO_ID, __x)
+#define MCDE_CRA0 0x00000800
+#define MCDE_CRA0_GROUPOFFSET 0x200
+#define MCDE_CRA0_FLOEN_SHIFT 0
+#define MCDE_CRA0_FLOEN_MASK 0x00000001
+#define MCDE_CRA0_FLOEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, FLOEN, __x)
+#define MCDE_CRA0_BLENDEN_SHIFT 2
+#define MCDE_CRA0_BLENDEN_MASK 0x00000004
+#define MCDE_CRA0_BLENDEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, BLENDEN, __x)
+#define MCDE_CRA0_AFLICKEN_SHIFT 3
+#define MCDE_CRA0_AFLICKEN_MASK 0x00000008
+#define MCDE_CRA0_AFLICKEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, AFLICKEN, __x)
+#define MCDE_CRA0_PALEN_SHIFT 4
+#define MCDE_CRA0_PALEN_MASK 0x00000010
+#define MCDE_CRA0_PALEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, PALEN, __x)
+#define MCDE_CRA0_DITHEN_SHIFT 5
+#define MCDE_CRA0_DITHEN_MASK 0x00000020
+#define MCDE_CRA0_DITHEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, DITHEN, __x)
+#define MCDE_CRA0_GAMEN_SHIFT 6
+#define MCDE_CRA0_GAMEN_MASK 0x00000040
+#define MCDE_CRA0_GAMEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, GAMEN, __x)
+#define MCDE_CRA0_KEYCTRL_SHIFT 7
+#define MCDE_CRA0_KEYCTRL_MASK 0x00000380
+#define MCDE_CRA0_KEYCTRL_OFF 0
+#define MCDE_CRA0_KEYCTRL_ALPHA_RGB 1
+#define MCDE_CRA0_KEYCTRL_RGB 2
+#define MCDE_CRA0_KEYCTRL_FALPHA_FRGB 4
+#define MCDE_CRA0_KEYCTRL_FRGB 5
+#define MCDE_CRA0_KEYCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, KEYCTRL, MCDE_CRA0_KEYCTRL_##__x)
+#define MCDE_CRA0_KEYCTRL(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, KEYCTRL, __x)
+#define MCDE_CRA0_BLENDCTRL_SHIFT 10
+#define MCDE_CRA0_BLENDCTRL_MASK 0x00000400
+#define MCDE_CRA0_BLENDCTRL_SOURCE 0
+#define MCDE_CRA0_BLENDCTRL_CONSTANT 1
+#define MCDE_CRA0_BLENDCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, BLENDCTRL, MCDE_CRA0_BLENDCTRL_##__x)
+#define MCDE_CRA0_BLENDCTRL(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, BLENDCTRL, __x)
+#define MCDE_CRA0_FLICKMODE_SHIFT 11
+#define MCDE_CRA0_FLICKMODE_MASK 0x00001800
+#define MCDE_CRA0_FLICKMODE_FORCE_FILTER_0 0
+#define MCDE_CRA0_FLICKMODE_ADAPTIVE 1
+#define MCDE_CRA0_FLICKMODE_TEST_MODE 2
+#define MCDE_CRA0_FLICKMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, FLICKMODE, MCDE_CRA0_FLICKMODE_##__x)
+#define MCDE_CRA0_FLICKMODE(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, FLICKMODE, __x)
+#define MCDE_CRA0_FLOCKFORMAT_SHIFT 13
+#define MCDE_CRA0_FLOCKFORMAT_MASK 0x00002000
+#define MCDE_CRA0_FLOCKFORMAT_YCBCR 0
+#define MCDE_CRA0_FLOCKFORMAT_RGB 1
+#define MCDE_CRA0_FLOCKFORMAT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, FLOCKFORMAT, MCDE_CRA0_FLOCKFORMAT_##__x)
+#define MCDE_CRA0_FLOCKFORMAT(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, FLOCKFORMAT, __x)
+#define MCDE_CRA0_PALMODE_SHIFT 14
+#define MCDE_CRA0_PALMODE_MASK 0x00004000
+#define MCDE_CRA0_PALMODE_PALETTE 0
+#define MCDE_CRA0_PALMODE_GAMMA 1
+#define MCDE_CRA0_PALMODE(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, PALMODE, __x)
+#define MCDE_CRA0_OLEDEN_SHIFT 15
+#define MCDE_CRA0_OLEDEN_MASK 0x00008000
+#define MCDE_CRA0_OLEDEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, OLEDEN, __x)
+#define MCDE_CRA0_ALPHABLEND_SHIFT 16
+#define MCDE_CRA0_ALPHABLEND_MASK 0x00FF0000
+#define MCDE_CRA0_ALPHABLEND(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, ALPHABLEND, __x)
+#define MCDE_CRA0_ROTEN_SHIFT 24
+#define MCDE_CRA0_ROTEN_MASK 0x01000000
+#define MCDE_CRA0_ROTEN(__x) \
+ MCDE_VAL2REG(MCDE_CRA0, ROTEN, __x)
+#define MCDE_CRB0 0x00000A00
+#define MCDE_CRB0_FLOEN_SHIFT 0
+#define MCDE_CRB0_FLOEN_MASK 0x00000001
+#define MCDE_CRB0_FLOEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, FLOEN, __x)
+#define MCDE_CRB0_BLENDEN_SHIFT 2
+#define MCDE_CRB0_BLENDEN_MASK 0x00000004
+#define MCDE_CRB0_BLENDEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, BLENDEN, __x)
+#define MCDE_CRB0_AFLICKEN_SHIFT 3
+#define MCDE_CRB0_AFLICKEN_MASK 0x00000008
+#define MCDE_CRB0_AFLICKEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, AFLICKEN, __x)
+#define MCDE_CRB0_PALEN_SHIFT 4
+#define MCDE_CRB0_PALEN_MASK 0x00000010
+#define MCDE_CRB0_PALEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, PALEN, __x)
+#define MCDE_CRB0_DITHEN_SHIFT 5
+#define MCDE_CRB0_DITHEN_MASK 0x00000020
+#define MCDE_CRB0_DITHEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, DITHEN, __x)
+#define MCDE_CRB0_GAMEN_SHIFT 6
+#define MCDE_CRB0_GAMEN_MASK 0x00000040
+#define MCDE_CRB0_GAMEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, GAMEN, __x)
+#define MCDE_CRB0_KEYCTRL_SHIFT 7
+#define MCDE_CRB0_KEYCTRL_MASK 0x00000380
+#define MCDE_CRB0_KEYCTRL_OFF 0
+#define MCDE_CRB0_KEYCTRL_ALPHA_RGB 1
+#define MCDE_CRB0_KEYCTRL_RGB 2
+#define MCDE_CRB0_KEYCTRL_FALPHA_FRGB 4
+#define MCDE_CRB0_KEYCTRL_FRGB 5
+#define MCDE_CRB0_KEYCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, KEYCTRL, MCDE_CRB0_KEYCTRL_##__x)
+#define MCDE_CRB0_KEYCTRL(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, KEYCTRL, __x)
+#define MCDE_CRB0_BLENDCTRL_SHIFT 10
+#define MCDE_CRB0_BLENDCTRL_MASK 0x00000400
+#define MCDE_CRB0_BLENDCTRL_SOURCE 0
+#define MCDE_CRB0_BLENDCTRL_CONSTANT 1
+#define MCDE_CRB0_BLENDCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, BLENDCTRL, MCDE_CRB0_BLENDCTRL_##__x)
+#define MCDE_CRB0_BLENDCTRL(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, BLENDCTRL, __x)
+#define MCDE_CRB0_FLICKMODE_SHIFT 11
+#define MCDE_CRB0_FLICKMODE_MASK 0x00001800
+#define MCDE_CRB0_FLICKMODE_FORCE_FILTER_0 0
+#define MCDE_CRB0_FLICKMODE_ADAPTIVE 1
+#define MCDE_CRB0_FLICKMODE_TEST_MODE 2
+#define MCDE_CRB0_FLICKMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, FLICKMODE, MCDE_CRB0_FLICKMODE_##__x)
+#define MCDE_CRB0_FLICKMODE(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, FLICKMODE, __x)
+#define MCDE_CRB0_FLOCKFORMAT_SHIFT 13
+#define MCDE_CRB0_FLOCKFORMAT_MASK 0x00002000
+#define MCDE_CRB0_FLOCKFORMAT_YCBCR 0
+#define MCDE_CRB0_FLOCKFORMAT_RGB 1
+#define MCDE_CRB0_FLOCKFORMAT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, FLOCKFORMAT, MCDE_CRB0_FLOCKFORMAT_##__x)
+#define MCDE_CRB0_FLOCKFORMAT(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, FLOCKFORMAT, __x)
+#define MCDE_CRB0_PALMODE_SHIFT 14
+#define MCDE_CRB0_PALMODE_MASK 0x00004000
+#define MCDE_CRB0_PALMODE_PALETTE 0
+#define MCDE_CRB0_PALMODE_GAMMA 1
+#define MCDE_CRB0_PALMODE(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, PALMODE, __x)
+#define MCDE_CRB0_OLEDEN_SHIFT 15
+#define MCDE_CRB0_OLEDEN_MASK 0x00008000
+#define MCDE_CRB0_OLEDEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, OLEDEN, __x)
+#define MCDE_CRB0_ALPHABLEND_SHIFT 16
+#define MCDE_CRB0_ALPHABLEND_MASK 0x00FF0000
+#define MCDE_CRB0_ALPHABLEND(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, ALPHABLEND, __x)
+#define MCDE_CRB0_ROTEN_SHIFT 24
+#define MCDE_CRB0_ROTEN_MASK 0x01000000
+#define MCDE_CRB0_ROTEN(__x) \
+ MCDE_VAL2REG(MCDE_CRB0, ROTEN, __x)
+#define MCDE_CRA1 0x00000804
+#define MCDE_CRA1_GROUPOFFSET 0x200
+#define MCDE_CRA1_PCD_SHIFT 0
+#define MCDE_CRA1_PCD_MASK 0x000003FF
+#define MCDE_CRA1_PCD(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, PCD, __x)
+#define MCDE_CRA1_CLKSEL_SHIFT 10
+#define MCDE_CRA1_CLKSEL_MASK 0x00001C00
+#define MCDE_CRA1_CLKSEL_CLKPLL72 0
+#define MCDE_CRA1_CLKSEL_CLKPLL27 2
+#define MCDE_CRA1_CLKSEL_TV1CLK 3
+#define MCDE_CRA1_CLKSEL_TV2CLK 4
+#define MCDE_CRA1_CLKSEL_MCDECLK 5
+#define MCDE_CRA1_CLKSEL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CLKSEL, MCDE_CRA1_CLKSEL_##__x)
+#define MCDE_CRA1_CLKSEL(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CLKSEL, __x)
+#define MCDE_CRA1_CDWIN_SHIFT 13
+#define MCDE_CRA1_CDWIN_MASK 0x0001E000
+#define MCDE_CRA1_CDWIN_8BPP_C1 0
+#define MCDE_CRA1_CDWIN_12BPP_C1 1
+#define MCDE_CRA1_CDWIN_12BPP_C2 2
+#define MCDE_CRA1_CDWIN_16BPP_C1 3
+#define MCDE_CRA1_CDWIN_16BPP_C2 4
+#define MCDE_CRA1_CDWIN_16BPP_C3 5
+#define MCDE_CRA1_CDWIN_18BPP_C1 6
+#define MCDE_CRA1_CDWIN_18BPP_C2 7
+#define MCDE_CRA1_CDWIN_24BPP 8
+#define MCDE_CRA1_CDWIN_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CDWIN, MCDE_CRA1_CDWIN_##__x)
+#define MCDE_CRA1_CDWIN(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CDWIN, __x)
+#define MCDE_CRA1_OUTBPP_SHIFT 25
+#define MCDE_CRA1_OUTBPP_MASK 0x1E000000
+#define MCDE_CRA1_OUTBPP_MONO1 0
+#define MCDE_CRA1_OUTBPP_MONO2 1
+#define MCDE_CRA1_OUTBPP_MONO4 2
+#define MCDE_CRA1_OUTBPP_MONO8 3
+#define MCDE_CRA1_OUTBPP_8BPP 4
+#define MCDE_CRA1_OUTBPP_12BPP 5
+#define MCDE_CRA1_OUTBPP_15BPP 6
+#define MCDE_CRA1_OUTBPP_16BPP 7
+#define MCDE_CRA1_OUTBPP_18BPP 8
+#define MCDE_CRA1_OUTBPP_24BPP 9
+#define MCDE_CRA1_OUTBPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, OUTBPP, MCDE_CRA1_OUTBPP_##__x)
+#define MCDE_CRA1_OUTBPP(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, OUTBPP, __x)
+#define MCDE_CRA1_BCD_SHIFT 29
+#define MCDE_CRA1_BCD_MASK 0x20000000
+#define MCDE_CRA1_BCD(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, BCD, __x)
+#define MCDE_CRA1_CLKTYPE_SHIFT 30
+#define MCDE_CRA1_CLKTYPE_MASK 0x40000000
+#define MCDE_CRA1_CLKTYPE_TVXCLKSEL0 0
+#define MCDE_CRA1_CLKTYPE_TVXCLKSEL1 1
+#define MCDE_CRA1_CLKTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CLKTYPE, MCDE_CRA1_CLKTYPE_##__x)
+#define MCDE_CRA1_CLKTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CRA1, CLKTYPE, __x)
+#define MCDE_CRB1 0x00000A04
+#define MCDE_CRB1_PCD_SHIFT 0
+#define MCDE_CRB1_PCD_MASK 0x000003FF
+#define MCDE_CRB1_PCD(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, PCD, __x)
+#define MCDE_CRB1_CLKSEL_SHIFT 10
+#define MCDE_CRB1_CLKSEL_MASK 0x00001C00
+#define MCDE_CRB1_CLKSEL_CLKPLL72 0
+#define MCDE_CRB1_CLKSEL_CLKPLL27 2
+#define MCDE_CRB1_CLKSEL_TV1CLK 3
+#define MCDE_CRB1_CLKSEL_TV2CLK 4
+#define MCDE_CRB1_CLKSEL_MCDECLK 5
+#define MCDE_CRB1_CLKSEL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CLKSEL, MCDE_CRB1_CLKSEL_##__x)
+#define MCDE_CRB1_CLKSEL(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CLKSEL, __x)
+#define MCDE_CRB1_CDWIN_SHIFT 13
+#define MCDE_CRB1_CDWIN_MASK 0x0001E000
+#define MCDE_CRB1_CDWIN_8BPP_C1 0
+#define MCDE_CRB1_CDWIN_12BPP_C1 1
+#define MCDE_CRB1_CDWIN_12BPP_C2 2
+#define MCDE_CRB1_CDWIN_16BPP_C1 3
+#define MCDE_CRB1_CDWIN_16BPP_C2 4
+#define MCDE_CRB1_CDWIN_16BPP_C3 5
+#define MCDE_CRB1_CDWIN_18BPP_C1 6
+#define MCDE_CRB1_CDWIN_18BPP_C2 7
+#define MCDE_CRB1_CDWIN_24BPP 8
+#define MCDE_CRB1_CDWIN_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CDWIN, MCDE_CRB1_CDWIN_##__x)
+#define MCDE_CRB1_CDWIN(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CDWIN, __x)
+#define MCDE_CRB1_OUTBPP_SHIFT 25
+#define MCDE_CRB1_OUTBPP_MASK 0x1E000000
+#define MCDE_CRB1_OUTBPP_MONO1 0
+#define MCDE_CRB1_OUTBPP_MONO2 1
+#define MCDE_CRB1_OUTBPP_MONO4 2
+#define MCDE_CRB1_OUTBPP_MONO8 3
+#define MCDE_CRB1_OUTBPP_8BPP 4
+#define MCDE_CRB1_OUTBPP_12BPP 5
+#define MCDE_CRB1_OUTBPP_15BPP 6
+#define MCDE_CRB1_OUTBPP_16BPP 7
+#define MCDE_CRB1_OUTBPP_18BPP 8
+#define MCDE_CRB1_OUTBPP_24BPP 9
+#define MCDE_CRB1_OUTBPP_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, OUTBPP, MCDE_CRB1_OUTBPP_##__x)
+#define MCDE_CRB1_OUTBPP(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, OUTBPP, __x)
+#define MCDE_CRB1_BCD_SHIFT 29
+#define MCDE_CRB1_BCD_MASK 0x20000000
+#define MCDE_CRB1_BCD(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, BCD, __x)
+#define MCDE_CRB1_CLKTYPE_SHIFT 30
+#define MCDE_CRB1_CLKTYPE_MASK 0x40000000
+#define MCDE_CRB1_CLKTYPE_TVXCLKSEL0 0
+#define MCDE_CRB1_CLKTYPE_TVXCLKSEL1 1
+#define MCDE_CRB1_CLKTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CLKTYPE, MCDE_CRB1_CLKTYPE_##__x)
+#define MCDE_CRB1_CLKTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CRB1, CLKTYPE, __x)
+#define MCDE_COLKEYA 0x00000808
+#define MCDE_COLKEYA_GROUPOFFSET 0x200
+#define MCDE_COLKEYA_KEYB_SHIFT 0
+#define MCDE_COLKEYA_KEYB_MASK 0x000000FF
+#define MCDE_COLKEYA_KEYB(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYA, KEYB, __x)
+#define MCDE_COLKEYA_KEYG_SHIFT 8
+#define MCDE_COLKEYA_KEYG_MASK 0x0000FF00
+#define MCDE_COLKEYA_KEYG(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYA, KEYG, __x)
+#define MCDE_COLKEYA_KEYR_SHIFT 16
+#define MCDE_COLKEYA_KEYR_MASK 0x00FF0000
+#define MCDE_COLKEYA_KEYR(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYA, KEYR, __x)
+#define MCDE_COLKEYA_KEYA_SHIFT 24
+#define MCDE_COLKEYA_KEYA_MASK 0xFF000000
+#define MCDE_COLKEYA_KEYA(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYA, KEYA, __x)
+#define MCDE_COLKEYB 0x00000A08
+#define MCDE_COLKEYB_KEYB_SHIFT 0
+#define MCDE_COLKEYB_KEYB_MASK 0x000000FF
+#define MCDE_COLKEYB_KEYB(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYB, KEYB, __x)
+#define MCDE_COLKEYB_KEYG_SHIFT 8
+#define MCDE_COLKEYB_KEYG_MASK 0x0000FF00
+#define MCDE_COLKEYB_KEYG(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYB, KEYG, __x)
+#define MCDE_COLKEYB_KEYR_SHIFT 16
+#define MCDE_COLKEYB_KEYR_MASK 0x00FF0000
+#define MCDE_COLKEYB_KEYR(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYB, KEYR, __x)
+#define MCDE_COLKEYB_KEYA_SHIFT 24
+#define MCDE_COLKEYB_KEYA_MASK 0xFF000000
+#define MCDE_COLKEYB_KEYA(__x) \
+ MCDE_VAL2REG(MCDE_COLKEYB, KEYA, __x)
+#define MCDE_FCOLKEYA 0x0000080C
+#define MCDE_FCOLKEYA_GROUPOFFSET 0x200
+#define MCDE_FCOLKEYA_FKEYB_SHIFT 0
+#define MCDE_FCOLKEYA_FKEYB_MASK 0x000000FF
+#define MCDE_FCOLKEYA_FKEYB(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYA, FKEYB, __x)
+#define MCDE_FCOLKEYA_FKEYG_SHIFT 8
+#define MCDE_FCOLKEYA_FKEYG_MASK 0x0000FF00
+#define MCDE_FCOLKEYA_FKEYG(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYA, FKEYG, __x)
+#define MCDE_FCOLKEYA_FKEYR_SHIFT 16
+#define MCDE_FCOLKEYA_FKEYR_MASK 0x00FF0000
+#define MCDE_FCOLKEYA_FKEYR(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYA, FKEYR, __x)
+#define MCDE_FCOLKEYA_FKEYA_SHIFT 24
+#define MCDE_FCOLKEYA_FKEYA_MASK 0xFF000000
+#define MCDE_FCOLKEYA_FKEYA(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYA, FKEYA, __x)
+#define MCDE_FCOLKEYB 0x00000A0C
+#define MCDE_FCOLKEYB_FKEYB_SHIFT 0
+#define MCDE_FCOLKEYB_FKEYB_MASK 0x000000FF
+#define MCDE_FCOLKEYB_FKEYB(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYB, FKEYB, __x)
+#define MCDE_FCOLKEYB_FKEYG_SHIFT 8
+#define MCDE_FCOLKEYB_FKEYG_MASK 0x0000FF00
+#define MCDE_FCOLKEYB_FKEYG(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYB, FKEYG, __x)
+#define MCDE_FCOLKEYB_FKEYR_SHIFT 16
+#define MCDE_FCOLKEYB_FKEYR_MASK 0x00FF0000
+#define MCDE_FCOLKEYB_FKEYR(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYB, FKEYR, __x)
+#define MCDE_FCOLKEYB_FKEYA_SHIFT 24
+#define MCDE_FCOLKEYB_FKEYA_MASK 0xFF000000
+#define MCDE_FCOLKEYB_FKEYA(__x) \
+ MCDE_VAL2REG(MCDE_FCOLKEYB, FKEYA, __x)
+#define MCDE_RGBCONV1A 0x00000810
+#define MCDE_RGBCONV1A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV1A_YR_GREEN_SHIFT 0
+#define MCDE_RGBCONV1A_YR_GREEN_MASK 0x000007FF
+#define MCDE_RGBCONV1A_YR_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV1A, YR_GREEN, __x)
+#define MCDE_RGBCONV1A_YR_RED_SHIFT 16
+#define MCDE_RGBCONV1A_YR_RED_MASK 0x07FF0000
+#define MCDE_RGBCONV1A_YR_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV1A, YR_RED, __x)
+#define MCDE_RGBCONV1B 0x00000A10
+#define MCDE_RGBCONV1B_YR_GREEN_SHIFT 0
+#define MCDE_RGBCONV1B_YR_GREEN_MASK 0x000007FF
+#define MCDE_RGBCONV1B_YR_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV1B, YR_GREEN, __x)
+#define MCDE_RGBCONV1B_YR_RED_SHIFT 16
+#define MCDE_RGBCONV1B_YR_RED_MASK 0x07FF0000
+#define MCDE_RGBCONV1B_YR_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV1B, YR_RED, __x)
+#define MCDE_RGBCONV2A 0x00000814
+#define MCDE_RGBCONV2A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV2A_CR_RED_SHIFT 0
+#define MCDE_RGBCONV2A_CR_RED_MASK 0x000007FF
+#define MCDE_RGBCONV2A_CR_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV2A, CR_RED, __x)
+#define MCDE_RGBCONV2A_YR_BLUE_SHIFT 16
+#define MCDE_RGBCONV2A_YR_BLUE_MASK 0x07FF0000
+#define MCDE_RGBCONV2A_YR_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV2A, YR_BLUE, __x)
+#define MCDE_RGBCONV2B 0x00000A14
+#define MCDE_RGBCONV2B_CR_RED_SHIFT 0
+#define MCDE_RGBCONV2B_CR_RED_MASK 0x000007FF
+#define MCDE_RGBCONV2B_CR_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV2B, CR_RED, __x)
+#define MCDE_RGBCONV2B_YR_BLUE_SHIFT 16
+#define MCDE_RGBCONV2B_YR_BLUE_MASK 0x07FF0000
+#define MCDE_RGBCONV2B_YR_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV2B, YR_BLUE, __x)
+#define MCDE_RGBCONV3A 0x00000818
+#define MCDE_RGBCONV3A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV3A_CR_BLUE_SHIFT 0
+#define MCDE_RGBCONV3A_CR_BLUE_MASK 0x000007FF
+#define MCDE_RGBCONV3A_CR_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV3A, CR_BLUE, __x)
+#define MCDE_RGBCONV3A_CR_GREEN_SHIFT 16
+#define MCDE_RGBCONV3A_CR_GREEN_MASK 0x07FF0000
+#define MCDE_RGBCONV3A_CR_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV3A, CR_GREEN, __x)
+#define MCDE_RGBCONV3B 0x00000A18
+#define MCDE_RGBCONV3B_CR_BLUE_SHIFT 0
+#define MCDE_RGBCONV3B_CR_BLUE_MASK 0x000007FF
+#define MCDE_RGBCONV3B_CR_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV3B, CR_BLUE, __x)
+#define MCDE_RGBCONV3B_CR_GREEN_SHIFT 16
+#define MCDE_RGBCONV3B_CR_GREEN_MASK 0x07FF0000
+#define MCDE_RGBCONV3B_CR_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV3B, CR_GREEN, __x)
+#define MCDE_RGBCONV4A 0x0000081C
+#define MCDE_RGBCONV4A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV4A_CB_GREEN_SHIFT 0
+#define MCDE_RGBCONV4A_CB_GREEN_MASK 0x000007FF
+#define MCDE_RGBCONV4A_CB_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV4A, CB_GREEN, __x)
+#define MCDE_RGBCONV4A_CB_RED_SHIFT 16
+#define MCDE_RGBCONV4A_CB_RED_MASK 0x07FF0000
+#define MCDE_RGBCONV4A_CB_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV4A, CB_RED, __x)
+#define MCDE_RGBCONV4B 0x00000A1C
+#define MCDE_RGBCONV4B_CB_GREEN_SHIFT 0
+#define MCDE_RGBCONV4B_CB_GREEN_MASK 0x000007FF
+#define MCDE_RGBCONV4B_CB_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV4B, CB_GREEN, __x)
+#define MCDE_RGBCONV4B_CB_RED_SHIFT 16
+#define MCDE_RGBCONV4B_CB_RED_MASK 0x07FF0000
+#define MCDE_RGBCONV4B_CB_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV4B, CB_RED, __x)
+#define MCDE_RGBCONV5A 0x00000820
+#define MCDE_RGBCONV5A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV5A_OFF_RED_SHIFT 0
+#define MCDE_RGBCONV5A_OFF_RED_MASK 0x000007FF
+#define MCDE_RGBCONV5A_OFF_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV5A, OFF_RED, __x)
+#define MCDE_RGBCONV5A_CB_BLUE_SHIFT 16
+#define MCDE_RGBCONV5A_CB_BLUE_MASK 0x07FF0000
+#define MCDE_RGBCONV5A_CB_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV5A, CB_BLUE, __x)
+#define MCDE_RGBCONV5B 0x00000A20
+#define MCDE_RGBCONV5B_OFF_RED_SHIFT 0
+#define MCDE_RGBCONV5B_OFF_RED_MASK 0x000007FF
+#define MCDE_RGBCONV5B_OFF_RED(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV5B, OFF_RED, __x)
+#define MCDE_RGBCONV5B_CB_BLUE_SHIFT 16
+#define MCDE_RGBCONV5B_CB_BLUE_MASK 0x07FF0000
+#define MCDE_RGBCONV5B_CB_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV5B, CB_BLUE, __x)
+#define MCDE_RGBCONV6A 0x00000824
+#define MCDE_RGBCONV6A_GROUPOFFSET 0x200
+#define MCDE_RGBCONV6A_OFF_BLUE_SHIFT 0
+#define MCDE_RGBCONV6A_OFF_BLUE_MASK 0x000007FF
+#define MCDE_RGBCONV6A_OFF_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV6A, OFF_BLUE, __x)
+#define MCDE_RGBCONV6A_OFF_GREEN_SHIFT 16
+#define MCDE_RGBCONV6A_OFF_GREEN_MASK 0x07FF0000
+#define MCDE_RGBCONV6A_OFF_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV6A, OFF_GREEN, __x)
+#define MCDE_RGBCONV6B 0x00000A24
+#define MCDE_RGBCONV6B_OFF_BLUE_SHIFT 0
+#define MCDE_RGBCONV6B_OFF_BLUE_MASK 0x000007FF
+#define MCDE_RGBCONV6B_OFF_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV6B, OFF_BLUE, __x)
+#define MCDE_RGBCONV6B_OFF_GREEN_SHIFT 16
+#define MCDE_RGBCONV6B_OFF_GREEN_MASK 0x07FF0000
+#define MCDE_RGBCONV6B_OFF_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_RGBCONV6B, OFF_GREEN, __x)
+#define MCDE_FFCOEF0 0x00000828
+#define MCDE_FFCOEF0_COEFF0_N1_SHIFT 0
+#define MCDE_FFCOEF0_COEFF0_N1_MASK 0x000000FF
+#define MCDE_FFCOEF0_COEFF0_N1(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF0, COEFF0_N1, __x)
+#define MCDE_FFCOEF0_COEFF0_N2_SHIFT 8
+#define MCDE_FFCOEF0_COEFF0_N2_MASK 0x0000FF00
+#define MCDE_FFCOEF0_COEFF0_N2(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF0, COEFF0_N2, __x)
+#define MCDE_FFCOEF0_COEFF0_N3_SHIFT 16
+#define MCDE_FFCOEF0_COEFF0_N3_MASK 0x00FF0000
+#define MCDE_FFCOEF0_COEFF0_N3(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF0, COEFF0_N3, __x)
+#define MCDE_FFCOEF0_T0_SHIFT 24
+#define MCDE_FFCOEF0_T0_MASK 0x0F000000
+#define MCDE_FFCOEF0_T0(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF0, T0, __x)
+#define MCDE_FFCOEF1 0x0000082C
+#define MCDE_FFCOEF1_COEFF1_N1_SHIFT 0
+#define MCDE_FFCOEF1_COEFF1_N1_MASK 0x000000FF
+#define MCDE_FFCOEF1_COEFF1_N1(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF1, COEFF1_N1, __x)
+#define MCDE_FFCOEF1_COEFF1_N2_SHIFT 8
+#define MCDE_FFCOEF1_COEFF1_N2_MASK 0x0000FF00
+#define MCDE_FFCOEF1_COEFF1_N2(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF1, COEFF1_N2, __x)
+#define MCDE_FFCOEF1_COEFF1_N3_SHIFT 16
+#define MCDE_FFCOEF1_COEFF1_N3_MASK 0x00FF0000
+#define MCDE_FFCOEF1_COEFF1_N3(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF1, COEFF1_N3, __x)
+#define MCDE_FFCOEF1_T1_SHIFT 24
+#define MCDE_FFCOEF1_T1_MASK 0x0F000000
+#define MCDE_FFCOEF1_T1(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF1, T1, __x)
+#define MCDE_FFCOEF2 0x00000830
+#define MCDE_FFCOEF2_COEFF2_N1_SHIFT 0
+#define MCDE_FFCOEF2_COEFF2_N1_MASK 0x000000FF
+#define MCDE_FFCOEF2_COEFF2_N1(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF2, COEFF2_N1, __x)
+#define MCDE_FFCOEF2_COEFF2_N2_SHIFT 8
+#define MCDE_FFCOEF2_COEFF2_N2_MASK 0x0000FF00
+#define MCDE_FFCOEF2_COEFF2_N2(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF2, COEFF2_N2, __x)
+#define MCDE_FFCOEF2_COEFF2_N3_SHIFT 16
+#define MCDE_FFCOEF2_COEFF2_N3_MASK 0x00FF0000
+#define MCDE_FFCOEF2_COEFF2_N3(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF2, COEFF2_N3, __x)
+#define MCDE_FFCOEF2_T2_SHIFT 24
+#define MCDE_FFCOEF2_T2_MASK 0x0F000000
+#define MCDE_FFCOEF2_T2(__x) \
+ MCDE_VAL2REG(MCDE_FFCOEF2, T2, __x)
+#define MCDE_MCDE_WDATAA 0x00000834
+#define MCDE_MCDE_WDATAA_GROUPOFFSET 0x200
+#define MCDE_MCDE_WDATAA_DC_SHIFT 24
+#define MCDE_MCDE_WDATAA_DC_MASK 0x01000000
+#define MCDE_MCDE_WDATAA_DC(__x) \
+ MCDE_VAL2REG(MCDE_MCDE_WDATAA, DC, __x)
+#define MCDE_MCDE_WDATAA_DATAVALUE_SHIFT 0
+#define MCDE_MCDE_WDATAA_DATAVALUE_MASK 0x00FFFFFF
+#define MCDE_MCDE_WDATAA_DATAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_MCDE_WDATAA, DATAVALUE, __x)
+#define MCDE_MCDE_WDATAB 0x00000A34
+#define MCDE_MCDE_WDATAB_DC_SHIFT 24
+#define MCDE_MCDE_WDATAB_DC_MASK 0x01000000
+#define MCDE_MCDE_WDATAB_DC(__x) \
+ MCDE_VAL2REG(MCDE_MCDE_WDATAB, DC, __x)
+#define MCDE_MCDE_WDATAB_DATAVALUE_SHIFT 0
+#define MCDE_MCDE_WDATAB_DATAVALUE_MASK 0x00FFFFFF
+#define MCDE_MCDE_WDATAB_DATAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_MCDE_WDATAB, DATAVALUE, __x)
+#define MCDE_TVCRA 0x00000838
+#define MCDE_TVCRA_GROUPOFFSET 0x200
+#define MCDE_TVCRA_SEL_MOD_SHIFT 0
+#define MCDE_TVCRA_SEL_MOD_MASK 0x00000001
+#define MCDE_TVCRA_SEL_MOD_LCD 0
+#define MCDE_TVCRA_SEL_MOD_TV 1
+#define MCDE_TVCRA_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, SEL_MOD, MCDE_TVCRA_SEL_MOD_##__x)
+#define MCDE_TVCRA_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, SEL_MOD, __x)
+#define MCDE_TVCRA_INTEREN_SHIFT 1
+#define MCDE_TVCRA_INTEREN_MASK 0x00000002
+#define MCDE_TVCRA_INTEREN(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, INTEREN, __x)
+#define MCDE_TVCRA_IFIELD_SHIFT 2
+#define MCDE_TVCRA_IFIELD_MASK 0x00000004
+#define MCDE_TVCRA_IFIELD(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, IFIELD, __x)
+#define MCDE_TVCRA_TVMODE_SHIFT 3
+#define MCDE_TVCRA_TVMODE_MASK 0x00000038
+#define MCDE_TVCRA_TVMODE_SDTV_656P 0
+#define MCDE_TVCRA_TVMODE_SDTV_656P_LE 3
+#define MCDE_TVCRA_TVMODE_SDTV_656P_BE 4
+#define MCDE_TVCRA_TVMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, TVMODE, MCDE_TVCRA_TVMODE_##__x)
+#define MCDE_TVCRA_TVMODE(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, TVMODE, __x)
+#define MCDE_TVCRA_SDTVMODE_SHIFT 6
+#define MCDE_TVCRA_SDTVMODE_MASK 0x000000C0
+#define MCDE_TVCRA_SDTVMODE_Y0CBY1CR 0
+#define MCDE_TVCRA_SDTVMODE_CBY0CRY1 1
+#define MCDE_TVCRA_SDTVMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, SDTVMODE, MCDE_TVCRA_SDTVMODE_##__x)
+#define MCDE_TVCRA_SDTVMODE(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, SDTVMODE, __x)
+#define MCDE_TVCRA_AVRGEN_SHIFT 8
+#define MCDE_TVCRA_AVRGEN_MASK 0x00000100
+#define MCDE_TVCRA_AVRGEN(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, AVRGEN, __x)
+#define MCDE_TVCRA_CKINV_SHIFT 9
+#define MCDE_TVCRA_CKINV_MASK 0x00000200
+#define MCDE_TVCRA_CKINV(__x) \
+ MCDE_VAL2REG(MCDE_TVCRA, CKINV, __x)
+#define MCDE_TVCRB 0x00000A38
+#define MCDE_TVCRB_SEL_MOD_SHIFT 0
+#define MCDE_TVCRB_SEL_MOD_MASK 0x00000001
+#define MCDE_TVCRB_SEL_MOD_LCD 0
+#define MCDE_TVCRB_SEL_MOD_TV 1
+#define MCDE_TVCRB_SEL_MOD_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, SEL_MOD, MCDE_TVCRB_SEL_MOD_##__x)
+#define MCDE_TVCRB_SEL_MOD(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, SEL_MOD, __x)
+#define MCDE_TVCRB_INTEREN_SHIFT 1
+#define MCDE_TVCRB_INTEREN_MASK 0x00000002
+#define MCDE_TVCRB_INTEREN(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, INTEREN, __x)
+#define MCDE_TVCRB_IFIELD_SHIFT 2
+#define MCDE_TVCRB_IFIELD_MASK 0x00000004
+#define MCDE_TVCRB_IFIELD(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, IFIELD, __x)
+#define MCDE_TVCRB_TVMODE_SHIFT 3
+#define MCDE_TVCRB_TVMODE_MASK 0x00000038
+#define MCDE_TVCRB_TVMODE_SDTV_656P 0
+#define MCDE_TVCRB_TVMODE_SDTV_656P_LE 3
+#define MCDE_TVCRB_TVMODE_SDTV_656P_BE 4
+#define MCDE_TVCRB_TVMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, TVMODE, MCDE_TVCRB_TVMODE_##__x)
+#define MCDE_TVCRB_TVMODE(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, TVMODE, __x)
+#define MCDE_TVCRB_SDTVMODE_SHIFT 6
+#define MCDE_TVCRB_SDTVMODE_MASK 0x000000C0
+#define MCDE_TVCRB_SDTVMODE_Y0CBY1CR 0
+#define MCDE_TVCRB_SDTVMODE_CBY0CRY1 1
+#define MCDE_TVCRB_SDTVMODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, SDTVMODE, MCDE_TVCRB_SDTVMODE_##__x)
+#define MCDE_TVCRB_SDTVMODE(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, SDTVMODE, __x)
+#define MCDE_TVCRB_AVRGEN_SHIFT 8
+#define MCDE_TVCRB_AVRGEN_MASK 0x00000100
+#define MCDE_TVCRB_AVRGEN(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, AVRGEN, __x)
+#define MCDE_TVCRB_CKINV_SHIFT 9
+#define MCDE_TVCRB_CKINV_MASK 0x00000200
+#define MCDE_TVCRB_CKINV(__x) \
+ MCDE_VAL2REG(MCDE_TVCRB, CKINV, __x)
+#define MCDE_TVBL1A 0x0000083C
+#define MCDE_TVBL1A_GROUPOFFSET 0x200
+#define MCDE_TVBL1A_BEL1_SHIFT 0
+#define MCDE_TVBL1A_BEL1_MASK 0x000007FF
+#define MCDE_TVBL1A_BEL1(__x) \
+ MCDE_VAL2REG(MCDE_TVBL1A, BEL1, __x)
+#define MCDE_TVBL1A_BSL1_SHIFT 16
+#define MCDE_TVBL1A_BSL1_MASK 0x07FF0000
+#define MCDE_TVBL1A_BSL1(__x) \
+ MCDE_VAL2REG(MCDE_TVBL1A, BSL1, __x)
+#define MCDE_TVBL1B 0x00000A3C
+#define MCDE_TVBL1B_BEL1_SHIFT 0
+#define MCDE_TVBL1B_BEL1_MASK 0x000007FF
+#define MCDE_TVBL1B_BEL1(__x) \
+ MCDE_VAL2REG(MCDE_TVBL1B, BEL1, __x)
+#define MCDE_TVBL1B_BSL1_SHIFT 16
+#define MCDE_TVBL1B_BSL1_MASK 0x07FF0000
+#define MCDE_TVBL1B_BSL1(__x) \
+ MCDE_VAL2REG(MCDE_TVBL1B, BSL1, __x)
+#define MCDE_TVISLA 0x00000840
+#define MCDE_TVISLA_GROUPOFFSET 0x200
+#define MCDE_TVISLA_FSL1_SHIFT 0
+#define MCDE_TVISLA_FSL1_MASK 0x000007FF
+#define MCDE_TVISLA_FSL1(__x) \
+ MCDE_VAL2REG(MCDE_TVISLA, FSL1, __x)
+#define MCDE_TVISLA_FSL2_SHIFT 16
+#define MCDE_TVISLA_FSL2_MASK 0x07FF0000
+#define MCDE_TVISLA_FSL2(__x) \
+ MCDE_VAL2REG(MCDE_TVISLA, FSL2, __x)
+#define MCDE_TVISLB 0x00000A40
+#define MCDE_TVISLB_FSL1_SHIFT 0
+#define MCDE_TVISLB_FSL1_MASK 0x000007FF
+#define MCDE_TVISLB_FSL1(__x) \
+ MCDE_VAL2REG(MCDE_TVISLB, FSL1, __x)
+#define MCDE_TVISLB_FSL2_SHIFT 16
+#define MCDE_TVISLB_FSL2_MASK 0x07FF0000
+#define MCDE_TVISLB_FSL2(__x) \
+ MCDE_VAL2REG(MCDE_TVISLB, FSL2, __x)
+#define MCDE_TVDVOA 0x00000844
+#define MCDE_TVDVOA_GROUPOFFSET 0x200
+#define MCDE_TVDVOA_DVO1_SHIFT 0
+#define MCDE_TVDVOA_DVO1_MASK 0x000007FF
+#define MCDE_TVDVOA_DVO1(__x) \
+ MCDE_VAL2REG(MCDE_TVDVOA, DVO1, __x)
+#define MCDE_TVDVOA_DVO2_SHIFT 16
+#define MCDE_TVDVOA_DVO2_MASK 0x07FF0000
+#define MCDE_TVDVOA_DVO2(__x) \
+ MCDE_VAL2REG(MCDE_TVDVOA, DVO2, __x)
+#define MCDE_TVDVOB 0x00000A44
+#define MCDE_TVDVOB_DVO1_SHIFT 0
+#define MCDE_TVDVOB_DVO1_MASK 0x000007FF
+#define MCDE_TVDVOB_DVO1(__x) \
+ MCDE_VAL2REG(MCDE_TVDVOB, DVO1, __x)
+#define MCDE_TVDVOB_DVO2_SHIFT 16
+#define MCDE_TVDVOB_DVO2_MASK 0x07FF0000
+#define MCDE_TVDVOB_DVO2(__x) \
+ MCDE_VAL2REG(MCDE_TVDVOB, DVO2, __x)
+#define MCDE_TVTIM1A 0x0000084C
+#define MCDE_TVTIM1A_GROUPOFFSET 0x200
+#define MCDE_TVTIM1A_DHO_SHIFT 0
+#define MCDE_TVTIM1A_DHO_MASK 0x000007FF
+#define MCDE_TVTIM1A_DHO(__x) \
+ MCDE_VAL2REG(MCDE_TVTIM1A, DHO, __x)
+#define MCDE_TVTIM1B 0x00000A4C
+#define MCDE_TVTIM1B_DHO_SHIFT 0
+#define MCDE_TVTIM1B_DHO_MASK 0x000007FF
+#define MCDE_TVTIM1B_DHO(__x) \
+ MCDE_VAL2REG(MCDE_TVTIM1B, DHO, __x)
+#define MCDE_TVLBALWA 0x00000850
+#define MCDE_TVLBALWA_GROUPOFFSET 0x200
+#define MCDE_TVLBALWA_LBW_SHIFT 0
+#define MCDE_TVLBALWA_LBW_MASK 0x000007FF
+#define MCDE_TVLBALWA_LBW(__x) \
+ MCDE_VAL2REG(MCDE_TVLBALWA, LBW, __x)
+#define MCDE_TVLBALWA_ALW_SHIFT 16
+#define MCDE_TVLBALWA_ALW_MASK 0x07FF0000
+#define MCDE_TVLBALWA_ALW(__x) \
+ MCDE_VAL2REG(MCDE_TVLBALWA, ALW, __x)
+#define MCDE_TVLBALWB 0x00000A50
+#define MCDE_TVLBALWB_LBW_SHIFT 0
+#define MCDE_TVLBALWB_LBW_MASK 0x000007FF
+#define MCDE_TVLBALWB_LBW(__x) \
+ MCDE_VAL2REG(MCDE_TVLBALWB, LBW, __x)
+#define MCDE_TVLBALWB_ALW_SHIFT 16
+#define MCDE_TVLBALWB_ALW_MASK 0x07FF0000
+#define MCDE_TVLBALWB_ALW(__x) \
+ MCDE_VAL2REG(MCDE_TVLBALWB, ALW, __x)
+#define MCDE_TVBL2A 0x00000854
+#define MCDE_TVBL2A_GROUPOFFSET 0x200
+#define MCDE_TVBL2A_BEL2_SHIFT 0
+#define MCDE_TVBL2A_BEL2_MASK 0x000007FF
+#define MCDE_TVBL2A_BEL2(__x) \
+ MCDE_VAL2REG(MCDE_TVBL2A, BEL2, __x)
+#define MCDE_TVBL2A_BSL2_SHIFT 16
+#define MCDE_TVBL2A_BSL2_MASK 0x07FF0000
+#define MCDE_TVBL2A_BSL2(__x) \
+ MCDE_VAL2REG(MCDE_TVBL2A, BSL2, __x)
+#define MCDE_TVBL2B 0x00000A54
+#define MCDE_TVBL2B_BEL2_SHIFT 0
+#define MCDE_TVBL2B_BEL2_MASK 0x000007FF
+#define MCDE_TVBL2B_BEL2(__x) \
+ MCDE_VAL2REG(MCDE_TVBL2B, BEL2, __x)
+#define MCDE_TVBL2B_BSL2_SHIFT 16
+#define MCDE_TVBL2B_BSL2_MASK 0x07FF0000
+#define MCDE_TVBL2B_BSL2(__x) \
+ MCDE_VAL2REG(MCDE_TVBL2B, BSL2, __x)
+#define MCDE_TVBLUA 0x00000858
+#define MCDE_TVBLUA_GROUPOFFSET 0x200
+#define MCDE_TVBLUA_TVBLU_SHIFT 0
+#define MCDE_TVBLUA_TVBLU_MASK 0x000000FF
+#define MCDE_TVBLUA_TVBLU(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUA, TVBLU, __x)
+#define MCDE_TVBLUA_TVBCB_SHIFT 8
+#define MCDE_TVBLUA_TVBCB_MASK 0x0000FF00
+#define MCDE_TVBLUA_TVBCB(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUA, TVBCB, __x)
+#define MCDE_TVBLUA_TVBCR_SHIFT 16
+#define MCDE_TVBLUA_TVBCR_MASK 0x00FF0000
+#define MCDE_TVBLUA_TVBCR(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUA, TVBCR, __x)
+#define MCDE_TVBLUB 0x00000A58
+#define MCDE_TVBLUB_TVBLU_SHIFT 0
+#define MCDE_TVBLUB_TVBLU_MASK 0x000000FF
+#define MCDE_TVBLUB_TVBLU(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUB, TVBLU, __x)
+#define MCDE_TVBLUB_TVBCB_SHIFT 8
+#define MCDE_TVBLUB_TVBCB_MASK 0x0000FF00
+#define MCDE_TVBLUB_TVBCB(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUB, TVBCB, __x)
+#define MCDE_TVBLUB_TVBCR_SHIFT 16
+#define MCDE_TVBLUB_TVBCR_MASK 0x00FF0000
+#define MCDE_TVBLUB_TVBCR(__x) \
+ MCDE_VAL2REG(MCDE_TVBLUB, TVBCR, __x)
+#define MCDE_LCDTIM1A 0x00000860
+#define MCDE_LCDTIM1A_GROUPOFFSET 0x200
+#define MCDE_LCDTIM1A_IVP_SHIFT 19
+#define MCDE_LCDTIM1A_IVP_MASK 0x00080000
+#define MCDE_LCDTIM1A_IVP(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1A, IVP, __x)
+#define MCDE_LCDTIM1A_IVS_SHIFT 20
+#define MCDE_LCDTIM1A_IVS_MASK 0x00100000
+#define MCDE_LCDTIM1A_IVS(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1A, IVS, __x)
+#define MCDE_LCDTIM1A_IHS_SHIFT 21
+#define MCDE_LCDTIM1A_IHS_MASK 0x00200000
+#define MCDE_LCDTIM1A_IHS(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1A, IHS, __x)
+#define MCDE_LCDTIM1A_IPC_SHIFT 22
+#define MCDE_LCDTIM1A_IPC_MASK 0x00400000
+#define MCDE_LCDTIM1A_IPC(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1A, IPC, __x)
+#define MCDE_LCDTIM1A_IOE_SHIFT 23
+#define MCDE_LCDTIM1A_IOE_MASK 0x00800000
+#define MCDE_LCDTIM1A_IOE(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1A, IOE, __x)
+#define MCDE_LCDTIM1B 0x00000A60
+#define MCDE_LCDTIM1B_IVP_SHIFT 19
+#define MCDE_LCDTIM1B_IVP_MASK 0x00080000
+#define MCDE_LCDTIM1B_IVP(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1B, IVP, __x)
+#define MCDE_LCDTIM1B_IVS_SHIFT 20
+#define MCDE_LCDTIM1B_IVS_MASK 0x00100000
+#define MCDE_LCDTIM1B_IVS(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1B, IVS, __x)
+#define MCDE_LCDTIM1B_IHS_SHIFT 21
+#define MCDE_LCDTIM1B_IHS_MASK 0x00200000
+#define MCDE_LCDTIM1B_IHS(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1B, IHS, __x)
+#define MCDE_LCDTIM1B_IPC_SHIFT 22
+#define MCDE_LCDTIM1B_IPC_MASK 0x00400000
+#define MCDE_LCDTIM1B_IPC(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1B, IPC, __x)
+#define MCDE_LCDTIM1B_IOE_SHIFT 23
+#define MCDE_LCDTIM1B_IOE_MASK 0x00800000
+#define MCDE_LCDTIM1B_IOE(__x) \
+ MCDE_VAL2REG(MCDE_LCDTIM1B, IOE, __x)
+#define MCDE_DITCTRLA 0x00000864
+#define MCDE_DITCTRLA_GROUPOFFSET 0x200
+#define MCDE_DITCTRLA_TEMP_SHIFT 0
+#define MCDE_DITCTRLA_TEMP_MASK 0x00000001
+#define MCDE_DITCTRLA_TEMP(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, TEMP, __x)
+#define MCDE_DITCTRLA_COMP_SHIFT 1
+#define MCDE_DITCTRLA_COMP_MASK 0x00000002
+#define MCDE_DITCTRLA_COMP(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, COMP, __x)
+#define MCDE_DITCTRLA_MODE_SHIFT 2
+#define MCDE_DITCTRLA_MODE_MASK 0x0000000C
+#define MCDE_DITCTRLA_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, MODE, __x)
+#define MCDE_DITCTRLA_MASK_SHIFT 4
+#define MCDE_DITCTRLA_MASK_MASK 0x00000010
+#define MCDE_DITCTRLA_MASK(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, MASK, __x)
+#define MCDE_DITCTRLA_FOFFX_SHIFT 5
+#define MCDE_DITCTRLA_FOFFX_MASK 0x000003E0
+#define MCDE_DITCTRLA_FOFFX(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, FOFFX, __x)
+#define MCDE_DITCTRLA_FOFFY_SHIFT 10
+#define MCDE_DITCTRLA_FOFFY_MASK 0x00007C00
+#define MCDE_DITCTRLA_FOFFY(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLA, FOFFY, __x)
+#define MCDE_DITCTRLB 0x00000A64
+#define MCDE_DITCTRLB_TEMP_SHIFT 0
+#define MCDE_DITCTRLB_TEMP_MASK 0x00000001
+#define MCDE_DITCTRLB_TEMP(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, TEMP, __x)
+#define MCDE_DITCTRLB_COMP_SHIFT 1
+#define MCDE_DITCTRLB_COMP_MASK 0x00000002
+#define MCDE_DITCTRLB_COMP(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, COMP, __x)
+#define MCDE_DITCTRLB_MODE_SHIFT 2
+#define MCDE_DITCTRLB_MODE_MASK 0x0000000C
+#define MCDE_DITCTRLB_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, MODE, __x)
+#define MCDE_DITCTRLB_MASK_SHIFT 4
+#define MCDE_DITCTRLB_MASK_MASK 0x00000010
+#define MCDE_DITCTRLB_MASK(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, MASK, __x)
+#define MCDE_DITCTRLB_FOFFX_SHIFT 5
+#define MCDE_DITCTRLB_FOFFX_MASK 0x000003E0
+#define MCDE_DITCTRLB_FOFFX(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, FOFFX, __x)
+#define MCDE_DITCTRLB_FOFFY_SHIFT 10
+#define MCDE_DITCTRLB_FOFFY_MASK 0x00007C00
+#define MCDE_DITCTRLB_FOFFY(__x) \
+ MCDE_VAL2REG(MCDE_DITCTRLB, FOFFY, __x)
+#define MCDE_DITOFFA 0x00000868
+#define MCDE_DITOFFA_GROUPOFFSET 0x200
+#define MCDE_DITOFFA_XG_SHIFT 0
+#define MCDE_DITOFFA_XG_MASK 0x0000001F
+#define MCDE_DITOFFA_XG(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFA, XG, __x)
+#define MCDE_DITOFFA_YG_SHIFT 8
+#define MCDE_DITOFFA_YG_MASK 0x00001F00
+#define MCDE_DITOFFA_YG(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFA, YG, __x)
+#define MCDE_DITOFFA_XB_SHIFT 16
+#define MCDE_DITOFFA_XB_MASK 0x001F0000
+#define MCDE_DITOFFA_XB(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFA, XB, __x)
+#define MCDE_DITOFFA_YB_SHIFT 24
+#define MCDE_DITOFFA_YB_MASK 0x1F000000
+#define MCDE_DITOFFA_YB(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFA, YB, __x)
+#define MCDE_DITOFFB 0x00000A68
+#define MCDE_DITOFFB_XG_SHIFT 0
+#define MCDE_DITOFFB_XG_MASK 0x0000001F
+#define MCDE_DITOFFB_XG(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFB, XG, __x)
+#define MCDE_DITOFFB_YG_SHIFT 8
+#define MCDE_DITOFFB_YG_MASK 0x00001F00
+#define MCDE_DITOFFB_YG(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFB, YG, __x)
+#define MCDE_DITOFFB_XB_SHIFT 16
+#define MCDE_DITOFFB_XB_MASK 0x001F0000
+#define MCDE_DITOFFB_XB(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFB, XB, __x)
+#define MCDE_DITOFFB_YB_SHIFT 24
+#define MCDE_DITOFFB_YB_MASK 0x1F000000
+#define MCDE_DITOFFB_YB(__x) \
+ MCDE_VAL2REG(MCDE_DITOFFB, YB, __x)
+#define MCDE_PAL0A 0x0000086C
+#define MCDE_PAL0A_GROUPOFFSET 0x200
+#define MCDE_PAL0A_BLUE_SHIFT 0
+#define MCDE_PAL0A_BLUE_MASK 0x00000FFF
+#define MCDE_PAL0A_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_PAL0A, BLUE, __x)
+#define MCDE_PAL0A_GREEN_SHIFT 16
+#define MCDE_PAL0A_GREEN_MASK 0x0FFF0000
+#define MCDE_PAL0A_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_PAL0A, GREEN, __x)
+#define MCDE_PAL0B 0x00000A6C
+#define MCDE_PAL0B_BLUE_SHIFT 0
+#define MCDE_PAL0B_BLUE_MASK 0x00000FFF
+#define MCDE_PAL0B_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_PAL0B, BLUE, __x)
+#define MCDE_PAL0B_GREEN_SHIFT 16
+#define MCDE_PAL0B_GREEN_MASK 0x0FFF0000
+#define MCDE_PAL0B_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_PAL0B, GREEN, __x)
+#define MCDE_PAL1A 0x00000870
+#define MCDE_PAL1A_GROUPOFFSET 0x200
+#define MCDE_PAL1A_RED_SHIFT 0
+#define MCDE_PAL1A_RED_MASK 0x00000FFF
+#define MCDE_PAL1A_RED(__x) \
+ MCDE_VAL2REG(MCDE_PAL1A, RED, __x)
+#define MCDE_PAL1B 0x00000A70
+#define MCDE_PAL1B_RED_SHIFT 0
+#define MCDE_PAL1B_RED_MASK 0x00000FFF
+#define MCDE_PAL1B_RED(__x) \
+ MCDE_VAL2REG(MCDE_PAL1B, RED, __x)
+#define MCDE_ROTADD0A 0x00000874
+#define MCDE_ROTADD0A_GROUPOFFSET 0x200
+#define MCDE_ROTADD0A_ROTADD0_SHIFT 3
+#define MCDE_ROTADD0A_ROTADD0_MASK 0xFFFFFFF8
+#define MCDE_ROTADD0A_ROTADD0(__x) \
+ MCDE_VAL2REG(MCDE_ROTADD0A, ROTADD0, __x)
+#define MCDE_ROTADD0B 0x00000A74
+#define MCDE_ROTADD0B_ROTADD0_SHIFT 3
+#define MCDE_ROTADD0B_ROTADD0_MASK 0xFFFFFFF8
+#define MCDE_ROTADD0B_ROTADD0(__x) \
+ MCDE_VAL2REG(MCDE_ROTADD0B, ROTADD0, __x)
+#define MCDE_ROTADD1A 0x00000878
+#define MCDE_ROTADD1A_GROUPOFFSET 0x200
+#define MCDE_ROTADD1A_ROTADD1_SHIFT 3
+#define MCDE_ROTADD1A_ROTADD1_MASK 0xFFFFFFF8
+#define MCDE_ROTADD1A_ROTADD1(__x) \
+ MCDE_VAL2REG(MCDE_ROTADD1A, ROTADD1, __x)
+#define MCDE_ROTADD1B 0x00000A78
+#define MCDE_ROTADD1B_ROTADD1_SHIFT 3
+#define MCDE_ROTADD1B_ROTADD1_MASK 0xFFFFFFF8
+#define MCDE_ROTADD1B_ROTADD1(__x) \
+ MCDE_VAL2REG(MCDE_ROTADD1B, ROTADD1, __x)
+#define MCDE_ROTACONF 0x0000087C
+#define MCDE_ROTACONF_GROUPOFFSET 0x200
+#define MCDE_ROTACONF_ROTBURSTSIZE_SHIFT 0
+#define MCDE_ROTACONF_ROTBURSTSIZE_MASK 0x00000007
+#define MCDE_ROTACONF_ROTBURSTSIZE_1W 0
+#define MCDE_ROTACONF_ROTBURSTSIZE_2W 1
+#define MCDE_ROTACONF_ROTBURSTSIZE_4W 2
+#define MCDE_ROTACONF_ROTBURSTSIZE_8W 3
+#define MCDE_ROTACONF_ROTBURSTSIZE_HW_1W 4
+#define MCDE_ROTACONF_ROTBURSTSIZE_HW_2W 5
+#define MCDE_ROTACONF_ROTBURSTSIZE_HW_4W 6
+#define MCDE_ROTACONF_ROTBURSTSIZE_HW_8W 7
+#define MCDE_ROTACONF_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, ROTBURSTSIZE, \
+ MCDE_ROTACONF_ROTBURSTSIZE_##__x)
+#define MCDE_ROTACONF_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, ROTBURSTSIZE, __x)
+#define MCDE_ROTACONF_ROTDIR_SHIFT 3
+#define MCDE_ROTACONF_ROTDIR_MASK 0x00000008
+#define MCDE_ROTACONF_ROTDIR_CCW 0
+#define MCDE_ROTACONF_ROTDIR_CW 1
+#define MCDE_ROTACONF_ROTDIR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, ROTDIR, MCDE_ROTACONF_ROTDIR_##__x)
+#define MCDE_ROTACONF_ROTDIR(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, ROTDIR, __x)
+#define MCDE_ROTACONF_WR_MAXOUT_SHIFT 4
+#define MCDE_ROTACONF_WR_MAXOUT_MASK 0x00000030
+#define MCDE_ROTACONF_WR_MAXOUT_1_REQ 0
+#define MCDE_ROTACONF_WR_MAXOUT_2_REQ 1
+#define MCDE_ROTACONF_WR_MAXOUT_4_REQ 2
+#define MCDE_ROTACONF_WR_MAXOUT_8_REQ 3
+#define MCDE_ROTACONF_WR_MAXOUT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, WR_MAXOUT, MCDE_ROTACONF_WR_MAXOUT_##__x)
+#define MCDE_ROTACONF_WR_MAXOUT(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, WR_MAXOUT, __x)
+#define MCDE_ROTACONF_RD_MAXOUT_SHIFT 6
+#define MCDE_ROTACONF_RD_MAXOUT_MASK 0x000000C0
+#define MCDE_ROTACONF_RD_MAXOUT_1_REQ 0
+#define MCDE_ROTACONF_RD_MAXOUT_2_REQ 1
+#define MCDE_ROTACONF_RD_MAXOUT_4_REQ 2
+#define MCDE_ROTACONF_RD_MAXOUT_8_REQ 3
+#define MCDE_ROTACONF_RD_MAXOUT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, RD_MAXOUT, MCDE_ROTACONF_RD_MAXOUT_##__x)
+#define MCDE_ROTACONF_RD_MAXOUT(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, RD_MAXOUT, __x)
+#define MCDE_ROTACONF_STRIP_WIDTH_SHIFT 8
+#define MCDE_ROTACONF_STRIP_WIDTH_MASK 0x00007F00
+#define MCDE_ROTACONF_STRIP_WIDTH_2PIX 0
+#define MCDE_ROTACONF_STRIP_WIDTH_4PIX 1
+#define MCDE_ROTACONF_STRIP_WIDTH_8PIX 2
+#define MCDE_ROTACONF_STRIP_WIDTH_16PIX 3
+#define MCDE_ROTACONF_STRIP_WIDTH_32PIX 4
+#define MCDE_ROTACONF_STRIP_WIDTH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, STRIP_WIDTH, \
+ MCDE_ROTACONF_STRIP_WIDTH_##__x)
+#define MCDE_ROTACONF_STRIP_WIDTH(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, STRIP_WIDTH, __x)
+#define MCDE_ROTACONF_SINGLE_BUF_SHIFT 15
+#define MCDE_ROTACONF_SINGLE_BUF_MASK 0x00008000
+#define MCDE_ROTACONF_SINGLE_BUF(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, SINGLE_BUF, __x)
+#define MCDE_ROTACONF_WR_ROPC_SHIFT 16
+#define MCDE_ROTACONF_WR_ROPC_MASK 0x00FF0000
+#define MCDE_ROTACONF_WR_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, WR_ROPC, __x)
+#define MCDE_ROTACONF_RD_ROPC_SHIFT 24
+#define MCDE_ROTACONF_RD_ROPC_MASK 0xFF000000
+#define MCDE_ROTACONF_RD_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_ROTACONF, RD_ROPC, __x)
+#define MCDE_ROTBCONF 0x00000A7C
+#define MCDE_ROTBCONF_ROTBURSTSIZE_SHIFT 0
+#define MCDE_ROTBCONF_ROTBURSTSIZE_MASK 0x00000007
+#define MCDE_ROTBCONF_ROTBURSTSIZE_1W 0
+#define MCDE_ROTBCONF_ROTBURSTSIZE_2W 1
+#define MCDE_ROTBCONF_ROTBURSTSIZE_4W 2
+#define MCDE_ROTBCONF_ROTBURSTSIZE_8W 3
+#define MCDE_ROTBCONF_ROTBURSTSIZE_HW_1W 4
+#define MCDE_ROTBCONF_ROTBURSTSIZE_HW_2W 5
+#define MCDE_ROTBCONF_ROTBURSTSIZE_HW_4W 6
+#define MCDE_ROTBCONF_ROTBURSTSIZE_HW_8W 7
+#define MCDE_ROTBCONF_ROTBURSTSIZE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, ROTBURSTSIZE, \
+ MCDE_ROTBCONF_ROTBURSTSIZE_##__x)
+#define MCDE_ROTBCONF_ROTBURSTSIZE(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, ROTBURSTSIZE, __x)
+#define MCDE_ROTBCONF_ROTDIR_SHIFT 3
+#define MCDE_ROTBCONF_ROTDIR_MASK 0x00000008
+#define MCDE_ROTBCONF_ROTDIR_CCW 0
+#define MCDE_ROTBCONF_ROTDIR_CW 1
+#define MCDE_ROTBCONF_ROTDIR_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, ROTDIR, MCDE_ROTBCONF_ROTDIR_##__x)
+#define MCDE_ROTBCONF_ROTDIR(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, ROTDIR, __x)
+#define MCDE_ROTBCONF_WR_MAXOUT_SHIFT 4
+#define MCDE_ROTBCONF_WR_MAXOUT_MASK 0x00000030
+#define MCDE_ROTBCONF_WR_MAXOUT_1_REQ 0
+#define MCDE_ROTBCONF_WR_MAXOUT_2_REQ 1
+#define MCDE_ROTBCONF_WR_MAXOUT_4_REQ 2
+#define MCDE_ROTBCONF_WR_MAXOUT_8_REQ 3
+#define MCDE_ROTBCONF_WR_MAXOUT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, WR_MAXOUT, MCDE_ROTBCONF_WR_MAXOUT_##__x)
+#define MCDE_ROTBCONF_WR_MAXOUT(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, WR_MAXOUT, __x)
+#define MCDE_ROTBCONF_RD_MAXOUT_SHIFT 6
+#define MCDE_ROTBCONF_RD_MAXOUT_MASK 0x000000C0
+#define MCDE_ROTBCONF_RD_MAXOUT_1_REQ 0
+#define MCDE_ROTBCONF_RD_MAXOUT_2_REQ 1
+#define MCDE_ROTBCONF_RD_MAXOUT_4_REQ 2
+#define MCDE_ROTBCONF_RD_MAXOUT_8_REQ 3
+#define MCDE_ROTBCONF_RD_MAXOUT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, RD_MAXOUT, MCDE_ROTBCONF_RD_MAXOUT_##__x)
+#define MCDE_ROTBCONF_RD_MAXOUT(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, RD_MAXOUT, __x)
+#define MCDE_ROTBCONF_STRIP_WIDTH_SHIFT 8
+#define MCDE_ROTBCONF_STRIP_WIDTH_MASK 0x00007F00
+#define MCDE_ROTBCONF_STRIP_WIDTH_2PIX 0
+#define MCDE_ROTBCONF_STRIP_WIDTH_4PIX 1
+#define MCDE_ROTBCONF_STRIP_WIDTH_8PIX 2
+#define MCDE_ROTBCONF_STRIP_WIDTH_16PIX 3
+#define MCDE_ROTBCONF_STRIP_WIDTH_32PIX 4
+#define MCDE_ROTBCONF_STRIP_WIDTH_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, STRIP_WIDTH, \
+ MCDE_ROTBCONF_STRIP_WIDTH_##__x)
+#define MCDE_ROTBCONF_STRIP_WIDTH(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, STRIP_WIDTH, __x)
+#define MCDE_ROTBCONF_SINGLE_BUF_SHIFT 15
+#define MCDE_ROTBCONF_SINGLE_BUF_MASK 0x00008000
+#define MCDE_ROTBCONF_SINGLE_BUF(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, SINGLE_BUF, __x)
+#define MCDE_ROTBCONF_WR_ROPC_SHIFT 16
+#define MCDE_ROTBCONF_WR_ROPC_MASK 0x00FF0000
+#define MCDE_ROTBCONF_WR_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, WR_ROPC, __x)
+#define MCDE_ROTBCONF_RD_ROPC_SHIFT 24
+#define MCDE_ROTBCONF_RD_ROPC_MASK 0xFF000000
+#define MCDE_ROTBCONF_RD_ROPC(__x) \
+ MCDE_VAL2REG(MCDE_ROTBCONF, RD_ROPC, __x)
+#define MCDE_SYNCHCONFA 0x00000880
+#define MCDE_SYNCHCONFA_GROUPOFFSET 0x200
+#define MCDE_SYNCHCONFA_HWREQVEVENT_SHIFT 0
+#define MCDE_SYNCHCONFA_HWREQVEVENT_MASK 0x00000003
+#define MCDE_SYNCHCONFA_HWREQVEVENT_VSYNC 0
+#define MCDE_SYNCHCONFA_HWREQVEVENT_BACK_PORCH 1
+#define MCDE_SYNCHCONFA_HWREQVEVENT_ACTIVE_VIDEO 2
+#define MCDE_SYNCHCONFA_HWREQVEVENT_FRONT_PORCH 3
+#define MCDE_SYNCHCONFA_HWREQVEVENT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, HWREQVEVENT, \
+ MCDE_SYNCHCONFA_HWREQVEVENT_##__x)
+#define MCDE_SYNCHCONFA_HWREQVEVENT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, HWREQVEVENT, __x)
+#define MCDE_SYNCHCONFA_HWREQVCNT_SHIFT 2
+#define MCDE_SYNCHCONFA_HWREQVCNT_MASK 0x0000FFFC
+#define MCDE_SYNCHCONFA_HWREQVCNT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, HWREQVCNT, __x)
+#define MCDE_SYNCHCONFA_SWINTVEVENT_SHIFT 16
+#define MCDE_SYNCHCONFA_SWINTVEVENT_MASK 0x00030000
+#define MCDE_SYNCHCONFA_SWINTVEVENT_VSYNC 0
+#define MCDE_SYNCHCONFA_SWINTVEVENT_BACK_PORCH 1
+#define MCDE_SYNCHCONFA_SWINTVEVENT_ACTIVE_VIDEO 2
+#define MCDE_SYNCHCONFA_SWINTVEVENT_FRONT_PORCH 3
+#define MCDE_SYNCHCONFA_SWINTVEVENT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, SWINTVEVENT, \
+ MCDE_SYNCHCONFA_SWINTVEVENT_##__x)
+#define MCDE_SYNCHCONFA_SWINTVEVENT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, SWINTVEVENT, __x)
+#define MCDE_SYNCHCONFA_SWINTVCNT_SHIFT 18
+#define MCDE_SYNCHCONFA_SWINTVCNT_MASK 0xFFFC0000
+#define MCDE_SYNCHCONFA_SWINTVCNT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFA, SWINTVCNT, __x)
+#define MCDE_SYNCHCONFB 0x00000A80
+#define MCDE_SYNCHCONFB_HWREQVEVENT_SHIFT 0
+#define MCDE_SYNCHCONFB_HWREQVEVENT_MASK 0x00000003
+#define MCDE_SYNCHCONFB_HWREQVEVENT_VSYNC 0
+#define MCDE_SYNCHCONFB_HWREQVEVENT_BACK_PORCH 1
+#define MCDE_SYNCHCONFB_HWREQVEVENT_ACTIVE_VIDEO 2
+#define MCDE_SYNCHCONFB_HWREQVEVENT_FRONT_PORCH 3
+#define MCDE_SYNCHCONFB_HWREQVEVENT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, HWREQVEVENT, \
+ MCDE_SYNCHCONFB_HWREQVEVENT_##__x)
+#define MCDE_SYNCHCONFB_HWREQVEVENT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, HWREQVEVENT, __x)
+#define MCDE_SYNCHCONFB_HWREQVCNT_SHIFT 2
+#define MCDE_SYNCHCONFB_HWREQVCNT_MASK 0x0000FFFC
+#define MCDE_SYNCHCONFB_HWREQVCNT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, HWREQVCNT, __x)
+#define MCDE_SYNCHCONFB_SWINTVEVENT_SHIFT 16
+#define MCDE_SYNCHCONFB_SWINTVEVENT_MASK 0x00030000
+#define MCDE_SYNCHCONFB_SWINTVEVENT_VSYNC 0
+#define MCDE_SYNCHCONFB_SWINTVEVENT_BACK_PORCH 1
+#define MCDE_SYNCHCONFB_SWINTVEVENT_ACTIVE_VIDEO 2
+#define MCDE_SYNCHCONFB_SWINTVEVENT_FRONT_PORCH 3
+#define MCDE_SYNCHCONFB_SWINTVEVENT_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, SWINTVEVENT, \
+ MCDE_SYNCHCONFB_SWINTVEVENT_##__x)
+#define MCDE_SYNCHCONFB_SWINTVEVENT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, SWINTVEVENT, __x)
+#define MCDE_SYNCHCONFB_SWINTVCNT_SHIFT 18
+#define MCDE_SYNCHCONFB_SWINTVCNT_MASK 0xFFFC0000
+#define MCDE_SYNCHCONFB_SWINTVCNT(__x) \
+ MCDE_VAL2REG(MCDE_SYNCHCONFB, SWINTVCNT, __x)
+#define MCDE_CTRLA 0x00000884
+#define MCDE_CTRLA_GROUPOFFSET 0x200
+#define MCDE_CTRLA_FIFOWTRMRK_SHIFT 0
+#define MCDE_CTRLA_FIFOWTRMRK_MASK 0x000003FF
+#define MCDE_CTRLA_FIFOWTRMRK(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FIFOWTRMRK, __x)
+#define MCDE_CTRLA_FIFOEMPTY_SHIFT 12
+#define MCDE_CTRLA_FIFOEMPTY_MASK 0x00001000
+#define MCDE_CTRLA_FIFOEMPTY(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FIFOEMPTY, __x)
+#define MCDE_CTRLA_FIFOFULL_SHIFT 13
+#define MCDE_CTRLA_FIFOFULL_MASK 0x00002000
+#define MCDE_CTRLA_FIFOFULL(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FIFOFULL, __x)
+#define MCDE_CTRLA_FORMID_SHIFT 16
+#define MCDE_CTRLA_FORMID_MASK 0x00070000
+#define MCDE_CTRLA_FORMID_DSI0VID 0
+#define MCDE_CTRLA_FORMID_DSI0CMD 1
+#define MCDE_CTRLA_FORMID_DSI1VID 2
+#define MCDE_CTRLA_FORMID_DSI1CMD 3
+#define MCDE_CTRLA_FORMID_DSI2VID 4
+#define MCDE_CTRLA_FORMID_DSI2CMD 5
+#define MCDE_CTRLA_FORMID_DPIA 0
+#define MCDE_CTRLA_FORMID_DPIB 1
+#define MCDE_CTRLA_FORMID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FORMID, MCDE_CTRLA_FORMID_##__x)
+#define MCDE_CTRLA_FORMID(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FORMID, __x)
+#define MCDE_CTRLA_FORMTYPE_SHIFT 20
+#define MCDE_CTRLA_FORMTYPE_MASK 0x00700000
+#define MCDE_CTRLA_FORMTYPE_DPITV 0
+#define MCDE_CTRLA_FORMTYPE_DBI 1
+#define MCDE_CTRLA_FORMTYPE_DSI 2
+#define MCDE_CTRLA_FORMTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FORMTYPE, MCDE_CTRLA_FORMTYPE_##__x)
+#define MCDE_CTRLA_FORMTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CTRLA, FORMTYPE, __x)
+#define MCDE_CTRLB 0x00000A84
+#define MCDE_CTRLB_FIFOWTRMRK_SHIFT 0
+#define MCDE_CTRLB_FIFOWTRMRK_MASK 0x000003FF
+#define MCDE_CTRLB_FIFOWTRMRK(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FIFOWTRMRK, __x)
+#define MCDE_CTRLB_FIFOEMPTY_SHIFT 12
+#define MCDE_CTRLB_FIFOEMPTY_MASK 0x00001000
+#define MCDE_CTRLB_FIFOEMPTY(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FIFOEMPTY, __x)
+#define MCDE_CTRLB_FIFOFULL_SHIFT 13
+#define MCDE_CTRLB_FIFOFULL_MASK 0x00002000
+#define MCDE_CTRLB_FIFOFULL(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FIFOFULL, __x)
+#define MCDE_CTRLB_FORMID_SHIFT 16
+#define MCDE_CTRLB_FORMID_MASK 0x00070000
+#define MCDE_CTRLB_FORMID_DSI0VID 0
+#define MCDE_CTRLB_FORMID_DSI0CMD 1
+#define MCDE_CTRLB_FORMID_DSI1VID 2
+#define MCDE_CTRLB_FORMID_DSI1CMD 3
+#define MCDE_CTRLB_FORMID_DSI2VID 4
+#define MCDE_CTRLB_FORMID_DSI2CMD 5
+#define MCDE_CTRLB_FORMID_DPIA 0
+#define MCDE_CTRLB_FORMID_DPIB 1
+#define MCDE_CTRLB_FORMID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FORMID, MCDE_CTRLB_FORMID_##__x)
+#define MCDE_CTRLB_FORMID(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FORMID, __x)
+#define MCDE_CTRLB_FORMTYPE_SHIFT 20
+#define MCDE_CTRLB_FORMTYPE_MASK 0x00700000
+#define MCDE_CTRLB_FORMTYPE_DPITV 0
+#define MCDE_CTRLB_FORMTYPE_DBI 1
+#define MCDE_CTRLB_FORMTYPE_DSI 2
+#define MCDE_CTRLB_FORMTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FORMTYPE, MCDE_CTRLB_FORMTYPE_##__x)
+#define MCDE_CTRLB_FORMTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CTRLB, FORMTYPE, __x)
+#define MCDE_GAM0A 0x00000888
+#define MCDE_GAM0A_GROUPOFFSET 0x200
+#define MCDE_GAM0A_BLUE_SHIFT 0
+#define MCDE_GAM0A_BLUE_MASK 0x00FFFFFF
+#define MCDE_GAM0A_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_GAM0A, BLUE, __x)
+#define MCDE_GAM0B 0x00000A88
+#define MCDE_GAM0B_BLUE_SHIFT 0
+#define MCDE_GAM0B_BLUE_MASK 0x00FFFFFF
+#define MCDE_GAM0B_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_GAM0B, BLUE, __x)
+#define MCDE_GAM1A 0x0000088C
+#define MCDE_GAM1A_GROUPOFFSET 0x200
+#define MCDE_GAM1A_GREEN_SHIFT 0
+#define MCDE_GAM1A_GREEN_MASK 0x00FFFFFF
+#define MCDE_GAM1A_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_GAM1A, GREEN, __x)
+#define MCDE_GAM1B 0x00000A8C
+#define MCDE_GAM1B_GREEN_SHIFT 0
+#define MCDE_GAM1B_GREEN_MASK 0x00FFFFFF
+#define MCDE_GAM1B_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_GAM1B, GREEN, __x)
+#define MCDE_GAM2A 0x00000890
+#define MCDE_GAM2A_GROUPOFFSET 0x200
+#define MCDE_GAM2A_RED_SHIFT 0
+#define MCDE_GAM2A_RED_MASK 0x00FFFFFF
+#define MCDE_GAM2A_RED(__x) \
+ MCDE_VAL2REG(MCDE_GAM2A, RED, __x)
+#define MCDE_GAM2B 0x00000A90
+#define MCDE_GAM2B_RED_SHIFT 0
+#define MCDE_GAM2B_RED_MASK 0x00FFFFFF
+#define MCDE_GAM2B_RED(__x) \
+ MCDE_VAL2REG(MCDE_GAM2B, RED, __x)
+#define MCDE_OLEDCONV1A 0x00000894
+#define MCDE_OLEDCONV1A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV1A_ALPHA_RED_SHIFT 0
+#define MCDE_OLEDCONV1A_ALPHA_RED_MASK 0x00003FFF
+#define MCDE_OLEDCONV1A_ALPHA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV1A, ALPHA_RED, __x)
+#define MCDE_OLEDCONV1A_ALPHA_GREEN_SHIFT 16
+#define MCDE_OLEDCONV1A_ALPHA_GREEN_MASK 0x3FFF0000
+#define MCDE_OLEDCONV1A_ALPHA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV1A, ALPHA_GREEN, __x)
+#define MCDE_OLEDCONV1B 0x00000A94
+#define MCDE_OLEDCONV1B_ALPHA_RED_SHIFT 0
+#define MCDE_OLEDCONV1B_ALPHA_RED_MASK 0x00003FFF
+#define MCDE_OLEDCONV1B_ALPHA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV1B, ALPHA_RED, __x)
+#define MCDE_OLEDCONV1B_ALPHA_GREEN_SHIFT 16
+#define MCDE_OLEDCONV1B_ALPHA_GREEN_MASK 0x3FFF0000
+#define MCDE_OLEDCONV1B_ALPHA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV1B, ALPHA_GREEN, __x)
+#define MCDE_OLEDCONV2A 0x00000898
+#define MCDE_OLEDCONV2A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV2A_ALPHA_BLUE_SHIFT 0
+#define MCDE_OLEDCONV2A_ALPHA_BLUE_MASK 0x00003FFF
+#define MCDE_OLEDCONV2A_ALPHA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV2A, ALPHA_BLUE, __x)
+#define MCDE_OLEDCONV2A_BETA_RED_SHIFT 16
+#define MCDE_OLEDCONV2A_BETA_RED_MASK 0x3FFF0000
+#define MCDE_OLEDCONV2A_BETA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV2A, BETA_RED, __x)
+#define MCDE_OLEDCONV2B 0x00000A98
+#define MCDE_OLEDCONV2B_ALPHA_BLUE_SHIFT 0
+#define MCDE_OLEDCONV2B_ALPHA_BLUE_MASK 0x00003FFF
+#define MCDE_OLEDCONV2B_ALPHA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV2B, ALPHA_BLUE, __x)
+#define MCDE_OLEDCONV2B_BETA_RED_SHIFT 16
+#define MCDE_OLEDCONV2B_BETA_RED_MASK 0x3FFF0000
+#define MCDE_OLEDCONV2B_BETA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV2B, BETA_RED, __x)
+#define MCDE_OLEDCONV3A 0x0000089C
+#define MCDE_OLEDCONV3A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV3A_BETA_GREEN_SHIFT 0
+#define MCDE_OLEDCONV3A_BETA_GREEN_MASK 0x00003FFF
+#define MCDE_OLEDCONV3A_BETA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV3A, BETA_GREEN, __x)
+#define MCDE_OLEDCONV3A_BETA_BLUE_SHIFT 16
+#define MCDE_OLEDCONV3A_BETA_BLUE_MASK 0x3FFF0000
+#define MCDE_OLEDCONV3A_BETA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV3A, BETA_BLUE, __x)
+#define MCDE_OLEDCONV3B 0x00000A9C
+#define MCDE_OLEDCONV3B_BETA_GREEN_SHIFT 0
+#define MCDE_OLEDCONV3B_BETA_GREEN_MASK 0x00003FFF
+#define MCDE_OLEDCONV3B_BETA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV3B, BETA_GREEN, __x)
+#define MCDE_OLEDCONV3B_BETA_BLUE_SHIFT 16
+#define MCDE_OLEDCONV3B_BETA_BLUE_MASK 0x3FFF0000
+#define MCDE_OLEDCONV3B_BETA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV3B, BETA_BLUE, __x)
+#define MCDE_OLEDCONV4A 0x000008A0
+#define MCDE_OLEDCONV4A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV4A_GAMMA_RED_SHIFT 0
+#define MCDE_OLEDCONV4A_GAMMA_RED_MASK 0x00003FFF
+#define MCDE_OLEDCONV4A_GAMMA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV4A, GAMMA_RED, __x)
+#define MCDE_OLEDCONV4A_GAMMA_GREEN_SHIFT 16
+#define MCDE_OLEDCONV4A_GAMMA_GREEN_MASK 0x3FFF0000
+#define MCDE_OLEDCONV4A_GAMMA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV4A, GAMMA_GREEN, __x)
+#define MCDE_OLEDCONV4B 0x00000AA0
+#define MCDE_OLEDCONV4B_GAMMA_RED_SHIFT 0
+#define MCDE_OLEDCONV4B_GAMMA_RED_MASK 0x00003FFF
+#define MCDE_OLEDCONV4B_GAMMA_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV4B, GAMMA_RED, __x)
+#define MCDE_OLEDCONV4B_GAMMA_GREEN_SHIFT 16
+#define MCDE_OLEDCONV4B_GAMMA_GREEN_MASK 0x3FFF0000
+#define MCDE_OLEDCONV4B_GAMMA_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV4B, GAMMA_GREEN, __x)
+#define MCDE_OLEDCONV5A 0x000008A4
+#define MCDE_OLEDCONV5A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV5A_GAMMA_BLUE_SHIFT 0
+#define MCDE_OLEDCONV5A_GAMMA_BLUE_MASK 0x00003FFF
+#define MCDE_OLEDCONV5A_GAMMA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV5A, GAMMA_BLUE, __x)
+#define MCDE_OLEDCONV5A_OFF_RED_SHIFT 16
+#define MCDE_OLEDCONV5A_OFF_RED_MASK 0x3FFF0000
+#define MCDE_OLEDCONV5A_OFF_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV5A, OFF_RED, __x)
+#define MCDE_OLEDCONV5B 0x00000AA4
+#define MCDE_OLEDCONV5B_GAMMA_BLUE_SHIFT 0
+#define MCDE_OLEDCONV5B_GAMMA_BLUE_MASK 0x00003FFF
+#define MCDE_OLEDCONV5B_GAMMA_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV5B, GAMMA_BLUE, __x)
+#define MCDE_OLEDCONV5B_OFF_RED_SHIFT 16
+#define MCDE_OLEDCONV5B_OFF_RED_MASK 0x3FFF0000
+#define MCDE_OLEDCONV5B_OFF_RED(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV5B, OFF_RED, __x)
+#define MCDE_OLEDCONV6A 0x000008A8
+#define MCDE_OLEDCONV6A_GROUPOFFSET 0x200
+#define MCDE_OLEDCONV6A_OFF_GREEN_SHIFT 0
+#define MCDE_OLEDCONV6A_OFF_GREEN_MASK 0x00003FFF
+#define MCDE_OLEDCONV6A_OFF_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV6A, OFF_GREEN, __x)
+#define MCDE_OLEDCONV6A_OFF_BLUE_SHIFT 16
+#define MCDE_OLEDCONV6A_OFF_BLUE_MASK 0x3FFF0000
+#define MCDE_OLEDCONV6A_OFF_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV6A, OFF_BLUE, __x)
+#define MCDE_OLEDCONV6B 0x00000AA8
+#define MCDE_OLEDCONV6B_OFF_GREEN_SHIFT 0
+#define MCDE_OLEDCONV6B_OFF_GREEN_MASK 0x00003FFF
+#define MCDE_OLEDCONV6B_OFF_GREEN(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV6B, OFF_GREEN, __x)
+#define MCDE_OLEDCONV6B_OFF_BLUE_SHIFT 16
+#define MCDE_OLEDCONV6B_OFF_BLUE_MASK 0x3FFF0000
+#define MCDE_OLEDCONV6B_OFF_BLUE(__x) \
+ MCDE_VAL2REG(MCDE_OLEDCONV6B, OFF_BLUE, __x)
+#define MCDE_CRC 0x00000C00
+#define MCDE_CRC_C1EN_SHIFT 2
+#define MCDE_CRC_C1EN_MASK 0x00000004
+#define MCDE_CRC_C1EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, C1EN, __x)
+#define MCDE_CRC_C2EN_SHIFT 3
+#define MCDE_CRC_C2EN_MASK 0x00000008
+#define MCDE_CRC_C2EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, C2EN, __x)
+#define MCDE_CRC_SYCEN0_SHIFT 7
+#define MCDE_CRC_SYCEN0_MASK 0x00000080
+#define MCDE_CRC_SYCEN0(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SYCEN0, __x)
+#define MCDE_CRC_SYCEN1_SHIFT 8
+#define MCDE_CRC_SYCEN1_MASK 0x00000100
+#define MCDE_CRC_SYCEN1(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SYCEN1, __x)
+#define MCDE_CRC_SIZE1_SHIFT 9
+#define MCDE_CRC_SIZE1_MASK 0x00000200
+#define MCDE_CRC_SIZE1(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SIZE1, __x)
+#define MCDE_CRC_SIZE2_SHIFT 10
+#define MCDE_CRC_SIZE2_MASK 0x00000400
+#define MCDE_CRC_SIZE2(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SIZE2, __x)
+#define MCDE_CRC_YUVCONVC1EN_SHIFT 15
+#define MCDE_CRC_YUVCONVC1EN_MASK 0x00008000
+#define MCDE_CRC_YUVCONVC1EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, YUVCONVC1EN, __x)
+#define MCDE_CRC_CS1EN_SHIFT 16
+#define MCDE_CRC_CS1EN_MASK 0x00010000
+#define MCDE_CRC_CS1EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CS1EN, __x)
+#define MCDE_CRC_CS2EN_SHIFT 17
+#define MCDE_CRC_CS2EN_MASK 0x00020000
+#define MCDE_CRC_CS2EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CS2EN, __x)
+#define MCDE_CRC_CS1POL_SHIFT 19
+#define MCDE_CRC_CS1POL_MASK 0x00080000
+#define MCDE_CRC_CS1POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CS1POL, __x)
+#define MCDE_CRC_CS2POL_SHIFT 20
+#define MCDE_CRC_CS2POL_MASK 0x00100000
+#define MCDE_CRC_CS2POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CS2POL, __x)
+#define MCDE_CRC_CD1POL_SHIFT 21
+#define MCDE_CRC_CD1POL_MASK 0x00200000
+#define MCDE_CRC_CD1POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CD1POL, __x)
+#define MCDE_CRC_CD2POL_SHIFT 22
+#define MCDE_CRC_CD2POL_MASK 0x00400000
+#define MCDE_CRC_CD2POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CD2POL, __x)
+#define MCDE_CRC_WR1POL_SHIFT 23
+#define MCDE_CRC_WR1POL_MASK 0x00800000
+#define MCDE_CRC_WR1POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, WR1POL, __x)
+#define MCDE_CRC_WR2POL_SHIFT 24
+#define MCDE_CRC_WR2POL_MASK 0x01000000
+#define MCDE_CRC_WR2POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, WR2POL, __x)
+#define MCDE_CRC_RD1POL_SHIFT 25
+#define MCDE_CRC_RD1POL_MASK 0x02000000
+#define MCDE_CRC_RD1POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, RD1POL, __x)
+#define MCDE_CRC_RD2POL_SHIFT 26
+#define MCDE_CRC_RD2POL_MASK 0x04000000
+#define MCDE_CRC_RD2POL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, RD2POL, __x)
+#define MCDE_CRC_SYNCCTRL_SHIFT 29
+#define MCDE_CRC_SYNCCTRL_MASK 0x60000000
+#define MCDE_CRC_SYNCCTRL_NO_SYNC 0
+#define MCDE_CRC_SYNCCTRL_DBI0 1
+#define MCDE_CRC_SYNCCTRL_DBI1 2
+#define MCDE_CRC_SYNCCTRL_PING_PONG 3
+#define MCDE_CRC_SYNCCTRL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SYNCCTRL, MCDE_CRC_SYNCCTRL_##__x)
+#define MCDE_CRC_SYNCCTRL(__x) \
+ MCDE_VAL2REG(MCDE_CRC, SYNCCTRL, __x)
+#define MCDE_CRC_CLAMPC1EN_SHIFT 31
+#define MCDE_CRC_CLAMPC1EN_MASK 0x80000000
+#define MCDE_CRC_CLAMPC1EN(__x) \
+ MCDE_VAL2REG(MCDE_CRC, CLAMPC1EN, __x)
+#define MCDE_PBCCRC0 0x00000C04
+#define MCDE_PBCCRC0_GROUPOFFSET 0x4
+#define MCDE_PBCCRC0_BSCM_SHIFT 0
+#define MCDE_PBCCRC0_BSCM_MASK 0x00000007
+#define MCDE_PBCCRC0_BSCM_1_8BIT 0
+#define MCDE_PBCCRC0_BSCM_2_8BIT 1
+#define MCDE_PBCCRC0_BSCM_3_8BIT 2
+#define MCDE_PBCCRC0_BSCM_1_16BIT 3
+#define MCDE_PBCCRC0_BSCM_2_16BIT 4
+#define MCDE_PBCCRC0_BSCM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, BSCM, MCDE_PBCCRC0_BSCM_##__x)
+#define MCDE_PBCCRC0_BSCM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, BSCM, __x)
+#define MCDE_PBCCRC0_BSDM_SHIFT 3
+#define MCDE_PBCCRC0_BSDM_MASK 0x00000038
+#define MCDE_PBCCRC0_BSDM_1_8BIT 0
+#define MCDE_PBCCRC0_BSDM_2_8BIT 1
+#define MCDE_PBCCRC0_BSDM_3_8BIT 2
+#define MCDE_PBCCRC0_BSDM_1_16BIT 3
+#define MCDE_PBCCRC0_BSDM_2_16BIT 4
+#define MCDE_PBCCRC0_BSDM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, BSDM, MCDE_PBCCRC0_BSDM_##__x)
+#define MCDE_PBCCRC0_BSDM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, BSDM, __x)
+#define MCDE_PBCCRC0_PDM_SHIFT 6
+#define MCDE_PBCCRC0_PDM_MASK 0x000000C0
+#define MCDE_PBCCRC0_PDM_NORMAL 0
+#define MCDE_PBCCRC0_PDM_16_TO_32 1
+#define MCDE_PBCCRC0_PDM_24_TO_32_RIGHT 2
+#define MCDE_PBCCRC0_PDM_24_TO_32_LEFT 3
+#define MCDE_PBCCRC0_PDM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, PDM, MCDE_PBCCRC0_PDM_##__x)
+#define MCDE_PBCCRC0_PDM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, PDM, __x)
+#define MCDE_PBCCRC0_PDCTRL_SHIFT 12
+#define MCDE_PBCCRC0_PDCTRL_MASK 0x00001000
+#define MCDE_PBCCRC0_PDCTRL(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, PDCTRL, __x)
+#define MCDE_PBCCRC0_BPP_SHIFT 13
+#define MCDE_PBCCRC0_BPP_MASK 0x0000E000
+#define MCDE_PBCCRC0_BPP_8BPP 0
+#define MCDE_PBCCRC0_BPP_12BPP 1
+#define MCDE_PBCCRC0_BPP_15BPP 2
+#define MCDE_PBCCRC0_BPP_16BPP 3
+#define MCDE_PBCCRC0_BPP_18BPP 4
+#define MCDE_PBCCRC0_BPP_24BPP 5
+#define MCDE_PBCCRC0_BPP(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC0, BPP, __x)
+#define MCDE_PBCCRC1 0x00000C08
+#define MCDE_PBCCRC1_BSCM_SHIFT 0
+#define MCDE_PBCCRC1_BSCM_MASK 0x00000007
+#define MCDE_PBCCRC1_BSCM_1_8BIT 0
+#define MCDE_PBCCRC1_BSCM_2_8BIT 1
+#define MCDE_PBCCRC1_BSCM_3_8BIT 2
+#define MCDE_PBCCRC1_BSCM_1_16BIT 3
+#define MCDE_PBCCRC1_BSCM_2_16BIT 4
+#define MCDE_PBCCRC1_BSCM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, BSCM, MCDE_PBCCRC1_BSCM_##__x)
+#define MCDE_PBCCRC1_BSCM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, BSCM, __x)
+#define MCDE_PBCCRC1_BSDM_SHIFT 3
+#define MCDE_PBCCRC1_BSDM_MASK 0x00000038
+#define MCDE_PBCCRC1_BSDM_1_8BIT 0
+#define MCDE_PBCCRC1_BSDM_2_8BIT 1
+#define MCDE_PBCCRC1_BSDM_3_8BIT 2
+#define MCDE_PBCCRC1_BSDM_1_16BIT 3
+#define MCDE_PBCCRC1_BSDM_2_16BIT 4
+#define MCDE_PBCCRC1_BSDM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, BSDM, MCDE_PBCCRC1_BSDM_##__x)
+#define MCDE_PBCCRC1_BSDM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, BSDM, __x)
+#define MCDE_PBCCRC1_PDM_SHIFT 6
+#define MCDE_PBCCRC1_PDM_MASK 0x000000C0
+#define MCDE_PBCCRC1_PDM_NORMAL 0
+#define MCDE_PBCCRC1_PDM_16_TO_32 1
+#define MCDE_PBCCRC1_PDM_24_TO_32_RIGHT 2
+#define MCDE_PBCCRC1_PDM_24_TO_32_LEFT 3
+#define MCDE_PBCCRC1_PDM_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, PDM, MCDE_PBCCRC1_PDM_##__x)
+#define MCDE_PBCCRC1_PDM(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, PDM, __x)
+#define MCDE_PBCCRC1_PDCTRL_SHIFT 12
+#define MCDE_PBCCRC1_PDCTRL_MASK 0x00001000
+#define MCDE_PBCCRC1_PDCTRL(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, PDCTRL, __x)
+#define MCDE_PBCCRC1_BPP_SHIFT 13
+#define MCDE_PBCCRC1_BPP_MASK 0x0000E000
+#define MCDE_PBCCRC1_BPP_8BPP 0
+#define MCDE_PBCCRC1_BPP_12BPP 1
+#define MCDE_PBCCRC1_BPP_15BPP 2
+#define MCDE_PBCCRC1_BPP_16BPP 3
+#define MCDE_PBCCRC1_BPP_18BPP 4
+#define MCDE_PBCCRC1_BPP_24BPP 5
+#define MCDE_PBCCRC1_BPP(__x) \
+ MCDE_VAL2REG(MCDE_PBCCRC1, BPP, __x)
+#define MCDE_PBCBMRC00 0x00000C0C
+#define MCDE_PBCBMRC00_GROUPOFFSET 0x4
+#define MCDE_PBCBMRC00_MUXI_SHIFT 0
+#define MCDE_PBCBMRC00_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC00_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC00, MUXI, __x)
+#define MCDE_PBCBMRC01 0x00000C10
+#define MCDE_PBCBMRC01_MUXI_SHIFT 0
+#define MCDE_PBCBMRC01_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC01_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC01, MUXI, __x)
+#define MCDE_PBCBMRC02 0x00000C14
+#define MCDE_PBCBMRC02_MUXI_SHIFT 0
+#define MCDE_PBCBMRC02_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC02_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC02, MUXI, __x)
+#define MCDE_PBCBMRC03 0x00000C18
+#define MCDE_PBCBMRC03_MUXI_SHIFT 0
+#define MCDE_PBCBMRC03_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC03_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC03, MUXI, __x)
+#define MCDE_PBCBMRC04 0x00000C1C
+#define MCDE_PBCBMRC04_MUXI_SHIFT 0
+#define MCDE_PBCBMRC04_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC04_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC04, MUXI, __x)
+#define MCDE_PBCBMRC10 0x00000C20
+#define MCDE_PBCBMRC10_MUXI_SHIFT 0
+#define MCDE_PBCBMRC10_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC10_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC10, MUXI, __x)
+#define MCDE_PBCBMRC11 0x00000C24
+#define MCDE_PBCBMRC11_MUXI_SHIFT 0
+#define MCDE_PBCBMRC11_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC11_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC11, MUXI, __x)
+#define MCDE_PBCBMRC12 0x00000C28
+#define MCDE_PBCBMRC12_MUXI_SHIFT 0
+#define MCDE_PBCBMRC12_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC12_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC12, MUXI, __x)
+#define MCDE_PBCBMRC13 0x00000C2C
+#define MCDE_PBCBMRC13_MUXI_SHIFT 0
+#define MCDE_PBCBMRC13_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC13_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC13, MUXI, __x)
+#define MCDE_PBCBMRC14 0x00000C30
+#define MCDE_PBCBMRC14_MUXI_SHIFT 0
+#define MCDE_PBCBMRC14_MUXI_MASK 0xFFFFFFFF
+#define MCDE_PBCBMRC14_MUXI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBMRC14, MUXI, __x)
+#define MCDE_PBCBCRC00 0x00000C34
+#define MCDE_PBCBCRC00_GROUPOFFSET 0x4
+#define MCDE_PBCBCRC00_CTLI_SHIFT 0
+#define MCDE_PBCBCRC00_CTLI_MASK 0xFFFFFFFF
+#define MCDE_PBCBCRC00_CTLI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBCRC00, CTLI, __x)
+#define MCDE_PBCBCRC10 0x00000C38
+#define MCDE_PBCBCRC10_CTLI_SHIFT 0
+#define MCDE_PBCBCRC10_CTLI_MASK 0xFFFFFFFF
+#define MCDE_PBCBCRC10_CTLI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBCRC10, CTLI, __x)
+#define MCDE_PBCBCRC01 0x00000C48
+#define MCDE_PBCBCRC01_GROUPOFFSET 0x4
+#define MCDE_PBCBCRC01_CTLI_SHIFT 0
+#define MCDE_PBCBCRC01_CTLI_MASK 0xFFFFFFFF
+#define MCDE_PBCBCRC01_CTLI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBCRC01, CTLI, __x)
+#define MCDE_PBCBCRC11 0x00000C4C
+#define MCDE_PBCBCRC11_CTLI_SHIFT 0
+#define MCDE_PBCBCRC11_CTLI_MASK 0xFFFFFFFF
+#define MCDE_PBCBCRC11_CTLI(__x) \
+ MCDE_VAL2REG(MCDE_PBCBCRC11, CTLI, __x)
+#define MCDE_VSCRC0 0x00000C5C
+#define MCDE_VSCRC0_GROUPOFFSET 0x4
+#define MCDE_VSCRC0_VSPMIN_SHIFT 0
+#define MCDE_VSCRC0_VSPMIN_MASK 0x00000FFF
+#define MCDE_VSCRC0_VSPMIN(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPMIN, __x)
+#define MCDE_VSCRC0_VSPMAX_SHIFT 12
+#define MCDE_VSCRC0_VSPMAX_MASK 0x00FFF000
+#define MCDE_VSCRC0_VSPMAX(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPMAX, __x)
+#define MCDE_VSCRC0_VSPDIV_SHIFT 24
+#define MCDE_VSCRC0_VSPDIV_MASK 0x07000000
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_1 0
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_2 1
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_4 2
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_8 3
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_16 4
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_32 5
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_64 6
+#define MCDE_VSCRC0_VSPDIV_MCDECLK_DIV_128 7
+#define MCDE_VSCRC0_VSPDIV_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPDIV, MCDE_VSCRC0_VSPDIV_##__x)
+#define MCDE_VSCRC0_VSPDIV(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPDIV, __x)
+#define MCDE_VSCRC0_VSPOL_SHIFT 27
+#define MCDE_VSCRC0_VSPOL_MASK 0x08000000
+#define MCDE_VSCRC0_VSPOL_ACTIVE_HIGH 0
+#define MCDE_VSCRC0_VSPOL_ACTIVE_LOW 1
+#define MCDE_VSCRC0_VSPOL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPOL, MCDE_VSCRC0_VSPOL_##__x)
+#define MCDE_VSCRC0_VSPOL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSPOL, __x)
+#define MCDE_VSCRC0_VSSEL_SHIFT 28
+#define MCDE_VSCRC0_VSSEL_MASK 0x10000000
+#define MCDE_VSCRC0_VSSEL_VSYNC0 0
+#define MCDE_VSCRC0_VSSEL_VSYNC1 1
+#define MCDE_VSCRC0_VSSEL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSSEL, MCDE_VSCRC0_VSSEL_##__x)
+#define MCDE_VSCRC0_VSSEL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSSEL, __x)
+#define MCDE_VSCRC0_VSDBL_SHIFT 29
+#define MCDE_VSCRC0_VSDBL_MASK 0xE0000000
+#define MCDE_VSCRC0_VSDBL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC0, VSDBL, __x)
+#define MCDE_VSCRC1 0x00000C60
+#define MCDE_VSCRC1_VSPMIN_SHIFT 0
+#define MCDE_VSCRC1_VSPMIN_MASK 0x00000FFF
+#define MCDE_VSCRC1_VSPMIN(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPMIN, __x)
+#define MCDE_VSCRC1_VSPMAX_SHIFT 12
+#define MCDE_VSCRC1_VSPMAX_MASK 0x00FFF000
+#define MCDE_VSCRC1_VSPMAX(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPMAX, __x)
+#define MCDE_VSCRC1_VSPDIV_SHIFT 24
+#define MCDE_VSCRC1_VSPDIV_MASK 0x07000000
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_1 0
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_2 1
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_4 2
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_8 3
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_16 4
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_32 5
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_64 6
+#define MCDE_VSCRC1_VSPDIV_MCDECLK_DIV_128 7
+#define MCDE_VSCRC1_VSPDIV_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPDIV, MCDE_VSCRC1_VSPDIV_##__x)
+#define MCDE_VSCRC1_VSPDIV(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPDIV, __x)
+#define MCDE_VSCRC1_VSPOL_SHIFT 27
+#define MCDE_VSCRC1_VSPOL_MASK 0x08000000
+#define MCDE_VSCRC1_VSPOL_ACTIVE_HIGH 0
+#define MCDE_VSCRC1_VSPOL_ACTIVE_LOW 1
+#define MCDE_VSCRC1_VSPOL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPOL, MCDE_VSCRC1_VSPOL_##__x)
+#define MCDE_VSCRC1_VSPOL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSPOL, __x)
+#define MCDE_VSCRC1_VSSEL_SHIFT 28
+#define MCDE_VSCRC1_VSSEL_MASK 0x10000000
+#define MCDE_VSCRC1_VSSEL_VSYNC0 0
+#define MCDE_VSCRC1_VSSEL_VSYNC1 1
+#define MCDE_VSCRC1_VSSEL_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSSEL, MCDE_VSCRC1_VSSEL_##__x)
+#define MCDE_VSCRC1_VSSEL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSSEL, __x)
+#define MCDE_VSCRC1_VSDBL_SHIFT 29
+#define MCDE_VSCRC1_VSDBL_MASK 0xE0000000
+#define MCDE_VSCRC1_VSDBL(__x) \
+ MCDE_VAL2REG(MCDE_VSCRC1, VSDBL, __x)
+#define MCDE_SCTRC 0x00000C64
+#define MCDE_SCTRC_SYNCDELC0_SHIFT 0
+#define MCDE_SCTRC_SYNCDELC0_MASK 0x000000FF
+#define MCDE_SCTRC_SYNCDELC0(__x) \
+ MCDE_VAL2REG(MCDE_SCTRC, SYNCDELC0, __x)
+#define MCDE_SCTRC_SYNCDELC1_SHIFT 8
+#define MCDE_SCTRC_SYNCDELC1_MASK 0x0000FF00
+#define MCDE_SCTRC_SYNCDELC1(__x) \
+ MCDE_VAL2REG(MCDE_SCTRC, SYNCDELC1, __x)
+#define MCDE_SCTRC_TRDELC_SHIFT 16
+#define MCDE_SCTRC_TRDELC_MASK 0x0FFF0000
+#define MCDE_SCTRC_TRDELC(__x) \
+ MCDE_VAL2REG(MCDE_SCTRC, TRDELC, __x)
+#define MCDE_SCSRC 0x00000C68
+#define MCDE_SCSRC_VSTAC0_SHIFT 0
+#define MCDE_SCSRC_VSTAC0_MASK 0x00000001
+#define MCDE_SCSRC_VSTAC0(__x) \
+ MCDE_VAL2REG(MCDE_SCSRC, VSTAC0, __x)
+#define MCDE_SCSRC_VSTAC1_SHIFT 1
+#define MCDE_SCSRC_VSTAC1_MASK 0x00000002
+#define MCDE_SCSRC_VSTAC1(__x) \
+ MCDE_VAL2REG(MCDE_SCSRC, VSTAC1, __x)
+#define MCDE_BCNR0 0x00000C6C
+#define MCDE_BCNR0_GROUPOFFSET 0x4
+#define MCDE_BCNR0_BCN_SHIFT 0
+#define MCDE_BCNR0_BCN_MASK 0x000000FF
+#define MCDE_BCNR0_BCN(__x) \
+ MCDE_VAL2REG(MCDE_BCNR0, BCN, __x)
+#define MCDE_BCNR1 0x00000C70
+#define MCDE_BCNR1_BCN_SHIFT 0
+#define MCDE_BCNR1_BCN_MASK 0x000000FF
+#define MCDE_BCNR1_BCN(__x) \
+ MCDE_VAL2REG(MCDE_BCNR1, BCN, __x)
+#define MCDE_CSCDTR0 0x00000C74
+#define MCDE_CSCDTR0_GROUPOFFSET 0x4
+#define MCDE_CSCDTR0_CSACT_SHIFT 0
+#define MCDE_CSCDTR0_CSACT_MASK 0x000000FF
+#define MCDE_CSCDTR0_CSACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR0, CSACT, __x)
+#define MCDE_CSCDTR0_CSDEACT_SHIFT 8
+#define MCDE_CSCDTR0_CSDEACT_MASK 0x0000FF00
+#define MCDE_CSCDTR0_CSDEACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR0, CSDEACT, __x)
+#define MCDE_CSCDTR0_CDACT_SHIFT 16
+#define MCDE_CSCDTR0_CDACT_MASK 0x00FF0000
+#define MCDE_CSCDTR0_CDACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR0, CDACT, __x)
+#define MCDE_CSCDTR0_CDDEACT_SHIFT 24
+#define MCDE_CSCDTR0_CDDEACT_MASK 0xFF000000
+#define MCDE_CSCDTR0_CDDEACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR0, CDDEACT, __x)
+#define MCDE_CSCDTR1 0x00000C78
+#define MCDE_CSCDTR1_CSACT_SHIFT 0
+#define MCDE_CSCDTR1_CSACT_MASK 0x000000FF
+#define MCDE_CSCDTR1_CSACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR1, CSACT, __x)
+#define MCDE_CSCDTR1_CSDEACT_SHIFT 8
+#define MCDE_CSCDTR1_CSDEACT_MASK 0x0000FF00
+#define MCDE_CSCDTR1_CSDEACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR1, CSDEACT, __x)
+#define MCDE_CSCDTR1_CDACT_SHIFT 16
+#define MCDE_CSCDTR1_CDACT_MASK 0x00FF0000
+#define MCDE_CSCDTR1_CDACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR1, CDACT, __x)
+#define MCDE_CSCDTR1_CDDEACT_SHIFT 24
+#define MCDE_CSCDTR1_CDDEACT_MASK 0xFF000000
+#define MCDE_CSCDTR1_CDDEACT(__x) \
+ MCDE_VAL2REG(MCDE_CSCDTR1, CDDEACT, __x)
+#define MCDE_RDWRTR0 0x00000C7C
+#define MCDE_RDWRTR0_GROUPOFFSET 0x4
+#define MCDE_RDWRTR0_RWACT_SHIFT 0
+#define MCDE_RDWRTR0_RWACT_MASK 0x000000FF
+#define MCDE_RDWRTR0_RWACT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR0, RWACT, __x)
+#define MCDE_RDWRTR0_RWDEACT_SHIFT 8
+#define MCDE_RDWRTR0_RWDEACT_MASK 0x0000FF00
+#define MCDE_RDWRTR0_RWDEACT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR0, RWDEACT, __x)
+#define MCDE_RDWRTR0_MOTINT_SHIFT 16
+#define MCDE_RDWRTR0_MOTINT_MASK 0x00010000
+#define MCDE_RDWRTR0_MOTINT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR0, MOTINT, __x)
+#define MCDE_RDWRTR1 0x00000C80
+#define MCDE_RDWRTR1_RWACT_SHIFT 0
+#define MCDE_RDWRTR1_RWACT_MASK 0x000000FF
+#define MCDE_RDWRTR1_RWACT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR1, RWACT, __x)
+#define MCDE_RDWRTR1_RWDEACT_SHIFT 8
+#define MCDE_RDWRTR1_RWDEACT_MASK 0x0000FF00
+#define MCDE_RDWRTR1_RWDEACT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR1, RWDEACT, __x)
+#define MCDE_RDWRTR1_MOTINT_SHIFT 16
+#define MCDE_RDWRTR1_MOTINT_MASK 0x00010000
+#define MCDE_RDWRTR1_MOTINT(__x) \
+ MCDE_VAL2REG(MCDE_RDWRTR1, MOTINT, __x)
+#define MCDE_DOTR0 0x00000C84
+#define MCDE_DOTR0_GROUPOFFSET 0x4
+#define MCDE_DOTR0_DOACT_SHIFT 0
+#define MCDE_DOTR0_DOACT_MASK 0x000000FF
+#define MCDE_DOTR0_DOACT(__x) \
+ MCDE_VAL2REG(MCDE_DOTR0, DOACT, __x)
+#define MCDE_DOTR0_DODEACT_SHIFT 8
+#define MCDE_DOTR0_DODEACT_MASK 0x0000FF00
+#define MCDE_DOTR0_DODEACT(__x) \
+ MCDE_VAL2REG(MCDE_DOTR0, DODEACT, __x)
+#define MCDE_DOTR1 0x00000C88
+#define MCDE_DOTR1_DOACT_SHIFT 0
+#define MCDE_DOTR1_DOACT_MASK 0x000000FF
+#define MCDE_DOTR1_DOACT(__x) \
+ MCDE_VAL2REG(MCDE_DOTR1, DOACT, __x)
+#define MCDE_DOTR1_DODEACT_SHIFT 8
+#define MCDE_DOTR1_DODEACT_MASK 0x0000FF00
+#define MCDE_DOTR1_DODEACT(__x) \
+ MCDE_VAL2REG(MCDE_DOTR1, DODEACT, __x)
+#define MCDE_WDATADC0 0x00000C94
+#define MCDE_WDATADC0_GROUPOFFSET 0x4
+#define MCDE_WDATADC0_DATAVALUE_SHIFT 0
+#define MCDE_WDATADC0_DATAVALUE_MASK 0x00FFFFFF
+#define MCDE_WDATADC0_DATAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_WDATADC0, DATAVALUE, __x)
+#define MCDE_WDATADC0_DC_SHIFT 24
+#define MCDE_WDATADC0_DC_MASK 0x01000000
+#define MCDE_WDATADC0_DC(__x) \
+ MCDE_VAL2REG(MCDE_WDATADC0, DC, __x)
+#define MCDE_WDATADC1 0x00000C98
+#define MCDE_WDATADC1_DATAVALUE_SHIFT 0
+#define MCDE_WDATADC1_DATAVALUE_MASK 0x00FFFFFF
+#define MCDE_WDATADC1_DATAVALUE(__x) \
+ MCDE_VAL2REG(MCDE_WDATADC1, DATAVALUE, __x)
+#define MCDE_WDATADC1_DC_SHIFT 24
+#define MCDE_WDATADC1_DC_MASK 0x01000000
+#define MCDE_WDATADC1_DC(__x) \
+ MCDE_VAL2REG(MCDE_WDATADC1, DC, __x)
+#define MCDE_RDATADC0 0x00000C9C
+#define MCDE_RDATADC0_GROUPOFFSET 0x4
+#define MCDE_RDATADC0_DATAREADFROMDISPLAYMODULE_SHIFT 0
+#define MCDE_RDATADC0_DATAREADFROMDISPLAYMODULE_MASK 0x0000FFFF
+#define MCDE_RDATADC0_DATAREADFROMDISPLAYMODULE(__x) \
+ MCDE_VAL2REG(MCDE_RDATADC0, DATAREADFROMDISPLAYMODULE, __x)
+#define MCDE_RDATADC0_STARTREAD_SHIFT 16
+#define MCDE_RDATADC0_STARTREAD_MASK 0x00010000
+#define MCDE_RDATADC0_STARTREAD(__x) \
+ MCDE_VAL2REG(MCDE_RDATADC0, STARTREAD, __x)
+#define MCDE_RDATADC1 0x00000CA0
+#define MCDE_RDATADC1_DATAREADFROMDISPLAYMODULE_SHIFT 0
+#define MCDE_RDATADC1_DATAREADFROMDISPLAYMODULE_MASK 0x0000FFFF
+#define MCDE_RDATADC1_DATAREADFROMDISPLAYMODULE(__x) \
+ MCDE_VAL2REG(MCDE_RDATADC1, DATAREADFROMDISPLAYMODULE, __x)
+#define MCDE_RDATADC1_STARTREAD_SHIFT 16
+#define MCDE_RDATADC1_STARTREAD_MASK 0x00010000
+#define MCDE_RDATADC1_STARTREAD(__x) \
+ MCDE_VAL2REG(MCDE_RDATADC1, STARTREAD, __x)
+#define MCDE_STATC 0x00000CA4
+#define MCDE_STATC_STATBUSY0_SHIFT 0
+#define MCDE_STATC_STATBUSY0_MASK 0x00000001
+#define MCDE_STATC_STATBUSY0(__x) \
+ MCDE_VAL2REG(MCDE_STATC, STATBUSY0, __x)
+#define MCDE_STATC_STATBUSY1_SHIFT 5
+#define MCDE_STATC_STATBUSY1_MASK 0x00000020
+#define MCDE_STATC_STATBUSY1(__x) \
+ MCDE_VAL2REG(MCDE_STATC, STATBUSY1, __x)
+#define MCDE_CTRLC0 0x00000CA8
+#define MCDE_CTRLC0_GROUPOFFSET 0x4
+#define MCDE_CTRLC0_FIFOWTRMRK_SHIFT 0
+#define MCDE_CTRLC0_FIFOWTRMRK_MASK 0x000000FF
+#define MCDE_CTRLC0_FIFOWTRMRK(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FIFOWTRMRK, __x)
+#define MCDE_CTRLC0_FIFOEMPTY_SHIFT 12
+#define MCDE_CTRLC0_FIFOEMPTY_MASK 0x00001000
+#define MCDE_CTRLC0_FIFOEMPTY(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FIFOEMPTY, __x)
+#define MCDE_CTRLC0_FIFOFULL_SHIFT 13
+#define MCDE_CTRLC0_FIFOFULL_MASK 0x00002000
+#define MCDE_CTRLC0_FIFOFULL(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FIFOFULL, __x)
+#define MCDE_CTRLC0_FORMID_SHIFT 16
+#define MCDE_CTRLC0_FORMID_MASK 0x00070000
+#define MCDE_CTRLC0_FORMID_DSI0VID 0
+#define MCDE_CTRLC0_FORMID_DSI0CMD 1
+#define MCDE_CTRLC0_FORMID_DSI1VID 2
+#define MCDE_CTRLC0_FORMID_DSI1CMD 3
+#define MCDE_CTRLC0_FORMID_DSI2VID 4
+#define MCDE_CTRLC0_FORMID_DSI2CMD 5
+#define MCDE_CTRLC0_FORMID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FORMID, MCDE_CTRLC0_FORMID_##__x)
+#define MCDE_CTRLC0_FORMID(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FORMID, __x)
+#define MCDE_CTRLC0_FORMTYPE_SHIFT 20
+#define MCDE_CTRLC0_FORMTYPE_MASK 0x00700000
+#define MCDE_CTRLC0_FORMTYPE_DPITV 0
+#define MCDE_CTRLC0_FORMTYPE_DBI 1
+#define MCDE_CTRLC0_FORMTYPE_DSI 2
+#define MCDE_CTRLC0_FORMTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FORMTYPE, MCDE_CTRLC0_FORMTYPE_##__x)
+#define MCDE_CTRLC0_FORMTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC0, FORMTYPE, __x)
+#define MCDE_CTRLC1 0x00000CAC
+#define MCDE_CTRLC1_FIFOWTRMRK_SHIFT 0
+#define MCDE_CTRLC1_FIFOWTRMRK_MASK 0x000000FF
+#define MCDE_CTRLC1_FIFOWTRMRK(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FIFOWTRMRK, __x)
+#define MCDE_CTRLC1_FIFOEMPTY_SHIFT 12
+#define MCDE_CTRLC1_FIFOEMPTY_MASK 0x00001000
+#define MCDE_CTRLC1_FIFOEMPTY(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FIFOEMPTY, __x)
+#define MCDE_CTRLC1_FIFOFULL_SHIFT 13
+#define MCDE_CTRLC1_FIFOFULL_MASK 0x00002000
+#define MCDE_CTRLC1_FIFOFULL(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FIFOFULL, __x)
+#define MCDE_CTRLC1_FORMID_SHIFT 16
+#define MCDE_CTRLC1_FORMID_MASK 0x00070000
+#define MCDE_CTRLC1_FORMID_DSI0VID 0
+#define MCDE_CTRLC1_FORMID_DSI0CMD 1
+#define MCDE_CTRLC1_FORMID_DSI1VID 2
+#define MCDE_CTRLC1_FORMID_DSI1CMD 3
+#define MCDE_CTRLC1_FORMID_DSI2VID 4
+#define MCDE_CTRLC1_FORMID_DSI2CMD 5
+#define MCDE_CTRLC1_FORMID_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FORMID, MCDE_CTRLC1_FORMID_##__x)
+#define MCDE_CTRLC1_FORMID(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FORMID, __x)
+#define MCDE_CTRLC1_FORMTYPE_SHIFT 20
+#define MCDE_CTRLC1_FORMTYPE_MASK 0x00700000
+#define MCDE_CTRLC1_FORMTYPE_DPITV 0
+#define MCDE_CTRLC1_FORMTYPE_DBI 1
+#define MCDE_CTRLC1_FORMTYPE_DSI 2
+#define MCDE_CTRLC1_FORMTYPE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FORMTYPE, MCDE_CTRLC1_FORMTYPE_##__x)
+#define MCDE_CTRLC1_FORMTYPE(__x) \
+ MCDE_VAL2REG(MCDE_CTRLC1, FORMTYPE, __x)
+#define MCDE_DSIVID0CONF0 0x00000E00
+#define MCDE_DSIVID0CONF0_GROUPOFFSET 0x20
+#define MCDE_DSIVID0CONF0_BLANKING_SHIFT 0
+#define MCDE_DSIVID0CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSIVID0CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, BLANKING, __x)
+#define MCDE_DSIVID0CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSIVID0CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSIVID0CONF0_VID_MODE_CMD 0
+#define MCDE_DSIVID0CONF0_VID_MODE_VID 1
+#define MCDE_DSIVID0CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, VID_MODE, \
+ MCDE_DSIVID0CONF0_VID_MODE_##__x)
+#define MCDE_DSIVID0CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, VID_MODE, __x)
+#define MCDE_DSIVID0CONF0_CMD8_SHIFT 13
+#define MCDE_DSIVID0CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSIVID0CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, CMD8, __x)
+#define MCDE_DSIVID0CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSIVID0CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSIVID0CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, BIT_SWAP, __x)
+#define MCDE_DSIVID0CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSIVID0CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSIVID0CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, BYTE_SWAP, __x)
+#define MCDE_DSIVID0CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSIVID0CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSIVID0CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSIVID0CONF0_PACKING_SHIFT 20
+#define MCDE_DSIVID0CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSIVID0CONF0_PACKING_RGB565 0
+#define MCDE_DSIVID0CONF0_PACKING_RGB666 1
+#define MCDE_DSIVID0CONF0_PACKING_RGB888 2
+#define MCDE_DSIVID0CONF0_PACKING_BGR888 3
+#define MCDE_DSIVID0CONF0_PACKING_HDTV 4
+#define MCDE_DSIVID0CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, PACKING, \
+ MCDE_DSIVID0CONF0_PACKING_##__x)
+#define MCDE_DSIVID0CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CONF0, PACKING, __x)
+#define MCDE_DSICMD0CONF0 0x00000E20
+#define MCDE_DSICMD0CONF0_BLANKING_SHIFT 0
+#define MCDE_DSICMD0CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSICMD0CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, BLANKING, __x)
+#define MCDE_DSICMD0CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSICMD0CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSICMD0CONF0_VID_MODE_CMD 0
+#define MCDE_DSICMD0CONF0_VID_MODE_VID 1
+#define MCDE_DSICMD0CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, VID_MODE, \
+ MCDE_DSICMD0CONF0_VID_MODE_##__x)
+#define MCDE_DSICMD0CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, VID_MODE, __x)
+#define MCDE_DSICMD0CONF0_CMD8_SHIFT 13
+#define MCDE_DSICMD0CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSICMD0CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, CMD8, __x)
+#define MCDE_DSICMD0CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSICMD0CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSICMD0CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, BIT_SWAP, __x)
+#define MCDE_DSICMD0CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSICMD0CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSICMD0CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, BYTE_SWAP, __x)
+#define MCDE_DSICMD0CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSICMD0CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSICMD0CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSICMD0CONF0_PACKING_SHIFT 20
+#define MCDE_DSICMD0CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSICMD0CONF0_PACKING_RGB565 0
+#define MCDE_DSICMD0CONF0_PACKING_RGB666 1
+#define MCDE_DSICMD0CONF0_PACKING_RGB888 2
+#define MCDE_DSICMD0CONF0_PACKING_BGR888 3
+#define MCDE_DSICMD0CONF0_PACKING_HDTV 4
+#define MCDE_DSICMD0CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, PACKING, \
+ MCDE_DSICMD0CONF0_PACKING_##__x)
+#define MCDE_DSICMD0CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CONF0, PACKING, __x)
+#define MCDE_DSIVID1CONF0 0x00000E40
+#define MCDE_DSIVID1CONF0_BLANKING_SHIFT 0
+#define MCDE_DSIVID1CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSIVID1CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, BLANKING, __x)
+#define MCDE_DSIVID1CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSIVID1CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSIVID1CONF0_VID_MODE_CMD 0
+#define MCDE_DSIVID1CONF0_VID_MODE_VID 1
+#define MCDE_DSIVID1CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, VID_MODE, \
+ MCDE_DSIVID1CONF0_VID_MODE_##__x)
+#define MCDE_DSIVID1CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, VID_MODE, __x)
+#define MCDE_DSIVID1CONF0_CMD8_SHIFT 13
+#define MCDE_DSIVID1CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSIVID1CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, CMD8, __x)
+#define MCDE_DSIVID1CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSIVID1CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSIVID1CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, BIT_SWAP, __x)
+#define MCDE_DSIVID1CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSIVID1CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSIVID1CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, BYTE_SWAP, __x)
+#define MCDE_DSIVID1CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSIVID1CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSIVID1CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSIVID1CONF0_PACKING_SHIFT 20
+#define MCDE_DSIVID1CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSIVID1CONF0_PACKING_RGB565 0
+#define MCDE_DSIVID1CONF0_PACKING_RGB666 1
+#define MCDE_DSIVID1CONF0_PACKING_RGB888 2
+#define MCDE_DSIVID1CONF0_PACKING_BGR888 3
+#define MCDE_DSIVID1CONF0_PACKING_HDTV 4
+#define MCDE_DSIVID1CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, PACKING, \
+ MCDE_DSIVID1CONF0_PACKING_##__x)
+#define MCDE_DSIVID1CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CONF0, PACKING, __x)
+#define MCDE_DSICMD1CONF0 0x00000E60
+#define MCDE_DSICMD1CONF0_BLANKING_SHIFT 0
+#define MCDE_DSICMD1CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSICMD1CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, BLANKING, __x)
+#define MCDE_DSICMD1CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSICMD1CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSICMD1CONF0_VID_MODE_CMD 0
+#define MCDE_DSICMD1CONF0_VID_MODE_VID 1
+#define MCDE_DSICMD1CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, VID_MODE, \
+ MCDE_DSICMD1CONF0_VID_MODE_##__x)
+#define MCDE_DSICMD1CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, VID_MODE, __x)
+#define MCDE_DSICMD1CONF0_CMD8_SHIFT 13
+#define MCDE_DSICMD1CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSICMD1CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, CMD8, __x)
+#define MCDE_DSICMD1CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSICMD1CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSICMD1CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, BIT_SWAP, __x)
+#define MCDE_DSICMD1CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSICMD1CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSICMD1CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, BYTE_SWAP, __x)
+#define MCDE_DSICMD1CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSICMD1CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSICMD1CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSICMD1CONF0_PACKING_SHIFT 20
+#define MCDE_DSICMD1CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSICMD1CONF0_PACKING_RGB565 0
+#define MCDE_DSICMD1CONF0_PACKING_RGB666 1
+#define MCDE_DSICMD1CONF0_PACKING_RGB888 2
+#define MCDE_DSICMD1CONF0_PACKING_BGR888 3
+#define MCDE_DSICMD1CONF0_PACKING_HDTV 4
+#define MCDE_DSICMD1CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, PACKING, \
+ MCDE_DSICMD1CONF0_PACKING_##__x)
+#define MCDE_DSICMD1CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CONF0, PACKING, __x)
+#define MCDE_DSIVID2CONF0 0x00000E80
+#define MCDE_DSIVID2CONF0_BLANKING_SHIFT 0
+#define MCDE_DSIVID2CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSIVID2CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, BLANKING, __x)
+#define MCDE_DSIVID2CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSIVID2CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSIVID2CONF0_VID_MODE_CMD 0
+#define MCDE_DSIVID2CONF0_VID_MODE_VID 1
+#define MCDE_DSIVID2CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, VID_MODE, \
+ MCDE_DSIVID2CONF0_VID_MODE_##__x)
+#define MCDE_DSIVID2CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, VID_MODE, __x)
+#define MCDE_DSIVID2CONF0_CMD8_SHIFT 13
+#define MCDE_DSIVID2CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSIVID2CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, CMD8, __x)
+#define MCDE_DSIVID2CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSIVID2CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSIVID2CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, BIT_SWAP, __x)
+#define MCDE_DSIVID2CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSIVID2CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSIVID2CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, BYTE_SWAP, __x)
+#define MCDE_DSIVID2CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSIVID2CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSIVID2CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSIVID2CONF0_PACKING_SHIFT 20
+#define MCDE_DSIVID2CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSIVID2CONF0_PACKING_RGB565 0
+#define MCDE_DSIVID2CONF0_PACKING_RGB666 1
+#define MCDE_DSIVID2CONF0_PACKING_RGB888 2
+#define MCDE_DSIVID2CONF0_PACKING_BGR888 3
+#define MCDE_DSIVID2CONF0_PACKING_HDTV 4
+#define MCDE_DSIVID2CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, PACKING, \
+ MCDE_DSIVID2CONF0_PACKING_##__x)
+#define MCDE_DSIVID2CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CONF0, PACKING, __x)
+#define MCDE_DSICMD2CONF0 0x00000EA0
+#define MCDE_DSICMD2CONF0_BLANKING_SHIFT 0
+#define MCDE_DSICMD2CONF0_BLANKING_MASK 0x000000FF
+#define MCDE_DSICMD2CONF0_BLANKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, BLANKING, __x)
+#define MCDE_DSICMD2CONF0_VID_MODE_SHIFT 12
+#define MCDE_DSICMD2CONF0_VID_MODE_MASK 0x00001000
+#define MCDE_DSICMD2CONF0_VID_MODE_CMD 0
+#define MCDE_DSICMD2CONF0_VID_MODE_VID 1
+#define MCDE_DSICMD2CONF0_VID_MODE_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, VID_MODE, \
+ MCDE_DSICMD2CONF0_VID_MODE_##__x)
+#define MCDE_DSICMD2CONF0_VID_MODE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, VID_MODE, __x)
+#define MCDE_DSICMD2CONF0_CMD8_SHIFT 13
+#define MCDE_DSICMD2CONF0_CMD8_MASK 0x00002000
+#define MCDE_DSICMD2CONF0_CMD8(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, CMD8, __x)
+#define MCDE_DSICMD2CONF0_BIT_SWAP_SHIFT 16
+#define MCDE_DSICMD2CONF0_BIT_SWAP_MASK 0x00010000
+#define MCDE_DSICMD2CONF0_BIT_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, BIT_SWAP, __x)
+#define MCDE_DSICMD2CONF0_BYTE_SWAP_SHIFT 17
+#define MCDE_DSICMD2CONF0_BYTE_SWAP_MASK 0x00020000
+#define MCDE_DSICMD2CONF0_BYTE_SWAP(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, BYTE_SWAP, __x)
+#define MCDE_DSICMD2CONF0_DCSVID_NOTGEN_SHIFT 18
+#define MCDE_DSICMD2CONF0_DCSVID_NOTGEN_MASK 0x00040000
+#define MCDE_DSICMD2CONF0_DCSVID_NOTGEN(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, DCSVID_NOTGEN, __x)
+#define MCDE_DSICMD2CONF0_PACKING_SHIFT 20
+#define MCDE_DSICMD2CONF0_PACKING_MASK 0x00700000
+#define MCDE_DSICMD2CONF0_PACKING_RGB565 0
+#define MCDE_DSICMD2CONF0_PACKING_RGB666 1
+#define MCDE_DSICMD2CONF0_PACKING_RGB888 2
+#define MCDE_DSICMD2CONF0_PACKING_BGR888 3
+#define MCDE_DSICMD2CONF0_PACKING_HDTV 4
+#define MCDE_DSICMD2CONF0_PACKING_ENUM(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, PACKING, \
+ MCDE_DSICMD2CONF0_PACKING_##__x)
+#define MCDE_DSICMD2CONF0_PACKING(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CONF0, PACKING, __x)
+#define MCDE_DSIVID0FRAME 0x00000E04
+#define MCDE_DSIVID0FRAME_GROUPOFFSET 0x20
+#define MCDE_DSIVID0FRAME_FRAME_SHIFT 0
+#define MCDE_DSIVID0FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSIVID0FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0FRAME, FRAME, __x)
+#define MCDE_DSICMD0FRAME 0x00000E24
+#define MCDE_DSICMD0FRAME_FRAME_SHIFT 0
+#define MCDE_DSICMD0FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSICMD0FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0FRAME, FRAME, __x)
+#define MCDE_DSIVID1FRAME 0x00000E44
+#define MCDE_DSIVID1FRAME_FRAME_SHIFT 0
+#define MCDE_DSIVID1FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSIVID1FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1FRAME, FRAME, __x)
+#define MCDE_DSICMD1FRAME 0x00000E64
+#define MCDE_DSICMD1FRAME_FRAME_SHIFT 0
+#define MCDE_DSICMD1FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSICMD1FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1FRAME, FRAME, __x)
+#define MCDE_DSIVID2FRAME 0x00000E84
+#define MCDE_DSIVID2FRAME_FRAME_SHIFT 0
+#define MCDE_DSIVID2FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSIVID2FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2FRAME, FRAME, __x)
+#define MCDE_DSICMD2FRAME 0x00000EA4
+#define MCDE_DSICMD2FRAME_FRAME_SHIFT 0
+#define MCDE_DSICMD2FRAME_FRAME_MASK 0x00FFFFFF
+#define MCDE_DSICMD2FRAME_FRAME(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2FRAME, FRAME, __x)
+#define MCDE_DSIVID0PKT 0x00000E08
+#define MCDE_DSIVID0PKT_GROUPOFFSET 0x20
+#define MCDE_DSIVID0PKT_PACKET_SHIFT 0
+#define MCDE_DSIVID0PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSIVID0PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0PKT, PACKET, __x)
+#define MCDE_DSICMD0PKT 0x00000E28
+#define MCDE_DSICMD0PKT_PACKET_SHIFT 0
+#define MCDE_DSICMD0PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSICMD0PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0PKT, PACKET, __x)
+#define MCDE_DSIVID1PKT 0x00000E48
+#define MCDE_DSIVID1PKT_PACKET_SHIFT 0
+#define MCDE_DSIVID1PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSIVID1PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1PKT, PACKET, __x)
+#define MCDE_DSICMD1PKT 0x00000E68
+#define MCDE_DSICMD1PKT_PACKET_SHIFT 0
+#define MCDE_DSICMD1PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSICMD1PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1PKT, PACKET, __x)
+#define MCDE_DSIVID2PKT 0x00000E88
+#define MCDE_DSIVID2PKT_PACKET_SHIFT 0
+#define MCDE_DSIVID2PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSIVID2PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2PKT, PACKET, __x)
+#define MCDE_DSICMD2PKT 0x00000EA8
+#define MCDE_DSICMD2PKT_PACKET_SHIFT 0
+#define MCDE_DSICMD2PKT_PACKET_MASK 0x0000FFFF
+#define MCDE_DSICMD2PKT_PACKET(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2PKT, PACKET, __x)
+#define MCDE_DSIVID0SYNC 0x00000E0C
+#define MCDE_DSIVID0SYNC_GROUPOFFSET 0x20
+#define MCDE_DSIVID0SYNC_DMA_SHIFT 0
+#define MCDE_DSIVID0SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSIVID0SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0SYNC, DMA, __x)
+#define MCDE_DSIVID0SYNC_SW_SHIFT 16
+#define MCDE_DSIVID0SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSIVID0SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0SYNC, SW, __x)
+#define MCDE_DSICMD0SYNC 0x00000E2C
+#define MCDE_DSICMD0SYNC_DMA_SHIFT 0
+#define MCDE_DSICMD0SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSICMD0SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0SYNC, DMA, __x)
+#define MCDE_DSICMD0SYNC_SW_SHIFT 16
+#define MCDE_DSICMD0SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSICMD0SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0SYNC, SW, __x)
+#define MCDE_DSIVID1SYNC 0x00000E4C
+#define MCDE_DSIVID1SYNC_DMA_SHIFT 0
+#define MCDE_DSIVID1SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSIVID1SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1SYNC, DMA, __x)
+#define MCDE_DSIVID1SYNC_SW_SHIFT 16
+#define MCDE_DSIVID1SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSIVID1SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1SYNC, SW, __x)
+#define MCDE_DSICMD1SYNC 0x00000E6C
+#define MCDE_DSICMD1SYNC_DMA_SHIFT 0
+#define MCDE_DSICMD1SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSICMD1SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1SYNC, DMA, __x)
+#define MCDE_DSICMD1SYNC_SW_SHIFT 16
+#define MCDE_DSICMD1SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSICMD1SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1SYNC, SW, __x)
+#define MCDE_DSIVID2SYNC 0x00000E8C
+#define MCDE_DSIVID2SYNC_DMA_SHIFT 0
+#define MCDE_DSIVID2SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSIVID2SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2SYNC, DMA, __x)
+#define MCDE_DSIVID2SYNC_SW_SHIFT 16
+#define MCDE_DSIVID2SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSIVID2SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2SYNC, SW, __x)
+#define MCDE_DSICMD2SYNC 0x00000EAC
+#define MCDE_DSICMD2SYNC_DMA_SHIFT 0
+#define MCDE_DSICMD2SYNC_DMA_MASK 0x00000FFF
+#define MCDE_DSICMD2SYNC_DMA(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2SYNC, DMA, __x)
+#define MCDE_DSICMD2SYNC_SW_SHIFT 16
+#define MCDE_DSICMD2SYNC_SW_MASK 0x0FFF0000
+#define MCDE_DSICMD2SYNC_SW(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2SYNC, SW, __x)
+#define MCDE_DSIVID0CMDW 0x00000E10
+#define MCDE_DSIVID0CMDW_GROUPOFFSET 0x20
+#define MCDE_DSIVID0CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSIVID0CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSIVID0CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSIVID0CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSIVID0CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSIVID0CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0CMDW, CMDW_START, __x)
+#define MCDE_DSICMD0CMDW 0x00000E30
+#define MCDE_DSICMD0CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSICMD0CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSICMD0CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSICMD0CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSICMD0CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSICMD0CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0CMDW, CMDW_START, __x)
+#define MCDE_DSIVID1CMDW 0x00000E50
+#define MCDE_DSIVID1CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSIVID1CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSIVID1CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSIVID1CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSIVID1CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSIVID1CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1CMDW, CMDW_START, __x)
+#define MCDE_DSICMD1CMDW 0x00000E70
+#define MCDE_DSICMD1CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSICMD1CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSICMD1CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSICMD1CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSICMD1CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSICMD1CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1CMDW, CMDW_START, __x)
+#define MCDE_DSIVID2CMDW 0x00000E90
+#define MCDE_DSIVID2CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSIVID2CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSIVID2CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSIVID2CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSIVID2CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSIVID2CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2CMDW, CMDW_START, __x)
+#define MCDE_DSICMD2CMDW 0x00000EB0
+#define MCDE_DSICMD2CMDW_CMDW_CONTINUE_SHIFT 0
+#define MCDE_DSICMD2CMDW_CMDW_CONTINUE_MASK 0x0000FFFF
+#define MCDE_DSICMD2CMDW_CMDW_CONTINUE(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CMDW, CMDW_CONTINUE, __x)
+#define MCDE_DSICMD2CMDW_CMDW_START_SHIFT 16
+#define MCDE_DSICMD2CMDW_CMDW_START_MASK 0xFFFF0000
+#define MCDE_DSICMD2CMDW_CMDW_START(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2CMDW, CMDW_START, __x)
+#define MCDE_DSIVID0DELAY0 0x00000E14
+#define MCDE_DSIVID0DELAY0_GROUPOFFSET 0x20
+#define MCDE_DSIVID0DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSIVID0DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSIVID0DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0DELAY0, INTPKTDEL, __x)
+#define MCDE_DSICMD0DELAY0 0x00000E34
+#define MCDE_DSICMD0DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSICMD0DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSICMD0DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0DELAY0, INTPKTDEL, __x)
+#define MCDE_DSIVID1DELAY0 0x00000E54
+#define MCDE_DSIVID1DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSIVID1DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSIVID1DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1DELAY0, INTPKTDEL, __x)
+#define MCDE_DSICMD1DELAY0 0x00000E74
+#define MCDE_DSICMD1DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSICMD1DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSICMD1DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1DELAY0, INTPKTDEL, __x)
+#define MCDE_DSIVID2DELAY0 0x00000E94
+#define MCDE_DSIVID2DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSIVID2DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSIVID2DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2DELAY0, INTPKTDEL, __x)
+#define MCDE_DSICMD2DELAY0 0x00000EB4
+#define MCDE_DSICMD2DELAY0_INTPKTDEL_SHIFT 0
+#define MCDE_DSICMD2DELAY0_INTPKTDEL_MASK 0x0000FFFF
+#define MCDE_DSICMD2DELAY0_INTPKTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2DELAY0, INTPKTDEL, __x)
+#define MCDE_DSIVID0DELAY1 0x00000E18
+#define MCDE_DSIVID0DELAY1_GROUPOFFSET 0x20
+#define MCDE_DSIVID0DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSIVID0DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSIVID0DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0DELAY1, TEREQDEL, __x)
+#define MCDE_DSIVID0DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSIVID0DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSIVID0DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID0DELAY1, FRAMESTARTDEL, __x)
+#define MCDE_DSICMD0DELAY1 0x00000E38
+#define MCDE_DSICMD0DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSICMD0DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSICMD0DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0DELAY1, TEREQDEL, __x)
+#define MCDE_DSICMD0DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSICMD0DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSICMD0DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD0DELAY1, FRAMESTARTDEL, __x)
+#define MCDE_DSIVID1DELAY1 0x00000E58
+#define MCDE_DSIVID1DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSIVID1DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSIVID1DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1DELAY1, TEREQDEL, __x)
+#define MCDE_DSIVID1DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSIVID1DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSIVID1DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID1DELAY1, FRAMESTARTDEL, __x)
+#define MCDE_DSICMD1DELAY1 0x00000E78
+#define MCDE_DSICMD1DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSICMD1DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSICMD1DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1DELAY1, TEREQDEL, __x)
+#define MCDE_DSICMD1DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSICMD1DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSICMD1DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD1DELAY1, FRAMESTARTDEL, __x)
+#define MCDE_DSIVID2DELAY1 0x00000E98
+#define MCDE_DSIVID2DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSIVID2DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSIVID2DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2DELAY1, TEREQDEL, __x)
+#define MCDE_DSIVID2DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSIVID2DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSIVID2DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSIVID2DELAY1, FRAMESTARTDEL, __x)
+#define MCDE_DSICMD2DELAY1 0x00000EB8
+#define MCDE_DSICMD2DELAY1_TEREQDEL_SHIFT 0
+#define MCDE_DSICMD2DELAY1_TEREQDEL_MASK 0x00000FFF
+#define MCDE_DSICMD2DELAY1_TEREQDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2DELAY1, TEREQDEL, __x)
+#define MCDE_DSICMD2DELAY1_FRAMESTARTDEL_SHIFT 16
+#define MCDE_DSICMD2DELAY1_FRAMESTARTDEL_MASK 0x00FF0000
+#define MCDE_DSICMD2DELAY1_FRAMESTARTDEL(__x) \
+ MCDE_VAL2REG(MCDE_DSICMD2DELAY1, FRAMESTARTDEL, __x)
diff --git a/firmware/Makefile b/firmware/Makefile
index 0d15a3d113a..b74752ef53f 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -32,6 +32,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
adaptec/starfire_tx.bin
fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
+fw-shipped-$(CONFIG_AV8100) += av8100.fw
fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.2.9.0.fw \
bnx2x/bnx2x-e1h-6.2.9.0.fw \
bnx2x/bnx2x-e2-6.2.9.0.fw
diff --git a/firmware/av8100.fw.ihex b/firmware/av8100.fw.ihex
new file mode 100644
index 00000000000..384a432ea43
--- /dev/null
+++ b/firmware/av8100.fw.ihex
@@ -0,0 +1,1281 @@
+:1000000080FECBFEA3EE5AF05AF0F8F159EFFDF165
+:1000100045F307F51CF52DF53FF552F557F55CF561
+:1000200061F566F57BF5B5F54CF69DEE9DEE9EEE21
+:10003000000000000000000000000081EAADECAD0F
+:1000400038201B7280814D514D514D514D514D51B4
+:100050004D51B420F42A5A9082FECD8000AF7293A5
+:10006000A3205F90808097908D200FAB01A6888998
+:100070009096AD97909AAD8B939EAD9790A2AD80E0
+:10008000B7A6AD81B7AAAD82B7AEAD263120087252
+:1000900082B721A681B7C2A680B701A6B420F52AEF
+:1000A0005A908000A77293CCAD492797905D90D469
+:1000B000AD82B7D8AD81B7DCAD80B7E0ADFFAE9013
+:1000C000815929EA265AFB382007724D38201A72C6
+:1000D000490038200572BCFFCD08AEF320792449D1
+:1000E0004424492324490BAD82FECD9E82FECD9F40
+:1000F0005B82FECD80B682FECD81B682FECD82B619
+:1001000082AD9F9086AD859084428C209F9001ABFC
+:100110000FA62A31200872FB382007724D38201AAA
+:1001200072BCFFCDFB382007723020107231201EC8
+:100130007230201C729505A09E94F6CC5F905F4FA4
+:1001400007382005720C39200572814129382018A2
+:1001500072D5265AFB382007729D9D4D38201A72A1
+:100160004DAEFFCD4DAEFFCD38201B724D4D4D4DE8
+:100170004D382019720425493820187208AE3420F1
+:1001800000000000000000191817161514131211B2
+:10019000100F0E0D0C0B0A090807060504030201D7
+:1001A000000000000000000000000000000000004F
+:1001B000000000000000000000000000000000003F
+:1001C000000000000000000000000000000000002F
+:1001D000000000000000000000000000000000001F
+:1001E000000000000000000000000000000000000F
+:1001F00000000000000000000000000000000000FF
+:1002000000000000000000000000000000000000EE
+:1002100000000000000000000000000000000000DE
+:1002200000000000000000000000000000000000CE
+:1002300000000000000000000000000000000000BE
+:1002400000000000000000000000000000000000AE
+:10025000000000000000000000000000000000009E
+:10026000000000000000000000000000000000008E
+:10027000000000000000000000000000000000007E
+:10028000000000000000000000000000000000006E
+:10029000000000000000000000000000000000005E
+:1002A000000000000000000000000000000000004E
+:1002B000000000000000000000000000000000003E
+:1002C000000000000000000000000000000000002E
+:1002D000000000000000000000000000000000001E
+:1002E000000000000000000000000000000000000E
+:1002F00000000000000000000000000000000000FE
+:1003000000000000000000000000000000000000ED
+:1003100000000000000000000000000000000000DD
+:1003200000000000000000000000000000000000CD
+:1003300000000000000000000000000000000000BD
+:1003400000000000000000000000000000000000AD
+:10035000000000000000000000000000000000009D
+:10036000000000000000000000000000000000008D
+:10037000000000000000000000000000000000007D
+:10038000000000000000000000000000000000006D
+:10039000000000000000000000000000000000005D
+:1003A000000000000000000000000000000000004D
+:1003B00000000000000000008101A60227FBD69289
+:1003C000FC3C0726FBD692FC3C0E26FBD692FC3C5E
+:1003D0001726FBD692FC3F81FAB7FBD8925CFAB69F
+:1003E000F9B7FBD8925CF9B6F8B7FBD89201AEF832
+:1003F000B6F7B7FBC892F7B6FCBF81FCBE84FAB76C
+:10040000FBD6925CF9B7FBD6925CF8B7FBD69201AB
+:10041000AEF7B7FBC69288FCBF81FAB7FBDA925CF5
+:10042000FAB6F9B7FBDA925CF9B6F8B7FBDA9201E3
+:10043000AEF8B6F7B7FBCA92F7B6FCBFBAFACCC4AF
+:10044000FBCD81FCBEE9264AFB003972FB006972D4
+:100450005AFB0069725AFB00687203AEFCBF1B278F
+:100460004DBAFACC0FFBCD81F12001ABFBD6920740
+:100470002B5A0A24FBD792FBDB9203AEFCBF81010F
+:10048000A60220FFA604240827FBD192FAB6FC3C62
+:100490000926FBD192F9B6FC3C1226FBD192F8B6A4
+:1004A000FC3C2326FBD192F7B6FC3F81FAB7FBD484
+:1004B000925CFAB6F9B7FBD4925CF9B6F8B7FBD404
+:1004C0009201AEF8B6F7B7FBC492F7B6FCBF81F75E
+:1004D000B7FBC992F7B6F8B7FBD9925AF8B6F9B795
+:1004E000FBD9925AF9B6FAB7FBDB92FAB603AEFC27
+:1004F000BF81F73C0224F8B7F8B99FF9B7F9BB42BE
+:10050000930F274D8400FBCDFFB60527FEBEFAB73B
+:10051000F9BF4293FFB6F8B7F7BF42FEB689FFB7FF
+:1005200081F73FF83FF9BFFAB781FCBE84FBD79251
+:10053000FAB65CFBD792F9B65CFBD792F8B601AE7F
+:10054000FBC792F7B688FCBF81FCBEFBD792FAB618
+:100550005CFBD792F9B65CFBD792F8B601AEFBC74D
+:1005600092F7B6FCBF8101A60227036D0426026D37
+:100570000826016D0E267D81F5264AFA36F936F8F1
+:1005800036F7340B274D8184FAB703E6F9B702E654
+:10059000F8B701E6F7B7F6888101A60227FA3D040D
+:1005A00026F93D0826F83D0E26F73D81F5264AF747
+:1005B00039F839F939FA380B274D81F7F7B9F601CF
+:1005C000E7F8B901E602E7F9B902E603E7FABB0387
+:1005D000E681F73FF83F81F7B7F8B7FFA6072AF99A
+:1005E000BFFAB78141FFBB41529384FFB7FFBB52B3
+:1005F000017BFEBEFFB7529F908881FCBEFAB7FB1D
+:10060000D6925CF9B7FBD6925CF8B7FBD69201AEF6
+:10061000F7B7FBC692FCBF81F73FF9B7F8BF5C01A3
+:1006200024F9BB4293F7B6FAB7F9BF4293F7BFE09C
+:10063000208FE326017B1A15CD0326B203CAB3032C
+:10064000C6DAEDCD032420A11227016B6AF6CDBBDB
+:10065000F6CD888155FACDF73FF83FF9B781F9B665
+:10066000FA3FE7FBCDFBB700A94101AB818484844D
+:100670008484062008359A1A2010721520C7EEA42B
+:100680001520C61420C77CA41420C61320C708A4B4
+:100690001320C609C0CD84848484848484846EDB62
+:1006A000CD47033B48033B49033B4A033B014B8097
+:1006B0004B854B804B1F2729FCCD47AEFB000335F4
+:1006C000B0840035B1840035B2840035B38413356D
+:1006D000A4840035A5840035A6840035A7840035A0
+:1006E000A0840035A1840035A2840035A3840035A0
+:1006F0000C8C00350D8C00350E8C00350F8C0035C0
+:10070000188C0035198C00351A8C00351B8C03357C
+:10071000048C0035058C0035068C0035078C0A35B5
+:10072000008C0035018C0035028C0035038C0035BF
+:100730001C8C00351D8C00351E8C00351F8C04353B
+:100740001FC1CDACC3CD248300352583003526835E
+:1007500002352783003584840035858400358684FE
+:10076000003587842035B4840035B5842035B684BF
+:100770000035B784A0350C20B5840035B68400352B
+:10078000B78480350E2420A1C803C618840035190B
+:100790008400351A8400351B84003578840035794F
+:1007A0008400357A8400357B8400353F2001353D57
+:1007B00020C7FFA63C20C706A6470301354803868D
+:1007C000354903A0354A03C70F20470302354803C4
+:1007D00049354903F0354A03C71C2048039B354976
+:1007E00003FC354A03C0352A2048038C354903BA37
+:1007F000354A0380353820480324354903F8354A03
+:1008000003C7492047035F7248035F7249035F7261
+:100810004A035F724C2708A03F274A34274A2927FA
+:100820004A1F270FA40820C6BE035F72BF03C7017B
+:10083000A63E20FE35C80310350A2003A63E202020
+:1008400035C803C721A6113F042023A61100033594
+:100850000827A3F9CD04A494F9CD5B172022A61193
+:100860000001350827A3F9CD02A494F9CD5B2A2015
+:1008700011B730A60627A3F9CD08A494F9CD5B01E2
+:100880006B9484C6026B9584C6036B9684C6046B16
+:100890009784C65A2510A10320C6F22510A1056B26
+:1008A0004CA2034F7205EE72056B4FAD025F72AE44
+:1008B000025F72B8035F7297025F7299025F72986B
+:1008C000025F72B3035F72B2035F7276030A357917
+:1008D000035F727A035F7283035F727B035F727CD4
+:1008E000035F727D035F7261035F72BD035F72C25B
+:1008F000035F724C035F724D035F7286025F724F3B
+:10090000035F7262035F7250035F729B025F729CAF
+:10091000025F729D025F724B035F72113F103F4E88
+:10092000035F72A0035F72A1035F72C3035F72C4AF
+:1009300003FF35C7035F72BC035F729B06205F72C3
+:1009400088888888888184E3ADF42540A1016B4CB8
+:10095000126F01EE72016B4F888105201072152015
+:100960001172101EADF9CC8BFFA606AE8185017BFE
+:100970009AA003C70FA4A003C6A2034F72A0035CF2
+:1009800072016BA203D6A003CE1827A003C1A10356
+:10099000C69B016B4F8881A103C70FA4A103C6A208
+:1009A00003D7A1035C72A103CE808602C75120C683
+:1009B00050201172808590FD0032FC0032FB003225
+:1009C000000132FF0032FE00328484848457F6CD69
+:1009D00063A60520B3035A72B2035A720426B30306
+:1009E000C60F27B203CAB303C67D035F72B2035FAB
+:1009F00072B3031835082500A2B203C619A0B303C9
+:100A0000C618207D030135062710A5047B016B1055
+:100A100040C6026B1140C6036B1240C6046B134004
+:100A2000C609C0CD4620C74620C641205F720A4293
+:100A3000200D7288888888FE003BFF003B00013B48
+:100A4000FB003BFC003BFD003B8990808590FD0056
+:100A500032FC0032FB0032000132FF0032FE003275
+:100A600057F6CD152010720727092B10B61220015A
+:100A700035FE003BFF003B00013BFB003BFC003B25
+:100A8000FD003B8990800C4000350D4000350E4044
+:100A900000350F400435112080358011204035800D
+:100AA0001120203580112010358011200835801745
+:100AB000201472801720157205172005721120046A
+:100AC0003580BB03C74A05201A7206201872112010
+:100AD000C702A680BB03C705201A7206201972112F
+:100AE00020C701A6800488003505883035068800B7
+:100AF00035078800351020803581B8FACDBCAEFBB3
+:100B000000843581FBB700A94101AB808590FD00D1
+:100B100032FC0032FB0032000132FF0032FE0032B4
+:100B2000FA0032F90032F80032F70032848484840B
+:100B30008484B8FACDA0AEFB008435C4FBCD33ADC0
+:100B40005BF73FF83FF91FD7FACDC903CECA03C6FA
+:100B5000036B80A4037B046B4F016BA084C6026B04
+:100B6000A184C6036BA284C6046BA384C68484C913
+:100B700003CFCA03C76EC0CD9802CE9902C6CB037D
+:100B80003BCC033B0F2052C0CD9802CE9902C6CB7E
+:100B9000033BCC033B112405E272CB03C606E07293
+:100BA000CC03C61F2405E2729802C606E0729902C1
+:100BB000C61C25CB03C2057BCC03C0067B0C249846
+:100BC00002C2057B9902C0067B5C20C903CF980254
+:100BD000CECA039902550D264C03C60D20CB03CE79
+:100BE000CA03C7CC03C60B274A4B03C607200135EF
+:100BF00007200335082604A105201D7205201C725C
+:100C0000082502A19702C61B269802C1057B222651
+:100C10009902C1067B29264A4B03C6CB035F72CCDF
+:100C200003C706A6FDF4CDF9B718AAF9B6E7FBCDC0
+:100C3000F5F4CD5B12200AA6FDF4CDF918E7FBCD43
+:100C4000F5F4CD5B102400A2057B0AA0067B1A25D3
+:100C500000A2057B06A0067B036BC7A4037B016B88
+:100C6000BC84C6026BBD84C6036BBE84C6046BBF66
+:100C700084C657274C03C6066BA783C6056BA6839D
+:100C8000C6CA035F72C9035F72CC035F72CB035F96
+:100C90007210204035888888888888F7003BF800E3
+:100CA0003BF9003BFA003BFE003BFF003B00013BF1
+:100CB000FB003BFC003BFD003B89908148830035F5
+:100CC000498300354A8300354B830F35808590FD7D
+:100CD0000032FC0032FB0032000132FF0032FE0025
+:100CE0003284848484BC035F725DC7CD20AD052649
+:100CF0004ABC03C60B2603A14B03C6C4035C7204A3
+:100D0000270FA1C403C60B20BB0301351126C40362
+:100D10005A721727C403C6112603EA72047B0727F9
+:100D20004C037B05264C047B1127037B04264A04D5
+:100D30007B7DDECD03EE729F036B04EF7203E272E4
+:100D40004104E0725F01A6036B01E272037B046B56
+:100D500002E072047B0E2403E2729F04E0724654A8
+:100D600001EF72026B46542903CE2A03C6082029DC
+:100D700003CE2A03C608264A2203C6E32603E172ED
+:100D8000A683C6EB2604E172A783C6046BA783C6BD
+:100D9000036BA683C605F3CC848484848B0235352B
+:100DA0008C0286358D0237358E02BD35C4030F3572
+:100DB000C703013534F3CD8AC0CD8F023B90023B8F
+:100DC00091023B92023B3126C703C62BC7CD0327B6
+:100DD000C403C61BF3CC032602A1BA03C605F3CC99
+:100DE000032702A14B03C61020203588888888FE7F
+:100DF000003BFF003B00013BFB003BFC003BFD00D8
+:100E00003B8990801020083581E7FBCDFBB700A916
+:100E10004102AB808590FD0032FC0032FB003200C5
+:100E20000132FF0032FE0032FA0032F90032F800DF
+:100E300032F700328484848484B8FACDFBBF84AE58
+:100E4000FA1A2FAD5B092004AEFB004435F73F3C96
+:100E5000AD5B026B0884C6036B0984C6046B0A840D
+:100E6000C6056B0B84C6B8FACDFBBF84AEFA1B5C1B
+:100E7000AD5B2D274D03C632279D02C6026B8484CD
+:100E8000C6036B8584C6046B8684C6056B8784C6DF
+:100E9000848484E8C8CD4102A941AFAB5F5221AE42
+:100EA000AD02C6024B104B004BAD025C720420AD8C
+:100EB000025F720626FFB1FFBF900D26FEB3FE3F14
+:100EC000AD02CE904A5A01264D5F3A2502A1AE02EC
+:100ED000C6EBC6CDBB035F7207264ABB03C6062618
+:100EE00004A14603C607264A4B03C6CFD5CDBD0392
+:100EF000C706264ABD03C661035C7204274C610322
+:100F0000C60A2061035F720627C403C6C5035C726C
+:100F10000424FFA1C503C6BC030135B8FACDA0AEB9
+:100F2000FB008435F71FEDF1CD5B026BA084C60397
+:100F30006BA184C6046BA284C6056BA384C684849B
+:100F400084848AC0CD8F023B90023B91023B920287
+:100F50003BC7035F72412504A1C503C665274A4B01
+:100F600003C6B8FACD9CAEFB008335F7B7F8B7F9E6
+:100F7000B74FFAB7016B9F83C60520147210200685
+:100F8000358888888888F7003BF8003BF9003BFAF1
+:100F9000003BFE003BFF003B00013BFB003BFC0035
+:100FA0003BFD003B899081FB008C35F7B7F8B7F922
+:100FB000B74FFAB7808590FD0032FC0032FB00325B
+:100FC000000132FF0032FE0032FA0032F90032F83E
+:100FD0000032F7003284B8FACD0CAE27ADF0A40190
+:100FE0007B62035F72052016720620C705AA0620E1
+:100FF000C61B2704A5017BB8FACD0CAE48ADF0A402
+:101000000520167206201472112062035A7247EFEF
+:10101000CD02A605264A05204F032502A16203C67C
+:10102000B8FACD10AE71AD6303D622276203CE5954
+:10103000270FA5017BB8FACD0CAE4CF0CD0FA4055F
+:10104000201672062012724F030135182720A501C1
+:101050007B98AD4F052780A5017B5103D7178CC620
+:1010600050035C725003CE0F2780A507205003CF9A
+:1010700006201372092710A520264F03CE016B0FFF
+:101080008CC61020103588F7003BF8003BF9003B78
+:10109000FA003BFE003BFF003B00013BFB003BFC3A
+:1010A000003BFD003B8990B8FACC0CAEFB008C35C0
+:1010B000F7B7F8B7F9B74FFAB7808590FD0032FC63
+:1010C0000032FB0032000132FF0032FE0032848425
+:1010D0008484A084C7017BA184C7027BA284C70348
+:1010E0007BA384C7047BBC030135016B7FA4017B18
+:1010F0000A20016B80AA017B122702A1BA03C60F46
+:101100002603A1042702A14B03C61A274C03C605D8
+:10111000264D03C6016BA084C6026BA184C6036B77
+:10112000A284C6046BA384C6C5035F72BA03C70357
+:10113000A48384C61FC1CD03264AB903C605201265
+:10114000721020013588888888FE003BFF003B0034
+:10115000013BFB003BFC003BFD003B8990801220E3
+:101160001035808113000135042712B7C084C6A74B
+:10117000F6CD11B71EEDCDA7F6CC11B701A6072409
+:1011800020A1C803C609206CEBCDD6206CEBCD05A1
+:101190002604A112B6062702A112B6112602A11139
+:1011A000B6B32057EBCD2A209CEACD2F2017EACDED
+:1011B000C22011B717EACD072602A111B68112008D
+:1011C000184D551300194D5514001A4D5515001B97
+:1011D0004D556E2520A1C803C6A7F6CD11B7C9E7A6
+:1011E000CD65202BE7CD6A2049E4CD9CF6CC8CE37D
+:1011F000CD7520ADE3CD7A20B4E2CD84EECC5EE2B5
+:10120000CD84EECC1EE2CD84EECC71E1CD84EECC6B
+:1012100047E0CD8188BCEDD688BDEDD658979CEED1
+:10122000CC03250FA14A7BEE5FEE5AEE55EE43EE5E
+:101230001FEE1AEE15EE0FEE0AEE05EEFFEDF9EDDC
+:10124000F3EDEDED81E7FBCDFBB700A94102ABF675
+:101250002001A6818585858585062611BE04204F3F
+:1012600026C0CD0AA69A7884C7027B7984C7037BFF
+:101270007A84C7047B7B84C7057BB8FACD78AEFB44
+:10128000008435F71836AD5B026B7884C6036B7942
+:1012900084C6046B7A84C6056B7B84C656C8CD01B0
+:1012A000A656C8CD4F9B492701E4724F01204C033D
+:1012B000264A11B6016B4F012001A6042655FACD2E
+:1012C000F83FF93FFA3F77AD5B026BC084C6036B12
+:1012D000C184C6046BC284C6056BC384C688888873
+:1012E000888881B8FACDB4AEFB00843581E7FBCDA8
+:1012F000FBB700A94101AB818585858585057BB854
+:10130000030135042702A111B60A264A13B6056B5C
+:1013100001A6042012009803550920D2C8CD052744
+:1013200085854D2F1ECD13BE14B6014B004B1E20DC
+:10133000850A1FCD13BE14B6014B9803C715B621FD
+:101340002033274D721FCD39209A5EADF91857AD65
+:101350005B9B016BB484C6026BB584C6036BB68419
+:10136000C6046BB784C626C0CDFAA69A1884003589
+:10137000198403351A8483351B84003514450035E0
+:1013800015450035164500351745023514EDCDF9E4
+:1013900016FA1209EDCD5B9B016BB484C6026BB5E6
+:1013A00084C6036BB684C6046BB784C68484848405
+:1013B000848484846EDBCD47033B48033B49033B75
+:1013C0004A033B044BC44BB44B004BEEECCCD2EC89
+:1013D000CC03264AC1ECCC03264AB9ECCC03264AFE
+:1013E00015274A12B6EEECCC032702A111B6F2EC97
+:1013F000CCBC03C74C9AB8FACD18AEFB008435F7C5
+:10140000B7F8B7F9B74FFAB712B69BF2ECCC03278F
+:1014100003A14B03C6056B01A6C2035F724B035FBA
+:10142000720C274A0F274A12274A15274AC203C6B9
+:10143000C0035F72C10301352320C0035F72C10383
+:10144000C702A602200AA6262006274A05274A0C1C
+:10145000274AC203C61D2420A1C803C6C203C77FF2
+:10146000A412B64B03033579264A11B6B8035F724E
+:101470009A18840035198400351A8400351B8400BD
+:10148000359B4B035F721A2702A111B6056B4F887B
+:1014900088888888814FD2C8CC032785854D2F1E28
+:1014A000CD11BE12B6804B004B8185858585854F59
+:1014B000848484E8C8CD00AE11A688047B88047BB0
+:1014C00088017BAE025C72042403A10826AE02C12F
+:1014D000047BE22205E17213B6056B4C9F90B202C9
+:1014E000D714E69005E6729705EB725221AE047BA5
+:1014F00015204FB102D713B6B002D712B6AF02D73C
+:1015000011B6975221AE432403A1047BE82503A121
+:10151000056B4C057B046B057B042611B1AF02D62D
+:10152000975221AE056B4F046BAE02C6036B10A63B
+:10153000026B02A67120026B03EF7206A94100AB99
+:10154000594859485948594859484A5A01264D5FFF
+:10155000016B0FA411B6222581A111B6016B4F8832
+:101560008888888881858585854F790301357A0348
+:10157000C74C082017B70C267B03C616B7047B019F
+:101580006B026B036B4F046B7E03C615B7017B14B4
+:10159000B7027B13B7037B12B7047B016B7F03C6D3
+:1015A000026B8003C6036B8103C6046B8203C61102
+:1015B000B74F01204C03267A03CE502079035F7287
+:1015C0007A03C74C5A2079035F727A035F725C27F3
+:1015D0004A17274A10274A11B678030835042712FC
+:1015E0003D78035F728888888881B8FACDB4AEFBF5
+:1015F00000843581E7FBCDFBB700A94101AB811029
+:101600004D0035114D0035124D0035819ACBCD017D
+:10161000A61CCACD044800350548003506480035EB
+:101620000748003531ADFA1A81858585854F9A7C4A
+:1016300003187288031A005589031B00558A031C7E
+:1016400000558B031D005584031E005585031F00A4
+:10165000558603200055870321005590031200553D
+:101660009103130055920314005593031500558CF4
+:10167000031600558D031700558E031800558F0370
+:10168000190055542628A111B65A207C03C710A46E
+:101690007C03C664207C031072062627A111B69B2A
+:1016A000FACDFBB748A94144AB5208AE11B668FA6F
+:1016B000CD12AE9BFACDFBB748A94140AB5208AE64
+:1016C00011B668FACD16AE1448880355154889033B
+:1016D0005516488A035517488B03551048840355FF
+:1016E000114885035512488603551348870355D87A
+:1016F000E9CDF81B02EACD5B016BB484C6026BB581
+:1017000084C6036BB684C6046BB784C64526113DF8
+:1017100077E9CC032528A111B6D1E9CC0DEACDF8A3
+:101720001B02EACD5B26C0CD0AA6016BB484C602BB
+:101730006BB584C6036BB684C6046BB784C67C03E2
+:1017400010726DE9CC032791A111B6F5E9CD134DC7
+:101750000335F5E9CD134D43350C4D1E00550D4DA8
+:101760001F00550E4D2000550F4D210055084D1AF4
+:101770000055094D1B00550A4D1C00550B4D1D0011
+:1017800055044D160055054D170055064D180055CA
+:10179000074D190055004D120055014D130055021B
+:1017A0004D140055034D150055C42755FACDF73F8C
+:1017B000F8B706A4F8B6F93FFA3F02EACD5B016B31
+:1017C000144DC6026B154DC6036B164DC6046B1740
+:1017D0004DC626C0CD0FA6F5E9CD134D0335F5E96D
+:1017E000CD134DC3352520026B036B046B4FD8E935
+:1017F000CDF81A02EACD5B016BB484C6026BB584E6
+:10180000C6036BB684C6046BB784C6622680A1117A
+:10181000B6F72492A111B6E7E8CC032480A111B653
+:101820009BD3E9CC01A6052420A1C803C60C2580C2
+:10183000A111B68888888881484200354942003520
+:101840004A42003581858585854F9A9DC5CD4D03DA
+:1018500001356E14CD03279D02C616AD4B420535EA
+:1018600004204B42013506277703C60CC4CDB8FAD5
+:10187000CDB4AEFB008435F916E7FBCDFBB700A96C
+:101880004101AB5B016BB484C6026BB584C6036BCC
+:10189000B684C6046BB784C6F4DACD502059AD4B7C
+:1018A00042053504204B42013506277703C613262F
+:1018B0004A4D03C66920CCC4CDACC3CD0826113D2A
+:1018C0009B77030135042077035F72062602A1117E
+:1018D000B68888888881B8FACD78AEFB00843581D7
+:1018E00018800035198000351A8000358108800085
+:1018F00035098000350A80003581585812BE81E7CD
+:10190000FBCDFBB700A94107AB81848B4100A94106
+:1019100009AB5B0A6B4F9ACCC4CD4C035F72BC849D
+:101920000035BD840035BE841835BF84003542AD16
+:101930001B808035148000351580003516800035F9
+:10194000178000354BAD0B800035048000350580D5
+:1019500000350680003507800035008000350180A5
+:101960000035028000350380003521E7CDFAB7F855
+:10197000A4FAB66AAD5B076B7884C6086B7984C637
+:10198000096B7A84C60A6B7B84C673209DC5CD4CD7
+:101990000301359084C7037B9184C7047B9284C77D
+:1019A000057B9384C7067BBEFBCDFBB700A9410333
+:1019B000AB5BF71EF7E6CD5B036BBFA4037B056B48
+:1019C000066B4F0F20F814F7E6CD5B036BBFA40343
+:1019D0007B046BC3A4047B056B066B4F192622A105
+:1019E000C803C69FFBCD10A6FBB700A94103AB5BA4
+:1019F000036B9484C6046B9584C6056B9684C606F7
+:101A00006B9784C682FBCD01A6FBB700A94107AB4B
+:101A10005B076B086B4F076B9884C6086B9984C68D
+:101A2000096B9A84C60A6B9B84C66DE6CC0325308D
+:101A3000A1C803C6CDD9CDBC840035BD840035BE58
+:101A4000841B35BF8440350420BF844135062614ED
+:101A50003D14E7CD1B808135B8FACD14AEFB008074
+:101A6000351DFACD5280AE30E4D602E7CD07E7CD82
+:101A70000B8065353080003531800035328000358F
+:101A800033808B352C8000352D8000352E8000353D
+:101A90002F80093528800035298000352A800035BF
+:101AA0002B802A3530264A30E4D602E7CD44810027
+:101AB000354581003546810035478132350C80003F
+:101AC000350D8000350E8000350F80083510800000
+:101AD00035118000351280003513800835B8FACDF5
+:101AE0005FFB0080351DFACD06AA4101EA72410272
+:101AF000EA7228AA5240AE2DE4D602E7CD01EF7279
+:101B0000026B5210AE15B6B8FACD04AEFB008035AC
+:101B10001DFACD4101EA724102EA7280AA5220AE5A
+:101B20002FE4D602E7CD01EF72026B5204AE2EE431
+:101B3000D602E7CD21E7CDFA10FA12FA14F7E6CD76
+:101B40005B076B7884C6086B7984C6096B7A84C698
+:101B50000A6B7B84C6B8FACDB4AEFB008435F916A7
+:101B6000F7E6CD5B076BB484C6086BB584C6096B1A
+:101B7000B684C60A6BB784C676E6CC03274A13B68A
+:101B80009BEBE6CC01A6052755FACDF73FF83FF9C8
+:101B9000B740A4F9B6FA3FF7E6CD5B076B9484C66D
+:101BA000086B9584C6096B9684C60A6B9784C68BAE
+:101BB0004100A2410AA05B000200010103010200F2
+:101BC0000200020002010300020102000301000002
+:101BD00003000081854F62035A729A0C8C00350D08
+:101BE0008C00350E8C00350F8C013504200F8C03D2
+:101BF0003506264A6203C6B8FACD10AEFB008C3516
+:101C0000F7B7F8B7F9B74FFA00630355B8FACD1C28
+:101C1000AEFB008C351DFACD5F0FA44E6303C69B4F
+:101C20000620C7FAA40620C65227E6256203C6622C
+:101C300003C1016B4C9F906303D712E69001E672DB
+:101C40009701E072102001A66303C712B66203C7B2
+:101C500011B68881854F4F035F72EF255003C10194
+:101C60006B4C9F14E75103D601EE720A204F13000C
+:101C700050035588814F9AA884290055A9842A00C9
+:101C800055AA842B0055AB842C0055B8FACD48AE2C
+:101C9000FB0084351DFACD27BE28B6B8FACD44AE78
+:101CA000FB0084351DFACD25BE26B6B8FACD40AE70
+:101CB000FB0084351DFACD23BE24B6B8FACD3CAE68
+:101CC000FB0084351DFACD21BE22B6B8FACD38AE60
+:101CD000FB0084351DFACD1FBE20B6B8FACD34AE58
+:101CE000FB0084351DFACD1DBE1EB6B8FACD30AE50
+:101CF000FB0084351DFACD1BBE1CB6B8FACD2CAE48
+:101D0000FB0084351DFACD19BE1AB6B8FACD28AE3F
+:101D1000FB0084351DFACD17BE18B6B8FACD24AE37
+:101D2000FB0084351DFACD15BE16B6B8FACD20AE2F
+:101D3000FB0084351DFACD13BE14B6B8FACD1CAE27
+:101D4000FB0084351DFACD11BE12B69B814FBD0339
+:101D500001352003CF1FBE2103C720B61E03CF1DB0
+:101D6000BE1F03C71EB61C03CF1BBE1D03C71CB678
+:101D70001A03CF19BE1B03C71AB61803CF17BE1913
+:101D800003C718B61603CF15BE1703C716B614033C
+:101D9000CF13BE1503C714B61203CF11BE1303C76A
+:101DA00012B6814F9A30420035314200353242003E
+:101DB0003533420035CFD5CD2BD7CD848484848470
+:101DC0008484846EDBCD47033B48033B49033B4A95
+:101DD000033B39033B3A033B3B033B3C033BFED213
+:101DE000CD9B8185858585854F9D0201359A8484AB
+:101DF000C7027B8584C7037B8684C7047B8784C72F
+:101E00009B056BFBA4057B042004AA057B06270128
+:101E10007B026B8484C6036B8584C6046B8684C690
+:101E2000056B8784C69A6E14CD9B05274D03C600AB
+:101E300010CD5A14CD9B02C712B6022004A6042668
+:101E400002A111B69AB8FACDFBBF84AEFA1BE7FB2C
+:101E5000CDFBB700A94102AB5B9B056B04AA057BD8
+:101E6000026B8484C6036B8584C6046B8684C605B6
+:101E70006B8784C616000135016B16B69C025F7233
+:101E800004209C0201350627173D888888888881B0
+:101E90008585858585017BBC0301359AB8FACDB46B
+:101EA000AEFB008435FA1FE7FBCDFBB700A941026A
+:101EB000AB5BB484C7027BB584C7037BB684C7041D
+:101EC0007BB784C7057BBEFBCDFBB700A94102AB46
+:101ED0005BFA1EF73FF83FF9B703A4F9B6FA3FE003
+:101EE000FACD5F90FE0001355F12B6046BFCA404CE
+:101EF0007B026BB484C6036BB584C6046BB684C620
+:101F0000056BB784C6CC840035CD840035CE844AB9
+:101F100035CF840035102520A1C803C6172603A19C
+:101F20004603C665C1CD1CBE20A69B4703220055B3
+:101F3000480323005549032400554A03250055143E
+:101F40002789FACD22AE4603C712B6C603C726B606
+:101F500026B69702C721B69802CF1FBE9902C720A6
+:101F6000B64003CF19BE4103C71AB64403CF17BE0C
+:101F70004503C718B63E03CF15BE3F03C716B6428A
+:101F800003CF13BE4303C714B669E1CCB903C74CF2
+:101F900069E1CC016B01A647274A11274A0D274D5D
+:101FA00097025F7299025F7298025F724B03C711CA
+:101FB000B6016B4F88888888880000BA420000B854
+:101FC000410AD7233C0000803F818B4100A9411486
+:101FD000AB5B84848484AFC0CD88127B88127B88FD
+:101FE000127B88127B0F208AC0CD88127B88127BDF
+:101FF00088127B88127B1127C403C6C7035F720453
+:102000002099FBCDFBB700A9410FAB5BE7FBCD8F60
+:10201000AEFB000235162BFFA20D7BFDA00E7B0A46
+:102020002B00A20D7B04A00E6B107B0D6B0F7B0FA2
+:102030006B6020C6106B6120C6116B6220C6126BEC
+:102040006320C66820263568202435642087025521
+:102050006520880255662089025567208A025568E6
+:102060002021356420C7057B6520C7067B6620C715
+:10207000077B6720C7087B60208B025561208C029C
+:102080005562208D025563208E02558702602055CF
+:10209000880261205589026220558A0263205568B2
+:1020A0002021356420C7017B6520C7027B6620C7DD
+:1020B000037B6720C7047B8B026420558C0265205C
+:1020C000558D026620558E02672055682064356460
+:1020D000208B025565208C025566208D02556720A5
+:1020E0008E0255682021356420C7097B6520C70A08
+:1020F0007B6620C70B7B6720C70C7B68202235B826
+:10210000FACD60AEFB0020351DFACD13EE72147BC4
+:1021100005E0CC032613EA72147BB8FACDFBB700B6
+:10212000A9410FAB5BF73FE7FBCD5FFB008435B800
+:10213000FACDFBB700A94109AB5BE7FBCD37AEFB9E
+:1021400000E03506203BAEFB00E03508264C61037D
+:10215000C6056B3FE0C6066B40E0C6076B41E0C6B4
+:10216000086B42E0C6016B43E0C6026B44E0C60365
+:102170006B45E0C6046B46E0C68B4100A24112A04D
+:102180005B898881F7B7F8B7F9B74FFAB781FBB722
+:1021900000A94101ABE2DDCC03A6E2DDCC02A681C1
+:1021A000204C8184848484B8FACD10AEFB00843541
+:1021B000F81EE7FBCD20AD5B1084C7017B1184C7FF
+:1021C000027B1284C7037B1384C7047B026B7FA44A
+:1021D000027BB8FACD40AD5BC4FBCDFBB700A94193
+:1021E00007AB5BF7B703A4F7B6F83FF93FFA3FE751
+:1021F000FBCD5DAD5B016B1084C6026B1184C60321
+:102200006B1284C6046B1384C6BEFBCDFBB700A95A
+:102210004107AB5B46FACD14A673DECD0B6B04A66B
+:1022200066DECC032608A061DECC032604A05EDEB9
+:10223000CC032602A0172702A01B204C1E2006A6B6
+:10224000222002A6262007A60C2710A00C2708A0F3
+:102250000C2704A0342702A03A2702A023240B7BDA
+:1022600020A1C803C6076B6020C6086B6120C609A1
+:102270006B6220C60A6B6320C66820263568202161
+:102280003568205235642000356520003566208091
+:1022900035672000359D9D682027356020930255C5
+:1022A000612094025562209502556320960255687C
+:1022B00020613568205235B8FACD64AEFB00203578
+:1022C00073DECD0B7B682022356020C7077B612041
+:1022D000C7087B6220C7097B6320C70A7B88888880
+:1022E00088816420003565200035662000358184B2
+:1022F000B8FACD10AEFB008435F9B755AAF9B6FA95
+:10230000B755AAFAB6F8B755AAF8B646FACD18A640
+:10231000F7B7F8B7F9B74FFAB7017BB8FACD14AEF3
+:10232000FB008435F7B73FA4F7B6F83FF93FFA3F13
+:1023300046FACD18A6E7FBCDFBB700A94104AB5B7D
+:1023400025240FA1077B26C0CD64A6848484848ABB
+:10235000C0CD8F023B90023B91023B92023B0F208B
+:10236000AFC0CD8F023B90023B91023B92023B11EA
+:10237000264A4B03C614840F351584003516840095
+:102380003517840035046B6020C6056B6120C606D6
+:102390006B6220C6076B6320C66820C74A9D9D6894
+:1023A00020C727A668205235642005356520F535FD
+:1023B0006620E13567200035602093025561209446
+:1023C0000255622095025563209602558F026020C7
+:1023D000559002612055910262205592026320556A
+:1023E0006820263568202135682052356420003564
+:1023F0006520003566208035672000356820273548
+:1024000093026020559402612055950262205596F2
+:1024100002632055682052356420C7047B6520C7BD
+:10242000057B6620C7067B6720C7077B6820C74AF5
+:102430006820C722A66020C7087B6120C7097B628D
+:1024400020C70A7B6320C70B7B68205235108402AB
+:1024500035118455351284553513845535016B0279
+:10246000A612DDCD67202835092001A612DDCD6733
+:102470002014350B2502A2087BDDA0097B1E204F0E
+:1024800012DDCD67200A350A2504A2087BD9A009F0
+:102490007B88812D03CE2E03C6B8FACD818484B803
+:1024A000FACD0CAEFB004135D7FACD412503C94129
+:1024B0002603CB17AD08AEFB004135D7FACD5C0142
+:1024C000264C26AD04AEFB004135D7FACD4123039F
+:1024D000C9412403CB4101E2724102E0722B03CED9
+:1024E0002C03C6B8FACD5FFB004135D7FACD5C01AD
+:1024F000264C4101E2724102E0722B03CE2C03C64E
+:10250000026B3003C6016B2F03C68888813303CE6C
+:102510003403C6B8FACD81412F03C9413003CB46FD
+:10252000542703CE2803C6812F03CE3003C6B8FA42
+:10253000CD8146FACD10A6D7FACD81FBB700A941CF
+:1025400001AB818484848484847C8300357D830012
+:10255000357E830F357F83FF35B8FACD6CAEFB0037
+:102560008335C4FBCD23AD5B2EAD43ADB8FACD2D85
+:10257000AD5BD7FACD4EAD0D2048AD39AD5BD7FA86
+:10258000CD2F03CE3003C610264A2203C6B8FACD9B
+:1025900068AEFB008335C4FBCD57AD5B62AD6DAD5E
+:1025A0005EAD5BD7FACD75AD64AEFB008335C4FB81
+:1025B000CD6FAD5B7AAD413503C9413603CB05EE36
+:1025C00072067BB8FACDBEDACD5BD7FACD05EE72D6
+:1025D000067BB8FACD60AEFB008335C4FBCDBEDA16
+:1025E000CD5BC6DACD413503C9413603CBEADACD3E
+:1025F000BEDACD5BD7FACDEADACD5CAEFB0083352F
+:10260000D7FACD46542703CE2803C605EF72066BD2
+:102610004A5A01264D3303CE3403C61020066B34CC
+:1026200003C6056B3303C60C264A2203C688888876
+:10263000888888812B03CE2C03C6B8FACD8133035A
+:10264000CE3403C6B8FACD814D412503C9412603D6
+:10265000CB81412F03C9413003CB46542703CE28F9
+:1026600003C681D7FACD41BE03C241BF03C031AD1D
+:10267000814D41BE03C241BF03C0412303C9412470
+:1026800003CB45AD812F03CE3003C6B8FACD8146CA
+:10269000FACD10A6D7FACD81FBB700A94101AB81D5
+:1026A0008B4100A9410EAB5B9883003599830035BF
+:1026B0009A8300359B831835B8FACD3CAEFB008376
+:1026C00035C4FBCD25AD5B30AD67ADB8FACD2FADD0
+:1026D0005BD7FACD72AD0D204AAD3BAD5BD7FACDDD
+:1026E0002F03CE3003C610264A2203C6B8FACD38CF
+:1026F000AEFB008335C4FBCD59AD5B64AD6FAD60FF
+:10270000AD5BD7FACD77AD34AEFB008335C4FBCDDE
+:1027100071AD5B7CAD413503C9413603CB07EE7229
+:10272000087BB8FACD61D9CD5BD7FACD07EE720838
+:102730007BB8FACD30AEFB008335C4FBCD61D9CD7B
+:102740005B69D9CD413503C9413603CBB9D9CD61D8
+:10275000D9CD5BD7FACDB9D9CD2CAEFB008335C42A
+:10276000FBCD61D9CD5B69D9CD413103C94132037C
+:10277000CB72D9CD61D9CD5BD7FACD72D9CD10AEA0
+:10278000FB008335C4FBCD61D9CD5B69D9CD4A5AF5
+:102790000126AFD9CD0DEE720E7BB8FACD61D9CD41
+:1027A0005BD7FACD4A5A01267CD9CD0CAEFB00830B
+:1027B00035C4FBCD61D9CD5B69D9CD0DEE720E7BF1
+:1027C000B8FACD61D9CD5B90D9CD08AEFB00833589
+:1027D000C4FBCD61D9CD5B69D9CD4A5A0126AFD9A9
+:1027E000CD0DEE720E7BB8FACD61D9CD5BD7FACDA7
+:1027F0004A5A01267CD9CD04AEFB008335C4FBCDFB
+:1028000061D9CD5B69D9CD0DEE720E7BB8FACD6181
+:10281000D9CD5B90D9CD40AEFB008335F73FF83F73
+:10282000F9B70FA4F9B6D7FACD05EE72067BB8FA60
+:10283000CD28AEFB008335F73FF83FF9B71FA4F969
+:10284000B6D7FACD2703CE2803C67884C7097B798B
+:1028500084C70A7B7A84C70B7B7B84C70C7B07EF1A
+:1028600072086B4A5A01264D3303CE3403C6066BF9
+:102870002A03C6056B2903C60A6B05AA0A7B20201A
+:10288000086B3403C6076B3303C605EF72066B593A
+:10289000482903CE2A03C60A6B01AA0A7B1F264ACF
+:1028A0002203C6096B80AA097B062604A14603C63B
+:1028B000096B20A60A6B0B6B0C6B4F0D6B0EEF7246
+:1028C0003303C9413403CB2D03CE2E03C68B410005
+:1028D000A2410EA05B8184848484BB030135B8FAD5
+:1028E000CDB4AEFB008435F716E7FBCDFBB700A9EE
+:1028F0004101AB5B016BE3A4017B016BB484C602B5
+:102900006BB584C6036BB684C6046BB784C630252A
+:1029100020A1C803C6B8FACD78AEFB008435C4FB4D
+:10292000CDFBB700A94101AB5BF7B703A4F7B6F83D
+:10293000B7C0A4F8B6F93FFA3F46FACD16A6F7B7E6
+:10294000F8B7F9B74FFA003D0355016BFCA4017BC2
+:10295000026B3FA4027B016B7884C6026B7984C64C
+:10296000036B7A84C6046B7B84C6B8FACD74AEFB65
+:10297000008435D7FACD2003CE2103C6B8FACD7036
+:10298000AEFB008435D7FACD1E03CE1F03C6B8FABE
+:10299000CD6CAEFB008435D7FACD1C03CE1D03C62B
+:1029A000B8FACD68AEFB008435D7FACD1A03CE1B3A
+:1029B00003C6B8FACD64AEFB008435D7FACD180350
+:1029C000CE1903C612206484003565840035668400
+:1029D00002356784CB35122502A21803C6CBA01995
+:1029E00003C61E2602A1C203C6252603A14B03C6A9
+:1029F0002C2420A1C803C6B8FACD60AEFB008435F4
+:102A0000D7FACD1603CE1703C6B8FACD5CAEFB00DD
+:102A10008435D7FACD1403CE1503C6B8FACD58AE17
+:102A2000FB008435D7FACD1203CE1303C6888888FD
+:102A30008881FBC692FCBFFBB781FBD692FC3FFBB3
+:102A4000B781842003CF1803CE2103C71903C6180A
+:102A500003CF1903C74A5A01264D59484003CE41B6
+:102A600003C60B200E264D4003CE4103C60B264A5B
+:102A70002203C61E03CF1603CE1F03C71703C617B4
+:102A8000035F7216035F721C03CF1403CE1D03C7CE
+:102A90001503C61403CF1503C74A5A01264DFA265B
+:102AA0005A90465406273D03CE903E03CE3F03C6C0
+:102AB0001A03CF1203CE1B03C71303C613035F729F
+:102AC00012035F723D035F72042604A1C203C60BAA
+:102AD0002603A10F202D035F722E03233519260331
+:102AE000A1C203C6202603A115244B03C620A1C8FA
+:102AF00003C6400325035541032603554403290318
+:102B00005545032A03553E032303553F032403552C
+:102B10004203270355430328035597D3CCC7D5CD8C
+:102B2000D0A94109AB521CAE017BB8FACD39AEFB3E
+:102B3000000335E9F9CDFBB7D0A94105AB521CAE76
+:102B4000017B3803C7C7D5CDD0A94104AB521CAE19
+:102B5000017B3703C7C7D5CDD0A94103AB521CAE0B
+:102B6000017B3603C7FBD692FC3C3503C7BFD5CDEE
+:102B7000D0A94101AB521CAE017B33035F72340319
+:102B800001353203C7FBD692FC3C3103C7BFD5CD1C
+:102B9000CFA941FDAB521CAE017B3003C7FBD692DF
+:102BA000FC3C2F03C7BFD5CDCFA941FBAB521CAE18
+:102BB000017B2E03C7FBD692FC3C2D03C7BFD5CDAE
+:102BC000CFA941F9AB521CAE017B2C03C7FBD692B7
+:102BD000FC3C2B03C7BFD5CDCFA941F7AB521CAEF0
+:102BE000017B2A03C7FBD692FC3C2903C7BFD5CD86
+:102BF000CFA941F5AB521CAE017B2803C7FBD6928F
+:102C0000FC3C2703C7BFD5CDCFA941F3AB521CAEC7
+:102C1000017B2603C7FBD692FC3C2503C7BFD5CD5D
+:102C2000CFA941F1AB521CAE017B2403C7FBD69266
+:102C3000FC3C2303C7BFD5CDCFA941EFAB521CAE9F
+:102C4000017B2203C7C7D5CDCFA941EEAB521CAE45
+:102C5000017BE6D4CC0ED5CC032702A1E6D4CC036D
+:102C60002603A14B03C63D03C729B639032A0055E5
+:102C70003A032B00553B032C00553C032D005537E0
+:102C800003C713B613B63503CF22BE3603C723B628
+:102C90003303CF20BE3403C721B63103CF1EBE326B
+:102CA00003C71FB62F03CF1CBE3003C71DB62D03AD
+:102CB000CF26BE2E03C727B62B03CF24BE2C03C7B7
+:102CC00025B62903CF18BE2A03C719B62703CF1488
+:102CD000BE2803C715B62503CF1ABE2603C71BB6E9
+:102CE0002303CF16BE2403C717B62203C728B6AEE8
+:102CF000D3CC03241DA111B60927113D016B4A1144
+:102D0000B68800F0701C050101030003008F004627
+:102D1000001B00AA011E030007000350050100600C
+:102D2000A01805010106000300700040001800B063
+:102D3000011B030007000350050100E01BFA04011A
+:102D40000006000300800048001C0090013F039033
+:102D500006200300050100C05F3B040001060003DC
+:102D600000200030001400A0003703A0052003005D
+:102D7000050100E012BD04010007000300800040CF
+:102D8000001B0080011E0380060003000501009067
+:102D9000691104000107000300200030001300A0A7
+:102DA000001603A00500030005010040D2DF030068
+:102DB000000600030088001800230040012603409D
+:102DC00005000300040100F0FB02020101080006F7
+:102DD00000700010001F00F00005024004E00150E8
+:102DE000030100005A620201010400010080002872
+:102DF000001B00000174022004580220030100108F
+:102E0000F76C040101050001002800E0061900E448
+:102E100007EE02E40CD0020005010010F76C04017B
+:102E20000105000100280074091900780AEE0278F3
+:102E30000FD00200050100405F8A03010105000177
+:102E4000002800E0061900E407EE02E40CD00200BE
+:102E500005010010F76C040101050001002C005869
+:102E60000029001801650498083804800701001043
+:102E7000F76C040101050001002C0010022900D0AC
+:102E8000026504500A38048007010010F76C040141
+:102E900001050001002C007E0229003E036504BEEE
+:102EA0000A38048007010020EED90801010500015D
+:102EB000002C0010022900D0026504500A3804805A
+:102EC00007010080F93703000005000100800018A9
+:102ED000002C0020017102C0064002A0050101C0C3
+:102EE000FC9B010000030001007E0018001600207A
+:102EF000017102C0062001A005000010F76C04015A
+:102F000001050001002C0010021400D002650450DD
+:102F10000A1C028007000010F76C04010105000183
+:102F2000002800B8011900BC02EE02BC07D0020064
+:102F3000050100C0FC9B0100000500010040000CE1
+:102F4000002C009000710260034002D002010020BA
+:102F5000EED9080101050001002C005800290018D5
+:102F6000016504980838048007010080F9370300E0
+:102F700000060007007C002000240014010D02B4AC
+:102F800006E001A0050101C0FC9B01000003000454
+:102F9000007C002600120014010D02B406F000A00F
+:102FA00005000010F76C040101050001002C005819
+:102FB0000014001801650498081C02800700001026
+:102FC000F76C0401010500010028006E0019007271
+:102FD00001EE027206D00200050100C0FC9B010058
+:102FE00000060007003E00100024008A000D025A6F
+:102FF00003E001D002010080858001000002000191
+:1030000000600010002300A0000D022003E00180FA
+:10301000020181848B4100A94108AB5B096B016B04
+:103020004F012001A604269803C1057B0B2604E16D
+:10303000729903C608279803C6B72655FBCDFBB780
+:1030400000A94102AB5BE7FBCDFBB700A94106AB92
+:103050005B066B3048C6076B3148C6086B3248C602
+:10306000096B3348C684842F1ECD74AE08A6024B6C
+:10307000004B026B067B036B077B046B087B056BC5
+:10308000097B066B3048C6076B3148C6086B32486F
+:10309000C6096B3348C6016B4F8B4100A24109A0A2
+:1030A0005B8118E7FEC692FFBF9019CECC17B6170A
+:1030B000B780AA027BC62505A10D6B4C0D7BD225DE
+:1030C00004A10C6B4C0C7B18CECC0327A0E118E6B6
+:1030D0009097900CEB720BEB7248480D7B9701EBCD
+:1030E0007248480D7B016B0CE07203A60C6B4F0D10
+:1030F0006B4F84842F1ECD74AE20A6144B8807AB73
+:103100000B7B761DCD84B417CD00AE18A6880AAB14
+:103110000B7BFD16CDAE2504A10D6B4C0D7B74AD64
+:10312000FE3C02249790FFBB0DE07203A693FFBF05
+:10313000FEB700A94107AB5B93909706AB0DEB720E
+:103140000B7B56CFCDFE3C02249790FFBB0DE07267
+:1031500003A693FFBFFEB700A94103AB5B93905C4E
+:103160005C970DEB720B7B0D6B4F076B2C48C60801
+:103170006B2D48C6096B2E48C60A6B2F48C6036BD9
+:103180002848C6046B2948C6056B2A48C6066B2B1F
+:1031900048C6F02505A10D6B4C9F18E79803D60D86
+:1031A000EE720D6B12264A027B84842F1ECD74AE04
+:1031B00043A6880C7B074B19E79903C618E79803C9
+:1031C000C60BEE724DCFCC0326027B0B6B5205AEC5
+:1031D000E82414A1026B7FA49803C681848B41006C
+:1031E000A9410CAB5B0D6B4F0D99030772052002D3
+:1031F00098030F7284842F1ECD74AE41A6024B003B
+:103200004B192660A160A49803C684842F1ECD7438
+:10321000AE40A6014B004B8B4100A2410DA05B814B
+:103220007B03C67B0301350498030D7284842F1E33
+:10323000CD74AE40A6014B004B7B035F7281859A33
+:10324000B8FACD14AEFB004835F7B7F8B7F9B74F69
+:10325000FA007E035510487F03551148800355122C
+:103260004881035513488203559BCD2505A1016B69
+:103270004C017BBEFBCD7FAEFB00033546FACD484B
+:1032800048489FF7B7F8B7F9B74FFAB79803D60190
+:10329000EE721F207E039C0355072604A1016B4F8D
+:1032A00084847F035F7280035F7281035F72820395
+:1032B0005F722F1ECD74AE4F054B004B8881848BFF
+:1032C0004100A94108AB5B096B016B850A1FCD74F6
+:1032D000AE10A6054B9C03C7057B026B9003C6038B
+:1032E0006B9103C6046B9203C6056B9303C69B03E5
+:1032F000C7027B9A03C7037B9903C7047B9803C764
+:10330000057B026B8C03C6036B8D03C6046B8E03B7
+:10331000C6056B8F03C6016B850A1FCD74AE18A658
+:10332000084B9F03C7067B9E03C7077B9D03C70807
+:103330007B9C03C7097B066B1C48C6076B1D48C6F0
+:10334000086B1E48C6096B1F48C69B03C7067B9ABD
+:1033500003C7077B9903C7087B9803C7097B066BE4
+:103360001848C6076B1948C6086B1A48C6096B1B74
+:1033700048C6016B4F8B4100A24109A05B81858546
+:10338000858585017B016B01A6042614A1027B0AB9
+:103390002614A1037BD12505A1056B4C057BDD25FA
+:1033A00008A1046B4C047B98034472026B4C027BB3
+:1033B0000520036B4C037B072601A49803D605EE7A
+:1033C00072046B4F056B4F44204F032785854D2FAB
+:1033D0001ECD74AE054B004B9A144890035515480A
+:1033E0009103551648920355174893035510488C7E
+:1033F000035511488D035512488E035513488F030A
+:10340000559B036B026B016B4F888888888881FB12
+:10341000004835F7B7F8B7F9B74FFAB78185858512
+:1034200085017B9AB8FACD0CAE0DAD037B9B016B89
+:1034300001A60426027B04264A037BEE26027B06B5
+:1034400026037B026B4A027B036B0F48C60A209A55
+:10345000B8FACD5F38AD047B9B026B32A6016B03DB
+:103460006B4F8888888881E7FBCDFBB700A94105B1
+:10347000AB8184848484848484849AB8FACD04AE35
+:10348000FB004835FA15F7B7F8B7F9B74FFAB703A5
+:10349000AA3FA4087B9B056B0448C6066B0548C67B
+:1034A000076B0648C6086B0748C69AB8FACD5FFB9B
+:1034B000004035C4FBCDFBB700A94101AB5BFA145A
+:1034C0004FAD5BB8FACDFBB700A94101AB5BF7B7D5
+:1034D000F8B7F9B74FFA007803559B056B0040C663
+:1034E000066B0140C6076B0240C6086B0340C69AD4
+:1034F000B8FACDB4AEFB008435FA1AFA198FCBCDE9
+:103500005B9B056BB484C6066BB584C6076BB6843B
+:10351000C6086BB784C6888888888888888881E7C9
+:10352000FBCDFBB700A94101AB81848484849AB8A8
+:10353000FACD04AEFB004835FA1411AD5B9B016B6C
+:103540000448C6026B0548C6036B0648C6046B07F1
+:1035500048C69AB8FACD5FFB004035FA1534AD5B2A
+:103560009B016B0040C6026B0140C6036B0240C664
+:10357000046B0340C68888888881858585854F9A35
+:10358000B8FACD04AEFB004835F73FF83FF93FFAF3
+:10359000B730A4FAB6F7B7F8B7F9B74FFAB7047B64
+:1035A0009B016B0448C6026B0548C6036B0648C600
+:1035B000046B0748C69AB8FACD5FFB004035FA1590
+:1035C000E7FBCDFBB700A94101AB5B9B016B004062
+:1035D000C6026B0140C6036B0240C6046B0340C6C3
+:1035E00088888888819A9BFACDFBB740A94100ABB7
+:1035F00081FBB700A94107AB818B4100A9410DAB0D
+:103600005B9AB8FACD30AEFB004235C4FBCDFBB7B8
+:1036100000A94101AB5B46FACD4848127BF73FF861
+:103620003FF93FFA0003359B016B3042C6026B3114
+:1036300042C6036B3242C6046B3342C639C9CC035F
+:103640002506E172FBD69202AEFCB70D7BFBB70CF0
+:103650007B066B04AB067B67AD5C012406EB721046
+:10366000EE72117BE7FBCD6FAD5B9BAF2504A10B29
+:103670006B4C0B7BFBC792FCBF85FB0032FBD692E9
+:1036800003AEFCBFFBB70EE972410FEB725F4A0756
+:103690006B4C077BFB003B89FB3C022497FCBB0B7C
+:1036A000E07203A6FCBF08CACD5B362505E172FBBC
+:1036B000D69202AEFCB70D7BFBB70C7B0B6B076B96
+:1036C000086B096B0A6B4F7420056B4F106B00A9D8
+:1036D000107B116B04AB117B10CACD10EE72117B05
+:1036E000E7FBCD08CACD5B9B076B4F086BFBD692FF
+:1036F0005C096BFBD69201AEFCB70D7BFBB70C7B74
+:103700000A6BFBC692FCB70D7BFBBF0CEE728B41C4
+:1037100000A2410BA05B89888101A61500DE35144B
+:1037200000C0351300AD351200DE35A7F6CD81841B
+:103730008484848493C7CDAC2510A1046B4C047B96
+:10374000C22508A1056B4C057BDBC7CD03275D03B4
+:10375000264D4101E4724102E472FA265A9059481A
+:10376000062705E67201A601EF72026B5F037B007C
+:10377000C8CD03209AAD0426057B0826047B056B83
+:103780004F036B12E69704E0720FA6046B4FF5250A
+:1037900010A1046B4C047B97AD046B4FDBC7CD933A
+:1037A000C7CDBDC7CD888888888881B3840035B0EF
+:1037B000840035B184003581B0840035B184003592
+:1037C000B28400350DADB284033513ADB284023539
+:1037D00019ADB2840035B384003581B0840035B1B1
+:1037E000840035B2840035B38400358101ADB084E6
+:1037F0000035B1840035B2840135B384003513AD92
+:103800008164A6B0840035B184003526C0CC03ADF8
+:10381000B2840035B384003526C0CD10ADB2840427
+:1038200035B384003581AD840035AE840035AF8476
+:10383000003581AC84003505AD81AC8480350CAD9C
+:1038400007274D26C0CC64A6B0840035B18400356E
+:10385000B2840035B384003526C0CD0AA6B08400FA
+:1038600035B1840035B2841035B384003581848449
+:103870008484BB030135B8FACD5FFB008435F71AA9
+:10388000E7FBCDFBB700A94101AB5B016B0084C630
+:10389000026B0184C6036B0284C6046B0384C68872
+:1038A0008888888184848484B8FACD5FFB0084355D
+:1038B000F71BE7FBCDFBB700A94101AB5B016B0038
+:1038C00084C6026B0184C6036B0284C6046B038446
+:1038D000C68888888881B8FACD78AEFB00843581A7
+:1038E000E7FBCDFBB700A94101AB81848484841040
+:1038F000ADFA1D09AD5B17ADFA1C10AD5B016B781D
+:1039000084C6026B7984C6036B7A84C6046B7B849D
+:10391000C68888888881D7FACD9802CE9902C68158
+:1039200084848484A084C7017BA184C7027BA28491
+:10393000C7037BA384C7047B036B80AA037B046B50
+:1039400006AA047B0C20BEFBCDFBB700A94101AB4E
+:103950005BF91E34AD112400A29802C606A099029C
+:10396000C60C274C03C6222502A19702C629264A67
+:103970004B03C6036B80A4037B046B4F016BA084D5
+:10398000C6026BA184C6036BA284C6046BA384C663
+:103990006C2502A19702C673264A4B03C60D274A1F
+:1039A0004C03C6B8FACD78AEFB008435F71CE7FBB4
+:1039B000CDFBB700A94101AB5B016B7884C6026BFC
+:1039C0007984C6036B7A84C6046B7B84C648830003
+:1039D00035498300354A8300354B830F3510264A1D
+:1039E0002483003525830035268300352783003561
+:1039F0004D274B03C6B8FACDA4AEFB008435F91EA3
+:103A0000F73FF83FF91FE1C6CD142603A1042701B3
+:103A1000A19702C61F264A4B03C6B8FACDA0AEFB3B
+:103A2000008435F71FF93FFA3F46FACD10A6D7FAC2
+:103A3000CD5C012402AB3303CE3403C60B20C0039C
+:103A4000CEC103C62A264A0B2702A04B03C6C703D2
+:103A50005F725DC6CC03274D03C608274C03C6889A
+:103A60008888888184848484A084C7017BA184C7DA
+:103A7000027BA284C7037BA384C7047BBEFBCDFB70
+:103A8000B700A94101AB5BF91ED7FACD9802CE99D8
+:103A900002C6036B80A4037B046B4F1F2502A19712
+:103AA00002C626264A4B03C6036B7FA4037B016B29
+:103AB000A084C6026BA184C6036BA284C6046BA358
+:103AC00084C65A264C03C65F202483003525830014
+:103AD000352683023527830035A0840035A1840074
+:103AE00035A2840035A3840035A4840035A5840064
+:103AF00035A6840035A7840035B8FACD78AEFB0032
+:103B00008435F71DE7FBCDFBB700A94101AB5B0195
+:103B10006B7884C6026B7984C6036B7A84C6046BA7
+:103B20007B84C6C703C75F264C03CE64264D03C6FD
+:103B30008888888881E7FBCDFBB700A94101AB816C
+:103B4000848484840040C7017B0140C7027B02401B
+:103B5000C7037B0340C7047BB8FACD5FFB00403549
+:103B6000F71E23AD5BB8FACD1CAEFB004035F7B7AE
+:103B7000F8B7F9B74FFAB713B614201C4000351D3B
+:103B80004000351E4000351F400035046B02AA047A
+:103B90007B1826123D046B40AA047B06263803C618
+:103BA000046B10AA047B06263703C6016B026B0365
+:103BB0006B4F046B01A6B8FACDB4AEFB008435FAA6
+:103BC00018F918C1C4CD5B016BB484C6026BB5840F
+:103BD000C6036BB684C6046BB784C626C0CDFAA6EE
+:103BE0001445003515450035164500351745023595
+:103BF00088888888810140003502400035034000F4
+:103C00003581848484844D035F72B8FACDB4AEFBF1
+:103C1000008435F919E7FBCDFBB700A94101AB5B87
+:103C2000016BB484C6026BB584C6036BB684C6044C
+:103C30006BB784C61445003515450035164500356B
+:103C4000174501350040003547AD004080354DAD8A
+:103C50008888888881B8FACDB4AEFB008435F91E17
+:103C600081AC840035AD840035AE84003581FBB76E
+:103C700000A94105AB81FBB700A94101AB81FBB7AE
+:103C800000A94109AB810088003501880035028810
+:103C9000003581F914FA14F73FF83FF9B701A4F998
+:103CA000B6FAB7F8A4FAB6D1F9CD08AE905FC6035C
+:103CB000C6818B4100A9410EAB5B28AD038801355D
+:103CC00008880035098830350A8800350B880035AA
+:103CD000B8FACD0CAEFB008835FA1EF7B7F8B7F985
+:103CE000B74FFAB707A40D7B18880035198800353F
+:103CF0001A88FF351B88FF35148800351588003574
+:103D00001688FF351788FF351088003511885F3514
+:103D10001288FF351388FF356EC3CD03880035A0A8
+:103D2000C3CDF71EE7FBCD83C3CD5B0C2621A110CD
+:103D3000209084C7057B9184C7067B9284C7077B4C
+:103D40009384C7087BB8FACD8BC3CD5BC4FBCD830E
+:103D5000C3CD5BC4FBCD7BC3CD5BF71EE7FBCD8B37
+:103D6000C3CD5B056BBFA4057B066BC3A4067B07B5
+:103D70006B086B4F9FFBCD10A68BC3CD5B9FFBCD1C
+:103D800010A67BC3CD5B096B0A6B0B6B4F0C6B3CB6
+:103D9000A60B2082FBCD04A67BC3CD5B0B2455FB79
+:103DA000CD61AEFB00C135E7FBCD7BC3CD5B096BBD
+:103DB0000A6B0B6B4F0C6B3CA4087B3E20096B4FCE
+:103DC0000A6B04A60B6B0C6B4F0E2430A1C803C604
+:103DD000056B9484C6066B9584C6076B9684C608EB
+:103DE0006B9784C6016B026B4F016B9884C6026BA4
+:103DF0009984C6036B9A84C6046B9B84C6A0C3CD0A
+:103E0000F7B760AAF7B6E7FBCD83C3CD5BD1C2CCD1
+:103E1000032422A1C803C6016BB484C6026BB58417
+:103E2000C6036BB684C6046BB784C693C3CDAF8498
+:103E30002035B8FACD7CAEFB008435F714F81AF8BB
+:103E4000104FC3CD0920F81AF8104FC3CD1220F837
+:103E5000104FC3CD19204FC3CD272017274A112754
+:103E60004A0D274A0B274A0D7B93C3CDAF840035FB
+:103E70007C8400357D8400357E8400357F84003568
+:103E80006EC3CD03880035D8C0CD212520A1C8033D
+:103E9000C68B4100A2410CA05B89883C00000081D8
+:103EA000AC840035AD840035AE840035AF84003578
+:103EB0007C8400357D8400357E8400357F84003528
+:103EC00000880035018800350288003503880035F8
+:103ED000A8AD022520A1C803C64B035F72B9035FDA
+:103EE000728184848484B484C7017BB584C7027BD7
+:103EF000B684C7037BB784C7047BB8FACDB4AEFBE6
+:103F0000008435F81CE7FBCDFBB700A94101AB5B92
+:103F1000016BB484C6026BB584C6036BB684C60459
+:103F20006BB784C68888888881E7FBCDFBB700A97A
+:103F30004103ABB8FACC5FFB008435F70030350C99
+:103F4000AD5BB8FACD5FFB008435F71AF73F1BADC8
+:103F50005B81F73FE7FBCDFBB700A94103ABB8FAA4
+:103F6000CC5FFB008435F7180AAD5BB8FACD5FFB78
+:103F700000843515AD5B818590859001EE72027BE2
+:103F8000052005EE72067B072405E2729F06E072AB
+:103F90008988818590859005EE72067B052001EE6B
+:103FA00072027B072405E2729F06E0728988818491
+:103FB00084E926FBB6ED265D016B00A2FBB7017B11
+:103FC000026B01A097027B9D012001EF72026B063C
+:103FD000FACD03AE90FE3F5F88888141204035488E
+:103FE000205F7246205F724520C701A60220D8A636
+:103FF000042420A1C803C6819AB203CFB303C79B90
+:1040000000000000000000000000000000000000B0
+:1040100000000000000000000000000000000000A0
+:104020000000000000000000000000000000000090
+:104030000000000000000000000000000000000080
+:1040400000000000814F13B75320C6502012728128
+:1040500001A603274DB61DCD88A612B75320C65022
+:104060002015728101A603274DB61DCD88A68101BA
+:10407000A603274D131ECD41A68101A603274DFEA1
+:104080001DCD86025F725020203552200935814DAA
+:10409000B61DCD88A6502020355320C7C5204F50CF
+:1040A000201272EC2506E172016B4C017BD42613C1
+:1040B000AD9803D601EE720D204F172760A1027B49
+:1040C00026C0CD05A6EC262BAD037BF2264DB61DF2
+:1040D000CD88A68185858501A606274D131ECD02B4
+:1040E0007B08264DFE1DCD86025F72502020355282
+:1040F000200935888988814DB61DCD88A64F1ECCF4
+:104100004F26C0CD05A6952506E172017B9803D701
+:104110005320C6016B4C9F01EE720D2011E7532016
+:10412000C69707EB724A016B4C017B112509A1066A
+:104130007B502022350426FFB1FFBF900B26FEB333
+:10414000FE3F01E6724A5A01264D5F067B5020155C
+:10415000720426FFB1FFBF900B26FEB3FE3F01E6BF
+:10416000725A012402A05F1A2502A1067BBA2672A8
+:10417000AD5020157204264A067BC7264D90AD012E
+:10418000AA027BD0264D84AD26C0CD05A6DA260333
+:104190001FCD502020355320C7037B02205280AE14
+:1041A000037B072680A1067BF526031FCD8185852D
+:1041B0008501A606274DC9AD027B07264DBBAD86FE
+:1041C000025F72016B4F50202035522009358889DB
+:1041D00088814F5020243526C0CD05A68101A60335
+:1041E000274DB7AD82A6502021355320C7814F26D9
+:1041F000C0CD05A68101A603274DCFAD81A65020D5
+:10420000293581854F86025F72818501A686025F0E
+:1042100072502022350C86020D72052601E17201D2
+:10422000E472FA278602C68F01208881854F818536
+:1042300001A650200535082701E17201E4725120E2
+:10424000C6FA51200F729D0120880218CCF5B545A1
+:10425000F4B445F33FF23FF13FF03FEF3FEE3FF65E
+:104260002538A3F6BEB66FF63C04200218CDF4251F
+:1042700040A1F6B6B66FF63CF6BE0820172539A168
+:10428000F6B6B6E780A6F63CF6BE8106FCCDFBB7D7
+:1042900000A941C6AB5204AE8106FCCDFBB700A914
+:1042A00041CEAB5204AE8106FCCDFBB700A941FA6A
+:1042B000AB5204AE81E9F9CDFBB700A941E6AB52A0
+:1042C00004AE81FBB700A94101AB81F7B7F8B7F99C
+:1042D000B74FFAB7B6E681B8FACDFBB700A9410DE2
+:1042E000AB810FFBCDFBB700A94111AB81FBB70040
+:1042F000A94119AB81FBB700A94105AB81FBB70010
+:10430000A94115AB81E7FBCDFBB700A9411DAB81EE
+:10431000FBB701A94106AB5204AE81FBB700A9412E
+:1043200009AB81E7FBCDFBB700A94121AB818B41F4
+:1043300000A94125AB5BF63F2FFACDB0AEE7FBCD30
+:10434000FBB700A94111AB5B2FFACDACAEE7FBCDBB
+:104350005CAD5B2FFACDA8AEE7FBCD57AD5B2FFA76
+:10436000CDA4AE36AD5B2FFACDA0AE5CAD5BC61B67
+:10437000CC032450A1256B4C257B1D6B0D7B1E6B44
+:104380000E7B1F6B0F7B206B107B216B1D7B226BC9
+:104390001E7B236B1F7B246B207BB8FACDFC1CCDCE
+:1043A0005BC4FBCDDE1CCD5B46FACD1EA6D31CCD77
+:1043B0005BB8FACDDE1CCD5B7AFACD02A6D31CCD5C
+:1043C0005B196B157B1A6B167B1B6B177B1C6B18B1
+:1043D0007B116B197B126B1A7B136B1B7B146B1C91
+:1043E0007B1F1DCD5B0FFBCDFEAEFB0017350FFB1A
+:1043F000CDE61CCD257B141DCD5B0FFBCDDE1CCD8A
+:104400005BC4FBCD041DCD5B46FACD05A6F11CCDEA
+:104410005BB8FACD041DCD5B7AFACD1BA6F11CCD9D
+:104420005BB8FACDDE1CCD5B06FCCD0C1DCD5B066A
+:10443000FCCDFC1CCD5BD31CCD5B256B3CA6D31AFD
+:10444000CC03243CA1256B4C257B1D6B0D7B1E6B87
+:104450000E7B1F6B0F7B206B107B216B1D7B226BF8
+:104460001E7B236B1F7B246B207BB8FACDFC1CCDFD
+:104470005BC4FBCDDE1CCD5B46FACD1EA6D31CCDA6
+:104480005BB8FACDDE1CCD5B7AFACD02A6D31CCD8B
+:104490005B196B157B1A6B167B1B6B177B1C6B18E0
+:1044A0007B116B197B126B1A7B136B1B7B146B1CC0
+:1044B0007B1F1DCD5B0FFBCDFAAEFB0017350FFB4D
+:1044C000CDE61CCD257B141DCD5B0FFBCD041DCD92
+:1044D0005BC4FBCD361DCD5B46FACD05A6F11CCDE8
+:1044E0005BB8FACD361DCD5B7AFACD1BA6F11CCD9B
+:1044F0005BB8FACD041DCD5BC4FBCDDE1CCD5B32B9
+:10450000FBCDFBB700A94121AB5BC4FBCD0C1DCD9E
+:104510005BE7FBCDFC1CCD5BB8FACDDE1CCD5B327E
+:10452000FBCD0C1DCD5BE7FBCDFC1CCD5B256B28CB
+:10453000A6031ACC032428A1256B4C257B1D6B0DEB
+:104540007B1E6B0E7B1F6B0F7B206B107B216B1D0B
+:104550007B226B1E7B236B1F7B246B207BB8FACDE9
+:10456000FC1CCD5BC4FBCDDE1CCD5B46FACD1EA68C
+:10457000D31CCD5BB8FACDDE1CCD5B7AFACD02A69A
+:10458000D31CCD5B196B157B1A6B167B1B6B177BD2
+:104590001C6B187B116B197B126B1A7B136B1B7BCB
+:1045A000146B1C7B1F1DCD5B0FFBCDF6AEFB001704
+:1045B000350FFBCDE61CCD257B141DCD5B0FFBCD50
+:1045C000DE1CCD5BC4FBCD041DCD5B46FACD05A63C
+:1045D000F11CCD5BB8FACD041DCD5B7AFACD1BA6DC
+:1045E000F11CCD5BB8FACDDE1CCD5B06FCCD0C1DFD
+:1045F000CD5B06FCCDFC1CCD5BD31CCD5B256B14C9
+:10460000A61919CC032414A1256B4C257B1D6B0D19
+:104610007B1E6B0E7B1F6B0F7B206B107B216B1D3A
+:104620007B226B1E7B236B1F7B246B207BB8FACD18
+:10463000FC1CCD5BC4FBCDDE1CCD5B46FACD1EA6BB
+:10464000D31CCD5BB8FACDDE1CCD5B7AFACD02A6C9
+:10465000D31CCD5B196B157B1A6B167B1B6B177B01
+:104660001C6B187B116B197B126B1A7B136B1B7BFA
+:10467000146B1C7B1F1DCD5B0FFBCDF2AEFB001737
+:10468000350FFBCDE61CCD257B141DCD5B0FFBCD7F
+:10469000041DCD5BC4FBCD361DCD5B46FACD05A612
+:1046A000F11CCD5BB8FACD361DCD5B7AFACD1BA6D9
+:1046B000F11CCD5BB8FACD041DCD5BC4FBCDDE1C77
+:1046C000CD5B32FBCDFC1CCD5BD31CCD5BB8FACDF2
+:1046D000DE1CCD5B32FBCD0C1DCD5BF733F833F91F
+:1046E00033FA33D31CCD5B256B4F116BB0B6126B15
+:1046F000B1B6136BB2B6146BB3B6196BACB61A6B1A
+:10470000ADB61B6BAEB61C6BAFB6156BA8B6166B11
+:10471000A9B6176BAAB6186BABB6216BA4B6226B01
+:10472000A5B6236BA6B6246BA7B61D6BA0B61E6BF1
+:10473000A1B61F6BA2B6206BA3B6AE2550A1256B08
+:104740004C257B9BFACDE61CCD257BC4FBCDDE1C26
+:10475000CD5BF739F839F939FA38681DCD257B5A20
+:104760001DCD257B4C1DCD257B3E1DCD257BB8FA6F
+:10477000CDDE1CCD5B7AFACD1FA6681DCD257B5AF8
+:104780001DCD257B4C1DCD257B3E1DCD256B10A65B
+:104790009D2510A1256B4C257BBEFBCDE61CCD25B0
+:1047A0007B2A1DCD9703AB9F585825EE72BEFBCDDB
+:1047B000E61CCD257BE0FACD5F90FE0001355FB6AB
+:1047C000E65C5C585825EE72BEFBCDE61CCD257B21
+:1047D00046FACD10A62A1DCD5C585825EE729BFADC
+:1047E000CDE61CCD257B46FACD18A62A1DCD5858FE
+:1047F00025EE72256B4F8B4100A24125A05BD6C1EF
+:1048000062CADCBC1B8FA1EBD96E9979825A818474
+:1048100084C9264C056B4A057B016B00A9017B020C
+:104820006B01AB027B27AD022640A1F6B6B43C0279
+:1048300024B5B708ABB5B6B6E7F63CF6BEFBC692F4
+:10484000FCB7027BFBB7017B2F208988818484849D
+:10485000B4B7B4B99FB5B7B5BB5208AEF6B7037BD2
+:10486000EF2503E172016B4C9FB6E74602D601EEDD
+:10487000720A204F76ADB4000235B53FF6004035E0
+:10488000F12540A1016B4C9FB6E701EE72027B015E
+:104890006B19A6ED2519A1016B4C9FB6E702E872D2
+:1048A00060FED601EE72016B4F88898881B000C32B
+:1048B00035B100D235B200E135B300F035AC0010AF
+:1048C00035AD003235AE005435AF007635A80098CE
+:1048D00035A900BA35AA00DC35AB00FE35A400EFDF
+:1048E00035A500CD35A600AB35A7008935A00067FA
+:1048F00035A1004535A2002335A3000135F63FB5AB
+:104900003FB43F818484761DCD5DAD5CAE14A60CB2
+:10491000ADDE2505A1026B4C027BEA2504A1016BEB
+:104920004C017B4602D7A0E69701EB724848027B18
+:10493000016B4F026B4F761DCD5417CD36AE05017E
+:10494000C63EAD05013235F02532A1026B4C9F46C3
+:1049500002D7CDA602EE72026B4F88883A15CC289A
+:104960004B1CCACD3E15CCC1A6004B084B87CACD07
+:104970003E15CCE0A6014BE04BBF15CC03267503DA
+:104980005A7281848475030235DF14CDE0A6014B91
+:10499000E04B10274D5FCFCD28277703C57903C69D
+:1049A0003E15CCC1A6004B284B3C15CC014B904B7F
+:1049B0001CCACD0A277703C57903C6C520284B3EFC
+:1049C00015CCE0A6014B904BE2CACD0C277703C56E
+:1049D0007903C6DD20084B3E15CC82A6014B904BD7
+:1049E00076035A72CE277603C612264DE1CDCD3E10
+:1049F00015CCC0A6004B504BB7274D5FCFCDE82656
+:104A00004D9ACBCD03A6262076030A35CB274D5FE2
+:104A1000CFCDD320604B04274D9ACBCD83A618274A
+:104A20004DC3CDCD3E15CC81A6004B604BEC264D41
+:104A30009ACBCD02A643CDCD3E15CCA0A6004B0807
+:104A40004B09274D83CCCD06264D9ACBCD4C8C20DF
+:104A500080A688884F932040A6004BA04B08264D87
+:104A6000F2CBCD9C16CC6016CC03261FA04516CCED
+:104A700003264A2D16CC032620A0E0271EA01116DF
+:104A8000CC03264A60274A392720A0C32720A02C20
+:104A90002720A0302720A09C16CC03268303C6DD48
+:104AA0002060A6004B504B1CCACD032561A1830397
+:104AB000C6122711A17C03C607277A03C681848406
+:104AC0009FAD20A6004B504B0B264D03C6052783F8
+:104AD00003C610204F004BA04B1CCACD03278303F5
+:104AE000C60F267D03C68184848400C0CD06EE7285
+:104AF000077B8303C7037B05201872042701E1723B
+:104B0000F0A48303C6016BF0A4037B0620C7026BED
+:104B100002EA72E0A4037B026B1FA40620C6888809
+:104B200088814442003545420035464200354742BF
+:104B30000035004200350142003502420135034292
+:104B4000013510200042083501420035024201358E
+:104B50000342003512264A9B02C620400035214000
+:104B60000035224000352340013504449E0255059E
+:104B7000449F02550644A002550744A10255004433
+:104B8000A202550144A302550244A402550344A5C0
+:104B9000025581854FF3259B02C1016B4C017B7649
+:104BA00012CD06204F88819A9BFACDF73FF83FF946
+:104BB0003F81F7B7F8B7F9B74FFAB7819A9BFACDAB
+:104BC000FBB701AA4181FBC692FCBFFBB7811DADBB
+:104BD000FA3FFBB701AA3313CC4F29ADFA003D359C
+:104BE00003EE72FBB7027B9B37ADFA000835FBB7CB
+:104BF00002AA4124AA02EE72037B9BD32604E1722F
+:104C000033AD02AA4103AA02EE72037B3213CC0336
+:104C100026016B4A017B9A9BFACDFBB702AA027B65
+:104C200003EE7268AD047B9B1C20016BFFA6046B36
+:104C300080AA047B062602A111B6046B03A60220FB
+:104C400001A6062002A60427153D0C279C02C67962
+:104C5000AD411CAA02EE72037B9B2A14CD4118AA17
+:104C600002EE72037B9B2A14CD4114AA02EE72035A
+:104C70007B9BD72604E1723314CD01AA4113AA020B
+:104C8000EE72037BB627016B4A017B3B14CD10AA61
+:104C900002EE72037B4514CD047B9B1720016BFF52
+:104CA000A6046BCFA602200FA606200CA60820069D
+:104CB000274A052714B6CC2604E1723314CD01AA85
+:104CC000410DAA02EE72037B81858585854C0626FF
+:104CD000016B4A017B3B14CD0CAA02EE72037B46AA
+:104CE000FACD10A64514CD047B9B2220016BFFA6B4
+:104CF000046BFCA60220F0A60620CCA60A20C0A6C3
+:104D00000E200CA612200FA616200CA618274A1754
+:104D1000274A16274A15274A14274A29274A1627B9
+:104D200013B6C92604E1723314CD01AA410BAA02BD
+:104D3000EE72037B6627016B4A017B3B14CD08AA08
+:104D400002EE72037BF7B703AAF7B6F8B7C3AAF768
+:104D5000B7F9B74FFAB7047B9B2520016BFFA60478
+:104D60006B4F01200CA60427153D2A14CD4104AA3F
+:104D700002EE72037B9B2A14CD9B026B03EF7250F1
+:104D8000AA414F5858978888888881E7FBCDA2AE02
+:104D9000FB00023581FBB700A94101AB81F7B7F8F1
+:104DA000B7F9B74FFAB781F7B703A4F7B6F83FF9E9
+:104DB0003FFA3F46FACD18A61DFACD4A81FBB7004F
+:104DC000A94107AB81A2020035A3020035A4021855
+:104DD00035812CAD18A44848484A12B6B8FACD43DC
+:104DE000AD818B4100A9410AAB5BB8FACD0CAEFB9B
+:104DF000008435FA36F936F836F73467AD0A20F70D
+:104E000039F839F939FA3873AD0C2602A111B68494
+:104E1000848484841FDDCD880B7B880B7B880B7B8F
+:104E2000880B7B88067B066B4444067B9FFBCD0288
+:104E3000A66DAD5B0E2602A111B6066B08A6076B28
+:104E40004F086BBBA6096B80A60A6BA2020035A3B4
+:104E5000020035A4026035A50200351820ACA60971
+:104E60006B44A60A6BA2020035A3020035A40262BD
+:104E700035A5020035392010A6076B4F086B5DA6DB
+:104E8000096BC0A60A6BA2020035A3020035A4027A
+:104E90003035A5020035182056A6096B22A60A6BEC
+:104EA000A2020035A3020035A4023135A502003567
+:104EB000742020A6076B4F086B2EA6096BE0A60A8C
+:104EC0006B2F12CDA5020035C411CC20A6076B4F65
+:104ED000086B2BA6096B11A60A6B2F12CDA50280B9
+:104EE00035C411CC20A6076B4F086B1FA6096B4079
+:104EF000A60A6BA2020035A3020035A4021035A554
+:104F0000020035C411CC20A6076B4F086B2EA609F2
+:104F10006BE0A60A6B4F2F12CDA5020035A511CC70
+:104F200003264A8B11CC03264A6A11CC03264A5029
+:104F300011CC03264A6D274A57274A382713B69AB9
+:104F4000B8FACDFBBF84AEFA1AE7FBCD3C12CD5BBD
+:104F50009BBEFBCD3C12CD5BC4FBCD6412CD5B1F71
+:104F600012CD5B4412CD5A01264D5F12B61520FAC0
+:104F700010C4FBCD6412CD5B1F12CD5B4412CD5A21
+:104F800001264D5F12B619264A11B63A20086B4029
+:104F9000AA087B0A6B02AA0A7B0E2602A111B60A96
+:104FA0006B04AA0A7B0627163DB8FACD3C12CD5BEE
+:104FB000F91EF7BFF8B73EA4F8B6F9BFFABF46FA34
+:104FC000CD11A65A12CD1420F714F73FF8B73EA41E
+:104FD000F8B6F93FFA3F46FACD11A65A12CD182776
+:104FE000B803CE056B18A6022014A6062010A6084A
+:104FF0002006274A052714B68B4100A2410AA05B70
+:00000001FF
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 3c9b616c834..b3d7e23440e 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -151,6 +151,7 @@ header-y += hid.h
header-y += hiddev.h
header-y += hidraw.h
header-y += hpet.h
+header-y += hwmem.h
header-y += hysdn_if.h
header-y += i2c-dev.h
header-y += i2c.h
diff --git a/include/linux/clonedev.h b/include/linux/clonedev.h
new file mode 100644
index 00000000000..575233f07e9
--- /dev/null
+++ b/include/linux/clonedev.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * ST-Ericsson Display overlay compositer device driver
+ *
+ * Author: Per-Daniel Olsson <per-daniel.olsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _CLONEDEV_H_
+#define _CLONEDEV_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/types.h>
+#include <video/mcde.h>
+#endif
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+#include <linux/mm_types.h>
+#include <linux/bitops.h>
+#else
+#define BIT(nr) (1UL << (nr))
+#endif
+
+#define CLONEDEV_DEFAULT_DEVICE_PREFIX "clone"
+
+/* Cloning mode */
+enum clonedev_mode {
+ CLONEDEV_CLONE_NONE,
+ CLONEDEV_CLONE_VIDEO_OR_UI,
+ CLONEDEV_CLONE_VIDEO_AND_UI,
+ CLONEDEV_CLONE_VIDEO,
+ CLONEDEV_CLONE_UI,
+};
+
+#define CLONEDEV_SET_MODE_IOC _IOW('D', 1, __u32*)
+
+#ifdef __KERNEL__
+
+int clonedev_create(void);
+void clonedev_destroy(void);
+
+#endif /* __KERNEL__ */
+
+#endif /* _CLONEDEV_H_ */
+
diff --git a/include/linux/compdev.h b/include/linux/compdev.h
new file mode 100644
index 00000000000..83285c61b62
--- /dev/null
+++ b/include/linux/compdev.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * ST-Ericsson Display overlay compositer device driver
+ *
+ * Author: Anders Bauer <anders.bauer@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * Modified: Per-Daniel Olsson <per-daniel.olsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _COMPDEV_H_
+#define _COMPDEV_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/types.h>
+#include <video/mcde.h>
+#endif
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+#include <linux/mm_types.h>
+#include <linux/bitops.h>
+#else
+#define BIT(nr) (1UL << (nr))
+#endif
+
+#define COMPDEV_DEFAULT_DEVICE_PREFIX "comp"
+
+
+enum compdev_fmt {
+ COMPDEV_FMT_RGB565,
+ COMPDEV_FMT_RGB888,
+ COMPDEV_FMT_RGBX8888,
+ COMPDEV_FMT_RGBA8888,
+ COMPDEV_FMT_YUV422,
+ COMPDEV_FMT_YCBCR42XMBN,
+ COMPDEV_FMT_YUV420_SP,
+ COMPDEV_FMT_YVU420_SP,
+ COMPDEV_FMT_YUV420_P,
+};
+
+struct compdev_size {
+ __u16 width;
+ __u16 height;
+};
+
+/* Display rotation */
+enum compdev_rotation {
+ COMPDEV_ROT_0 = 0,
+ COMPDEV_ROT_90_CCW = 90,
+ COMPDEV_ROT_180 = 180,
+ COMPDEV_ROT_270_CCW = 270,
+ COMPDEV_ROT_90_CW = COMPDEV_ROT_270_CCW,
+ COMPDEV_ROT_270_CW = COMPDEV_ROT_90_CCW,
+};
+
+enum compdev_flag {
+ COMPDEV_NO_FLAG = 0x00,
+ COMPDEV_OVERLAY_FLAG = 0x01,
+ COMPDEV_FRAMEBUFFER_FLAG = 0x02,
+ COMPDEV_BYPASS_FLAG = 0x04,
+ COMPDEV_EXTERNAL_DISP_FLAG = 0x08,
+ COMPDEV_PROTECTED_FLAG = 0x0F,
+};
+
+enum compdev_ptr_type {
+ COMPDEV_PTR_PHYSICAL,
+ COMPDEV_PTR_HWMEM_BUF_NAME_OFFSET,
+};
+
+enum compdev_listener_state {
+ COMPDEV_LISTENER_OFF,
+ COMPDEV_LISTENER_ON,
+};
+
+
+struct compdev_rect {
+ __s16 x;
+ __s16 y;
+ __u16 width;
+ __u16 height;
+};
+
+struct compdev_buf {
+ enum compdev_ptr_type type;
+ __s32 hwmem_buf_name;
+ __s32 fd;
+ __u32 offset;
+ __u32 len;
+};
+
+struct compdev_img {
+ enum compdev_fmt fmt;
+ struct compdev_buf buf;
+ __u16 width;
+ __u16 height;
+ __u16 pitch;
+ __u8 z_position;
+ struct compdev_rect dst_rect;
+ struct compdev_rect src_rect;
+ enum compdev_rotation rotation;
+ __u32 flags;
+};
+
+struct compdev_scene_info {
+ enum compdev_rotation ovly_rotation;
+ enum compdev_rotation fb_rotation;
+ __u8 img_count;
+};
+
+
+#define COMPDEV_GET_SIZE_IOC _IOR('D', 1, struct compdev_size)
+#define COMPDEV_POST_BUFFER_IOC _IOW('D', 2, struct compdev_img)
+#define COMPDEV_POST_SCENE_INFO_IOC _IOW('D', 3, struct compdev_scene_info)
+#define COMPDEV_GET_LISTENER_STATE_IOC _IOR('D', 4, enum compdev_listener_state)
+
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+
+#define MAX_NBR_OF_COMPDEVS 2
+
+struct compdev;
+typedef void (*post_buffer_callback)(void *data, struct compdev_img *img);
+typedef void (*post_scene_info_callback)(void *data,
+ struct compdev_scene_info *s_info);
+
+
+int compdev_create(struct mcde_display_device *ddev,
+ struct mcde_overlay *parent_ovly,
+ bool mcde_rotation);
+void compdev_destroy(struct mcde_display_device *ddev);
+
+int compdev_get(int dev_idx, struct compdev **dev);
+int compdev_put(struct compdev *dev);
+int compdev_get_size(struct compdev *dev, struct compdev_size *size);
+int compdev_post_buffer(struct compdev *dev, struct compdev_img *img);
+int compdev_post_scene_info(struct compdev *dev,
+ struct compdev_scene_info *s_info);
+int compdev_get_listener_state(struct compdev *dev,
+ enum compdev_listener_state *listener_state);
+
+int compdev_register_listener_callbacks(struct compdev *dev, void *data,
+ post_buffer_callback pb_cb, post_scene_info_callback si_cb);
+int compdev_deregister_callbacks(struct compdev *dev);
+
+#endif /* __KERNEL__ */
+
+#endif /* _COMPDEV_H_ */
+
diff --git a/include/linux/dispdev.h b/include/linux/dispdev.h
new file mode 100644
index 00000000000..cbcf6705150
--- /dev/null
+++ b/include/linux/dispdev.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * ST-Ericsson Display device driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _DISPDEV_H_
+#define _DISPDEV_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/types.h>
+#include <video/mcde.h>
+#endif
+
+#define DISPDEV_DEFAULT_DEVICE_PREFIX "disp"
+
+enum dispdev_fmt {
+ DISPDEV_FMT_RGB565,
+ DISPDEV_FMT_RGB888,
+ DISPDEV_FMT_RGBX8888,
+ DISPDEV_FMT_RGBA8888,
+ DISPDEV_FMT_YUV422,
+};
+
+struct dispdev_config {
+ uint16_t format;
+ uint16_t stride;
+ uint16_t x;
+ uint16_t y;
+ uint16_t z;
+ uint16_t width;
+ uint16_t height;
+
+ uint32_t user_flags;
+};
+
+struct dispdev_buffer_info {
+ uint16_t buf_idx;
+ uint16_t display_update;
+ struct dispdev_config buf_cfg;
+};
+
+#define DISPDEV_SET_CONFIG_IOC _IOW('D', 1, struct dispdev_config)
+#define DISPDEV_GET_CONFIG_IOC _IOR('D', 2, struct dispdev_config)
+#define DISPDEV_REGISTER_BUFFER_IOC _IO('D', 3)
+#define DISPDEV_UNREGISTER_BUFFER_IOC _IO('D', 4)
+#define DISPDEV_QUEUE_BUFFER_IOC _IOW('D', 5, struct dispdev_buffer_info)
+#define DISPDEV_DEQUEUE_BUFFER_IOC _IO('D', 6)
+
+#ifdef __KERNEL__
+
+int dispdev_create(struct mcde_display_device *ddev, bool overlay,
+ struct mcde_overlay *parent_ovly);
+void dispdev_destroy(struct mcde_display_device *ddev);
+
+#endif /* __KERNEL__ */
+
+#endif /* _DISPDEV_H_ */
+
diff --git a/include/video/Kbuild b/include/video/Kbuild
index ad3e622c533..d73b95df921 100644
--- a/include/video/Kbuild
+++ b/include/video/Kbuild
@@ -1,3 +1,4 @@
+header-y += b2r2_blt.h
header-y += edid.h
header-y += sisfb.h
header-y += uvesafb.h
diff --git a/include/video/av8100.h b/include/video/av8100.h
new file mode 100644
index 00000000000..23e96a0b871
--- /dev/null
+++ b/include/video/av8100.h
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * AV8100 driver
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __AV8100__H__
+#define __AV8100__H__
+
+#define AV8100_CEC_MESSAGE_SIZE 16
+#define AV8100_HDCP_SEND_KEY_SIZE 16
+#define AV8100_INFOFRAME_SIZE 28
+#define AV8100_FUSE_KEY_SIZE 16
+#define AV8100_CHIPVER_1 1
+#define AV8100_CHIPVER_2 2
+
+struct av8100_platform_data {
+ unsigned gpio_base;
+ int irq;
+ int reset;
+ const char *inputclk_id;
+ const char *regulator_pwr_id;
+ bool alt_powerupseq;
+ unsigned char mclk_freq;
+};
+
+enum av8100_command_type {
+ AV8100_COMMAND_VIDEO_INPUT_FORMAT = 0x1,
+ AV8100_COMMAND_AUDIO_INPUT_FORMAT,
+ AV8100_COMMAND_VIDEO_OUTPUT_FORMAT,
+ AV8100_COMMAND_VIDEO_SCALING_FORMAT,
+ AV8100_COMMAND_COLORSPACECONVERSION,
+ AV8100_COMMAND_CEC_MESSAGE_WRITE,
+ AV8100_COMMAND_CEC_MESSAGE_READ_BACK,
+ AV8100_COMMAND_DENC,
+ AV8100_COMMAND_HDMI,
+ AV8100_COMMAND_HDCP_SENDKEY,
+ AV8100_COMMAND_HDCP_MANAGEMENT,
+ AV8100_COMMAND_INFOFRAMES,
+ AV8100_COMMAND_EDID_SECTION_READBACK,
+ AV8100_COMMAND_PATTERNGENERATOR,
+ AV8100_COMMAND_FUSE_AES_KEY,
+};
+
+enum interface_type {
+ I2C_INTERFACE = 0x0,
+ DSI_INTERFACE = 0x1,
+};
+
+enum av8100_dsi_mode {
+ AV8100_HDMI_DSI_OFF,
+ AV8100_HDMI_DSI_COMMAND_MODE,
+ AV8100_HDMI_DSI_VIDEO_MODE
+};
+
+enum av8100_pixel_format {
+ AV8100_INPUT_PIX_RGB565,
+ AV8100_INPUT_PIX_RGB666,
+ AV8100_INPUT_PIX_RGB666P,
+ AV8100_INPUT_PIX_RGB888,
+ AV8100_INPUT_PIX_YCBCR422
+};
+
+enum av8100_video_mode {
+ AV8100_VIDEO_INTERLACE,
+ AV8100_VIDEO_PROGRESSIVE
+};
+
+enum av8100_dsi_nb_data_lane {
+ AV8100_DATA_LANES_USED_0,
+ AV8100_DATA_LANES_USED_1,
+ AV8100_DATA_LANES_USED_2,
+ AV8100_DATA_LANES_USED_3,
+ AV8100_DATA_LANES_USED_4
+};
+
+enum av8100_te_config {
+ AV8100_TE_OFF, /* NO TE*/
+ AV8100_TE_DSI_LANE, /* TE generated on DSI lane */
+ AV8100_TE_IT_LINE, /* TE generated on IT line (GPIO) */
+ AV8100_TE_DSI_IT, /* TE generatedon both DSI lane & IT line*/
+ AV8100_TE_GPIO_IT /* TE on GPIO I2S DAT3 & or IT line*/
+};
+
+enum av8100_audio_if_format {
+ AV8100_AUDIO_I2S_MODE,
+ AV8100_AUDIO_I2SDELAYED_MODE, /* I2S Mode by default*/
+ AV8100_AUDIO_TDM_MODE /* 8 Channels by default*/
+};
+
+enum av8100_sample_freq {
+ AV8100_AUDIO_FREQ_32KHZ,
+ AV8100_AUDIO_FREQ_44_1KHZ,
+ AV8100_AUDIO_FREQ_48KHZ,
+ AV8100_AUDIO_FREQ_64KHZ,
+ AV8100_AUDIO_FREQ_88_2KHZ,
+ AV8100_AUDIO_FREQ_96KHZ,
+ AV8100_AUDIO_FREQ_128KHZ,
+ AV8100_AUDIO_FREQ_176_1KHZ,
+ AV8100_AUDIO_FREQ_192KHZ
+};
+
+enum av8100_audio_word_length {
+ AV8100_AUDIO_16BITS,
+ AV8100_AUDIO_20BITS,
+ AV8100_AUDIO_24BITS
+};
+
+enum av8100_audio_format {
+ AV8100_AUDIO_LPCM_MODE,
+ AV8100_AUDIO_COMPRESS_MODE
+};
+
+enum av8100_audio_if_mode {
+ AV8100_AUDIO_SLAVE,
+ AV8100_AUDIO_MASTER
+};
+
+enum av8100_audio_mute {
+ AV8100_AUDIO_MUTE_DISABLE,
+ AV8100_AUDIO_MUTE_ENABLE
+};
+
+enum av8100_output_CEA_VESA {
+ AV8100_CUSTOM,
+ AV8100_CEA1_640X480P_59_94HZ,
+ AV8100_CEA2_3_720X480P_59_94HZ,
+ AV8100_CEA4_1280X720P_60HZ,
+ AV8100_CEA5_1920X1080I_60HZ,
+ AV8100_CEA6_7_NTSC_60HZ,
+ AV8100_CEA14_15_480p_60HZ,
+ AV8100_CEA16_1920X1080P_60HZ,
+ AV8100_CEA17_18_720X576P_50HZ,
+ AV8100_CEA19_1280X720P_50HZ,
+ AV8100_CEA20_1920X1080I_50HZ,
+ AV8100_CEA21_22_576I_PAL_50HZ,
+ AV8100_CEA29_30_576P_50HZ,
+ AV8100_CEA31_1920x1080P_50Hz,
+ AV8100_CEA32_1920X1080P_24HZ,
+ AV8100_CEA33_1920X1080P_25HZ,
+ AV8100_CEA34_1920X1080P_30HZ,
+ AV8100_CEA60_1280X720P_24HZ,
+ AV8100_CEA61_1280X720P_25HZ,
+ AV8100_CEA62_1280X720P_30HZ,
+ AV8100_VESA9_800X600P_60_32HZ,
+ AV8100_VESA14_848X480P_60HZ,
+ AV8100_VESA16_1024X768P_60HZ,
+ AV8100_VESA22_1280X768P_59_99HZ,
+ AV8100_VESA23_1280X768P_59_87HZ,
+ AV8100_VESA27_1280X800P_59_91HZ,
+ AV8100_VESA28_1280X800P_59_81HZ,
+ AV8100_VESA39_1360X768P_60_02HZ,
+ AV8100_VESA81_1366X768P_59_79HZ,
+ AV8100_VIDEO_OUTPUT_CEA_VESA_MAX
+};
+
+enum av8100_video_sync_pol {
+ AV8100_SYNC_POSITIVE,
+ AV8100_SYNC_NEGATIVE
+};
+
+enum av8100_hdmi_mode {
+ AV8100_HDMI_OFF,
+ AV8100_HDMI_ON,
+ AV8100_HDMI_AVMUTE
+};
+
+enum av8100_hdmi_format {
+ AV8100_HDMI,
+ AV8100_DVI
+};
+
+enum av8100_DVI_format {
+ AV8100_DVI_CTRL_CTL0,
+ AV8100_DVI_CTRL_CTL1,
+ AV8100_DVI_CTRL_CTL2
+};
+
+enum av8100_pattern_type {
+ AV8100_PATTERN_OFF,
+ AV8100_PATTERN_GENERATOR,
+ AV8100_PRODUCTION_TESTING
+};
+
+enum av8100_pattern_format {
+ AV8100_NO_PATTERN,
+ AV8100_PATTERN_VGA,
+ AV8100_PATTERN_720P,
+ AV8100_PATTERN_1080P
+};
+
+enum av8100_pattern_audio {
+ AV8100_PATTERN_AUDIO_OFF,
+ AV8100_PATTERN_AUDIO_ON,
+ AV8100_PATTERN_AUDIO_I2S_MEM
+};
+
+struct av8100_video_input_format_cmd {
+ enum av8100_dsi_mode dsi_input_mode;
+ enum av8100_pixel_format input_pixel_format;
+ unsigned short total_horizontal_pixel;
+ unsigned short total_horizontal_active_pixel;
+ unsigned short total_vertical_lines;
+ unsigned short total_vertical_active_lines;
+ enum av8100_video_mode video_mode;
+ enum av8100_dsi_nb_data_lane nb_data_lane;
+ unsigned char nb_virtual_ch_command_mode;
+ unsigned char nb_virtual_ch_video_mode;
+ unsigned short TE_line_nb;
+ enum av8100_te_config TE_config;
+ unsigned long master_clock_freq;
+ unsigned char ui_x4;
+};
+
+struct av8100_audio_input_format_cmd {
+ enum av8100_audio_if_format audio_input_if_format;
+ unsigned char i2s_input_nb;
+ enum av8100_sample_freq sample_audio_freq;
+ enum av8100_audio_word_length audio_word_lg;
+ enum av8100_audio_format audio_format;
+ enum av8100_audio_if_mode audio_if_mode;
+ enum av8100_audio_mute audio_mute;
+};
+
+struct av8100_video_output_format_cmd {
+ enum av8100_output_CEA_VESA video_output_cea_vesa;
+ enum av8100_video_sync_pol vsync_polarity;
+ enum av8100_video_sync_pol hsync_polarity;
+ unsigned short total_horizontal_pixel;
+ unsigned short total_horizontal_active_pixel;
+ unsigned short total_vertical_in_half_lines;
+ unsigned short total_vertical_active_in_half_lines;
+ unsigned short hsync_start_in_pixel;
+ unsigned short hsync_length_in_pixel;
+ unsigned short vsync_start_in_half_line;
+ unsigned short vsync_length_in_half_line;
+ unsigned short hor_video_start_pixel;
+ unsigned short vert_video_start_pixel;
+ enum av8100_video_mode video_type;
+ unsigned short pixel_repeat;
+ unsigned long pixel_clock_freq_Hz;
+};
+
+struct av8100_video_scaling_format_cmd {
+ unsigned short h_start_in_pixel;
+ unsigned short h_stop_in_pixel;
+ unsigned short v_start_in_line;
+ unsigned short v_stop_in_line;
+ unsigned short h_start_out_pixel;
+ unsigned short h_stop_out_pixel;
+ unsigned short v_start_out_line;
+ unsigned short v_stop_out_line;
+};
+
+enum av8100_color_transform {
+ AV8100_COLOR_TRANSFORM_INDENTITY,
+ AV8100_COLOR_TRANSFORM_INDENTITY_CLAMP_YUV,
+ AV8100_COLOR_TRANSFORM_YUV_TO_RGB,
+ AV8100_COLOR_TRANSFORM_YUV_TO_DENC,
+ AV8100_COLOR_TRANSFORM_RGB_TO_DENC,
+};
+
+struct av8100_cec_message_write_format_cmd {
+ unsigned char buffer_length;
+ unsigned char buffer[AV8100_CEC_MESSAGE_SIZE];
+};
+
+struct av8100_cec_message_read_back_format_cmd {
+};
+
+enum av8100_cvbs_video_format {
+ AV8100_CVBS_625,
+ AV8100_CVBS_525,
+};
+
+enum av8100_standard_selection {
+ AV8100_PAL_BDGHI,
+ AV8100_PAL_N,
+ AV8100_NTSC_M,
+ AV8100_PAL_M
+};
+
+struct av8100_denc_format_cmd {
+ enum av8100_cvbs_video_format cvbs_video_format;
+ enum av8100_standard_selection standard_selection;
+ unsigned char enable;
+ unsigned char macrovision_enable;
+ unsigned char internal_generator;
+};
+
+struct av8100_hdmi_cmd {
+ enum av8100_hdmi_mode hdmi_mode;
+ enum av8100_hdmi_format hdmi_format;
+ enum av8100_DVI_format dvi_format; /* used only if HDMI_format = DVI*/
+};
+
+struct av8100_hdcp_send_key_format_cmd {
+ unsigned char key_number;
+ unsigned char data_len;
+ unsigned char data[AV8100_HDCP_SEND_KEY_SIZE];
+};
+
+enum av8100_hdcp_auth_req_type {
+ AV8100_HDCP_AUTH_REQ_OFF = 0,
+ AV8100_HDCP_AUTH_REQ_ON = 1,
+ AV8100_HDCP_REV_LIST_REQ = 2,
+ AV8100_HDCP_AUTH_CONT = 3,
+};
+
+enum av8100_hdcp_encr_use {
+ AV8100_HDCP_ENCR_USE_OESS = 0,
+ AV8100_HDCP_ENCR_USE_EESS = 1,
+};
+
+struct av8100_hdcp_management_format_cmd {
+ unsigned char req_type;
+ unsigned char encr_use;
+};
+
+struct av8100_infoframes_format_cmd {
+ unsigned char type;
+ unsigned char version;
+ unsigned char length;
+ unsigned char crc;
+ unsigned char data[AV8100_INFOFRAME_SIZE];
+};
+
+struct av8100_edid_section_readback_format_cmd {
+ unsigned char address;
+ unsigned char block_number;
+};
+
+struct av8100_pattern_generator_format_cmd {
+ enum av8100_pattern_type pattern_type;
+ enum av8100_pattern_format pattern_video_format;
+ enum av8100_pattern_audio pattern_audio_mode;
+};
+
+enum av8100_fuse_operation {
+ AV8100_FUSE_READ = 0,
+ AV8100_FUSE_WRITE = 1,
+};
+
+struct av8100_fuse_aes_key_format_cmd {
+ unsigned char fuse_operation;
+ unsigned char key[AV8100_FUSE_KEY_SIZE];
+};
+
+union av8100_configuration {
+ struct av8100_video_input_format_cmd video_input_format;
+ struct av8100_audio_input_format_cmd audio_input_format;
+ struct av8100_video_output_format_cmd video_output_format;
+ struct av8100_video_scaling_format_cmd video_scaling_format;
+ enum av8100_color_transform color_transform;
+ struct av8100_cec_message_write_format_cmd
+ cec_message_write_format;
+ struct av8100_cec_message_read_back_format_cmd
+ cec_message_read_back_format;
+ struct av8100_denc_format_cmd denc_format;
+ struct av8100_hdmi_cmd hdmi_format;
+ struct av8100_hdcp_send_key_format_cmd hdcp_send_key_format;
+ struct av8100_hdcp_management_format_cmd hdcp_management_format;
+ struct av8100_infoframes_format_cmd infoframes_format;
+ struct av8100_edid_section_readback_format_cmd
+ edid_section_readback_format;
+ struct av8100_pattern_generator_format_cmd pattern_generator_format;
+ struct av8100_fuse_aes_key_format_cmd fuse_aes_key_format;
+};
+
+enum av8100_operating_mode {
+ AV8100_OPMODE_UNDEFINED = 0,
+ AV8100_OPMODE_SHUTDOWN,
+ AV8100_OPMODE_STANDBY,
+ AV8100_OPMODE_SCAN,
+ AV8100_OPMODE_INIT,
+ AV8100_OPMODE_IDLE,
+ AV8100_OPMODE_VIDEO,
+};
+
+enum av8100_plugin_status {
+ AV8100_PLUGIN_NONE = 0x0,
+ AV8100_HDMI_PLUGIN = 0x1,
+ AV8100_CVBS_PLUGIN = 0x2,
+};
+
+enum av8100_hdmi_event {
+ AV8100_HDMI_EVENT_NONE = 0x0,
+ AV8100_HDMI_EVENT_HDMI_PLUGIN = 0x1,
+ AV8100_HDMI_EVENT_HDMI_PLUGOUT = 0x2,
+ AV8100_HDMI_EVENT_CEC = 0x4,
+ AV8100_HDMI_EVENT_HDCP = 0x8,
+ AV8100_HDMI_EVENT_CECTXERR = 0x10,
+ AV8100_HDMI_EVENT_CECTX = 0x20, /* Transm no error */
+};
+
+struct av8100_status {
+ enum av8100_operating_mode av8100_state;
+ enum av8100_plugin_status av8100_plugin_status;
+ int hdmi_on;
+};
+
+
+int av8100_init(void);
+void av8100_exit(void);
+int av8100_powerscan(void);
+int av8100_powerup(void);
+int av8100_powerdown(void);
+int av8100_disable_interrupt(void);
+int av8100_enable_interrupt(void);
+int av8100_download_firmware(enum interface_type if_type);
+int av8100_reg_stby_w(
+ unsigned char cpd,
+ unsigned char stby,
+ unsigned char mclkrng);
+int av8100_reg_hdmi_5_volt_time_w(
+ unsigned char denc_off_time,
+ unsigned char hdmi_off_time,
+ unsigned char on_time);
+int av8100_reg_stby_int_mask_w(
+ unsigned char hpdm,
+ unsigned char cpdm,
+ unsigned char stbygpiocfg,
+ unsigned char ipol);
+int av8100_reg_stby_pend_int_w(
+ unsigned char hpdi,
+ unsigned char cpdi,
+ unsigned char oni,
+ unsigned char bpdig);
+int av8100_reg_gen_int_mask_w(
+ unsigned char eocm,
+ unsigned char vsim,
+ unsigned char vsom,
+ unsigned char cecm,
+ unsigned char hdcpm,
+ unsigned char uovbm,
+ unsigned char tem);
+int av8100_reg_gen_int_w(
+ unsigned char eoci,
+ unsigned char vsii,
+ unsigned char vsoi,
+ unsigned char ceci,
+ unsigned char hdcpi,
+ unsigned char uovbi);
+int av8100_reg_gpio_conf_w(
+ unsigned char dat3dir,
+ unsigned char dat3val,
+ unsigned char dat2dir,
+ unsigned char dat2val,
+ unsigned char dat1dir,
+ unsigned char dat1val,
+ unsigned char ucdbg);
+int av8100_reg_gen_ctrl_w(
+ unsigned char fdl,
+ unsigned char hld,
+ unsigned char wa,
+ unsigned char ra);
+int av8100_reg_fw_dl_entry_w(
+ unsigned char mbyte_code_entry);
+int av8100_reg_w(
+ unsigned char offset,
+ unsigned char value);
+int av8100_reg_stby_r(
+ unsigned char *cpd,
+ unsigned char *stby,
+ unsigned char *hpds,
+ unsigned char *cpds,
+ unsigned char *mclkrng);
+int av8100_reg_hdmi_5_volt_time_r(
+ unsigned char *denc_off_time,
+ unsigned char *hdmi_off_time,
+ unsigned char *on_time);
+int av8100_reg_stby_int_mask_r(
+ unsigned char *hpdm,
+ unsigned char *cpdm,
+ unsigned char *stbygpiocfg,
+ unsigned char *ipol);
+int av8100_reg_stby_pend_int_r(
+ unsigned char *hpdi,
+ unsigned char *cpdi,
+ unsigned char *oni,
+ unsigned char *sid);
+int av8100_reg_gen_int_mask_r(
+ unsigned char *eocm,
+ unsigned char *vsim,
+ unsigned char *vsom,
+ unsigned char *cecm,
+ unsigned char *hdcpm,
+ unsigned char *uovbm,
+ unsigned char *tem);
+int av8100_reg_gen_int_r(
+ unsigned char *eoci,
+ unsigned char *vsii,
+ unsigned char *vsoi,
+ unsigned char *ceci,
+ unsigned char *hdcpi,
+ unsigned char *uovbi,
+ unsigned char *tei);
+int av8100_reg_gen_status_r(
+ unsigned char *cectxerr,
+ unsigned char *cecrec,
+ unsigned char *cectrx,
+ unsigned char *uc,
+ unsigned char *onuvb,
+ unsigned char *hdcps);
+int av8100_reg_gpio_conf_r(
+ unsigned char *dat3dir,
+ unsigned char *dat3val,
+ unsigned char *dat2dir,
+ unsigned char *dat2val,
+ unsigned char *dat1dir,
+ unsigned char *dat1val,
+ unsigned char *ucdbg);
+int av8100_reg_gen_ctrl_r(
+ unsigned char *fdl,
+ unsigned char *hld,
+ unsigned char *wa,
+ unsigned char *ra);
+int av8100_reg_fw_dl_entry_r(
+ unsigned char *mbyte_code_entry);
+int av8100_reg_r(
+ unsigned char offset,
+ unsigned char *value);
+int av8100_conf_get(enum av8100_command_type command_type,
+ union av8100_configuration *config);
+int av8100_conf_prep(enum av8100_command_type command_type,
+ union av8100_configuration *config);
+int av8100_conf_w(enum av8100_command_type command_type,
+ unsigned char *return_buffer_length,
+ unsigned char *return_buffer, enum interface_type if_type);
+int av8100_conf_w_raw(enum av8100_command_type command_type,
+ unsigned char buffer_length,
+ unsigned char *buffer,
+ unsigned char *return_buffer_length,
+ unsigned char *return_buffer);
+struct av8100_status av8100_status_get(void);
+enum av8100_output_CEA_VESA av8100_video_output_format_get(int xres,
+ int yres,
+ int htot,
+ int vtot,
+ int pixelclk,
+ bool interlaced);
+void av8100_hdmi_event_cb_set(void (*event_callback)(enum av8100_hdmi_event));
+u8 av8100_ver_get(void);
+
+#endif /* __AV8100__H__ */
diff --git a/include/video/b2r2_blt.h b/include/video/b2r2_blt.h
new file mode 100644
index 00000000000..4fdc40ab3b9
--- /dev/null
+++ b/include/video/b2r2_blt.h
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson B2R2 user interface
+ *
+ * Author: Robert Fekete <robert.fekete@stericsson.com>
+ * Author: Paul Wannback
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+
+#ifndef _LINUX_VIDEO_B2R2_BLT_H
+#define _LINUX_VIDEO_B2R2_BLT_H
+
+#include <linux/types.h>
+
+#if defined(__KERNEL__)
+#include <linux/mm_types.h>
+#include <linux/bitops.h>
+#else
+#define BIT(nr) (1UL << (nr))
+#endif
+
+/**
+ * struct b2r2_blt_rect - Specifies a B2R2 rectangle
+ *
+ * @left: X-coordinate of top left corner
+ * @top: Y-coordinate of top left corner
+ * @width: Rectangle width. Must be >= 0.
+ * @height: Rectangle height. Must be >= 0.
+ */
+struct b2r2_blt_rect {
+ __s32 x;
+ __s32 y;
+ __s32 width;
+ __s32 height;
+};
+
+/**
+ * enum b2r2_blt_fmt - Defines the available B2R2 buffer formats
+ *
+ * Inspired by Khronos OpenMAX, please see
+ * OpenMAX IL specification for detailed descriptions of the formats
+ *
+ * @B2R2_BLT_FMT_UNUSED: Placeholder value when format is unknown,
+ * or specified using a vendor-specific means.
+ * @B2R2_BLT_FMT_16_BIT_ARGB4444: 16 bits per pixel ARGB format with colors
+ * stored as Alpha 15:12, Red 11:8, Green 7:4, and Blue 3:0.
+ * @B2R2_BLT_FMT_16_BIT_ARGB1555: 16 bits per pixel ARGB format with colors
+ * stored as Alpha 15, Red 14:10, Green 9:5, and Blue 4:0.
+ * @B2R2_BLT_FMT_16_BIT_RGB565: 16 bits per pixel RGB format with colors
+ * stored as Red 15:11, Green 10:5, and Blue 4:0.
+ * @B2R2_BLT_FMT_24_BIT_RGB888: 24 bits per pixel RGB format with colors
+ * stored as Red 23:16, Green 15:8, and Blue 7:0.
+ * @B2R2_BLT_FMT_32_BIT_ARGB8888: 32 bits per pixel ARGB format with colors
+ * stored as Alpha 31:24, Red 23:16, Green 15:8, and Blue 7:0.
+ * @B2R2_BLT_FMT_YUV420_PACKED_PLANAR: YUV planar format, organized with
+ * three separate planes for each color component, namely Y, U, and V.
+ * U and V pixels are sub-sampled by a factor of two both horizontally and
+ * vertically. The buffer shall contain a plane of Y, U, and V data in this
+ * order
+ * @B2R2_BLT_FMT_YUV422_PACKED_PLANAR: YUV planar format, organized with
+ * three separate planes for each color component, namely Y, U, and V.
+ * U and V pixels are subsampled by a factor of two horizontally.
+ * The buffer shall contain a plane of Y, U, and V data in this order.
+ * @B2R2_BLT_FMT_Y_CB_Y_CR: 16 bits per pixel YUV interleaved format organized
+ * as YUYV (i.e., YCbYCr).
+ * (Corresponds to YUV422 interleaved)
+ * @B2R2_BLT_FMT_CB_Y_CR_Y: 16 bits per pixel YUV interleaved format organized
+ * as UYVY (i.e., CbYCrY).
+ * (Corresponds to YUV422R)
+ * @B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR: YUV planar format, organized with
+ * a first plane containing Y pixels, and a second plane containing U and V
+ * pixels interleaved with the first U value first. U and V pixels are
+ * sub-sampled by a factor of two both horizontally and vertically. The buffer
+ * shall contain a plane of Y, U and V data.
+ * (Same as B2R2 420 Raster 2 buffer - 420 R2B)
+ * @B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR: YUV planar format, organized with
+ * a first plane containing Y pixels, and a second plane containing U and V
+ * pixels interleaved with the first U value first. U and V pixels are
+ * sub-sampled by a factor of two horizontally. The buffer shall contain a
+ * plane of Y, U and V data.
+ * (Same as B2R2 422 Raster 2 buffer - 422 R2B)
+ * @B2R2_BLT_FMT_32_BIT_ABGR8888: 32 bits per pixel ABGR format with colors
+ * stored as Alpha 31:24,Blue 23:16, Green 15:8, and Red 7:0.
+ * @B2R2_BLT_FMT_24_BIT_ARGB8565: 24 bits per pixel ARGB format with colors
+ * stored as Alpha 23:16, Red 15:11, Green 10:5, and Blue 4:0.
+ * @B2R2_BLT_FMT_24_BIT_YUV888: 24 bits per pixel YUV format with colors
+ * stored as Y 23:16, U 15:8, and V 7:0.
+ * @B2R2_BLT_FMT_32_BIT_AYUV8888: 32 bits per pixel AYUV format with colors
+ * stored as Alpha 31:24, Y 23:16, U 15:8, and V 7:0.
+ * @B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE: Nomadik YUV 420 macro block
+ * format, see B2R2 spec for details
+ * @B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE: Nomadik YUV 422 macro block
+ * format, see B2R2 spec for details
+ * @B2R2_BLT_FMT_1_BIT_A1: 1 bit per pixel A format, 1 bit alpha
+ * @B2R2_BLT_FMT_8_BIT_A8: 8 bit per pixel A format, 8 bit alpha
+ * @B2R2_BLT_FMT_YUV444_PACKED_PLANAR: YUV planar format, organized with
+ * three separate planes, one for each color component, namely Y, U, and V.
+ * All planes use full resolution, there is no subsampling.
+ * The buffer shall contain a plane of Y, U, and V data in this order.
+ * @B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR: YVU planar format, organized with
+ * a first plane containing Y pixels, and a second plane containing V and U
+ * pixels interleaved with the first V value first. V and U pixels are
+ * sub-sampled by a factor of two both horizontally and vertically. The buffer
+ * shall contain two planes, one plane with Y, and one with V and U data.
+ * (Same as B2R2 420 Raster 2 buffer - 420 R2B except that chroma order is
+ * swapped.)
+ * @B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR: YVU planar format, organized with
+ * a first plane containing Y pixels, and a second plane containing V and U
+ * pixels interleaved with the first V value first. V and U pixels are
+ * sub-sampled by a factor of two horizontally. The buffer shall contain a
+ * two planes, one with Y, and one with V and U data.
+ * (Same as B2R2 422 Raster 2 buffer - 422 R2B except that chroma order is
+ * swapped.)
+ * @B2R2_BLT_FMT_YVU420_PACKED_PLANAR: YVU planar format, organized with
+ * three separate planes for each color component, namely Y, V, and U.
+ * V and U pixels are sub-sampled by a factor of two both horizontally and
+ * vertically. The buffer shall contain a plane of Y, V, and U data in this
+ * order. (Same as B2R2_BLT_FMT_YUV420_PACKED_PLANAR except that chroma
+ * order is swapped.)
+ * @B2R2_BLT_FMT_YVU422_PACKED_PLANAR: YVU planar format, organized with
+ * three separate planes for each color component, namely Y, V, and U.
+ * V and U pixels are subsampled by a factor of two horizontally.
+ * The buffer shall contain a plane of Y, V, and U data in this order.
+ * (Same as B2R2_BLT_FMT_YUV422_PACKED_PLANAR except that chroma
+ * order is swapped.)
+ * @B2R2_BLT_FMT_24_BIT_VUY888: 24 bits per pixel VUY format with colors
+ * stored as V 23:16, U 15:8, and Y 7:0.
+ * @B2R2_BLT_FMT_32_BIT_VUYA8888: 32 bits per pixel VUYA format with colors
+ * stored as V 31:24, U 23:16, Y 15:8, and Alpha 7:0.
+ */
+enum b2r2_blt_fmt {
+ B2R2_BLT_FMT_UNUSED = 0,
+ B2R2_BLT_FMT_16_BIT_ARGB4444 = 4,
+ B2R2_BLT_FMT_16_BIT_ARGB1555 = 5,
+ B2R2_BLT_FMT_16_BIT_RGB565 = 6,
+ B2R2_BLT_FMT_24_BIT_RGB888 = 11,
+ B2R2_BLT_FMT_32_BIT_ARGB8888 = 16,
+ B2R2_BLT_FMT_YUV420_PACKED_PLANAR = 20,
+ B2R2_BLT_FMT_YUV422_PACKED_PLANAR = 23,
+ B2R2_BLT_FMT_Y_CB_Y_CR = 25,
+ B2R2_BLT_FMT_CB_Y_CR_Y = 27,
+ B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR = 39,
+ B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR = 40,
+ /* Extensions, non OpenMAX formats */
+ B2R2_BLT_FMT_32_BIT_ABGR8888 = 0x7F000000, /* OpenMax vendor start */
+ B2R2_BLT_FMT_24_BIT_ARGB8565 = 0x7F000001,
+ B2R2_BLT_FMT_24_BIT_YUV888 = 0x7F000002,
+ B2R2_BLT_FMT_32_BIT_AYUV8888 = 0x7F000003,
+ B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE = 0x7F000004,
+ B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE = 0x7F000005,
+ B2R2_BLT_FMT_1_BIT_A1 = 0x7F000006,
+ B2R2_BLT_FMT_8_BIT_A8 = 0x7F000007,
+ B2R2_BLT_FMT_YUV444_PACKED_PLANAR = 0x7F000008,
+ B2R2_BLT_FMT_YVU420_PACKED_SEMI_PLANAR = 0x7F000009,
+ B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR = 0x7F00000A,
+ B2R2_BLT_FMT_YVU420_PACKED_PLANAR = 0x7F00000B,
+ B2R2_BLT_FMT_YVU422_PACKED_PLANAR = 0x7F00000C,
+ B2R2_BLT_FMT_24_BIT_VUY888 = 0x7F00000D,
+ B2R2_BLT_FMT_32_BIT_VUYA8888 = 0x7F00000E,
+};
+
+/**
+ * enum b2r2_blt_ptr_type - Specifies a B2R2 buffer pointer type
+ *
+ * @B2R2_BLT_PTR_NONE:
+ * No pointer (NULL). E.g. src fill.
+ * @B2R2_BLT_PTR_VIRTUAL:
+ * Use offset as a userspace virtual address
+ * @B2R2_BLT_PTR_PHYSICAL:
+ * Use offset as a physical address
+ * @B2R2_BLT_PTR_FD_OFFSET:
+ * Use fd + offset to determine buffer location.
+ * @B2R2_BLT_PTR_HWMEM_BUF_NAME:
+ * Use hwmem_buf_name and offset to determine buffer location.
+ */
+enum b2r2_blt_ptr_type {
+ B2R2_BLT_PTR_NONE,
+ B2R2_BLT_PTR_VIRTUAL,
+ B2R2_BLT_PTR_PHYSICAL,
+ B2R2_BLT_PTR_FD_OFFSET,
+ B2R2_BLT_PTR_HWMEM_BUF_NAME_OFFSET,
+};
+
+/**
+ * struct b2r2_blt_buf - Specifies a B2R2 buffer pointer
+ *
+ * @type: Buffer pointer type
+ * @hwmem_global_buf_id: Hwmem buffer name
+ * @fd: File descriptor (e.g. file handle to pmem or fb device)
+ * @offset: Offset where buffer can be found or address.
+ * @len: Size of buffer in bytes
+ * @bits: Pointer to the bitmap data. This field can be used to specify
+ * an alternative way to access the buffer. Whenever the 'bits' pointer
+ * is set to non-NULL, the underlying implementation is free to decide
+ * whether or not to use it in favor of other ways to locate the buffer.
+ */
+struct b2r2_blt_buf {
+ enum b2r2_blt_ptr_type type;
+ __s32 hwmem_buf_name;
+ __s32 fd;
+ __u32 offset;
+ __u32 len;
+ void *bits;
+};
+
+
+/**
+ * struct b2r2_blt_img - Specifies a B2R2 image
+ *
+ * @fmt: Pixel format of image
+ * @buf: Pixel buffer
+ * @width: Width in pixels
+ * @height: Height in pixels
+ * @pitch: Pitch in bytes (from start of one line to start of next)
+ */
+struct b2r2_blt_img {
+ enum b2r2_blt_fmt fmt;
+ struct b2r2_blt_buf buf;
+ __s32 width;
+ __s32 height;
+ __u32 pitch;
+};
+
+
+/**
+ * enum b2r2_blt_transform- Specifies rotation and flipping, mutually exclusive
+ * @B2R2_BLT_TRANSFORM_NONE:
+ * No rotation or flip
+ * @B2R2_BLT_TRANSFORM_FLIP_H
+ * Flip horizontally
+ * @B2R2_BLT_TRANSFORM_FLIP_V
+ * Flip vertically
+ * @B2R2_BLT_TRANSFORM_CCW_ROT_90
+ * Rotate 90 degrees counter clockwise
+ * @B2R2_BLT_TRANSFORM_CCW_ROT_180
+ * Rotate 180 degrees (same as flip horizontally together with
+ * flip vertically)
+ * @B2R2_BLT_TRANSFORM_CCW_ROT_270
+ * Rotate 270 degrees counter clockwise
+ * @B2R2_BLT_TRANSFORM_FLIP_H_CCW_ROT_90
+ * Flip horizontally and then rotate 90 degrees counter clockwise
+ * @B2R2_BLT_TRANSFORM_FLIP_V_CCW_ROT_90
+ * Flip vertically and then rotate 90 degrees counter clockwise
+ */
+enum b2r2_blt_transform {
+ B2R2_BLT_TRANSFORM_NONE = 0,
+ B2R2_BLT_TRANSFORM_FLIP_H = 1,
+ B2R2_BLT_TRANSFORM_FLIP_V = 2,
+ B2R2_BLT_TRANSFORM_CCW_ROT_90 = 4,
+ B2R2_BLT_TRANSFORM_CCW_ROT_180 = 3,
+ B2R2_BLT_TRANSFORM_CCW_ROT_270 = 7,
+ B2R2_BLT_TRANSFORM_FLIP_H_CCW_ROT_90 = 5,
+ B2R2_BLT_TRANSFORM_FLIP_V_CCW_ROT_90 = 6,
+};
+
+
+/**
+ * enum b2r2_blt_flag - Flags that controls the B2R2 request
+ *
+ * Can be combined.
+ *
+ * @B2R2_BLT_FLAG_ASYNCH:
+ * Asynchronous request. b2r2_blt will returns when the request
+ * has been queued.
+ * @B2R2_BLT_FLAG_DRY_RUN:
+ * Dry run, just to check if request can be performed.
+ * @B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND:
+ * Enable per pixel alpha blend
+ * @B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND:
+ * Enable global alpha blend (alpha value in global_alpha)
+ * @B2R2_BLT_FLAG_SOURCE_COLOR_KEY:
+ * Enable source color key (color in src_color). Color should be in raw
+ * format.
+ * B2R2_BLT_FLAG_SOURCE_COLOR_KEY, B2R2_BLT_FLAG_SOURCE_FILL and
+ * B2R2_BLT_FLAG_SOURCE_FILL_RAW cannot be specified at the same time.
+ * B2R2_BLT_FLAG_SOURCE_COLOR_KEY and B2R2_BLT_FLAG_DEST_COLOR_KEY cannot be
+ * specified at the same time.
+ * @B2R2_BLT_FLAG_SOURCE_FILL:
+ * Enable ARGB/AYUV source fill (color in src_color). Which of ARGB and AYUV
+ * is determined by the destination format.
+ * B2R2_BLT_FLAG_SOURCE_COLOR_KEY, B2R2_BLT_FLAG_SOURCE_FILL and
+ * B2R2_BLT_FLAG_SOURCE_FILL_RAW cannot be specified at the same time
+ * @B2R2_BLT_FLAG_SOURCE_FILL_RAW:
+ * Enable raw color source fill (color in src_color)
+ * B2R2_BLT_FLAG_SOURCE_COLOR_KEY, B2R2_BLT_FLAG_SOURCE_FILL and
+ * B2R2_BLT_FLAG_SOURCE_FILL_RAW cannot be specified at the same time
+ * @B2R2_BLT_FLAG_DEST_COLOR_KEY:
+ * Enable dest color key (color in dst_color). Color in raw format.
+ * @B2R2_BLT_FLAG_SRC_IS_NOT_PREMULT:
+ * Source color not premultiplied (Valid for alpha formats only).
+ * @B2R2_BLT_FLAG_DITHER:
+ * Enable dithering
+ * @B2R2_BLT_FLAG_BLUR:
+ * Enable blur
+ * @B2R2_BLT_FLAG_SOURCE_MASK:
+ * Enable source mask
+ * @B2R2_BLT_FLAG_DESTINATION_CLIP:
+ * Enable destination clip rectangle
+ * @B2R2_BLT_FLAG_INHERIT_PRIO
+ * Inherit process priority
+ * @B2R2_BLT_FLAG_SRC_NO_CACHE_FLUSH
+ * Skip cache flush of source image buffer
+ * @B2R2_BLT_FLAG_SRC_MASK_NO_CACHE_FLUSH
+ * Skip cache flush of source mask buffer
+ * @B2R2_BLT_FLAG_DST_NO_CACHE_FLUSH
+ * Skip cache flush of destination image buffer
+ * @B2R2_BLT_FLAG_BG_BLEND
+ * Indicate that a background buffer is supplied
+ * to the blit operation. B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND,
+ * B2R2_BLT_FLAG_SRC_IS_NOT_PREMULT, and
+ * B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND will control the blend operation.
+ * The destination blending is in this case disabled and the destination
+ * buffer will be overwritten with the source and background blend result.
+ * @B2R2_BLT_FLAG_BG_NO_CACHE_FLUSH
+ * Skip cache flush of background image buffer
+ * @B2R2_BLT_FLAG_REPORT_WHEN_DONE
+ * Report through b2r2_blt file when done. A b2r2_blt_report structure is
+ * read. Use poll() or select() if anything to read. (i.e. to help user space
+ * to implement callback functionality)
+ * @B2R2_BLT_FLAG_REPORT_PERFORMANCE
+ * Include performance data in the report structure
+ * @B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION
+ * Use color look-up table for color correction.
+ * Pointer to the table must be specified in *clut field of
+ * the b2r2_blt_req structure.
+ * The table must map all input color values
+ * for each channel to the desired output values.
+ * It is an array with the following format:
+ * R0 G0 B0 A0 R1 G1 B1 A1...R255 G255 B255 A255
+ * where R0 is the 8 bit output value for red channel whenever its input
+ * equals 0.
+ * Similarly, R1 through R255 are the red channel outputs whenever
+ * the channel's inputs equal 1 through 255 respectively.
+ * Gn, Bn, An denote green, blue and alpha channel.
+ * Whenever the input bitmap format lacks the alpha channel,
+ * all alpha values in the color correction table should be set to 255.
+ * Size of the array that specifies the color correction table
+ * must be 1024 bytes.
+ * A table that does not change anything has the form:
+ * 0 0 0 0 1 1 1 1 2 2 2 2 ... 254 254 254 254 255 255 255 255.
+ * CLUT color correction can be applied to YUV raster buffers as well,
+ * in which case the RGB color channels are mapped onto YUV-space
+ * as follows:
+ * R = red chrominance
+ * G = luminance
+ * B = blue chrominance
+ * A = alpha
+ * If any of the planar or semi-planar formats is used, luminance cannot
+ * be changed by the color correction table.
+ */
+enum b2r2_blt_flag {
+ B2R2_BLT_FLAG_ASYNCH = BIT(0),/*0x1*/
+ B2R2_BLT_FLAG_DRY_RUN = BIT(1),/*0x2*/
+ B2R2_BLT_FLAG_PER_PIXEL_ALPHA_BLEND = BIT(2),/*0x4*/
+ B2R2_BLT_FLAG_GLOBAL_ALPHA_BLEND = BIT(3),/*0x8*/
+ B2R2_BLT_FLAG_SOURCE_COLOR_KEY = BIT(4),/*0x10*/
+ B2R2_BLT_FLAG_SOURCE_FILL = BIT(5),/*0x20*/
+ B2R2_BLT_FLAG_SOURCE_FILL_RAW = BIT(6),/*0x40*/
+ B2R2_BLT_FLAG_DEST_COLOR_KEY = BIT(7),/*0x80*/
+ B2R2_BLT_FLAG_SRC_IS_NOT_PREMULT = BIT(8),/*0x100*/
+ B2R2_BLT_FLAG_DITHER = BIT(9),/*0x200*/
+ B2R2_BLT_FLAG_BLUR = BIT(10),/*0x400*/
+ B2R2_BLT_FLAG_SOURCE_MASK = BIT(11),/*0x800*/
+ B2R2_BLT_FLAG_DESTINATION_CLIP = BIT(12),/*0x1000*/
+ B2R2_BLT_FLAG_INHERIT_PRIO = BIT(13),/*0x2000*/
+ B2R2_BLT_FLAG_SRC_NO_CACHE_FLUSH = BIT(14),/*0x4000*/
+ B2R2_BLT_FLAG_SRC_MASK_NO_CACHE_FLUSH = BIT(15),/*0x8000*/
+ B2R2_BLT_FLAG_DST_NO_CACHE_FLUSH = BIT(16),/*0x10000*/
+ B2R2_BLT_FLAG_BG_BLEND = BIT(17),/*0x20000*/
+ B2R2_BLT_FLAG_BG_NO_CACHE_FLUSH = BIT(18),/*0x40000*/
+ B2R2_BLT_FLAG_FULL_RANGE_YUV = BIT(19),/*0x20000*/
+ B2R2_BLT_FLAG_REPORT_WHEN_DONE = BIT(29),/*0x20000000*/
+ B2R2_BLT_FLAG_REPORT_PERFORMANCE = BIT(30),/*0x40000000*/
+ B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION = BIT(31),/*0x80000000*/
+};
+
+
+/**
+ * struct b2r2_blt_req - Specifies a request to B2R2
+ *
+ * @size: Size of this structure. Used for versioning. MUST be specified.
+ * @flags: Flags that control the B2R2 request ORed together
+ * @tfm: How source should be flipped and rotated when blitting
+ * @prio: Priority (-20 to 19). Inherits process prio
+ * if B2R2_BLT_FLAG_INHERIT_PRIO. Given priority is mapped onto B2R2.
+ * TBD: How?
+ * @clut: Pointer to the look-up table for color correction.
+ * @src_img: Source image. Not used if source fill.
+ * @src_mask: Source mask. Not used if source fill.
+ * @src_rect: Source area to be blitted.
+ * @src_color: Source fill color or color key
+ * @bg_img: Background image.
+ * @bg_rect: Background area to blend with.
+ * @dst_img: Destination image.
+ * @dst_rect: Destination area to be blitted to.
+ * @dst_color: Destination color key
+ * @dst_clip_rect: Destination clip rectangle.
+ * @global_alpha: Global alpha value (0 - 255)
+ * @report1: Data 1 to report back when request is done.
+ * See struct b2r2_blt_report.
+ * @report2: Data 2 to report back when request is done.
+ * See struct b2r2_blt_report.
+ *
+ */
+struct b2r2_blt_req {
+ __u32 size;
+ enum b2r2_blt_flag flags;
+ enum b2r2_blt_transform transform;
+ __s32 prio;
+ void *clut;
+ struct b2r2_blt_img src_img;
+ struct b2r2_blt_img src_mask;
+ struct b2r2_blt_rect src_rect;
+ __u32 src_color;
+ struct b2r2_blt_img bg_img;
+ struct b2r2_blt_rect bg_rect;
+ struct b2r2_blt_img dst_img;
+ struct b2r2_blt_rect dst_rect;
+ struct b2r2_blt_rect dst_clip_rect;
+ __u32 dst_color;
+ __u8 global_alpha;
+ __u32 report1;
+ __u32 report2;
+};
+
+/**
+ * enum b2r2_blt_cap - Capabilities that can be queried for.
+ *
+ * Capabilities can be queried for a specific format or for formats in
+ * general. To query for capabilities in general, specify BLT_FMT_UNUSED
+ * as format.
+ *
+ * B2R2_BLT_CAP_UNUSED: Unused/unspecified capability
+ * B2R2_BLT_CAP_FMT_SOURCE: Is format supported as source?
+ * B2R2_BLT_CAP_FMT_SOURCE_MASK: Is format supported as source mask?
+ * B2R2_BLT_CAP_FMT_DEST: Is format supported as dest?
+ * B2R2_BLT_CAP_PER_PIXEL_ALPHA_BLEND: Is per pixel alpha blending supported
+ * with format as source
+ * B2R2_BLT_CAP_GLOBAL_ALPHA_BLEND: Is per global alpha blending supported
+ * with format as source
+ * B2R2_BLT_CAP_SOURCE_COLOR_KEY: Is source color key supported with format as
+ * source
+ * B2R2_BLT_CAP_SOURCE_FILL: Is source fill supported with format as source
+ * B2R2_BLT_CAP_SOURCE_FILL_RAW: Is source fill raw supported with format as
+ * dest
+ * B2R2_BLT_CAP_DEST_COLOR_KEY: Is dest color key supported with format as dest
+ * B2R2_BLT_CAP_DITHER: Is dithering supported with format as source
+ * B2R2_BLT_CAP_BLUR: Is blur supported with format as source
+ * B2R2_BLT_CAP_MINIFICATION_LIMIT: Minification limit (copybit support)
+ * B2R2_BLT_CAP_MAGNIFICATION_LIMIT: Magnification limit (copybit support)
+ * B2R2_BLT_CAP_SCALING_FRAC_BITS: Number of scaling fractional bits (copybit
+ * support)
+ * B2R2_BLT_CAP_ROTATION_STEP_DEG: Supported rotation step in degrees (copybit
+ * support)
+ */
+
+enum b2r2_blt_cap {
+ B2R2_BLT_CAP_UNUSED = 0,
+ /**
+ * @brief Is format supported as source.
+ */
+ B2R2_BLT_CAP_FMT_SOURCE,
+ /**
+ * @brief Is format supported as source mask
+ */
+ B2R2_BLT_CAP_FMT_SOURCE_MASK,
+ /**
+ * @brief Is format supported as destination
+ */
+ B2R2_BLT_CAP_FMT_DEST,
+ /**
+ * @brief Is per pixel alpha blending supported with format as source
+ */
+ B2R2_BLT_CAP_PER_PIXEL_ALPHA_BLEND,
+ /**
+ * @brief Is global alpha blending supported with format as source
+ */
+ B2R2_BLT_CAP_GLOBAL_ALPHA_BLEND,
+ /**
+ * @brief Is source color key supported with format as source
+ */
+ B2R2_BLT_CAP_SOURCE_COLOR_KEY,
+ /**
+ * @brief Is source fill supported with format as source
+ */
+ B2R2_BLT_CAP_SOURCE_FILL,
+ /**
+ * @brief Is source fill raw supported with format as dest
+ */
+ B2R2_BLT_CAP_SOURCE_FILL_RAW,
+ /**
+ * @brief Is dest color key supported with format as dest
+ */
+ B2R2_BLT_CAP_DEST_COLOR_KEY,
+ /**
+ * @brief Is dithering supported with format as source
+ */
+ B2R2_BLT_CAP_DITHER,
+ /**
+ * @brief Is blur supported with format as source
+ */
+ B2R2_BLT_CAP_BLUR,
+ /**
+ * @brief Minification limit (copybit support)
+ */
+ B2R2_BLT_CAP_MINIFICATION_LIMIT,
+ /**
+ * @brief Magnification limit (copybit support)
+ */
+ B2R2_BLT_CAP_MAGNIFICATION_LIMIT,
+ /**
+ * @brief Number of scaling fractional bits (copybit support)
+ */
+ B2R2_BLT_CAP_SCALING_FRAC_BITS,
+ /**
+ * @brief Supported rotation step in degrees (copybit support)
+ */
+ B2R2_BLT_CAP_ROTATION_STEP_DEG,
+};
+
+/**
+ * struct b2r2_blt_query_cap - Query B2R2 capabilities
+ *
+ * fmt: Format to query capabilities for or BLT_FMT_UNUSED for all
+ * cap: Capability to query for
+ * result: Returned capability. Interpretaion of this variable varies
+ * with the capability queried
+ */
+struct b2r2_blt_query_cap {
+ enum b2r2_blt_fmt fmt;
+ enum b2r2_blt_cap cap;
+ __u32 result;
+};
+
+/**
+ * struct b2r2_blt_report - Report from B2R2 driver back to user space
+ *
+ * This structure can be read from B2R2 driver if B2R2_BLT_FLAG_REPORT_WHEN_DONE
+ * flag was specified when the request was issued.
+ *
+ * @request_id: The id for the request, same as reported from blt_request
+ * @report1: Client data specified in struct blt_request
+ * @report2: Client data specified in struct blt_request
+ * @usec_elapsed: Number of microseconds needed to perform this blit
+ * if B2R2_BLT_FLAG_REPORT_PERFORMANCE was specified when the
+ * request was issued.
+ *
+ */
+struct b2r2_blt_report {
+ __u32 request_id;
+ __u32 report1;
+ __u32 report2;
+ __u32 usec_elapsed;
+};
+
+/**
+ * B2R2 BLT driver is used in the following way:
+ *
+ * Obtain a file descriptor to the driver:
+ * fd = open("/dev/b2r2_blt", O_RDWR);
+ *
+ * Issue requests:
+ * struct b2r2_blt_request blt_request;
+ * blt_request.size = sizeof(blt_request);
+ * ... Fill request with data...
+ *
+ * request_id = ioctl(fd, B2R2_BLT_IOC, (__u32) &blt_request);
+ *
+ * Wait for a request to finish
+ * ret = ioctl(fd, B2R2_BLT_SYNCH_IOC, (__u32) request_id);
+ *
+ * Wait for all requests from this context to finish
+ * ret = ioctl(fd, B2R2_BLT_SYNCH_IOC, (__u32) 0);
+ *
+ * Wait indefinitely for report data from driver:
+ * pollfd.fd = fd
+ * pollfd.events = 0xFFFFFFFF;
+ * pollfd.revents = 0;
+ * ret = poll(&pollfd, 1, -1);
+ *
+ * Read report data from driver
+ * struct b2r2_blt_report blt_report;
+ *
+ * nread = read(fd, &blt_report, sizeof(blt_report));
+ *
+ * Close the driver
+ * close(fd);
+ */
+
+/* B2R2 BLT IOCTLS */
+
+/**
+ * B2R2_BLT_IOC_MAGIC is ioctl type group for B2R2 driver
+ */
+#define B2R2_BLT_IOC_MAGIC 0xb2
+
+/**
+ * The B2R2_BLT_IOC ioctl adds a blit request to B2R2.
+ *
+ * The ioctl returns when the blit has been performed if not
+ * asynchronous execution has been specified. If asynchronous,
+ * control is returned as soon as the request has been queued.
+ *
+ * Supplied parameter shall be a pointer to a struct b2r2_blt_req.
+ *
+ * Returns an unique request id if >= 0, else a negative error code.
+ * This request id can be waited for using B2R2_BLT_SYNC_IOC.
+ * Return values: -ESOMERROR Description of an error
+ */
+#define B2R2_BLT_IOC _IOW(B2R2_BLT_IOC_MAGIC, 1, struct b2r2_blt_req)
+
+/**
+ * The B2R2_BLT_SYNC_IOC waits for all or a specified request to be finished.
+ *
+ * Supplied parameter shall be a request id previously returned by
+ * B2R2_BLT_IOC or 0 for all requests.
+ *
+ * Returns 0 if OK, else a negative error code
+ * Return value: -ESOMERROR Description of an error
+ */
+#define B2R2_BLT_SYNCH_IOC _IOW(B2R2_BLT_IOC_MAGIC, 2, int)
+
+/**
+ * The BLT_QUERY_CAP_IOC returns capability information for all or
+ * for a certain format
+ *
+ * Supplied parameter shall be a pointer to a struct b2r2_blt_query_cap.
+ *
+ * @return Returns 0 if OK, else a negative error code
+ * @retval -ESOMERROR Description of an error
+ */
+#define B2R2_BLT_QUERY_CAP_IOC _IOWR(B2R2_BLT_IOC_MAGIC, 3, \
+ struct b2r2_blt_query_cap)
+
+/**
+ * struct b2r2_platform_data - The b2r2 core hardware configuration
+ *
+ * @regulator_id: The name of the b2r2 power source
+ * @clock_id: The name of the b2r2 clock
+ *
+ */
+struct b2r2_platform_data {
+ const char *regulator_id;
+ const char *clock_id;
+};
+
+/**
+ * b2r2_blt_open - Opening a handle for use with the blitter interface
+ *
+ * Returns a handle (0 or greater) to a B2R2 blitter intance on success
+ */
+int b2r2_blt_open(void);
+
+/**
+ * b2r2_blt_close - Free the blitter instance and its resources
+ *
+ * @handle: The B2R2 BLT instance handle
+ *
+ * All active jobs are finished or cancelled and allocated data
+ * is released.
+ *
+ * Returns 0 on success
+ */
+int b2r2_blt_close(int handle);
+
+/**
+ * b2r2_blt_request - Request a blit operation
+ *
+ * @handle: The B2R2 BLT instance handle
+ *
+ * Returns 0 on success
+ */
+int b2r2_blt_request(int handle, struct b2r2_blt_req *user_req);
+
+/**
+ * b2r2_blt_synch - Wait for all or a specified job
+ *
+ * @handle: The B2R2 BLT instance handle
+ * @request_id: If 0, wait for all requests on this instance to finish.
+ * Else wait for the request with the given request id to finish.
+ *
+ * Returns 0 on success
+ */
+int b2r2_blt_synch(int handle, int request_id);
+
+#endif /* #ifdef _LINUX_VIDEO_B2R2_BLT_H */
diff --git a/include/video/hdmi.h b/include/video/hdmi.h
new file mode 100644
index 00000000000..55dcd003fcd
--- /dev/null
+++ b/include/video/hdmi.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * HDMI driver
+ *
+ * Author: Per Persson <per.xb.persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __HDMI__H__
+#define __HDMI__H__
+
+#define HDMI_RESULT_OK 0
+#define HDMI_RESULT_NOT_OK 1
+#define HDMI_AES_NOT_FUSED 2
+#define HDMI_RESULT_CRC_MISMATCH 3
+
+#define HDMI_CEC_READ_MAXSIZE 16
+#define HDMI_CEC_WRITE_MAXSIZE 15
+#define HDMI_INFOFRAME_MAX_SIZE 27
+#define HDMI_HDCP_FUSEAES_KEYSIZE 16
+#define HDMI_HDCP_AES_BLOCK_START 128
+#define HDMI_HDCP_KSV_BLOCK 40
+#define HDMI_HDCP_AES_NR_OF_BLOCKS 18
+#define HDMI_HDCP_AES_KEYSIZE 16
+#define HDMI_HDCP_AES_KSVSIZE 5
+#define HDMI_HDCP_AES_KSVZEROESSIZE 3
+#define HDMI_EDID_DATA_SIZE 128
+#define HDMI_CEC_SIZE 15
+#define HDMI_INFOFR_SIZE 27
+#define HDMI_FUSE_KEYSIZE 16
+#define HDMI_AES_KSVSIZE 5
+#define HDMI_AES_KEYSIZE 288
+#define HDMI_CRC32_SIZE 4
+#define HDMI_HDCPAUTHRESP_SIZE 126
+
+#define HDMI_STOREASTEXT_TEXT_SIZE 2
+#define HDMI_STOREASTEXT_BIN_SIZE 1
+#define HDMI_PLUGDETEN_TEXT_SIZE 6
+#define HDMI_PLUGDETEN_BIN_SIZE 3
+#define HDMI_EDIDREAD_TEXT_SIZE 4
+#define HDMI_EDIDREAD_BIN_SIZE 2
+#define HDMI_CECEVEN_TEXT_SIZE 2
+#define HDMI_CECEVEN_BIN_SIZE 1
+#define HDMI_CECSEND_TEXT_SIZE_MAX 37
+#define HDMI_CECSEND_TEXT_SIZE_MIN 6
+#define HDMI_CECSEND_BIN_SIZE_MAX 18
+#define HDMI_CECSEND_BIN_SIZE_MIN 3
+#define HDMI_INFOFRSEND_TEXT_SIZE_MIN 8
+#define HDMI_INFOFRSEND_TEXT_SIZE_MAX 63
+#define HDMI_INFOFRSEND_BIN_SIZE_MIN 4
+#define HDMI_INFOFRSEND_BIN_SIZE_MAX 31
+#define HDMI_HDCPEVEN_TEXT_SIZE 2
+#define HDMI_HDCPEVEN_BIN_SIZE 1
+#define HDMI_HDCP_FUSEAES_TEXT_SIZE 34
+#define HDMI_HDCP_FUSEAES_BIN_SIZE 17
+#define HDMI_HDCP_LOADAES_TEXT_SIZE 594
+#define HDMI_HDCP_LOADAES_BIN_SIZE 297
+#define HDMI_HDCPAUTHENCR_TEXT_SIZE 4
+#define HDMI_HDCPAUTHENCR_BIN_SIZE 2
+#define HDMI_EVCLR_TEXT_SIZE 2
+#define HDMI_EVCLR_BIN_SIZE 1
+#define HDMI_AUDIOCFG_TEXT_SIZE 14
+#define HDMI_AUDIOCFG_BIN_SIZE 7
+#define HDMI_POWERONOFF_TEXT_SIZE 2
+#define HDMI_POWERONOFF_BIN_SIZE 1
+
+#define HDMI_IOC_MAGIC 0xcc
+
+/** IOCTL Operations */
+#define IOC_PLUG_DETECT_ENABLE _IOWR(HDMI_IOC_MAGIC, 1, int)
+#define IOC_EDID_READ _IOWR(HDMI_IOC_MAGIC, 2, int)
+#define IOC_CEC_EVENT_ENABLE _IOWR(HDMI_IOC_MAGIC, 3, int)
+#define IOC_CEC_READ _IOWR(HDMI_IOC_MAGIC, 4, int)
+#define IOC_CEC_SEND _IOWR(HDMI_IOC_MAGIC, 5, int)
+#define IOC_INFOFRAME_SEND _IOWR(HDMI_IOC_MAGIC, 6, int)
+#define IOC_HDCP_EVENT_ENABLE _IOWR(HDMI_IOC_MAGIC, 7, int)
+#define IOC_HDCP_CHKAESOTP _IOWR(HDMI_IOC_MAGIC, 8, int)
+#define IOC_HDCP_FUSEAES _IOWR(HDMI_IOC_MAGIC, 9, int)
+#define IOC_HDCP_LOADAES _IOWR(HDMI_IOC_MAGIC, 10, int)
+#define IOC_HDCP_AUTHENCR_REQ _IOWR(HDMI_IOC_MAGIC, 11, int)
+#define IOC_HDCP_STATE_GET _IOWR(HDMI_IOC_MAGIC, 12, int)
+#define IOC_EVENTS_READ _IOWR(HDMI_IOC_MAGIC, 13, int)
+#define IOC_EVENTS_CLEAR _IOWR(HDMI_IOC_MAGIC, 14, int)
+#define IOC_AUDIO_CFG _IOWR(HDMI_IOC_MAGIC, 15, int)
+#define IOC_PLUG_STATUS _IOWR(HDMI_IOC_MAGIC, 16, int)
+#define IOC_POWERONOFF _IOWR(HDMI_IOC_MAGIC, 17, int)
+#define IOC_EVENT_WAKEUP _IOWR(HDMI_IOC_MAGIC, 18, int)
+#define IOC_POWERSTATE _IOWR(HDMI_IOC_MAGIC, 19, int)
+
+
+/* HDMI driver */
+void hdmi_event(enum av8100_hdmi_event);
+int hdmi_init(void);
+void hdmi_exit(void);
+
+enum hdmi_event {
+ HDMI_EVENT_NONE = 0x0,
+ HDMI_EVENT_HDMI_PLUGIN = 0x1,
+ HDMI_EVENT_HDMI_PLUGOUT = 0x2,
+ HDMI_EVENT_CEC = 0x4,
+ HDMI_EVENT_HDCP = 0x8,
+ HDMI_EVENT_CECTXERR = 0x10,
+ HDMI_EVENT_WAKEUP = 0x20,
+ HDMI_EVENT_CECTX = 0x40,
+};
+
+enum hdmi_hdcp_auth_type {
+ HDMI_HDCP_AUTH_OFF = 0,
+ HDMI_HDCP_AUTH_START = 1,
+ HDMI_HDCP_AUTH_REV_LIST_REQ = 2,
+ HDMI_HDCP_AUTH_CONT = 3,
+};
+
+enum hdmi_hdcp_encr_type {
+ HDMI_HDCP_ENCR_OESS = 0,
+ HDMI_HDCP_ENCR_EESS = 1,
+};
+
+struct plug_detect {
+ __u8 hdmi_detect_enable;
+ __u8 on_time;
+ __u8 hdmi_off_time;
+};
+
+struct edid_read {
+ __u8 address;
+ __u8 block_nr;
+ __u8 data_length;
+ __u8 data[HDMI_EDID_DATA_SIZE];
+};
+
+struct cec_rw {
+ __u8 src;
+ __u8 dest;
+ __u8 length;
+ __u8 data[HDMI_CEC_SIZE];
+};
+
+struct info_fr {
+ __u8 type;
+ __u8 ver;
+ __u8 crc;
+ __u8 length;
+ __u8 data[HDMI_INFOFR_SIZE];
+};
+
+struct hdcp_fuseaes {
+ __u8 key[HDMI_FUSE_KEYSIZE];
+ __u8 crc;
+ __u8 result;
+};
+
+struct hdcp_loadaesall {
+ __u8 key[HDMI_AES_KEYSIZE];
+ __u8 ksv[HDMI_AES_KSVSIZE];
+ __u8 crc32[HDMI_CRC32_SIZE];
+ __u8 result;
+};
+
+
+/* hdcp_authencr resp coding
+ *
+ * When encr_type is 2 (request revoc list), the response is given by
+ * resp_size is != 0 and resp containing the folllowing:
+ *
+ * __u8[5] Bksv from sink (not belonging to revocation list)
+ * __u8 Device count
+ * Additional output if Nrofdevices > 0:
+ * __u8[5 * Nrofdevices] Bksv per connected equipment
+ * __u8[20] SHA signature
+ *
+ * Device count coding:
+ * 0 = a simple receiver is connected
+ * 0x80 = a repeater is connected without downstream equipment
+ * 0x81 = a repeater is connected with one downstream equipment
+ * up to 0x94 = (0x80 + 0x14) a repeater is connected with downstream
+ * equipment (thus up to 20 connected equipments)
+ * 1 = repeater without sink equipment connected
+ * >1 = number of connected equipment on the repeater
+ * Nrofdevices = Device count & 0x7F (max 20)
+ *
+ * Max resp_size is 5 + 1 + 5 * 20 + 20 = 126 bytes
+ *
+ */
+struct hdcp_authencr {
+ __u8 auth_type;
+ __u8 encr_type;
+ __u8 result;
+ __u8 resp_size;
+ __u8 resp[HDMI_HDCPAUTHRESP_SIZE];
+};
+
+struct audio_cfg {
+ __u8 if_format;
+ __u8 i2s_entries;
+ __u8 freq;
+ __u8 word_length;
+ __u8 format;
+ __u8 if_mode;
+ __u8 mute;
+};
+
+#endif /* __HDMI__H__ */
diff --git a/include/video/mcde.h b/include/video/mcde.h
new file mode 100644
index 00000000000..499ce5cfecc
--- /dev/null
+++ b/include/video/mcde.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE base driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE__H__
+#define __MCDE__H__
+
+/* Physical interface types */
+enum mcde_port_type {
+ MCDE_PORTTYPE_DSI = 0,
+ MCDE_PORTTYPE_DPI = 1,
+};
+
+/* Interface mode */
+enum mcde_port_mode {
+ MCDE_PORTMODE_CMD = 0,
+ MCDE_PORTMODE_VID = 1,
+};
+
+/* MCDE fifos */
+enum mcde_fifo {
+ MCDE_FIFO_A = 0,
+ MCDE_FIFO_B = 1,
+ MCDE_FIFO_C0 = 2,
+ MCDE_FIFO_C1 = 3,
+};
+
+/* MCDE channels (pixel pipelines) */
+enum mcde_chnl {
+ MCDE_CHNL_A = 0,
+ MCDE_CHNL_B = 1,
+ MCDE_CHNL_C0 = 2,
+ MCDE_CHNL_C1 = 3,
+};
+
+/* Update sync mode */
+enum mcde_sync_src {
+ MCDE_SYNCSRC_OFF = 0, /* No sync */
+ MCDE_SYNCSRC_TE0 = 1, /* MCDE ext TE0 */
+ MCDE_SYNCSRC_TE1 = 2, /* MCDE ext TE1 */
+ MCDE_SYNCSRC_BTA = 3, /* DSI BTA */
+ MCDE_SYNCSRC_TE_POLLING = 4, /* DSI TE_POLLING */
+};
+
+/* Frame trig method */
+enum mcde_trig_method {
+ MCDE_TRIG_HW = 0, /* frame trig from MCDE formatter */
+ MCDE_TRIG_SW = 1, /* frame trig from software */
+};
+
+/* Interface pixel formats (output) */
+/*
+* REVIEW: Define formats
+* Add explanatory comments how the formats are ordered in memory
+*/
+enum mcde_port_pix_fmt {
+ /* MIPI standard formats */
+
+ MCDE_PORTPIXFMT_DPI_16BPP_C1 = 0x21,
+ MCDE_PORTPIXFMT_DPI_16BPP_C2 = 0x22,
+ MCDE_PORTPIXFMT_DPI_16BPP_C3 = 0x23,
+ MCDE_PORTPIXFMT_DPI_18BPP_C1 = 0x24,
+ MCDE_PORTPIXFMT_DPI_18BPP_C2 = 0x25,
+ MCDE_PORTPIXFMT_DPI_24BPP = 0x26,
+
+ MCDE_PORTPIXFMT_DSI_16BPP = 0x31,
+ MCDE_PORTPIXFMT_DSI_18BPP = 0x32,
+ MCDE_PORTPIXFMT_DSI_18BPP_PACKED = 0x33,
+ MCDE_PORTPIXFMT_DSI_24BPP = 0x34,
+
+ /* Custom formats */
+ MCDE_PORTPIXFMT_DSI_YCBCR422 = 0x40,
+};
+
+enum mcde_hdmi_sdtv_switch {
+ HDMI_SWITCH,
+ SDTV_SWITCH,
+ DVI_SWITCH
+};
+
+enum mcde_col_convert {
+ MCDE_CONVERT_RGB_2_RGB,
+ MCDE_CONVERT_RGB_2_YCBCR,
+ MCDE_CONVERT_YCBCR_2_RGB,
+ MCDE_CONVERT_YCBCR_2_YCBCR,
+};
+
+struct mcde_col_transform {
+ u16 matrix[3][3];
+ u16 offset[3];
+};
+
+/* DSI video mode */
+enum mcde_dsi_vid_mode {
+ NON_BURST_MODE_WITH_SYNC_EVENT = 0,
+ /* enables tvg, test video generator */
+ NON_BURST_MODE_WITH_SYNC_EVENT_TVG_ENABLED = 1,
+ BURST_MODE_WITH_SYNC_EVENT = 2,
+ BURST_MODE_WITH_SYNC_PULSE = 3,
+};
+
+#define MCDE_PORT_DPI_NO_CLOCK_DIV 0
+
+#define DPI_ACT_HIGH_ALL 0 /* all signals are active high */
+#define DPI_ACT_LOW_HSYNC 1 /* horizontal sync signal is active low */
+#define DPI_ACT_LOW_VSYNC 2 /* vertical sync signal is active low */
+#define DPI_ACT_LOW_DATA_ENABLE 4 /* data enable signal is active low */
+#define DPI_ACT_ON_FALLING_EDGE 8 /* drive data on the falling edge of the
+ * pixel clock
+ */
+
+struct mcde_port {
+ enum mcde_port_type type;
+ enum mcde_port_mode mode;
+ enum mcde_port_pix_fmt pixel_format;
+ u8 refresh_rate; /* display refresh rate given in Hz */
+ u8 ifc;
+ u8 link;
+ enum mcde_sync_src sync_src;
+ enum mcde_trig_method frame_trig;
+ bool update_auto_trig;
+ enum mcde_hdmi_sdtv_switch hdmi_sdtv_switch;
+ union {
+ struct {
+ u8 virt_id;
+ u8 num_data_lanes;
+ u8 ui;
+ bool clk_cont;
+ bool host_eot_gen;
+
+ /* DSI video mode operating modes */
+ enum mcde_dsi_vid_mode vid_mode;
+
+ /*
+ * wakeup_time is the time to perform
+ * LP->HS on D-PHY. Given in clock
+ * cycles of byte clock frequency.
+ */
+ u32 vid_wakeup_time;
+
+ u32 hs_freq;
+ u32 lp_freq;
+
+ /* DSI data lanes are swapped if true */
+ bool data_lanes_swap;
+ } dsi;
+ struct {
+ u8 bus_width;
+ bool tv_mode;
+ u16 clock_div; /* use 0 or 1 for no clock divider */
+ u32 polarity; /* see DPI_ACT_LOW_* definitions */
+ u32 lcd_freq;
+ } dpi;
+ } phy;
+};
+
+/* Overlay pixel formats (input) *//* REVIEW: Define byte order */
+enum mcde_ovly_pix_fmt {
+ MCDE_OVLYPIXFMT_RGB565 = 1,
+ MCDE_OVLYPIXFMT_RGBA5551 = 2,
+ MCDE_OVLYPIXFMT_RGBA4444 = 3,
+ MCDE_OVLYPIXFMT_RGB888 = 4,
+ MCDE_OVLYPIXFMT_RGBX8888 = 5,
+ MCDE_OVLYPIXFMT_RGBA8888 = 6,
+ MCDE_OVLYPIXFMT_YCbCr422 = 7,
+};
+
+/* Display power modes */
+enum mcde_display_power_mode {
+ MCDE_DISPLAY_PM_OFF = 0, /* Power off */
+ MCDE_DISPLAY_PM_STANDBY = 1, /* DCS sleep mode */
+ MCDE_DISPLAY_PM_ON = 2, /* DCS normal mode, display on */
+};
+
+/* Display rotation */
+enum mcde_display_rotation {
+ MCDE_DISPLAY_ROT_0 = 0,
+ MCDE_DISPLAY_ROT_90_CCW = 90,
+ MCDE_DISPLAY_ROT_180_CCW = 180,
+ MCDE_DISPLAY_ROT_270_CCW = 270,
+ MCDE_DISPLAY_ROT_90_CW = MCDE_DISPLAY_ROT_270_CCW,
+ MCDE_DISPLAY_ROT_180_CW = MCDE_DISPLAY_ROT_180_CCW,
+ MCDE_DISPLAY_ROT_270_CW = MCDE_DISPLAY_ROT_90_CCW,
+};
+
+/* REVIEW: Verify */
+#define MCDE_MIN_WIDTH 16
+#define MCDE_MIN_HEIGHT 16
+#define MCDE_MAX_WIDTH 2048
+#define MCDE_MAX_HEIGHT 2048
+#define MCDE_BUF_START_ALIGMENT 8
+#define MCDE_BUF_LINE_ALIGMENT 8
+
+/* Tv-out defines */
+#define MCDE_CONFIG_TVOUT_BACKGROUND_LUMINANCE 0x83
+#define MCDE_CONFIG_TVOUT_BACKGROUND_CHROMINANCE_CB 0x9C
+#define MCDE_CONFIG_TVOUT_BACKGROUND_CHROMINANCE_CR 0x2C
+
+/* In seconds */
+#define MCDE_AUTO_SYNC_WATCHDOG 5
+
+/* DSI modes */
+#define DSI_VIDEO_MODE 0
+#define DSI_CMD_MODE 1
+
+/* Video mode descriptor */
+struct mcde_video_mode {
+ u32 xres;
+ u32 yres;
+ u32 pixclock; /* pixel clock in ps (pico seconds) */
+ u32 hbp; /* horizontal back porch: left margin (excl. hsync) */
+ u32 hfp; /* horizontal front porch: right margin (excl. hsync) */
+ u32 hsw; /* horizontal sync width */
+ u32 vbp; /* vertical back porch: upper margin (excl. vsync) */
+ u32 vfp; /* vertical front porch: lower margin (excl. vsync) */
+ u32 vsw; /* vertical sync width*/
+ bool interlaced;
+ bool force_update; /* when switching between hdmi and sdtv */
+};
+
+struct mcde_rectangle {
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+};
+
+struct mcde_overlay_info {
+ u32 paddr;
+ u32 *vaddr;
+ u16 stride; /* buffer line len in bytes */
+ enum mcde_ovly_pix_fmt fmt;
+
+ u16 src_x;
+ u16 src_y;
+ u16 dst_x;
+ u16 dst_y;
+ u16 dst_z;
+ u16 w;
+ u16 h;
+ struct mcde_rectangle dirty;
+};
+
+struct mcde_overlay {
+ struct kobject kobj;
+ struct list_head list; /* mcde_display_device.ovlys */
+
+ struct mcde_display_device *ddev;
+ struct mcde_overlay_info info;
+ struct mcde_ovly_state *state;
+};
+
+/*
+ * Three functions for mapping 8 bits colour channels on 12 bits colour
+ * channels. The colour channels (ch0, ch1, ch2) can represent (r, g, b) or
+ * (Y, Cb, Cr) respectively.
+ */
+struct mcde_palette_table {
+ u16 (*map_col_ch0)(u8);
+ u16 (*map_col_ch1)(u8);
+ u16 (*map_col_ch2)(u8);
+};
+
+struct mcde_chnl_state;
+
+struct mcde_chnl_state *mcde_chnl_get(enum mcde_chnl chnl_id,
+ enum mcde_fifo fifo, const struct mcde_port *port);
+int mcde_chnl_set_pixel_format(struct mcde_chnl_state *chnl,
+ enum mcde_port_pix_fmt pix_fmt);
+int mcde_chnl_set_palette(struct mcde_chnl_state *chnl,
+ struct mcde_palette_table *palette);
+void mcde_chnl_set_col_convert(struct mcde_chnl_state *chnl,
+ struct mcde_col_transform *transform,
+ enum mcde_col_convert convert);
+int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl,
+ struct mcde_video_mode *vmode);
+/* TODO: Remove rotbuf* parameters when ESRAM allocator is implemented*/
+int mcde_chnl_set_rotation(struct mcde_chnl_state *chnl,
+ enum mcde_display_rotation rotation);
+int mcde_chnl_set_power_mode(struct mcde_chnl_state *chnl,
+ enum mcde_display_power_mode power_mode);
+
+int mcde_chnl_apply(struct mcde_chnl_state *chnl);
+int mcde_chnl_update(struct mcde_chnl_state *chnl,
+ struct mcde_rectangle *update_area,
+ bool tripple_buffer);
+void mcde_chnl_put(struct mcde_chnl_state *chnl);
+
+void mcde_chnl_stop_flow(struct mcde_chnl_state *chnl);
+
+void mcde_chnl_enable(struct mcde_chnl_state *chnl);
+void mcde_chnl_disable(struct mcde_chnl_state *chnl);
+
+/* MCDE overlay */
+struct mcde_ovly_state;
+
+struct mcde_ovly_state *mcde_ovly_get(struct mcde_chnl_state *chnl);
+void mcde_ovly_set_source_buf(struct mcde_ovly_state *ovly,
+ u32 paddr);
+void mcde_ovly_set_source_info(struct mcde_ovly_state *ovly,
+ u32 stride, enum mcde_ovly_pix_fmt pix_fmt);
+void mcde_ovly_set_source_area(struct mcde_ovly_state *ovly,
+ u16 x, u16 y, u16 w, u16 h);
+void mcde_ovly_set_dest_pos(struct mcde_ovly_state *ovly,
+ u16 x, u16 y, u8 z);
+void mcde_ovly_apply(struct mcde_ovly_state *ovly);
+void mcde_ovly_put(struct mcde_ovly_state *ovly);
+
+/* MCDE dsi */
+
+#define DCS_CMD_ENTER_IDLE_MODE 0x39
+#define DCS_CMD_ENTER_INVERT_MODE 0x21
+#define DCS_CMD_ENTER_NORMAL_MODE 0x13
+#define DCS_CMD_ENTER_PARTIAL_MODE 0x12
+#define DCS_CMD_ENTER_SLEEP_MODE 0x10
+#define DCS_CMD_EXIT_IDLE_MODE 0x38
+#define DCS_CMD_EXIT_INVERT_MODE 0x20
+#define DCS_CMD_EXIT_SLEEP_MODE 0x11
+#define DCS_CMD_GET_ADDRESS_MODE 0x0B
+#define DCS_CMD_GET_BLUE_CHANNEL 0x08
+#define DCS_CMD_GET_DIAGNOSTIC_RESULT 0x0F
+#define DCS_CMD_GET_DISPLAY_MODE 0x0D
+#define DCS_CMD_GET_GREEN_CHANNEL 0x07
+#define DCS_CMD_GET_PIXEL_FORMAT 0x0C
+#define DCS_CMD_GET_POWER_MODE 0x0A
+#define DCS_CMD_GET_RED_CHANNEL 0x06
+#define DCS_CMD_GET_SCANLINE 0x45
+#define DCS_CMD_GET_SIGNAL_MODE 0x0E
+#define DCS_CMD_NOP 0x00
+#define DCS_CMD_READ_DDB_CONTINUE 0xA8
+#define DCS_CMD_READ_DDB_START 0xA1
+#define DCS_CMD_READ_MEMORY_CONTINE 0x3E
+#define DCS_CMD_READ_MEMORY_START 0x2E
+#define DCS_CMD_SET_ADDRESS_MODE 0x36
+#define DCS_CMD_SET_COLUMN_ADDRESS 0x2A
+#define DCS_CMD_SET_DISPLAY_OFF 0x28
+#define DCS_CMD_SET_DISPLAY_ON 0x29
+#define DCS_CMD_SET_GAMMA_CURVE 0x26
+#define DCS_CMD_SET_PAGE_ADDRESS 0x2B
+#define DCS_CMD_SET_PARTIAL_AREA 0x30
+#define DCS_CMD_SET_PIXEL_FORMAT 0x3A
+#define DCS_CMD_SET_SCROLL_AREA 0x33
+#define DCS_CMD_SET_SCROLL_START 0x37
+#define DCS_CMD_SET_TEAR_OFF 0x34
+#define DCS_CMD_SET_TEAR_ON 0x35
+#define DCS_CMD_SET_TEAR_SCANLINE 0x44
+#define DCS_CMD_SOFT_RESET 0x01
+#define DCS_CMD_WRITE_LUT 0x2D
+#define DCS_CMD_WRITE_CONTINUE 0x3C
+#define DCS_CMD_WRITE_START 0x2C
+
+#define MCDE_MAX_DCS_READ 4
+#define MCDE_MAX_DSI_DIRECT_CMD_WRITE 15
+
+int mcde_dsi_generic_write(struct mcde_chnl_state *chnl, u8* para, int len);
+int mcde_dsi_dcs_write(struct mcde_chnl_state *chnl,
+ u8 cmd, u8 *data, int len);
+int mcde_dsi_dcs_read(struct mcde_chnl_state *chnl,
+ u8 cmd, u32 *data, int *len);
+int mcde_dsi_set_max_pkt_size(struct mcde_chnl_state *chnl);
+
+/* MCDE */
+
+/* Driver data */
+#define MCDE_IRQ "MCDE IRQ"
+#define MCDE_IO_AREA "MCDE I/O Area"
+
+struct mcde_platform_data {
+ /* DPI */
+ u8 outmux[5]; /* MCDE_CONF0.OUTMUXx */
+ u8 syncmux; /* MCDE_CONF0.SYNCMUXx */
+
+ /* TODO: Remove once ESRAM allocator is done */
+ u32 rotbuf1;
+ u32 rotbuf2;
+ u32 rotbufsize;
+
+ const char *regulator_vana_id;
+ const char *regulator_mcde_epod_id;
+ const char *regulator_esram_epod_id;
+ const char *clock_dsi_id;
+ const char *clock_dsi_lp_id;
+ const char *clock_dpi_id;
+ const char *clock_mcde_id;
+
+ int (*platform_set_clocks)(void);
+ int (*platform_enable_dsipll)(void);
+ int (*platform_disable_dsipll)(void);
+};
+
+int mcde_init(void);
+void mcde_exit(void);
+
+#endif /* __MCDE__H__ */
diff --git a/include/video/mcde_display-ab8500.h b/include/video/mcde_display-ab8500.h
new file mode 100644
index 00000000000..ffebe62af92
--- /dev/null
+++ b/include/video/mcde_display-ab8500.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * AB8500 tvout driver interface
+ *
+ * Author: Marcel Tunnissen <marcel.tuennissen@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __DISPLAY_AB8500__H__
+#define __DISPLAY_AB8500__H__
+
+#include <video/mcde.h>
+
+struct ab8500_display_platform_data {
+ /* Platform info */
+ struct mcde_col_transform *rgb_2_yCbCr_transform;
+ int nr_regulators;
+ const char *regulator_id[];
+};
+
+#endif /* __DISPLAY_AB8500__H__*/
+
diff --git a/include/video/mcde_display-av8100.h b/include/video/mcde_display-av8100.h
new file mode 100644
index 00000000000..7c13b49e58f
--- /dev/null
+++ b/include/video/mcde_display-av8100.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE HDMI display driver
+ *
+ * Author: Per Persson <per-xb-persson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __DISPLAY_AV8100__H__
+#define __DISPLAY_AV8100__H__
+
+#include <linux/regulator/consumer.h>
+
+#include "mcde_display.h"
+
+#define GPIO_AV8100_RSTN 196
+#define NATIVE_XRES_HDMI 1280
+#define NATIVE_YRES_HDMI 720
+#define NATIVE_XRES_SDTV 720
+#define NATIVE_YRES_SDTV 576
+#define DISPONOFF_SIZE 6
+#define TIMING_SIZE 2
+#define STAYALIVE_SIZE 1
+
+struct mcde_display_hdmi_platform_data {
+ /* Platform info */
+ int reset_gpio;
+ bool reset_high;
+ const char *regulator_id;
+ const char *cvbs_regulator_id;
+ int reset_delay; /* ms */
+ u32 ddb_id;
+ struct mcde_col_transform *rgb_2_yCbCr_transform;
+
+ /* Driver data */ /* TODO: move to driver data instead */
+ bool hdmi_platform_enable;
+ struct regulator *regulator;
+};
+
+struct display_driver_data {
+ struct regulator *cvbs_regulator;
+ bool cvbs_regulator_enabled;
+ bool update_port_pixel_format;
+ const char *fbdevname;
+ struct mcde_video_mode *video_mode;
+};
+
+void hdmi_fb_onoff(struct mcde_display_device *ddev, bool enable,
+ u8 cea, u8 vesa_cea_nr);
+
+#endif /* __DISPLAY_AV8100__H__ */
diff --git a/include/video/mcde_display-generic_dsi.h b/include/video/mcde_display-generic_dsi.h
new file mode 100644
index 00000000000..87ef6baf67a
--- /dev/null
+++ b/include/video/mcde_display-generic_dsi.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE generic DCS display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE_DISPLAY_GENERIC__H__
+#define __MCDE_DISPLAY_GENERIC__H__
+
+#include <linux/regulator/consumer.h>
+
+#include "mcde_display.h"
+
+struct mcde_display_generic_platform_data {
+ /* Platform info */
+ int reset_gpio;
+ bool reset_high;
+ const char *regulator_id;
+ int reset_delay; /* ms */
+ int sleep_out_delay; /* ms */
+ u32 ddb_id;
+
+ /* Driver data */
+ bool generic_platform_enable;
+ struct regulator *regulator;
+ int max_supply_voltage;
+ int min_supply_voltage;
+};
+
+#endif /* __MCDE_DISPLAY_GENERIC__H__ */
+
diff --git a/include/video/mcde_display-sony_acx424akp_dsi.h b/include/video/mcde_display-sony_acx424akp_dsi.h
new file mode 100644
index 00000000000..29fb14a3fdb
--- /dev/null
+++ b/include/video/mcde_display-sony_acx424akp_dsi.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE Sony acx424akp DCS display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE_DISPLAY_SONY_ACX424AKP__H__
+#define __MCDE_DISPLAY_SONY_ACX424AKP__H__
+
+enum display_panel_type {
+ DISPLAY_NONE = 0,
+ DISPLAY_SONY_ACX424AKP = 0x1b81,
+ DISPLAY_SONY_ACX424AKP_ID2 = 0x1a81,
+};
+
+struct mcde_display_sony_acx424akp_platform_data {
+ /* Platform info */
+ int reset_gpio;
+ enum display_panel_type disp_panel; /* display panel types */
+};
+
+#endif /* __MCDE_DISPLAY_SONY_ACX424AKP__H__ */
+
diff --git a/include/video/mcde_display-vuib500-dpi.h b/include/video/mcde_display-vuib500-dpi.h
new file mode 100644
index 00000000000..94bad83bf97
--- /dev/null
+++ b/include/video/mcde_display-vuib500-dpi.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE DPI display driver
+ *
+ * Author: Torbjorn Svensson <torbjorn.x.svensson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __MCDE_DISPLAY_DPI__H__
+#define __MCDE_DISPLAY_DPI__H__
+
+#include <linux/regulator/consumer.h>
+
+#include "mcde_display.h"
+
+struct mcde_display_dpi_platform_data {
+ /* Platform info */
+ int reset_gpio;
+ bool reset_high;
+ const char *regulator_id;
+ int reset_delay;
+
+ /* Driver data */
+ struct regulator *regulator;
+ int max_supply_voltage;
+ int min_supply_voltage;
+};
+#endif /* __MCDE_DISPLAY_DPI__H__ */
diff --git a/include/video/mcde_display.h b/include/video/mcde_display.h
new file mode 100644
index 00000000000..5130b228d84
--- /dev/null
+++ b/include/video/mcde_display.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * ST-Ericsson MCDE display driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE_DISPLAY__H__
+#define __MCDE_DISPLAY__H__
+
+#include <linux/device.h>
+#include <linux/pm.h>
+
+#include <video/mcde.h>
+
+#define UPDATE_FLAG_PIXEL_FORMAT 0x1
+#define UPDATE_FLAG_VIDEO_MODE 0x2
+#define UPDATE_FLAG_ROTATION 0x4
+
+struct mcde_display_dsi_platform_data {
+ int reset_gpio;
+ int link;
+};
+
+#define to_mcde_display_device(__dev) \
+ container_of((__dev), struct mcde_display_device, dev)
+
+struct mcde_display_device {
+ /* MCDE driver static */
+ struct device dev;
+ const char *name;
+ int id;
+ struct mcde_port *port;
+ struct fb_info *fbi;
+ bool fictive;
+
+ /* MCDE dss driver internal */
+ bool initialized;
+ enum mcde_chnl chnl_id;
+ enum mcde_fifo fifo;
+ bool first_update;
+ struct mutex display_lock;
+
+ bool enabled;
+ struct mcde_chnl_state *chnl_state;
+ struct list_head ovlys;
+ struct mcde_rectangle update_area;
+
+
+ /* Display driver internal */
+ u16 native_x_res;
+ u16 native_y_res;
+ u16 physical_width;
+ u16 physical_height;
+ enum mcde_display_power_mode power_mode;
+ enum mcde_ovly_pix_fmt default_pixel_format;
+ enum mcde_ovly_pix_fmt pixel_format;
+ enum mcde_display_rotation rotation;
+ enum mcde_display_rotation orientation;
+ struct mcde_video_mode video_mode;
+ int update_flags;
+ bool stay_alive;
+ int check_transparency;
+
+ /* Driver API */
+ void (*get_native_resolution)(struct mcde_display_device *dev,
+ u16 *x_res, u16 *y_res);
+ enum mcde_ovly_pix_fmt (*get_default_pixel_format)(
+ struct mcde_display_device *dev);
+ void (*get_physical_size)(struct mcde_display_device *dev,
+ u16 *x_size, u16 *y_size);
+
+ int (*set_power_mode)(struct mcde_display_device *dev,
+ enum mcde_display_power_mode power_mode);
+ enum mcde_display_power_mode (*get_power_mode)(
+ struct mcde_display_device *dev);
+
+ int (*try_video_mode)(struct mcde_display_device *dev,
+ struct mcde_video_mode *video_mode);
+ int (*set_video_mode)(struct mcde_display_device *dev,
+ struct mcde_video_mode *video_mode);
+ void (*get_video_mode)(struct mcde_display_device *dev,
+ struct mcde_video_mode *video_mode);
+ int (*set_pixel_format)(struct mcde_display_device *dev,
+ enum mcde_ovly_pix_fmt pix_fmt);
+ enum mcde_ovly_pix_fmt (*get_pixel_format)(
+ struct mcde_display_device *dev);
+ enum mcde_port_pix_fmt (*get_port_pixel_format)(
+ struct mcde_display_device *dev);
+
+ int (*set_rotation)(struct mcde_display_device *dev,
+ enum mcde_display_rotation rotation);
+ enum mcde_display_rotation (*get_rotation)(
+ struct mcde_display_device *dev);
+
+ int (*apply_config)(struct mcde_display_device *dev);
+ int (*invalidate_area)(struct mcde_display_device *dev,
+ struct mcde_rectangle *area);
+ int (*update)(struct mcde_display_device *dev, bool tripple_buffer);
+ int (*on_first_update)(struct mcde_display_device *dev);
+ int (*platform_enable)(struct mcde_display_device *dev);
+ int (*platform_disable)(struct mcde_display_device *dev);
+ int (*ceanr_convert)(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr, int buffering,
+ u16 *w, u16 *h, u16 *vw, u16 *vh);
+};
+
+struct mcde_display_driver {
+ int (*probe)(struct mcde_display_device *dev);
+ int (*remove)(struct mcde_display_device *dev);
+ void (*shutdown)(struct mcde_display_device *dev);
+ int (*suspend)(struct mcde_display_device *dev,
+ pm_message_t state);
+ int (*resume)(struct mcde_display_device *dev);
+
+ struct device_driver driver;
+};
+
+/* MCDE dsi (Used by MCDE display drivers) */
+
+int mcde_display_dsi_dcs_write(struct mcde_display_device *dev,
+ u8 cmd, u8 *data, int len);
+int mcde_display_dsi_dcs_read(struct mcde_display_device *dev,
+ u8 cmd, u8 *data, int *len);
+int mcde_display_dsi_bta_sync(struct mcde_display_device *dev);
+
+/* MCDE display bus */
+
+int mcde_display_driver_register(struct mcde_display_driver *drv);
+void mcde_display_driver_unregister(struct mcde_display_driver *drv);
+int mcde_display_device_register(struct mcde_display_device *dev);
+void mcde_display_device_unregister(struct mcde_display_device *dev);
+
+void mcde_display_init_device(struct mcde_display_device *dev);
+
+int mcde_display_init(void);
+void mcde_display_exit(void);
+
+#endif /* __MCDE_DISPLAY__H__ */
+
diff --git a/include/video/mcde_dss.h b/include/video/mcde_dss.h
new file mode 100644
index 00000000000..efed79ad023
--- /dev/null
+++ b/include/video/mcde_dss.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson MCDE display sub system driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE_DSS__H__
+#define __MCDE_DSS__H__
+
+#include <linux/kobject.h>
+#include <linux/notifier.h>
+
+#include "mcde.h"
+#include "mcde_display.h"
+
+/* Public MCDE dss (Used by MCDE fb ioctl & MCDE display sysfs) */
+int mcde_dss_open_channel(struct mcde_display_device *ddev);
+void mcde_dss_close_channel(struct mcde_display_device *ddev);
+int mcde_dss_enable_display(struct mcde_display_device *ddev);
+void mcde_dss_disable_display(struct mcde_display_device *ddev);
+int mcde_dss_apply_channel(struct mcde_display_device *ddev);
+struct mcde_overlay *mcde_dss_create_overlay(struct mcde_display_device *ddev,
+ struct mcde_overlay_info *info);
+void mcde_dss_destroy_overlay(struct mcde_overlay *ovl);
+int mcde_dss_enable_overlay(struct mcde_overlay *ovl);
+void mcde_dss_disable_overlay(struct mcde_overlay *ovl);
+int mcde_dss_apply_overlay(struct mcde_overlay *ovl,
+ struct mcde_overlay_info *info);
+void mcde_dss_get_overlay_info(struct mcde_overlay *ovly,
+ struct mcde_overlay_info *info);
+int mcde_dss_update_overlay(struct mcde_overlay *ovl, bool tripple_buffer);
+
+void mcde_dss_get_native_resolution(struct mcde_display_device *ddev,
+ u16 *x_res, u16 *y_res);
+enum mcde_ovl_pix_fmt mcde_dss_get_default_color_format(
+ struct mcde_display_device *ddev);
+void mcde_dss_get_physical_size(struct mcde_display_device *ddev,
+ u16 *x_size, u16 *y_size); /* mm */
+
+int mcde_dss_try_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+int mcde_dss_set_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+void mcde_dss_get_video_mode(struct mcde_display_device *ddev,
+ struct mcde_video_mode *video_mode);
+
+int mcde_dss_set_pixel_format(struct mcde_display_device *ddev,
+ enum mcde_ovly_pix_fmt pix_fmt);
+int mcde_dss_get_pixel_format(struct mcde_display_device *ddev);
+
+int mcde_dss_set_rotation(struct mcde_display_device *ddev,
+ enum mcde_display_rotation rotation);
+enum mcde_display_rotation mcde_dss_get_rotation(
+ struct mcde_display_device *ddev);
+
+int mcde_dss_set_synchronized_update(struct mcde_display_device *ddev,
+ bool enable);
+bool mcde_dss_get_synchronized_update(struct mcde_display_device *ddev);
+
+/* MCDE dss events */
+
+/* A display device and driver has been loaded, probed and bound */
+#define MCDE_DSS_EVENT_DISPLAY_REGISTERED 1
+/* A display device has been removed */
+#define MCDE_DSS_EVENT_DISPLAY_UNREGISTERED 2
+
+/* Note! Notifier callback will be called holding the dev sem */
+int mcde_dss_register_notifier(struct notifier_block *nb);
+int mcde_dss_unregister_notifier(struct notifier_block *nb);
+
+/* MCDE dss driver */
+
+int mcde_dss_init(void);
+void mcde_dss_exit(void);
+
+#endif /* __MCDE_DSS__H__ */
+
diff --git a/include/video/mcde_fb.h b/include/video/mcde_fb.h
new file mode 100644
index 00000000000..17556414aa0
--- /dev/null
+++ b/include/video/mcde_fb.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * ST-Ericsson MCDE display sub system frame buffer driver
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#ifndef __MCDE_FB__H__
+#define __MCDE_FB__H__
+
+#include <linux/fb.h>
+#include <linux/ioctl.h>
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/types.h>
+#include <linux/hwmem.h>
+#endif
+
+#ifdef __KERNEL__
+#include "mcde_dss.h"
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#endif
+
+#define MCDE_GET_BUFFER_NAME_IOC _IO('M', 1)
+
+#ifdef __KERNEL__
+#define to_mcde_fb(x) ((struct mcde_fb *)(x)->par)
+
+#define MCDE_FB_MAX_NUM_OVERLAYS 3
+
+struct mcde_fb {
+ int num_ovlys;
+ struct mcde_overlay *ovlys[MCDE_FB_MAX_NUM_OVERLAYS];
+ u32 pseudo_palette[17];
+ enum mcde_ovly_pix_fmt pix_fmt;
+ int id;
+ struct hwmem_alloc *alloc;
+ int alloc_name;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+};
+
+/* MCDE fbdev API */
+struct fb_info *mcde_fb_create(struct mcde_display_device *ddev,
+ uint16_t w, uint16_t h, uint16_t vw, uint16_t vh,
+ enum mcde_ovly_pix_fmt pix_fmt, uint32_t rotate);
+
+int mcde_fb_attach_overlay(struct fb_info *fb_info,
+ struct mcde_overlay *ovl);
+void mcde_fb_destroy(struct mcde_display_device *ddev);
+
+/* MCDE fb driver */
+int mcde_fb_init(void);
+void mcde_fb_exit(void);
+#endif
+
+#endif /* __MCDE_FB__H__ */
+